feat(5.20): US-013 retragere accounts.rar_creds_enc -> per-env + DROP cu garda

Toate citirile pe coloana legacy accounts.rar_creds_enc mutate pe sloturile
per-env (rar_creds_test_enc/rar_creds_prod_enc): worker fallback+keepalive,
are_creds (web) si are_creds_rar (integrare, +are_creds_test/_prod), write-back
API la reactivare, purjare la stergere cont, _get_acasa_context/_fetch_cont_env_state.

Contract API (aditiv): POST /v1/conturi/rar-creds primeste rar_target optional
(test/prod), scrie in slotul corect + activeaza mediul; DELETE primeste ?env
(sterge un slot sau ambele). Documentat in docs/api-rar-contract.md.

DROP cu garda in db.py (schema.sql fara coloana pe DB fresh):
- 6a: eliminat ADD COLUMN rar_creds_enc (fara ping-pong re-ADD dupa DROP)
- 6b: try/except fail-safe (nu crapa boot-ul) + garda sqlite_version >= 3.35
- 6c: re-backfill old->new imediat inainte de assert (ancora globala)
- garda orfane: DROP anulat daca vreun creds legacy nu a aterizat in slot per-env
- backup criptat accounts_rar_creds_enc_backup inainte de DROP
- 6d: verificare prin PRAGMA table_info (NU grep — submissions are aceeasi coloana)
Garda one-way, idempotenta la boot repetat (verificat). submissions.rar_creds_enc
ramane neatinsa.

tests/test_retragere_creds_enc.py: niciun read pe coloana veche, conturi rar-creds
env-aware, are_creds per-env, DROP blocat de garda la lipsa copiere. 9 teste
existente actualizate pe sloturi per-env.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-07-02 21:03:08 +00:00
parent 3d3eb71a1e
commit b1d825e66b
19 changed files with 657 additions and 138 deletions

View File

@@ -238,7 +238,8 @@ def delete_account(conn: sqlite3.Connection, account_id: int) -> None:
NU acest tombstone — de aceea purjam PII aici, la momentul stergerii."""
set_status(conn, account_id, "deleted") # valideaza existenta + protejeaza id=1; seteaza status+active=0
conn.execute(
"UPDATE accounts SET rar_creds_enc=NULL, cui=NULL WHERE id=?", (account_id,)
"UPDATE accounts SET rar_creds_test_enc=NULL, rar_creds_prod_enc=NULL, cui=NULL WHERE id=?",
(account_id,),
)
conn.execute(
"UPDATE api_keys SET active=0, revoked_at=datetime('now') WHERE account_id=? AND active=1",
@@ -247,7 +248,7 @@ def delete_account(conn: sqlite3.Connection, account_id: int) -> None:
def list_accounts(conn: sqlite3.Connection) -> list[dict]:
"""Metadate conturi (FARA `rar_creds_enc`), ordonate dupa id. Exclude conturile 'deleted'
"""Metadate conturi (FARA creds RAR criptate), ordonate dupa id. Exclude conturile 'deleted'
(stergere soft -> invizibile in panou)."""
rows = conn.execute(
"SELECT id, name, cui, email, active, status, tier, trial_until, "