fix(account): close deletion cache gap
CI and Deploy / test (pull_request) Successful in 5m22s
CI and Deploy / deploy (pull_request) Has been skipped

Require authenticated sidecar cache purge before a deletion can complete and keep failures retryable. Mount tombstones outside restored application data while leaving deletion disabled by default.
This commit is contained in:
cesnimda
2026-08-15 19:40:07 +02:00
parent c0e190d5b5
commit 7185491a05
14 changed files with 134 additions and 20 deletions
@@ -37,15 +37,18 @@ No existing generated file is moved or guessed. Legacy shared-date outputs stay
- Self-service requires an exact server-provided `DELETE <email>` phrase and a session created within 15 minutes. Last-administrator protection remains enforced. Admin deletion uses the same coordinator and exact-email confirmation header.
- One managed-root inventory covers attachments, CV artifacts, file-backed avatars, generated CVs, daily exports, and previously generated account-export ZIPs. Files move to same-volume quarantine markers before any database delete; partial file failure restores them and leaves rows untouched.
- Database deletion is explicit and transactional across all owned application, Career, CV, correspondence, provider-credential, queue/notification, security, and Identity rows. Request/file ledgers survive for retry and audit. Commit-acknowledgement ambiguity leaves files quarantined and replays deletion instead of risking data resurrection.
- Purge clears backend in-memory caches, removes quarantined files, then writes a minimal pseudonymous tombstone to a separate append-only JSONL root. Invalid ledger records fail closed.
- Purge clears backend in-memory caches, removes quarantined files, and calls the authenticated AI-sidecar maintenance endpoint before it can write a minimal pseudonymous tombstone. A sidecar failure leaves the durable request at `purging_files` for retry rather than falsely completing. Invalid ledger records fail closed.
- Production Compose maps the tombstone root to the separate `jobtracker_deletion_tombstones` named volume and exposes only the disabled-by-default `ACCOUNT_DELETION_ENABLED` switch. This is repository configuration evidence, not proof that the volume exists or is protected on production.
- Startup stages restored identities matching tombstones before readiness, and the background reconciler resumes all durable non-completed requests even while new deletion requests remain disabled.
- Settings explains the disabled production gate; when enabled it uses the reusable prompt dialog and exact phrase. Admin user deletion supplies the matching account email.
## Verification
- Owner-storage focused CV/export/controller/background tests: 77/77.
- Account lifecycle/export/auth/admin focused backend/API tests: 21/21. Five real-SQLite deletion tests cover disabled requests, exact confirmation/recent authentication, immediate lockout/idempotency, two-owner row/file isolation, quarantine failure, repeat reconciliation, tombstone creation, and restored-backup replay.
- Full backend: 657/657.
- Account lifecycle focused backend/API tests: 6/6. The new failure test proves a sidecar outage prevents completion/tombstone creation and a later retry succeeds. The broader lifecycle/export/auth/admin slice remains 21/21 from the prior checkpoint.
- Full backend: 658/658.
- AI sidecar: 23/23, including authenticated cache purge; cache access is lock-protected.
- Production Compose configuration: valid with a distinct tombstone volume and deletion disabled by default.
- Frontend export/Settings/admin tests: 8/8; full frontend 58 suites/237 tests.
- Backend build: pass, zero warnings/errors.
- Optimized frontend build/TypeScript: pass.
@@ -56,8 +59,8 @@ No existing generated file is moved or guessed. Legacy shared-date outputs stay
## Remaining external/production work
1. Decide backup, audit/security-log, quarantine, and tombstone retention plus any legal-hold obligations.
2. Mount/protect the tombstone root outside restored application data and rehearse a pre-deletion backup restore with tombstone replay.
3. Rehearse sidecar cache purge/restart and remote provider-revocation semantics using a disposable synthetic account.
2. Deploy and protect the separately configured tombstone volume, then rehearse a pre-deletion backup restore with tombstone replay.
3. Rehearse the implemented sidecar cache purge across container restart and define remote provider-revocation semantics using a disposable synthetic account.
4. Only then enable admin deletion, observe it, and separately approve self-service activation.
Production retention, legal hold and restored-backup decisions remain recorded in `BLOCKERS.md`.