|
12 | 12 | * | security-owd-alias (error) | ADR-0090 D4 canonical enum | |
13 | 13 | * | security-external-wider (error) | ADR-0090 D11 external ≤ internal| |
14 | 14 | * | security-wildcard-vama (error) | ADR-0066 superuser wildcard | |
15 | | - * | security-anchor-high-privilege(error) | ADR-0090 D5/D9 anchors | |
| 15 | + * | security-anchor-high-privilege(error) | ADR-0090 D5/D9 anchors — declared `everyone` suggestions (`isDefault: true`) only; a `guest`-bound set is outside a package-time linter's sight and is the bind-time gate's alone (#16110) | |
16 | 16 | * | security-role-word (error) | ADR-0090 D3 vocabulary freeze — own function/registry entry since #8310 | |
17 | 17 | * | security-book-audience-unknown-set(warn)| ADR-0046 §6.7 { permissionSet } | |
18 | 18 | * | security-private-no-readscope (info) | admin-intent mismatch class | |
|
26 | 26 | * BUT ONE mirrors a runtime enforcement point (D1 fail-closed OWD default, D4 |
27 | 27 | * zod enum + fail-closed evaluator, D5/D9 anchor binding gate, D3 rename wave) |
28 | 28 | * — the lint moves the failure from runtime-deny to author-time fix-it. |
| 29 | + * `security-anchor-high-privilege` mirrors that gate for the one suggestion a |
| 30 | + * package can actually declare (`isDefault: true` → the `everyone` anchor, |
| 31 | + * `suggested-audience-bindings.ts`'s "the only declarable suggestion"); a set |
| 32 | + * an operator binds to `guest` at install time is a decision ADR-0090 D9 |
| 33 | + * ("a package may suggest bindings … the admin confirms each individually") |
| 34 | + * puts past authoring, so this rule is not — and cannot be — coverage for an |
| 35 | + * app-authored anchor set bound to `guest` (#16110). That binding is held by |
| 36 | + * the runtime's own `describeAnchorForbiddenBits(set, 'guest')` gate instead. |
29 | 37 | * |
30 | 38 | * The exception INVERTS that argument rather than weakening it. |
31 | 39 | * `security-cbp-ambiguous-relation` has no runtime refusal to mirror precisely |
@@ -531,6 +539,10 @@ export function validateSecurityPosture(stack: AnyRec, opts?: { nowMs?: number } |
531 | 539 | // D5: an isDefault set is a SUGGESTED binding to the `everyone` anchor — |
532 | 540 | // hold it to the anchor tier at author time (the runtime gate enforces the |
533 | 541 | // same predicate at bind time; this moves the failure to the author). |
| 542 | + // Scope: `isDefault: true` is the only declarable suggestion today — a set |
| 543 | + // an operator binds to `guest` at install carries no author-time flag for |
| 544 | + // this rule to key off, so that binding is outside what a package-time |
| 545 | + // linter can see and is judged by the bind-time gate alone (#16110). |
534 | 546 | if (ps.isDefault === true) { |
535 | 547 | const offending = describeAnchorForbiddenBits(ps, 'everyone'); |
536 | 548 | if (offending) { |
|
0 commit comments