-- open-time schema check
check  after create -> match
-- decisions.blocking
refuse raise without blocking -> NOT NULL constraint failed: decisions.blocking
refuse raise with blocking 2 -> CHECK constraint failed: blocking IN (0,1)
refuse raise blocking without task_ref -> a blocking decision cites the task it blocks
ok     raise blocking gated with task_ref
ok     raise non-blocking gated
ok     raise blocking cross-role
view   urgent_inbox -> [{"id":"d-3","task_ref":"vikunja:3/41"}]
ok     resolve d-3 with A
view   urgent_inbox after resolve -> []
-- events: closed kinds and the new kinds
refuse unknown kind task.deleted -> CHECK constraint failed: kind IN ( 'session.launched', 'session.ended', 'action.allowed', 
ok     credential.expiring vikunja coder
ok     credential.expired vikunja coder
ok     credential.changed gitea pm
refuse credential.changed without instance -> credential events name a service and a role instance
refuse credential.expiring service github -> credential events name a service and a role instance
ok     task.missing
ok     digest.sent
refuse launch.revoked by pm run -> only the human revokes or restores launching
ok     launch.revoked by human
view   launch_state -> [{"business":"mosaic-stack","state":"revoked"}]
ok     launch.restored by human
view   launch_state -> [{"business":"mosaic-stack","state":"allowed"}]
-- task_snapshots
refuse self without role and run -> CHECK constraint failed: (source = 'self') = (role IS NOT NULL AND run IS NOT NULL)
refuse poll with a role -> CHECK constraint failed: (source = 'self') = (role IS NOT NULL AND run IS NOT NULL)
refuse bad task_ref -> CHECK constraint failed: task_ref GLOB 'vikunja:[0-9]*/[0-9]*'
refuse bad digest -> CHECK constraint failed: length(digest) = 64 AND NOT digest GLOB '*[^0-9a-f]*'
ok     self X by coder, updated 12:00:00
ok     poll X (unchanged)
view   external after poll X -> []
ok     poll Y, same second (person edit)
view   external after poll Y -> [{"task_ref":"vikunja:3/41","seq":3}]
ok     self Z by coder, updated 12:00:05
ok     stale poll W, updated 11:59:00
view   external after self Z, stale poll W -> []
ok     poll on vikunja:3/42 with no self row
view   external, task 42 -> [{"task_ref":"vikunja:3/42"}]
-- append-only on every table
refuse meta UPDATE -> meta is append-only
refuse meta DELETE -> meta is append-only
refuse meta INSERT OR REPLACE -> meta is append-only
refuse events UPDATE -> events is append-only
refuse events DELETE -> events is append-only
refuse events INSERT OR REPLACE -> events is append-only
refuse role_claims UPDATE -> role_claims is append-only
refuse role_claims DELETE -> role_claims is append-only
refuse role_claims INSERT OR REPLACE -> role_claims is append-only
refuse decisions UPDATE -> decisions is append-only
refuse decisions DELETE -> decisions is append-only
refuse decisions INSERT OR REPLACE -> decisions is append-only
refuse decision_events UPDATE -> decision_events is append-only
refuse decision_events DELETE -> decision_events is append-only
refuse decision_events INSERT OR REPLACE -> decision_events is append-only
refuse messages UPDATE -> messages is append-only
refuse messages DELETE -> messages is append-only
refuse messages INSERT OR REPLACE -> messages is append-only
refuse deliveries UPDATE -> deliveries is append-only
refuse deliveries DELETE -> deliveries is append-only
refuse deliveries INSERT OR REPLACE -> deliveries is append-only
refuse task_snapshots UPDATE -> task_snapshots is append-only
refuse task_snapshots DELETE -> task_snapshots is append-only
refuse task_snapshots INSERT OR REPLACE -> task_snapshots is append-only
-- tamper: drop a guard, reopen
check  on reopen -> match
check  after DROP TRIGGER -> MISMATCH
node 26.8.1 | sqlite 3.53.4 | journal: wal | tables: 8 | triggers: 32 | views: 3
