test(rest): drive the two authorization-input absorb seams in computeExecCtx — phase-1 measurement (#13906) - #14272
Merged
Conversation
…teExecCtx Phase-1 MEASUREMENT — no production code changed. Drives, with positive controls beside every fault leg: - tenancy posture (kernelManager path): a healthy isolated posture refuses an ex-member org-stamped API key (organization_membership_ended, 401 on the wire); a tenancy service that is REGISTERED AND FAILS to construct skips the refusal and the same key is served 200 — the permissive path is reachable. "Registered and failed" and "never registered" answer byte-identically. - tenancy posture (single-kernel provider path): the local `kernel` is only assigned on kernelManager branches, so the posture probe is never issued — a healthy, wall-enforcing tenancy service is NEVER INVOKED (recorded), and the same deployment facts answer 401 via kernelManager and 200 via the shipped provider wiring. The always-undefined claim holds as the normal state of that wiring. - ADR-0069 auth gate: an active gate blocks the gated user (403 + gate code); an inactive gate, a throwing probe, and a failed session re-read are byte-indistinguishable at the ExecutionContext field and at enforceAuth. - Section 0 pins the enumeration criterion in-file (flags the two seams, never wiredEngineOrLoud); the historical control (same criterion flagging the provider engine seam pre-13910, 10 sites before / 9 after) is recorded on the card. Pins are measurements, not endorsements. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015YPiiDdw96RGS25WLctCQP
…atcher gates The fixture find double now holds the caller's limit bound by presence and filters through one hand-written matcher that supports equality and the $in shape the shared resolver actually issues, refusing every other shape loudly. check:objectql-double-limit graded the new double (301 graded, bound applied) and check:where-matcher counts the matcher among the refusing conformers. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015YPiiDdw96RGS25WLctCQP
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
os-justin
marked this pull request as ready for review
September 1, 2026 20:24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #13906
What this PR is
Phase-1 MEASUREMENT delivery: one new test file (
packages/rest/src/execctx-authz-input-seam-reachability.test.ts), zero production changes —rest-server.tsis not touched, per the dispatch's read-only order. It turns the card's code reading into driven readings, with a positive control beside every fault leg. Pins on permissive answers are measurements, not endorsements: whether any seam should change is the phase-2 ruling, deliberately not taken here. #13906 stays open on merge: the measured defect is unrepaired and phase 2 awaits the maintainer's ruling — which is why the first line above says Part of rather than a closing keyword.Measured answers to the four dispatch questions (driven at
b93d4fd49f)Q1 — the permissive path IS reachable, driven. With a real
ObjectKernelon the kernelManager path: a healthyisolatedtenancy service makes the Layer 0organization_membership_endedrefusal fire for an ex-member's org-stamped API key (401 on the wire; the resolver names the reason — that is the positive control that the refusal APPLIES to this fixture). Change ONE condition — register the tenancy service as a factory that throws, the registry's own "registered and failed to construct" rejection (#13905 class) — and the same key is served 200 with full grants. The refusal was skipped, not inapplicable: the resolver-level leg showsaccessible_org_idsin hand and lacking the stamped org while the principal is admitted. "Registered and failed" and "never registered" answer byte-identically at the door. The sibling posture-conditional refusal (organization_required, org-less key underisolated) is skipped the same way — measured in the same section. Note:api-key.tsdocuments absent-posture-admit as a deliberate decision for the org-less refusal; what that comment does not distinguish is "no tenancy service" from "the tenancy service failed" — both arrive as the same absent posture.Q2 — the card's sharper claim HOLDS, and it is the normal state of the shipped single-kernel wiring. The local
kernelincomputeExecCtxis assigned only on kernelManager branches (section 0 pins this mechanically from source). Driven: ONE real kernel with a healthy, wall-enforcing tenancy service behind a RECORDING factory, wired both ways. Via kernelManager: 401 refusal, tenancy factory invoked. Via the shipped provider wiring (byte-faithful to the post-#14250rest-api-plugin.tsproviders): 200 for the same ex-member key, and the tenancy factory was never invoked — invocation count 0. On that path the posture is undefined before any failure can occur; no failure is even required.Q3 — a failed probe and an inactive gate are indistinguishable, at the context field and at the consumer. Positive control: an ACTIVE gate with a healthy session re-read blocks the gated user —
enforceAuthanswers 403 with the gate'scodeandmessage. An inactive gate, a THROWINGisAuthGateActiveprobe, and a FAILED session re-read under an active gate (transient class: identity read succeeds, the gate's second read rejects — the fixture counts the reads, so the gate is proven to have probed) all produceauthGate: undefinedon the assembled ExecutionContext and the identical not-blocked observable, asserted deep-equal against the inactive leg. The gated user whose session policy says must be blocked is not blocked, and the wire carries no trace.Q4 — the criterion controls. In-file: the enumeration criterion flags the two named seams (known positives) and never flags
wiredEngineOrLoud(the known kept-apart site). Historical control, run outside vitest with the same criterion overgit showtrees: at the pre-#13910 tree (836a29c27a~1) it reports 10 absorb site lines incomputeExecCtxand flags the provider engine seam — the known positive that #13476 was filed to repair; at today's HEAD it reports 9, the provider engine line is gone andwiredEngineOrLoudis present — exactly reproducing the card's own census (10 before / 9 after / 1 loud after).Premise re-derivation (ZONE 3)
Both seams are still live and still collapse on today's tree after the three 09-01
rest-server.tsmerges (#13811, #13910, #14120) and after #13904's provider repair (#14250). #13910 repaired the ENGINE seam beside them; #14250 narrowed the provider absorb to the branded not-registered rejection. Neither reaches the tenancy or auth-gate seams. One repair-relevant fact for phase 2: the tenancy seam's blanket catch now absorbs the #13905 branded not-registered rejection and unbranded construction failures indistinguishably, although the discriminator exists —isServiceNotRegisteredErroris exported and the shipped objectql provider already uses it one layer down.Out of scope, not entered
The auth-service seams and the
getSessionswallow (the CONTEXT-LOST degrade recorded on #13255, which 404s in this repo as the routing comment warned), and the settings/localization seam.Verification
pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 src/execctx-authz-input-seam-reachability.test.ts— "Test Files 1 passed (1) · Tests 17 passed (17)".pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2— "Test Files 167 passed (167) · Tests 2802 passed (2802)".pnpm --filter @objectstack/rest typecheck— tsc clean plus "check:test-typecheck: OK — test layer compiles under tsconfig.test.json" (the build tsconfig excludes tests, so the test-layer half is the one that measures this file).node scripts/pm/dispatch-gates.mjs, re-derived after the last commit atb93d4fd49f(stderr names this repo and commit): 26 families both times,commreconciliation empty in both directions. 25 of 26 green with their own verdict lines — includingcheck:objectql-double-limit("301 doubles graded, bound applied" — it caught the first fixture being limit-blind; repaired by holding the bound by presence) andcheck:where-matcher("325 matchers, refusing conformer"),check:engine-double-contract,check:type-check-debt("27 ledger entries re-measured, none above recorded"),check:nul-bytes(standard any-edit family, additionally run).scripts/check-test-completeness.mjsexits 3 locally and its own text says to record it as NOT MEASURED outside CI (it parses a saved turbo test log CI supplies).rest-server.ts(the dispatch names that suite for diffs that do).skip-changesetapplied per the closed list.Session: https://claude.ai/code/session_015YPiiDdw96RGS25WLctCQP
Generated by Claude Code