# Slice 1 prototype, v2 (addendum A, item A3) Darkwing, 2026-10-04, for lead decision 49. Design work, uncommitted. The v1 files (`schema.sql`, `proto.mjs`, `replace.mjs` and their outputs) are unchanged. `schema-v2.sql` is a full schema that stands on its own, and it replaces v1. It isn't a migration. What changed from `schema.sql`: - `decisions.blocking` is `INTEGER NOT NULL CHECK (blocking IN (0,1))` with no default, so whoever raises a decision has to choose a value. A trigger refuses `blocking = 1` without a `task_ref`. Addendum A section 8 said a blocking decision "should" cite its task. The prototype enforces it. - `task_snapshots` is new. Its columns follow addendum A section 5. A `self` row needs a role and a run, and a `poll` row has neither. The task ref must match `vikunja:/`, and the digest must be 64 lowercase hex characters. It has the same three guards as every other table (UPDATE, DELETE, and an existing `seq` on INSERT). - `events.kind` is now a closed list in a CHECK constraint. It holds every kind from note section 4 that has no table of its own, plus the seven from addendum A. Adding a kind is a schema change, and the open-time digest notices one made outside review. - Two body rules on events. `launch.revoked` and `launch.restored` must carry no role and no run, because only the human writes them (REQ- LAUNCH-1). A `credential.*` event must name a service (`gitea` or `vikunja`) and a role instance. - Three views: - `urgent_inbox` lists open gated decisions with `blocking = 1`. These go out at once under REQ-DEC-4. - `launch_state` gives the latest revoke or restore per business. - `task_external_changes` lists tasks whose newest snapshot is a poll that differs from the broker's last write, with an `updated` no older than that write. A stale poll that started before the write doesn't count. A person's edit in the same second as a write does. - The open-time check now hashes every schema object (tables, indexes, triggers and views), not only triggers. A CHECK list lives in a table's SQL, so a trigger-only digest would miss a widened kind list. Results: `proto-v2-node24.txt` (Node 24.21.0 in the `node:24` image) and `proto-v2-node26.txt` (Node 26.8.1 on the host). Both use SQLite 3.53.4, and the two outputs differ only in the version line. Every refusal the script expects happens. UPDATE, DELETE and INSERT OR REPLACE are refused on all eight tables. Dropping one guard and reopening the file gives `MISMATCH`. Limits, the same as v1. The triggers catch our own bugs. A process running as the same user can still drop a trigger, and the digest check only notices that afterwards. The views are demonstrations. The broker will run its own queries, and the views exist so a reviewer can see the rules in SQL.