Uh oh!
There was an error while loading. Please reload this page.
feat(verify): bootStack({ orgContext: true }) — a harness admin whose execution context carries an organization (#7762) - #7977
Conversation
…rries an organization (#7762) `bootStack` could not mint an admin whose resolved execution context carried an `organizationId`, so every `organization_id`-filtered read was structurally untestable at the HTTP layer in the open core. That is the direct reason #7676 escaped both suites: the HTTP regression test written for its fix was green against the UNFIXED code — the filter never engaged — and was correctly deleted rather than shipped as phantom coverage. `orgContext: true` flips AuthPlugin's ADR-0081 D1 default-organization bootstrap back on (the same one `objectstack dev`/`serve` run), binds the admin as owner, and the session hook stamps `activeOrganizationId` — the one wire field `resolveAuthzContext` reads into the execution context. The boot asserts the bind and refuses a stack without it. It stands up NO organization wall, and does not move the tenancy posture: `probeIsolation` is `() => !!ctx.getService('org-scoping')`, service registration only. Both facts are pinned, not asserted in prose. It refuses to compose with either spelling of `multiTenant` rather than silently no-op. Restores the deleted #7676 regression test at the dogfood layer, now booted org-bound so it can actually fail. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CAE5bmz7qUK7FDZWj9Wxog
…xt test (#7762) The extensionless relative import was a TS2835 the `check:type-check-debt` ratchet counts, taking @objectstack/verify's TEST_DEBT from 8 to 9. The sibling test files predate the gate and carry theirs in the ledger; a new test file does not get to raise it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CAE5bmz7qUK7FDZWj9Wxog
…ify-org-scoped-context
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 2 release-owned page(s) reference the affected code. These are read-only:
|
hotlong
commented
Aug 12, 2026
PM review — Every binding condition from the ruling is met: named away from the wall ( The part I did not ask for, and it is the one that completes the proofThe dispatch required reverse-verifying the restored test against the unfixed production code. This PR does that — and then measures the vacuum too: same broken code, boot switched back to org-less, and all three of those assertions go green. That is the difference between "this test catches the bug" and "this test catches the bug because of the harness change". One direction proves the test has teeth; the other proves the teeth come from Three judgements better than the dispatch's own framingThe mechanism. The claim comment reasoned about "stamping an The boot asserts the bind. Refusing to compose with Also verifiedThe type-check-debt ratchet caught the new test file's extensionless relative import (TS2835, The risk I flagged at dispatch — that the org id might not be stampable inside Scope respected: #7761 untouched, #7676 not reopened, dogfood suite 599 passed / 3 skipped with no churn. Enqueueing once CI lands. Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#7762
The gap
@objectstack/verify'sbootStackcould not mint an admin whose resolved execution context carried anorganizationId. Everyorganization_id-filtered read in the platform was therefore structurally untestable at the HTTP layer in the open core: the filter never engaged, so a fixture asserting on the difference between a filtered and an unfiltered read saw no difference and passed for the wrong reason.That is the direct reason #7676 escaped both suites and needed a manual QA run to find — and why PR #7760's dev wrote the HTTP-layer regression test for it, measured it green against the unfixed code, and correctly deleted it rather than ship phantom coverage.
What this does — Option A, narrowed
One new
BootOptionsflag inpackages/verify/src/harness.ts:It flips
AuthPlugin's ADR-0081 D1 default-organization bootstrap (autoDefaultOrganization) back on — the same bootstrapobjectstack dev/servegive a real single-tenant deployment, not a harness-local imitation. The admin is bound to a realsys_organizationasowner; thesession.create.beforehook stampsactiveOrganizationIdonto the session, which is the one wire fieldresolveAuthzContextreads intotenantId→ExecutionContext.No enterprise package, no wall, no posture change. The name deliberately avoids
multiTenant/tenant/isolated.The boot asserts the bind.
ensureDefaultOrganizationis best-effort by design (it swallows every failure so a login can never break on org bookkeeping), so a fixture that asked for an org-bound admin and silently got an org-less one is exactly the shape this option exists to abolish. Nosys_memberrow for the harness admin → no stack, with an error that says why.It refuses to compose with
multiTenant, both spellings, rather than boot something weaker than it reads. UndermultiTenant: truethe enterprise package already owns the org bootstrap; under'posture-only'the open bootstrap deliberately abstains (walled posture,postureEnforcesWall), so the flag would be a pure no-op that still reads as coverage. Both stated in the doc block and pinned by tests.⛔ What it must never be used for
It stamps the caller's organization; it stands up no organization wall. With no
org-scopingservice registered — and this flag registers none —SecurityPluginstrips the wildcardorganization_idRLS policies (collectRLSPolicies). A fixture asserting "tenant B cannot read tenant A's rows" and booting this way would assert nothing and pass: the #4700 constant-false shape wearing the opposite mask.Cross-tenant isolation still has exactly one honest proof in this repo:
multiTenant: truewith the real@objectstack/organizations. A ⛔ doc block says so, in the same register as the existing'posture-only'one.The posture proof — verified, not inherited
The claim comment resolved the card's posture gate from code:
probeIsolationis() => !!ctx.getService('org-scoping')(plugin-auth/src/auth-plugin.ts), so the effective posture derives from service registration only and reads nothing about what any context carries.harness.org-context.test.tsproves it rather than assuming it:posture,requestedPosture,isolationActiveanddegradedare asserted identical with the flag off vs on (single/single,degraded: falseboth sides). The ruling holds.The vacuity guard — reverse-verified
packages/qa/dogfood/test/org-scoped-sharing-rule-listing.dogfood.test.tsrestores the deleted #7676 test: package-seeded (organization_id = null) sharing rules vs an org-bound admin, driven through real HTTP.Reverted
adminOrgScopeto the pre-#7676 strict equality (andfindRuleRowByNameto the single scoped lookup), rebuiltplugin-sharing, re-ran:The list comes back holding only the admin's own org-stamped probe row and none of the four seeded rules; by-name GET and evaluate both 404 — #7676's reported symptoms, reproduced.
And the vacuum itself, measured. Same broken code, boot changed to org-less (
bootStack(showcaseStack)): all three of those assertions go green, and only the two new guards fail (expected null to be truthyon the org stamp; the foreign-org row appears in the list). That is precisely the phantom coverage PR #7760's dev observed and deleted — reproduced, and now impossible to ship, because the precondition test fails loudly instead.Both reverts were restored from the commit (
git checkout HEAD -- …) and the suite re-run green before pushing.Other pins
organization_idnon-null — the card's own measurement, inverted, taken through the samePOST /api/v1/sharing/rulesroute — and the id resolves to a realsys_organization.Verification
pnpm -w typecheck— 126/126 clean.pnpm check:type-check-debt— clean, ledger not raised. It caught the new test file's extensionless relative import (TS2835,@objectstack/verifyTEST_DEBT 8 → 9); fixed at the source with an explicit./harness.jsrather than by raising the entry.pnpm lint— clean.packages/verify— 28/28 pass (6 files).origin/main(a44d1b4), which landedplugin-authchanges.Scope notes
#7761 not touched; #7676 not reopened. The org id turned out to be stampable entirely inside
packages/verify— no change was needed inplugin-author REST context resolution — so the seam is where the card assumed it was.Generated by Claude Code