Files
grok-free-register-oss/xai_enroller/ledger.py
chaos d10009d639 Initial commit: grok-free-register-oss
Open-source Grok free registration CLI, xai_enroller auth pipeline,
local auth service, tests and docs.
2026-07-16 21:04:05 +08:00

276 lines
11 KiB
Python

import hashlib
import hmac
import os
import sqlite3
from datetime import datetime, timezone
from pathlib import Path
from .models import JobStatus
class Ledger:
def __init__(self, path: Path, salt: bytes):
self.path = Path(path)
self.salt = bytes(salt)
self._init()
def _connect(self):
connection = sqlite3.connect(self.path)
connection.row_factory = sqlite3.Row
return connection
def _init(self):
with self._connect() as connection:
connection.execute(
"""
CREATE TABLE IF NOT EXISTS jobs (
job_id INTEGER PRIMARY KEY,
source_fingerprint TEXT NOT NULL,
attempt_number INTEGER NOT NULL,
status TEXT NOT NULL,
started_at TEXT NOT NULL,
finished_at TEXT,
reason_code TEXT,
sink_receipt_fingerprint TEXT
)
"""
)
columns = {
row["name"] for row in connection.execute("PRAGMA table_info(jobs)")
}
if "authorization_started" not in columns:
connection.execute(
"ALTER TABLE jobs ADD COLUMN authorization_started INTEGER NOT NULL DEFAULT 0"
)
connection.execute(
"CREATE INDEX IF NOT EXISTS jobs_source_status_idx "
"ON jobs(source_fingerprint, status)"
)
connection.execute(
"""
CREATE TABLE IF NOT EXISTS credential_inventory (
sink_receipt_fingerprint TEXT PRIMARY KEY,
state TEXT NOT NULL CHECK(state IN ('available', 'claiming', 'claimed')),
claimed_at TEXT NOT NULL DEFAULT '',
batch_id TEXT NOT NULL DEFAULT '',
note TEXT NOT NULL DEFAULT ''
)
"""
)
connection.execute(
"CREATE INDEX IF NOT EXISTS credential_inventory_state_idx "
"ON credential_inventory(state)"
)
connection.execute(
"""
INSERT OR IGNORE INTO credential_inventory(
sink_receipt_fingerprint, state
)
SELECT sink_receipt_fingerprint, 'available'
FROM jobs
WHERE status=?
AND COALESCE(TRIM(sink_receipt_fingerprint), '') <> ''
""",
(JobStatus.IMPORTED.value,),
)
os.chmod(self.path, 0o600)
def fingerprint(self, source_id):
return hmac.new(self.salt, source_id.encode(), hashlib.sha256).hexdigest()
def _fingerprint(self, source_id):
return self.fingerprint(source_id)
def start(self, source_id, attempt=1):
return self.start_fingerprint(self.fingerprint(source_id), attempt=attempt)
def start_fingerprint(self, source_fingerprint, attempt=None):
if attempt is None:
attempt = self.next_attempt(source_fingerprint)
now = datetime.now(timezone.utc).isoformat()
with self._connect() as connection:
cursor = connection.execute(
"INSERT INTO jobs(source_fingerprint, attempt_number, status, started_at) "
"VALUES (?, ?, ?, ?)",
(source_fingerprint, attempt, "pending", now),
)
return cursor.lastrowid
def next_attempt(self, source_fingerprint):
with self._connect() as connection:
row = connection.execute(
"SELECT COALESCE(MAX(attempt_number), 0) + 1 AS next_attempt "
"FROM jobs WHERE source_fingerprint=?",
(source_fingerprint,),
).fetchone()
return int(row["next_attempt"])
def mark_authorization_started(self, job_id):
with self._connect() as connection:
connection.execute(
"UPDATE jobs SET authorization_started=1 "
"WHERE job_id=? AND status='pending'",
(job_id,),
)
def finish(self, job_id, status, reason_code, sink_receipt_fingerprint=None):
status_value = status.value if isinstance(status, JobStatus) else str(status)
now = datetime.now(timezone.utc).isoformat()
with self._connect() as connection:
cursor = connection.execute(
"UPDATE jobs SET status=?, finished_at=?, reason_code=?, "
"sink_receipt_fingerprint=? "
"WHERE job_id=? AND status='pending'",
(status_value, now, reason_code, sink_receipt_fingerprint, job_id),
)
if (
cursor.rowcount == 1
and status_value == JobStatus.IMPORTED.value
and sink_receipt_fingerprint
):
connection.execute(
"INSERT OR IGNORE INTO credential_inventory("
"sink_receipt_fingerprint, state) VALUES (?, 'available')",
(sink_receipt_fingerprint,),
)
def claim_available(self, limit, batch_id):
limit = int(limit)
if limit <= 0:
return []
batch_id = str(batch_id).strip()
if not batch_id:
raise ValueError("batch_id must not be empty")
with self._connect() as connection:
connection.execute("BEGIN IMMEDIATE")
rows = connection.execute(
"""
WITH latest_import AS (
SELECT sink_receipt_fingerprint, MAX(finished_at) AS finished_at
FROM jobs
WHERE status=?
AND COALESCE(TRIM(sink_receipt_fingerprint), '') <> ''
GROUP BY sink_receipt_fingerprint
)
SELECT inventory.sink_receipt_fingerprint
FROM credential_inventory AS inventory
JOIN latest_import USING (sink_receipt_fingerprint)
WHERE inventory.state='available'
ORDER BY latest_import.finished_at DESC,
inventory.sink_receipt_fingerprint ASC
LIMIT ?
""",
(JobStatus.IMPORTED.value, limit),
).fetchall()
fingerprints = [row["sink_receipt_fingerprint"] for row in rows]
connection.executemany(
"UPDATE credential_inventory SET state='claiming', batch_id=?, "
"claimed_at='', note='' "
"WHERE sink_receipt_fingerprint=? AND state='available'",
((batch_id, fingerprint) for fingerprint in fingerprints),
)
return fingerprints
def mark_claimed(self, batch_id, note=""):
batch_id = str(batch_id).strip()
if not batch_id:
raise ValueError("batch_id must not be empty")
with self._connect() as connection:
cursor = connection.execute(
"UPDATE credential_inventory SET state='claimed', claimed_at=?, note=? "
"WHERE state='claiming' AND batch_id=?",
(datetime.now(timezone.utc).isoformat(), str(note), batch_id),
)
return cursor.rowcount
def inventory_counts(self):
counts = {"available": 0, "claiming": 0, "claimed": 0}
with self._connect() as connection:
rows = connection.execute(
"SELECT state, COUNT(*) AS count FROM credential_inventory GROUP BY state"
)
for row in rows:
counts[row["state"]] = int(row["count"])
return counts
def pending_claims(self, batch_id=None):
query = (
"SELECT sink_receipt_fingerprint, batch_id, note "
"FROM credential_inventory WHERE state='claiming'"
)
params = ()
if batch_id is not None:
query += " AND batch_id=?"
params = (str(batch_id),)
query += " ORDER BY batch_id, sink_receipt_fingerprint"
with self._connect() as connection:
rows = connection.execute(query, params)
return [dict(row) for row in rows]
def recover_claiming(self, batch_id=None, *, note=""):
query = (
"UPDATE credential_inventory SET state='available', claimed_at='', "
"batch_id='', note=? WHERE state='claiming'"
)
params = [str(note)]
if batch_id is not None:
query += " AND batch_id=?"
params.append(str(batch_id))
with self._connect() as connection:
cursor = connection.execute(query, params)
return cursor.rowcount
def recover_pending(self, *, reason="recovered_pending"):
with self._connect() as connection:
connection.execute(
"UPDATE jobs SET status=?, finished_at=?, reason_code=? WHERE status='pending'",
(JobStatus.CANCELLED.value, datetime.now(timezone.utc).isoformat(), reason),
)
def has_imported(self, source_id):
with self._connect() as connection:
row = connection.execute(
"SELECT 1 FROM jobs WHERE source_fingerprint=? AND status=? LIMIT 1",
(self.fingerprint(source_id), JobStatus.IMPORTED.value),
).fetchone()
return row is not None
def imported_fingerprints(self):
with self._connect() as connection:
rows = connection.execute(
"SELECT DISTINCT source_fingerprint FROM jobs WHERE status=?",
(JobStatus.IMPORTED.value,),
)
return {row["source_fingerprint"] for row in rows}
def aggregate_counts(self):
with self._connect() as connection:
row = connection.execute(
"""
SELECT
COUNT(DISTINCT CASE WHEN authorization_started=1 OR status=?
THEN source_fingerprint END) AS attempted_unique,
COUNT(DISTINCT CASE WHEN status=?
THEN source_fingerprint END) AS imported_unique,
COUNT(CASE WHEN finished_at IS NOT NULL THEN 1 END) AS finalized_attempts,
COUNT(CASE WHEN status=? THEN 1 END) AS imported_attempts,
COUNT(CASE WHEN reason_code='rate_limited' THEN 1 END) AS rate_limited
FROM jobs
""",
(
JobStatus.IMPORTED.value,
JobStatus.IMPORTED.value,
JobStatus.IMPORTED.value,
),
).fetchone()
return {key: int(row[key] or 0) for key in row.keys()}
def get(self, job_id):
with self._connect() as connection:
row = connection.execute(
"SELECT source_fingerprint, attempt_number, status, started_at, finished_at, "
"reason_code, sink_receipt_fingerprint FROM jobs WHERE job_id=?",
(job_id,),
).fetchone()
return dict(row) if row else None