feat(5.6): observabilitate + jurnal aplicatie + lifecycle trimiteri blocate
Implementeaza PRD 5.6 complet (14 stories, TDD). Doua axe:
Lifecycle trimiteri blocate (Val A):
- submissions_admin.py: sterge/repune scoped (404 cross-account inaintea lui 409 stare)
- reactivare dedup peste `error` cu CAS (WHERE id=? AND status='error'), creds noi in
submissions + accounts.rar_creds_enc; worker invalideaza sesiunea RAR la creds proaspete
(JWT 30h vechi nu mai trimite cu parola gresita); camp aditiv `reactivated:true`
- retentie randuri blocate 30z; purge_expired exclude queued/sending; purge_after curatat
la reactivare/requeue
- API DELETE /v1/prezentari/{id} + /repune (200+JSON); UI butoane + bulk + banner actionabil
Observabilitate:
- app/observ.py log_event: dublu canal app_events (DB) + RotatingFileHandler per-proces,
redactare creds/PII la scriere (redact_pii/vin_partial)
- request_id middleware + X-Request-ID pe toate raspunsurile
- handler global excepții -> 500 envelope 6-chei + request_id (traceback doar in jurnal)
- audit cerere API (api_prezentari/api_auth_esuat) + audit worker (rar_login/tranzitii)
- tab "Jurnal" filtrabil scoped (non-admin doar contul sau); retentie jurnal 90z
- rar_error expus in GET /v1/prezentari/{id} (recovery observabil)
pytest -q: 741 passed, 0 failed. Docs: PRD raport VERIFY, contract endpointuri noi, ROADMAP.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -154,6 +154,29 @@ CREATE TABLE IF NOT EXISTS users (
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
-- Jurnal de aplicatie la nivel de eveniment (PRD 5.6). Dublu canal: aici (vizibil
|
||||
-- in tab "Jurnal") + log text rotativ (depanare). `tip` e text liber documentat
|
||||
-- (lista extensibila, decizie §5) — adaugam tipuri fara migrare. Toate valorile
|
||||
-- sunt REDACTATE la scriere (app/observ.py via app/security.py): parole/token ->
|
||||
-- ***REDACTED***, VIN/nr partial. `context_json` = metadate (NU payload PII integral).
|
||||
CREATE TABLE IF NOT EXISTS app_events (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
ts TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
request_id TEXT, -- corelare cu raspunsul clientului (US-002)
|
||||
account_id INTEGER, -- NULL = eveniment de sistem (fara cont)
|
||||
sursa TEXT NOT NULL DEFAULT 'api'
|
||||
CHECK (sursa IN ('api','worker')),
|
||||
tip TEXT NOT NULL, -- ex. api_prezentari, rar_login, submission_repus
|
||||
nivel TEXT NOT NULL DEFAULT 'INFO',
|
||||
cod TEXT, -- cod din catalogul de erori (app/errors.py) daca aplica
|
||||
mesaj TEXT, -- mesaj scurt redactat
|
||||
context_json TEXT, -- JSON metadate redactate (submission_id, count, status...)
|
||||
purge_after TEXT -- ts + log_retention_days (US-008)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_app_events_ts ON app_events(ts);
|
||||
CREATE INDEX IF NOT EXISTS idx_app_events_account ON app_events(account_id, ts);
|
||||
CREATE INDEX IF NOT EXISTS idx_app_events_tip ON app_events(tip);
|
||||
|
||||
-- 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),
|
||||
|
||||
Reference in New Issue
Block a user