feat: schelet gateway FastAPI (API v1 + worker + dashboard + SQLite WAL)
Structura repo conform plan.md sect. 4, booteaza cu /healthz verde:
- app/main.py: FastAPI (lifespan init_db), /healthz (worker viu + last login + queue), /metrics
- app/api/v1: POST /v1/prezentari (enqueue + dedup idempotency UNIQUE), GET prezentari/{id}, nomenclator, mapari
- app/rar_client.py: client RAR real (login/JWT, nomenclator, postPrezentare, getFinalizate) cu User-Agent obligatoriu (fix WAF 403)
- app/worker: proces separat, claim atomic BEGIN IMMEDIATE, heartbeat, login+send (send dezactivat by default)
- app/web: dashboard Jinja2+HTMX (coada, banner alerta blocate, worker viu/mort, stari empty)
- app/db.py + schema.sql: SQLite WAL, tabele accounts/api_keys/operations_mapping/nomenclator_rar/submissions/worker_heartbeat
- app/idempotency.py + payload.py: hash continut canonic + builder payload (status FINALIZATA, fara tipPrestatie)
- Dockerfile + docker-compose.yml (api+worker, volum SQLite persistent, restart:always)
- tools/import_dbf.py: stub T5
Verificat live: login prin rar_client OK (token 259), nomenclator 18 coduri, worker heartbeat -> /healthz worker_alive=True.
Ramas: T3 validare Pydantic, T4 snapshot payload, T2 reconciliere/retry worker, T5 import DBF, auth API-key, middleware redactare creds, criptare PII.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
73
app/schema.sql
Normal file
73
app/schema.sql
Normal file
@@ -0,0 +1,73 @@
|
||||
-- Schema SQLite (WAL) pentru gateway RAR AUTOPASS.
|
||||
-- Vezi plan.md sect. 5. NICIUN camp pentru parole RAR.
|
||||
-- Validarea completa (T3) si criptarea PII (P2) vin ulterior; in schelet
|
||||
-- payload-ul e stocat ca JSON text (camp payload_json), de inlocuit cu BLOB
|
||||
-- criptat + purge_after cand se face T7/criptare.
|
||||
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
-- Conturi ROAAUTO (clientii care folosesc gateway-ul).
|
||||
CREATE TABLE IF NOT EXISTS accounts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
cui TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
-- Chei API per cont (separate de creds RAR). Stocam doar hash-ul.
|
||||
CREATE TABLE IF NOT EXISTS api_keys (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
account_id INTEGER NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
key_hash TEXT NOT NULL UNIQUE,
|
||||
active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
revoked_at TEXT
|
||||
);
|
||||
|
||||
-- Mapare operatie service -> codPrestatie RAR (← mapare_prestatii.DBF, T5).
|
||||
CREATE TABLE IF NOT EXISTS operations_mapping (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
account_id INTEGER NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
|
||||
cod_op_service TEXT NOT NULL,
|
||||
cod_prestatie TEXT NOT NULL,
|
||||
auto_send INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
UNIQUE (account_id, cod_op_service)
|
||||
);
|
||||
|
||||
-- Cache nomenclator RAR {codPrestatie, numePrestatie} (← prestatii_rar.DBF / live).
|
||||
CREATE TABLE IF NOT EXISTS nomenclator_rar (
|
||||
cod_prestatie TEXT PRIMARY KEY,
|
||||
nume_prestatie TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
-- Coada de prezentari catre RAR. Masina de stari: plan.md sect. 3.
|
||||
CREATE TABLE IF NOT EXISTS submissions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
idempotency_key TEXT NOT NULL UNIQUE,
|
||||
account_id INTEGER REFERENCES accounts(id) ON DELETE SET NULL,
|
||||
status TEXT NOT NULL DEFAULT 'queued'
|
||||
CHECK (status IN ('queued','sending','sent','needs_mapping','needs_data','error')),
|
||||
payload_json TEXT NOT NULL, -- TODO(P2): inlocuit cu BLOB criptat
|
||||
rar_status_code INTEGER,
|
||||
rar_error TEXT,
|
||||
id_prezentare INTEGER, -- data.id intors de RAR la succes
|
||||
retry_count INTEGER NOT NULL DEFAULT 0,
|
||||
sending_since TEXT, -- pentru lease/timeout pe randuri 'sending' orfane (T2)
|
||||
purge_after TEXT, -- sent + 90z (P2)
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_submissions_status ON submissions(status);
|
||||
|
||||
-- Heartbeat worker (un singur rand, id=1). /healthz citeste de aici.
|
||||
CREATE TABLE IF NOT EXISTS worker_heartbeat (
|
||||
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||
last_beat TEXT,
|
||||
last_rar_login_ok TEXT,
|
||||
detail TEXT
|
||||
);
|
||||
INSERT OR IGNORE INTO worker_heartbeat (id, last_beat, detail) VALUES (1, NULL, 'never started');
|
||||
Reference in New Issue
Block a user