d582f15681
- Implemented tests for import polling functionality, ensuring correct behavior for active and terminal import statuses. - Created tests for the login page, validating user interactions and error handling. - Added unit tests for money utility functions, covering parsing, formatting, and summation of monetary values. - Developed tests for query keys, ensuring proper scoping and invalidation roots. chore: setup testing environment and configuration - Added setup file for testing with Vitest and Testing Library. - Configured TypeScript and Vite for the frontend project. - Created Docker and Nginx configurations for local development and production environments. - Established a PostgreSQL initialization script for setting up application roles. docs: add README and environment configuration for infra - Included README for the infra directory, detailing local development setup and service descriptions. - Created an example environment configuration file for local development with placeholders for sensitive information.
37 lines
2.0 KiB
Markdown
37 lines
2.0 KiB
Markdown
# Deletion Ledger
|
|
|
|
> Status: **contract definition**. The hardening workstream (plan §9) implements
|
|
> this; nothing here is verified in code yet.
|
|
|
|
## Purpose
|
|
|
|
Space deletion is final and must survive disaster restores. A backup restored
|
|
after a purge would otherwise resurrect rows, objects and metadata of deleted
|
|
spaces. The deletion ledger is an append-only record of completed deletions that
|
|
any restore **must** replay before serving traffic.
|
|
|
|
## Lifecycle
|
|
|
|
1. **Request** — user requests space deletion. The space is locked immediately (no logins, writes or imports); a 30-day cancellation window starts.
|
|
2. **Cancel** — within the window the owner may cancel; the lock is lifted, nothing is purged.
|
|
3. **Purge** (after the window, via Celery worker):
|
|
- hard-delete all space rows (financial tables, categories, payees, imports, memberships, users where applicable);
|
|
- delete all S3 objects of the space and destroy the per-file DEK rows (crypto-shred, ADR 0004);
|
|
- append one ledger entry **only after** all phases succeed.
|
|
4. **Ledger entry** — append-only, minimal fields: `space_id`, `requested_at`, `purged_at`, `executed_by (job id)`, `phases_completed`, `integrity_hash` (chain hash over prior entry). No financial payloads.
|
|
|
|
## Replay after restore
|
|
|
|
On any disaster restore (see `backup-and-restore.md` step 6):
|
|
|
|
1. Load ledger entries with `purged_at` later than the restored backup timestamp.
|
|
2. For each: re-delete the space's rows (restored backups may contain them again), re-delete its objects, re-destroy DEK rows.
|
|
3. Verify: no row with `space_id` in any financial table; bucket prefix absent; decryption of the space's files impossible.
|
|
4. Record the replay in the drill log.
|
|
|
|
## Implementation notes
|
|
|
|
- The ledger table itself is never purged by space deletion and is included in backups.
|
|
- A purge job must be idempotent and resumable: each phase is committed separately and the ledger entry is written last, in the same transaction as the final phase marker.
|
|
- Ledger integrity is checked on startup after restore (chain hash mismatch = manual escalation).
|