From 97305d699e461045ba0a07c8e643f5aa886af7cd Mon Sep 17 00:00:00 2001 From: weichen Date: Tue, 15 Sep 2026 08:52:19 +0000 Subject: [PATCH] feat(db): add event inventory, repair audit, replay plans, and service principals E0A needs additive tables for classification and per-consumer identities before any dispatcher can claim work. FAV principals are rejected at the schema check. Co-authored-by: Cursor --- ...6-09-15-event-inventory-and-principals.sql | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 deploy/postgres/goose/00039_2026-09-15-event-inventory-and-principals.sql diff --git a/deploy/postgres/goose/00039_2026-09-15-event-inventory-and-principals.sql b/deploy/postgres/goose/00039_2026-09-15-event-inventory-and-principals.sql new file mode 100644 index 00000000..bbf27fe6 --- /dev/null +++ b/deploy/postgres/goose/00039_2026-09-15-event-inventory-and-principals.sql @@ -0,0 +1,65 @@ +-- +goose Up +-- E0A: inventory, repair audit, replay plans, and per-consumer service principals. +-- Dispatcher/lease remains off. Do not drop historical envelopes. + +CREATE TABLE IF NOT EXISTS event_inventory_decisions ( + event_id TEXT NOT NULL, + consumer TEXT NOT NULL DEFAULT '', + classification TEXT NOT NULL, + reason TEXT NOT NULL, + payload_digest CHAR(64) NOT NULL DEFAULT '', + operator TEXT NOT NULL, + approval_ref TEXT NOT NULL DEFAULT '', + decided_at TIMESTAMPTZ NOT NULL DEFAULT now(), + PRIMARY KEY (event_id, consumer), + CONSTRAINT chk_event_inventory_class CHECK (classification IN ('safe','repair','quarantine','expire')) +); + +CREATE TABLE IF NOT EXISTS event_repair_audit ( + id BIGSERIAL PRIMARY KEY, + event_id TEXT NOT NULL, + field_name TEXT NOT NULL, + old_digest CHAR(64) NOT NULL, + new_digest CHAR(64) NOT NULL, + operator TEXT NOT NULL, + reason TEXT NOT NULL, + approval_ref TEXT NOT NULL, + repaired_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS event_replay_plans ( + plan_id TEXT PRIMARY KEY, + operator TEXT NOT NULL, + approver TEXT NOT NULL DEFAULT '', + environment TEXT NOT NULL, + project_id BIGINT, + consumer TEXT NOT NULL, + event_ids_digest CHAR(64) NOT NULL, + plan_digest CHAR(64) NOT NULL, + reason TEXT NOT NULL, + approval_ref TEXT NOT NULL DEFAULT '', + dry_run BOOLEAN NOT NULL DEFAULT TRUE, + created_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS event_service_principals ( + principal_id TEXT PRIMARY KEY, + environment TEXT NOT NULL, + consumer TEXT NOT NULL, + actions TEXT[] NOT NULL DEFAULT '{}', + UNIQUE (environment, consumer), + CONSTRAINT chk_event_principal_not_fav CHECK (consumer <> 'fav') +); + +INSERT INTO event_service_principals (principal_id, environment, consumer, actions) +VALUES + ('notify-dev', 'dev', 'notify', ARRAY['notify.emit']), + ('projection-dev', 'dev', 'projection', ARRAY['projection.write']), + ('workflow-advance-dev', 'dev', 'workflow_advance', ARRAY['workflow.advance']) +ON CONFLICT (principal_id) DO NOTHING; + +-- +goose Down +DROP TABLE IF EXISTS event_service_principals; +DROP TABLE IF EXISTS event_replay_plans; +DROP TABLE IF EXISTS event_repair_audit; +DROP TABLE IF EXISTS event_inventory_decisions;