You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(authz): can_anchor_host accepts canonical name or snake_case key
E2E follow-up. Before: only canonical_name resolved in can_anchor_host;
operator-natural forms ("videofoundry" vs "VideoFoundry") returned a
misleading "not registered" error that masked real boundary violations.
Now: every repo registers a lowercased alias map at manifest-load time.
The dict-key form from PM-style YAML is registered as an alias when it
differs from canonical_name. can_anchor_host normalizes input through
the global alias map (case-insensitive) before lookup.
Changes:
- ManifestRecord.repo_aliases (lowercased alias → canonical)
- AuthorizationView.repo_aliases (global, merged across manifests)
- _iter_repos yields (canonical, fields, aliases); 3 call sites updated
- can_anchor_host normalizes input; reasons always name canonical form
- also_hosts validation resolves entries through aliases
- Load-time alias-conflict check (fatal if same alias → 2 canonicals)
Tests: +5 new (canonical, alias, case-insensitive, block-reason-uses-
canonical, alias-conflict-fatal). 43 pass (was 38).
E2E re-verified: capture(repos_touched=["videofoundry"]) from PM anchor
now raises BoundaryViolation naming canonical 'VideoFoundry'.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Follow-up to e2e test of ADR 0002. Operators naturally refer to repos by either form: `VideoFoundry` (canonical_name) or `videofoundry` (the dict key in PM-style YAML, or just the lowercased canonical). Before this change, only canonical_name resolved; other forms returned "not registered in any manifest", which masked real boundary violations behind a misleading error.
5
+
6
+
Changes:
7
+
-`ManifestRecord` gains `repo_aliases: dict[str, str]` (lowercased alias → canonical).
8
+
-`AuthorizationView` gains a global `repo_aliases` map merged across all registered manifests.
9
+
-`_iter_repos` now yields `(canonical, fields, aliases)` — for PM-style dict YAML, the dict key is registered as an alias when it differs from canonical_name. Caller signature updated at three call sites.
10
+
-`can_anchor_host` normalizes the input through the global alias map before lookup; reasons always name the canonical form.
11
+
-`also_hosts` validation likewise resolves entries through aliases.
12
+
- Load-time check: alias-to-canonical mapping must be consistent both within a manifest and across registered manifests (fatal if conflict).
13
+
14
+
5 new tests in `test_authorization.py`: canonical match, alias match, case-insensitive variants, block-reason names canonical even when called via alias, alias conflict fatal. 43/43 passing (was 38).
15
+
16
+
E2E re-verified: `capture(repos_touched=["videofoundry"])` from a PM anchor now raises BoundaryViolation with the canonical 'VideoFoundry' in the reason, instead of the previous misleading "not registered".
17
+
2
18
3
19
## 2026-05-22 — P2: manifest registry + authorization API
0 commit comments