/** Additive index: historical intake evidence is neither rewritten nor replayed. */ export declare const FEED_MIGRATION: { readonly id: "events_feed_0001"; readonly sql: ` CREATE TABLE events_consumer_grants ( tenant_id TEXT NOT NULL, consumer_id UUID NOT NULL, producer_id UUID NOT NULL, kid TEXT NOT NULL REFERENCES api_keys(kid), event_types TEXT[] NOT NULL CHECK (cardinality(event_types) BETWEEN 1 AND 50), subject TEXT, active BOOLEAN NOT NULL DEFAULT TRUE, generation BIGINT NOT NULL DEFAULT 1 CHECK (generation>0), PRIMARY KEY(tenant_id,consumer_id,producer_id,kid), FOREIGN KEY(tenant_id,producer_id) REFERENCES events_producer_bindings(tenant_id,producer_id) ); CREATE TABLE events_feed_log ( sequence BIGSERIAL PRIMARY KEY, tenant_id TEXT NOT NULL, producer_id UUID NOT NULL, event_id TEXT NOT NULL, event_type TEXT NOT NULL, subject TEXT, UNIQUE(tenant_id,producer_id,event_id), FOREIGN KEY(tenant_id,producer_id,event_id) REFERENCES events_intake_records(tenant_id,producer_id,event_id) ); CREATE INDEX events_feed_producer_sequence ON events_feed_log(tenant_id,producer_id,sequence); CREATE INDEX events_feed_type_sequence ON events_feed_log(tenant_id,producer_id,event_type,sequence); CREATE TRIGGER consumer_owner BEFORE INSERT OR UPDATE ON events_consumer_grants FOR EACH ROW EXECUTE FUNCTION events_intake_owner_write(); CREATE TRIGGER consumer_immutable BEFORE DELETE OR TRUNCATE ON events_consumer_grants FOR EACH STATEMENT EXECUTE FUNCTION events_intake_immutable(); CREATE TRIGGER feed_immutable BEFORE UPDATE OR DELETE OR TRUNCATE ON events_feed_log FOR EACH STATEMENT EXECUTE FUNCTION events_intake_immutable(); CREATE FUNCTION events_feed_insert_guard() RETURNS TRIGGER LANGUAGE plpgsql SET search_path=pg_catalog AS $$ BEGIN IF pg_trigger_depth()<>2 THEN RAISE EXCEPTION 'feed writes require intake trigger'; END IF; RETURN NEW; END $$; CREATE TRIGGER feed_insert_guard BEFORE INSERT ON events_feed_log FOR EACH ROW EXECUTE FUNCTION events_feed_insert_guard(); CREATE FUNCTION events_feed_capture() RETURNS TRIGGER LANGUAGE plpgsql SET search_path=pg_catalog AS $$ BEGIN -- The lock precedes sequence allocation and is held through COMMIT. Readers -- scoped to this producer cannot skip an earlier uncommitted event. PERFORM pg_advisory_xact_lock(hashtextextended(NEW.tenant_id||':'||NEW.producer_id::text,728319)); EXECUTE format('INSERT INTO %I.events_feed_log(tenant_id,producer_id,event_id,event_type,subject) VALUES($1,$2,$3,$4,$5)',TG_TABLE_SCHEMA) USING NEW.tenant_id,NEW.producer_id,NEW.event_id,NEW.envelope_json::jsonb->>'type',NEW.envelope_json::jsonb->>'subject'; RETURN NEW; END $$; CREATE TRIGGER feed_capture AFTER INSERT ON events_intake_records FOR EACH ROW EXECUTE FUNCTION events_feed_capture(); ${string} `; };