Track B Phase 3 (CR-4) — dry multi-source scope composition
2026-06-21
LOCKSTEP TRACEABILITY MATRIX --- api_endpoints: ["POST /auth/governance/scope-check"] sdk_methods_updated: ["none — dashboard JWT surface"] mcp_tools_updated: ["none"] ---
What We Built
POST /auth/governance/scope-check runs a dry multi-source scope composition: given a requested model and the scope sources (api_key, br_scope, plan, delegation), it returns the composed verdict and which sources contributed to it — the real per-source lanes (R8), not a fabricated drawing. Crucially it invokes the same evaluateComposedModelScope core the request path uses, with a no-op recorder injected, so there are zero enforcement side effects and zero audit rows: a true simulation that cannot diverge from real enforcement because it _is_ the real enforcement algebra.
Why It Matters
Scope in this platform is a deny-wins intersection of up to four independent sources. "Will model X be allowed?" isn't answerable by looking at any one of them — you have to compose. CR-4 exposes that composition as a safe, side-effect-free check, so an operator (or a future composer UI) can ask "given this api-key allowlist, this br_scope, this plan, and this delegation chain — what's the effective verdict, and which source is the binding constraint?" and get the same answer enforcement would render.
How It Works
The composer was already parameterized (ComposedScopeInput is structured, not request-coupled) and takes an injectable DenialRecorder. CR-4 threads the supplied sources into it per requested model with record = async () => null (dry) and projects {decision, composedGrant, enforcedSources} into a per-model, per-source result. The design flagged the principal-side _auto-resolution_ of sources as composer-refactor work; this route delivers the composition itself and leaves auto-resolution (looking a principal's sources up from the key/grant/plan stores) as the documented follow-up.
The Numbers
- 1 new JWT route, reusing the real composer; no-op recorder ⇒ no side effects. 9,031 backend tests pass;
pnpm checkgreen. (Az.unionrequest schema was avoided — the contract-compiler skips unions — by accepting the unrestricted br_scope as the["*"]array form.)
Competitive Edge
A dry-run that calls the actual production decision core — not a reimplementation — is the only kind that's trustworthy. CR-4 lets an operator simulate the exact deny-wins intersection that governs every request, with the binding source named, and nothing written.
Lockstep Checklist
- [x] API Routes:
POST /auth/governance/scope-check. - [x] TS/Python SDK / MCP: none — dashboard JWT surface.
- [x] Generated contract:
docs/openapi.yaml+ static-assets regenerated.
Track B status
With CR-4 shipped, Track B Phases 1, 2, 4 and Phase 3 are complete except CR-2 (per-request cohort divergence — the one piece that needs a cohort-state route that does not yet exist) and the deferred composer principal-auto-resolution. Everything else — capability grants UI, chain badge + ledger, would-deny, effective-state, governance events + live feed, plans, and dry composition — is live.