feat(suppress): template_suppressions marker for per-app opt-out (§11 tail S1)

A group TRIGGER/ROUTE template inherits to every descendant app; until now
a descendant could shadow one but not decline it. This marker records that
an app opts OUT of a specific inherited template — coarse by REFERENCE (a
handler script name for triggers, a path for routes), not row id (template
ids churn on re-apply, references are stable so re-apply is a NoOp).

App-only (a group would just not declare the template) → app_id NOT NULL,
no polymorphic owner; pure app config → ON DELETE CASCADE. A target_kind
discriminator ('trigger'|'route') keeps it one table, one reconcile loop.

Schema blessed at 58 migrations.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-07-01 07:20:46 +02:00
parent b048daa700
commit 18ac9f5afa
2 changed files with 54 additions and 0 deletions

View File

@@ -376,6 +376,13 @@ table: secrets
group_id: uuid NULL
environment_scope: text NOT NULL default='*'::text
table: template_suppressions
id: uuid NOT NULL default=gen_random_uuid()
app_id: uuid NOT NULL
target_kind: text NOT NULL
reference: text NOT NULL
created_at: timestamp with time zone NOT NULL default=now()
table: topics
app_id: uuid NOT NULL
name: text NOT NULL
@@ -605,6 +612,11 @@ indexes on secrets:
secrets_app_uidx: public.secrets USING btree (app_id, environment_scope, name) WHERE (app_id IS NOT NULL)
secrets_group_uidx: public.secrets USING btree (group_id, environment_scope, name) WHERE (group_id IS NOT NULL)
indexes on template_suppressions:
template_suppressions_app_idx: public.template_suppressions USING btree (app_id)
template_suppressions_pkey: public.template_suppressions USING btree (id)
template_suppressions_uidx: public.template_suppressions USING btree (app_id, target_kind, reference)
indexes on topics:
topics_pkey: public.topics USING btree (app_id, name)
@@ -833,6 +845,11 @@ constraints on secrets:
[FOREIGN KEY] secrets_app_id_fkey: FOREIGN KEY (app_id) REFERENCES apps(id) ON DELETE CASCADE
[FOREIGN KEY] secrets_group_id_fkey: FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE
constraints on template_suppressions:
[CHECK] template_suppressions_target_kind_check: CHECK ((target_kind = ANY (ARRAY['trigger'::text, 'route'::text])))
[FOREIGN KEY] template_suppressions_app_id_fkey: FOREIGN KEY (app_id) REFERENCES apps(id) ON DELETE CASCADE
[PRIMARY KEY] template_suppressions_pkey: PRIMARY KEY (id)
constraints on topics:
[CHECK] topics_auth_mode_check: CHECK ((auth_mode = ANY (ARRAY['public'::text, 'token'::text, 'session'::text])))
[FOREIGN KEY] topics_app_id_fkey: FOREIGN KEY (app_id) REFERENCES apps(id) ON DELETE CASCADE
@@ -913,3 +930,4 @@ constraints on vars:
0055: group files
0056: group triggers
0057: group routes
0058: template suppressions