-- §11 tail (v1.2 Hierarchies): per-app opt-out of inherited group templates. -- -- A group TRIGGER or ROUTE template inherits to every descendant app. Until now -- a descendant could SHADOW a template (declare its own identical binding) but -- not DECLINE one. This marker records that a specific app opts OUT of a -- specific inherited template — the template then stops resolving for that app -- (and only that app; a sibling subtree is unaffected). -- -- Coarse by REFERENCE (not row id — template ids churn on re-apply): a -- suppression names a handler SCRIPT NAME (target_kind='trigger') or a PATH -- (target_kind='route'). A reference may decline more than one inherited -- template (a group that bound several to the same script/path). The dispatch -- filters gate to group-owned rows, so an app can only decline what it -- INHERITS — never its own trigger/route, never a sibling's. -- -- App-only: only an app suppresses (a group would just not declare the -- template). So `app_id NOT NULL` — no polymorphic owner. It is pure app config -- (like `extension_points`), so ON DELETE CASCADE (not the code-owner RESTRICT). CREATE TABLE template_suppressions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), app_id UUID NOT NULL REFERENCES apps(id) ON DELETE CASCADE, target_kind TEXT NOT NULL CHECK (target_kind IN ('trigger', 'route')), -- A handler script name (trigger) or a path (route). Matched -- case-insensitively for triggers (as script-name resolution is -- elsewhere) and exactly for routes; stored as authored. reference TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- One marker per (app, kind, reference) — re-apply is a NoOp. CREATE UNIQUE INDEX template_suppressions_uidx ON template_suppressions (app_id, target_kind, reference); -- The trigger anti-join / route rebuild both look up by app_id. CREATE INDEX template_suppressions_app_idx ON template_suppressions (app_id);