aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
parentae60b7d2c87cc9ed6878faa57cd4233f77f6f7c3 (diff)
downloadbokf-9ee8cb18b1017dce11e7c8c9b7fafad301cb766e.tar.gz
bokf-9ee8cb18b1017dce11e7c8c9b7fafad301cb766e.zip
db: make attachments append-only (schema v7)
Diffstat (limited to 'src')
-rw-r--r--src/db.c29
-rw-r--r--src/db.h2
2 files changed, 30 insertions, 1 deletions
diff --git a/src/db.c b/src/db.c
index 627efbc..c809bea 100644
--- a/src/db.c
+++ b/src/db.c
@@ -206,6 +206,12 @@ static const char SCHEMA_V1[] =
" UNIQUE (org_id, id),"
" UNIQUE (org_id, sha256, filename)"
") STRICT;\n"
+ "CREATE TRIGGER attachments_no_update BEFORE UPDATE ON attachments BEGIN"
+ " SELECT RAISE(ABORT, 'attachments are append-only');"
+ "END;\n"
+ "CREATE TRIGGER attachments_no_delete BEFORE DELETE ON attachments BEGIN"
+ " SELECT RAISE(ABORT, 'attachments are append-only');"
+ "END;\n"
"CREATE TABLE voucher_attachments ("
" org_id INTEGER NOT NULL,"
@@ -433,6 +439,25 @@ static int db_upgrade_v6(sqlite3 *db, char **err)
" DEFAULT ''", err);
}
+/* v7: attachments are immutable too — the content-addressed underlag may
+ never be updated or deleted, only linked/unlinked. */
+static int db_upgrade_v7(sqlite3 *db, char **err)
+{
+ if (db_exec(db,
+ "CREATE TRIGGER IF NOT EXISTS attachments_no_update"
+ " BEFORE UPDATE ON attachments BEGIN"
+ " SELECT RAISE(ABORT, 'attachments are append-only');"
+ "END",
+ err) != 0)
+ return -1;
+ return db_exec(db,
+ "CREATE TRIGGER IF NOT EXISTS attachments_no_delete"
+ " BEFORE DELETE ON attachments BEGIN"
+ " SELECT RAISE(ABORT, 'attachments are append-only');"
+ "END",
+ err);
+}
+
static int db_upgrade(sqlite3 *db, int from, char **err)
{
if (db_exec(db, "BEGIN IMMEDIATE", err) != 0)
@@ -457,6 +482,10 @@ static int db_upgrade(sqlite3 *db, int from, char **err)
db_exec(db, "ROLLBACK", NULL);
return -1;
}
+ if (from < 7 && db_upgrade_v7(db, err) != 0) {
+ db_exec(db, "ROLLBACK", NULL);
+ return -1;
+ }
char *sql = sqlite3_mprintf(
"UPDATE meta SET value='%d' WHERE key='schema_version'",
BOKF_SCHEMA_VERSION);
diff --git a/src/db.h b/src/db.h
index fe3bfbc..03ee5e5 100644
--- a/src/db.h
+++ b/src/db.h
@@ -4,7 +4,7 @@
#include <sqlite3.h>
#include <stdint.h>
-#define BOKF_SCHEMA_VERSION 6
+#define BOKF_SCHEMA_VERSION 7
int db_open(const char *path, sqlite3 **out, char **err);
int db_migrate(sqlite3 *db, char **err);