Files
finance/docs/operations/deletion-ledger.md
T
k1nq d582f15681 feat: add tests for import polling, login page, money utilities, and query keys
- 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.
2026-09-14 09:26:33 +05:00

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).