aboutsummaryrefslogtreecommitdiff
path: root/docs/SCHEMA.md
diff options
context:
space:
mode:
authorAnders Betts <anders.betts@gmail.com>2026-09-20 10:36:09 +0200
committerAnders Betts <anders.betts@gmail.com>2026-09-20 10:36:09 +0200
commit9ee8cb18b1017dce11e7c8c9b7fafad301cb766e (patch)
treeab28600c9c29bb425a25d2375d28e95a97aa1f2c /docs/SCHEMA.md
parentae60b7d2c87cc9ed6878faa57cd4233f77f6f7c3 (diff)
downloadbokf-9ee8cb18b1017dce11e7c8c9b7fafad301cb766e.tar.gz
bokf-9ee8cb18b1017dce11e7c8c9b7fafad301cb766e.zip
db: make attachments append-only (schema v7)
Diffstat (limited to 'docs/SCHEMA.md')
-rw-r--r--docs/SCHEMA.md12
1 files changed, 10 insertions, 2 deletions
diff --git a/docs/SCHEMA.md b/docs/SCHEMA.md
index 89dd0b1..2a85521 100644
--- a/docs/SCHEMA.md
+++ b/docs/SCHEMA.md
@@ -306,6 +306,11 @@ CREATE TABLE attachments (
UNIQUE (org_id, sha256, filename)
) STRICT;
+CREATE TRIGGER attachments_no_update BEFORE UPDATE ON attachments
+BEGIN SELECT RAISE(ABORT, 'attachments are append-only'); END;
+CREATE TRIGGER attachments_no_delete BEFORE DELETE ON attachments
+BEGIN SELECT RAISE(ABORT, 'attachments are append-only'); END;
+
CREATE TABLE voucher_attachments (
org_id INTEGER NOT NULL,
voucher_id INTEGER NOT NULL,
@@ -317,8 +322,11 @@ CREATE TABLE voucher_attachments (
) STRICT;
```
-Attachments are content-addressed and immutable; linking is an insert into
-`voucher_attachments` and is itself audited. Unlinked attachments form the
+Attachments are content-addressed and immutable — the triggers abort updates
+and deletes even for a root `sqlite3` session, and `audit.verify full:true`
+re-hashes the content; linking is an insert into
+`voucher_attachments` and is itself audited (the link table stays mutable so
+underlag can be unlinked). Unlinked attachments form the
inbox the TUI shows. The 7-year archive rule means content must never be
garbage-collected; deduplication by hash keeps repeated receipts cheap.