Filed by the PM dispatch loop as option A of an open question from the #15350 round (PR #16011). ⛔ Unassigned and ungraded — domain:*, type and priority are triage's.
⛔ BLOCKED until all four tenancy-posture seam cards land: #15349 (PR #15996), #15350 (PR #16011), #15351, #15352. ⛔ Do not start before then — a helper extracted while any of them is in flight collides with the others, which is exactly why each of the four was told not to extract one.
What exists now, and why it was deliberate
Four seams each supply tenancyPosture to resolveAuthzContext through a local, private resolveAdmissionTenancyPosture, each copying the classification structure of packages/rest/src/rest-server.ts:2458-2502: never-registered (isServiceNotRegisteredError) ⇒ quiet undefined; every other rejection ⇒ AuthzStoreUnavailableError('tenancy', err). No shared helper was extracted, on the PM's instruction, because four in-flight cards cannot each extract the same one.
The case for folding them: the bodies are the same shape, and the classification is the part nobody may get wrong — a quiet catch at any one of them re-opens #13906. One tested helper is worth more than four correct copies that must each stay correct forever.
⚠️ The constraint that makes this card non-trivial, measured on #15350
The four seams are NOT byte-identical, and a helper that erases the differences would be WORSE than the copies.
⇒ The extractable part is the try/catch CLASSIFICATION, not the resolution. A helper should take an already-resolved service (or a resolver callback) and own only the branded/unbranded decision. Anything that also owns how the service is reached will either be wrong for one of the seams or grow a flag per seam, which is the copies again with extra steps.
Natural home: @objectstack/core, beside effectiveTenancyPosture (packages/core/src/security/index.ts:93), which all four already import.
Scope when unblocked
Fold the four call sites plus rest-server.ts's two branches onto the one helper. ⚠️ Re-measure the seam count before starting — the census was 2 of 8 when these cards were written and was 4 of 8 by the time #15349 landed; it will be higher again once this family lands.
Refs
#15349 / PR #15996 · #15350 / PR #16011 · #15351 · #15352 · #15256 (the census and the one-card-per-site ruling) · #13906 (decision 1 option A — the classification that must not be got wrong) · #15997 (the KernelBase residual, a separate family-wide question)
Generated by Claude Code
Filed by the PM dispatch loop as option A of an open question from the #15350 round (PR #16011). ⛔ Unassigned and ungraded —
domain:*, type and priority are triage's.⛔ BLOCKED until all four tenancy-posture seam cards land: #15349 (PR #15996), #15350 (PR #16011), #15351, #15352. ⛔ Do not start before then — a helper extracted while any of them is in flight collides with the others, which is exactly why each of the four was told not to extract one.
What exists now, and why it was deliberate
Four seams each supply
tenancyPosturetoresolveAuthzContextthrough a local, privateresolveAdmissionTenancyPosture, each copying the classification structure ofpackages/rest/src/rest-server.ts:2458-2502: never-registered (isServiceNotRegisteredError) ⇒ quietundefined; every other rejection ⇒AuthzStoreUnavailableError('tenancy', err). No shared helper was extracted, on the PM's instruction, because four in-flight cards cannot each extract the same one.The case for folding them: the bodies are the same shape, and the classification is the part nobody may get wrong — a quiet
catchat any one of them re-opens #13906. One tested helper is worth more than four correct copies that must each stay correct forever.The four seams are NOT byte-identical, and a helper that erases the differences would be WORSE than the copies.
rest-server.tsbranches on kernel-vs-provider — two wirings, and asking twice would let a provider bound to the local kernel answer for a request that resolved to another environment.tenancyPosturetoresolveAuthzContext— an ex-member's org-stamped API key keeps its claim #15349 (plugin-sharing) and service-datasource: the admin routes supply notenancyPosturetoresolveAuthzContext— an ex-member's org-stamped API key is admitted #15350 (service-datasource) readctx.getKernel().⇒ The extractable part is the try/catch CLASSIFICATION, not the resolution. A helper should take an already-resolved service (or a resolver callback) and own only the branded/unbranded decision. Anything that also owns how the service is reached will either be wrong for one of the seams or grow a flag per seam, which is the copies again with extra steps.
Natural home:
@objectstack/core, besideeffectiveTenancyPosture(packages/core/src/security/index.ts:93), which all four already import.Scope when unblocked
Fold the four call sites plus⚠️ Re-measure the seam count before starting — the census was 2 of 8 when these cards were written and was 4 of 8 by the time #15349 landed; it will be higher again once this family lands.
rest-server.ts's two branches onto the one helper.Refs
#15349 / PR #15996 · #15350 / PR #16011 · #15351 · #15352 · #15256 (the census and the one-card-per-site ruling) · #13906 (decision 1 option A — the classification that must not be got wrong) · #15997 (the KernelBase residual, a separate family-wide question)
Generated by Claude Code