feat(suppress): suppression journey + docs (§11 tail S5)
- Journey tests/suppress.rs: a group declares a `[[routes]]` template; a descendant app applies `[suppress] routes=["/ghello"]` → stops serving it (via `routes match`), a sibling still serves it, `pic suppress ls --app` shows it, re-apply is a NoOp; pruning the block re-inherits. The trigger-side filter + isolation are pinned at the repo layer by template_suppression.rs. - Docs: design §4.5 (per-app opt-out closing the deferred gap for both templates — coarse-by-reference, inheritance-only, the two consumption points; group-level suppress still deferred), CLAUDE.md current-focus. Full journey suite 121/121; workspace tests 34 suites/0 failures. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -417,9 +417,27 @@ Two distinct constraints:
|
||||
> Authoring is `[[routes]]` on a `[group]`; read-only `pic routes ls --group`. **Disabled semantic
|
||||
> (§4.3):** the shadow check runs *after* the `enabled` filter, so a **disabled** own-route does not
|
||||
> claim its binding — an enabled ancestor template at the same path then falls through and serves
|
||||
> ("disabled = absent"). The corollary: a descendant can't 404 an inherited route by disabling a
|
||||
> same-path own route. **Deferred:** per-app route opt-out (the true way to decline an inherited
|
||||
> route), and multi-node route-snapshot propagation (cluster mode).
|
||||
> ("disabled = absent"). To actually 404 an inherited route, an app SUPPRESSES its path (below).
|
||||
> **Deferred:** multi-node route-snapshot propagation (cluster mode).
|
||||
>
|
||||
> **Shipped — per-app opt-out of inherited templates (suppression).** A descendant could shadow a
|
||||
> template but not decline one; for triggers there was no decline path at all (an app's own identical
|
||||
> trigger double-fires). An app now declares `[suppress]` — `triggers = [...]` (handler SCRIPT names)
|
||||
> and `routes = [...]` (PATHS) — to opt out of inherited group templates. **Coarse by reference,** not
|
||||
> a full definition (template row-ids churn on re-apply; a reference is stable, so re-apply is a NoOp
|
||||
> and a reference may decline several templates bound to the same script/path). Marker table
|
||||
> `0058_template_suppressions.sql` — app-only (`app_id NOT NULL`, ON DELETE CASCADE; a group just
|
||||
> wouldn't declare the template), a `target_kind` discriminator (`trigger`|`route`), reconciled with the
|
||||
> extension-point marker pattern (idempotent create, prunable delete → the template re-inherits).
|
||||
> **Consumed at the two existing resolution points:** the trigger dispatch queries gain a correlated
|
||||
> `NOT EXISTS` anti-join (excluding a group-owned trigger whose handler the app suppresses, gated to
|
||||
> `t.group_id IS NOT NULL`), and `compile_effective_routes` drops an inherited (`depth > 0`) route at a
|
||||
> suppressed path (loaded once per rebuild via `RouteRepository::list_route_suppressions`). **Suppression
|
||||
> 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).
|
||||
|
||||
### 4.6 Secrets & `pull`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user