docs(suppress): flag advisory-by-default trust model; test dangling-suppress warning (§11 tail review)

Two review findings.

1. Per-app opt-out changes the group-template guarantee from "runs on every
   descendant" to "runs unless the descendant declines" — a footgun for
   compliance hooks (an audit/security trigger a tenant can silently opt out
   of). There is no non-suppressible flag. Document this in design §4.5 +
   CLAUDE.md, and record the deferred mitigation: a `sealed`/`mandatory`
   group-template marker the trigger anti-join + route filter skip (cheap —
   both filters are centralized).

2. The dangling-suppress warning path had no coverage. The suppress journey
   now applies a `[suppress] triggers=["does-not-exist"]`, asserts the apply
   still succeeds and the report warns "no effect".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-07-01 18:59:20 +02:00
parent b74e1a401b
commit 3df37b2b85
3 changed files with 39 additions and 3 deletions

View File

@@ -436,8 +436,18 @@ Two distinct constraints:
> is inheritance-only** — the `group_id IS NOT NULL` / `depth > 0` gates mean an app can only decline
> what it inherits, never its own resource nor a sibling's (pinned by `tests/template_suppression.rs`).
> A dangling suppress (matching no inherited template) is an apply-time **warning**, not an error;
> read-only `pic suppress ls --app`. **Deferred:** group-level suppression (decline an ancestor's
> template for a whole subtree).
> read-only `pic suppress ls --app`.
>
> **Trust-model consequence — group templates are now advisory-by-default.** Before opt-out, a group
> template was *guaranteed* to run on every descendant; with suppression the guarantee weakens to "runs
> unless the descendant declines." This is fine for convenience templates (a shared webhook, a default
> route) but is a **footgun for compliance** templates — an audit-logging or security trigger a
> multi-tenant operator deploys at a group can be silently opted out of by a tenant app. There is
> currently **no non-suppressible flag**; an operator who needs an unconditional hook must not rely on a
> group template for it (deploy it per-app, or gate at the platform layer). **Deferred:** a `sealed` /
> `mandatory` marker on a group template that the trigger anti-join + route filter skip (making it
> non-declinable) — cheap to add since both filters are centralized; and group-level suppression
> (decline an ancestor's template for a whole subtree).
### 4.6 Secrets & `pull`