0062 adds `materialized_from` on triggers (a managed app-owned copy links back to its group template; CASCADE). The scheduler + queue-consumer queries gain `AND t.app_id IS NOT NULL` so a group-owned stateful TEMPLATE is never dispatched directly — only the per-descendant materialized app rows are. validate_bundle_for + manifest parse now allow cron/queue on a group (email stays rejected pending its per-app inbound-secret handling in M5.5). The materialization reconcile that expands templates into app rows lands in M5.2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
26 lines
1.4 KiB
SQL
26 lines
1.4 KiB
SQL
-- §4.5 M5: STATEFUL group trigger templates (cron / queue / email) via
|
|
-- per-descendant MATERIALIZATION.
|
|
--
|
|
-- The event kinds (kv/docs/files/pubsub) resolve a group template LIVE at
|
|
-- dispatch via the chain CTE — no per-app rows. The stateful kinds can't:
|
|
-- * cron needs a per-app `last_fired_at` the scheduler advances;
|
|
-- * queue needs the one-consumer-per-(app_id, queue_name) advisory lock;
|
|
-- * email needs a per-app SEALED inbound secret.
|
|
-- So a group stateful template is instead MATERIALIZED into an app-owned
|
|
-- trigger row per descendant app (created/removed as the tree changes), and the
|
|
-- unchanged dispatch paths (scheduler, queue consumer, email webhook) only ever
|
|
-- see app-owned rows.
|
|
--
|
|
-- `materialized_from` links a managed app-owned row back to the group template
|
|
-- it was expanded from: NULL = a hand-authored trigger; set = a reconciler-owned
|
|
-- copy (dropped + re-created as descendants come and go). ON DELETE CASCADE so
|
|
-- deleting the group template (RESTRICT-guarded elsewhere) or the group cleans
|
|
-- up the copies; a plain app delete CASCADEs the row away via `triggers.app_id`.
|
|
|
|
ALTER TABLE triggers
|
|
ADD COLUMN materialized_from UUID REFERENCES triggers(id) ON DELETE CASCADE;
|
|
|
|
-- The reconciler looks up existing copies by their source template.
|
|
CREATE INDEX idx_triggers_materialized_from
|
|
ON triggers (materialized_from) WHERE materialized_from IS NOT NULL;
|