From 483e4cb11624e2a7da008b8c41c29554855649b9 Mon Sep 17 00:00:00 2001 From: MechaCat02 Date: Wed, 1 Jul 2026 19:12:34 +0200 Subject: [PATCH] =?UTF-8?q?feat(sealed):=20sealed=20column=20on=20triggers?= =?UTF-8?q?=20+=20routes=20(=C2=A711=20tail=20M1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A group template can be marked `sealed = true` so the per-app suppression filters skip it — closing the advisory-by-default compliance footgun the suppression review flagged. Only meaningful on a group-owned template; existing rows default unsealed. Consumption gates land in M3. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../migrations/0059_sealed_templates.sql | 19 +++++++++++++++++++ crates/manager-core/tests/expected_schema.txt | 3 +++ 2 files changed, 22 insertions(+) create mode 100644 crates/manager-core/migrations/0059_sealed_templates.sql diff --git a/crates/manager-core/migrations/0059_sealed_templates.sql b/crates/manager-core/migrations/0059_sealed_templates.sql new file mode 100644 index 0000000..1a062c8 --- /dev/null +++ b/crates/manager-core/migrations/0059_sealed_templates.sql @@ -0,0 +1,19 @@ +-- §11 tail (v1.2 Hierarchies): `sealed` (mandatory) group templates. +-- +-- Per-app opt-out (0058_template_suppressions) made an inherited group TRIGGER +-- or ROUTE template advisory-by-default: it runs on a descendant *unless* that +-- descendant declares a `[suppress]` declining it. That is a compliance footgun +-- — a group's audit / security / rate-limit template can be silently opted out +-- of by the very tenant it is meant to police. +-- +-- A `sealed` template closes the gap: the two suppression filters skip a sealed +-- row, so it fires / serves on every descendant regardless of any suppression. +-- The column is only meaningful on a group-owned template (`group_id IS NOT +-- NULL`); an app-owned row is never inherited, so sealing it is meaningless and +-- rejected at apply. Existing rows default to unsealed (the prior behaviour). +-- +-- * triggers.sealed — a sealed group trigger template is never suppressible. +-- * routes.sealed — a sealed group route template is never suppressible. + +ALTER TABLE triggers ADD COLUMN sealed BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE routes ADD COLUMN sealed BOOLEAN NOT NULL DEFAULT FALSE; diff --git a/crates/manager-core/tests/expected_schema.txt b/crates/manager-core/tests/expected_schema.txt index 0d1a31e..64a16da 100644 --- a/crates/manager-core/tests/expected_schema.txt +++ b/crates/manager-core/tests/expected_schema.txt @@ -342,6 +342,7 @@ table: routes dispatch_mode: text NOT NULL default='sync'::text enabled: boolean NOT NULL default=true group_id: uuid NULL + sealed: boolean NOT NULL default=false table: script_imports app_id: uuid NOT NULL @@ -406,6 +407,7 @@ table: triggers updated_at: timestamp with time zone NOT NULL default=now() name: text NOT NULL default=(gen_random_uuid())::text group_id: uuid NULL + sealed: boolean NOT NULL default=false table: vars id: uuid NOT NULL default=gen_random_uuid() @@ -931,3 +933,4 @@ constraints on vars: 0056: group triggers 0057: group routes 0058: template suppressions + 0059: sealed templates