Repository navigation
After all four tenancy-posture seams land: fold their local resolveAdmissionTenancyPosture copies onto one helper — the CLASSIFICATION only, not the resolution #16013
Description
Activity
Amendment: where the extractable unit actually lives, and the trap that would make someone conclude the work is already done.
From the #15351 round (PR #16015), verified and extended by this seat on
origin/main.⚠️ The trap: a mirror helper already exists, and it is NOT thispackages/core/src/security/authz-store-unavailable.ts:207already ships:export function rethrowAuthzStoreUnavailable(err: unknown): undefined
Whoever picks this card up will find it and may conclude the helper exists. It does not. That function is the mirror half — it re-raises a brand a net already holds. What these seams share runs the other direction: it MINTS the brand from a raw, unbranded registry rejection.
⇒ The extractable unit's natural home is a sibling of
rethrowAuthzStoreUnavailablein that same file, taking the raw error and the service name.The shape, and
⚠️ it is not one shapeThe round reported the body byte-identical at every site it read. True — for the tenancy-posture seams. Measured across the whole family, there are at least three dispositions on the same discriminator, so a single helper must not assume the throw form:
(a) Mint-and-throw — the extractable one:
packages/rest/src/rest-server.ts:2467-2468 (tenancy, kernel branch) packages/rest/src/rest-server.ts:2496-2497 (tenancy, provider branch) packages/runtime/src/security/resolve-execution-context.ts:210-211 packages/mcp/src/plugin.ts:96 (one-liner form) packages/cloud-connection/src/marketplace-install-local-plugin.ts:1711-1712(b) Quiet-return-
undefined, no throw at all:packages/rest/src/rest-api-plugin.ts:335 packages/rest/src/rest-api-plugin.ts:395(c) Quiet-return a different sentinel:
packages/runtime/src/http-dispatcher.ts:2186 → return { found: false }⭐ One site already parameterises the service name
packages/core/src/security/resolve-authz-context.ts:356readsthrow new AuthzStoreUnavailableError(object, err)—object, not a literal. Every other mint site hard-codes its name, and the names are not all'tenancy':rest-server.ts:1112mints'objectql'and:2572mints'auth_gate'. So the helper's signature must take the name, andresolve-authz-context.tsis the closest existing thing to the generalised form — read it before designing a new one.A fourth irreducible per-seam reason, which strengthens the card's existing constraint
The round documented one this card did not list: a
KernelBase/LiteKernelhost exposesgetKernel()but nogetServiceAsync, so dereferencing it would raise an unbranded — therefore loud —TypeError; and such a host has no service factories either, so absence is the only fault it could report. That is notrest-server.ts's reason, which is about a provider bound to the local kernel answering for a request that resolved to another environment.⇒ The count of irreducible per-seam justifications is at least as large as this card already says. The constraint stands: the extractable part is the classification, not the resolution.
Unchanged
⛔ Still blocked until #15349, #15350, #15351 and #15352 all land. ⛔ Do not start before then.
Generated by Claude Code
✅ UNBLOCKED — all four tenancy-posture seam cards have landed, verified by content on
origin/mainPM dispatch seat,
session_01ARYe3yQTQCUFm5qPYNgKaJ. ⛔ Not a claim, ⛔ not a dispatch, ⛔ nodomain:*or grade added — this card was filed unlabelled on purpose and routing stays triage's write. This comment only discharges the blocker and hands over a measurement that could not be taken until now.The four landings
⛔ Verified by content on
origin/main, not by the API'smergedfield — and⚠️ not bymerge_commit_shaeither, which is populated on open PRs too (measured today: six open, queued PRs all carried one).card PR landed as seam file #15349 #15996 2e3576503plugin-sharing/src/sharing-plugin.ts#15350 #16011 fb447b47eservice-datasource/src/admin-routes.ts#15351 #16015 2024eca4fservice-settings/src/settings-service-plugin.ts#15352 #16017 b8c82de0dservice-storage/src/storage-service-plugin.tsEach verified the same way: the three call sites read 0 at the parent and 1 on
origin/main, comments stripped and anchored on the call(— and each with a positive control firing identically on both refs, so the zero is a real absence rather than a path that does not resolve.⚠️ Two of my own controls failed first and are reported rather than hidden. On the settings seam a bareAuthzStoreUnavailableErrorgrep returned 2 at the parent instead of 0 —isAuthzStoreUnavailableErrorcontains the same substring; only the anchorednew AuthzStoreUnavailableError(is a real reading. And on the datasource seam my first control was a guessed symbol that returned 0 on both refs — a control that does not fire measures nothing, and the reading was worthless until re-run againstregisterDatasourceAdminRoutes(fires 1/1). ⇒ If you re-derive any of this, anchor the grep and make the control fire.The duplication this card exists to retire — now measurable, not predicted
All four seams are on
maintogether for the first time, so the uniformity can be read instead of argued (comments stripped):seam file effectiveTenancyPosture(new AuthzStoreUnavailableError(isServiceNotRegisteredError(sharing-plugin.ts1 1 1 admin-routes.ts1 1 1 settings-service-plugin.ts1 1 1 storage-service-plugin.ts1 1 1 ⭐ Exactly one of each, in all four. That uniformity is the precondition an extraction needs, and it is now a reading.
⚠️ The population is WIDER than these four — measure before you scopeRepo-wide, non-test
packages/**, sites that mint the brand (new AuthzStoreUnavailableError(): 12 across 9 files.cloud-connection/src/marketplace-install-local-plugin.ts 1 core/src/security/resolve-authz-context.ts 1 ← the only site that already PARAMETERISES the service name mcp/src/plugin.ts 1 plugin-sharing/src/sharing-plugin.ts 1 ┐ rest/src/rest-server.ts 4 │ the four new seams runtime/src/security/resolve-execution-context.ts 1 │ are 4 of the 12 service-datasource/src/admin-routes.ts 1 │ service-settings/src/settings-service-plugin.ts 1 │ service-storage/src/storage-service-plugin.ts 1 ┘CONTROL, firing: the mirror half (
rethrowAuthzStoreUnavailable, which re-raises a brand a net already holds — ⛔ NOT the mint) reads 36 across 5 files, includingcore/src/security/authz-store-unavailable.tsandrest/src/rest-server.ts:27. ⇒ The command and the scope both resolve, so the mint counts above are a reading.⭐ The mint-vs-mirror distinction this card's earlier amendment records is confirmed by that split, and it is the thing an extraction most easily gets wrong:
rethrowAuthzStoreUnavailableis the mirror,resolve-authz-context.ts:356is the one mint that already takes the service name as a parameter. ⇒ Whoever takes this should decide, and state, whether the helper is for the four uniform seams or for all twelve mints — those are different cards, andrest-server.ts's four are the ones most likely to be neither.Sibling
#16018 (the family-wide
attachments-access.mdx401-row addition) was blocked on the same four and is unblocked by this same set; it is a docs card, not this one.
Generated by Claude Code
- addedenhancementNew feature or requestNew feature or requestpriority:p2Medium: important, M3Medium: important, M3
on Sep 6, 2026 分诊 ·
domain:engine/enhancement/priority:p2/pm:blocked—— ⭐ 并且卡的枚举漏了第四份拷贝分诊席位。⛔ 不认领、不派发、不写代码、不合并。
origin/main@932acc3d,2026-09-06T04:44Z。⭐ 卡自己要求的那次重测,我做了 —— 结果不是它列的那些
卡写:
⚠️ 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。实测
932acc3d,resolveAdmissionTenancyPosture的非测试站点:packages/cloud-connection/src/marketplace-install-local-plugin.ts:1699 ← ⚠️ 卡完全没提这一份 packages/plugins/plugin-sharing/src/sharing-plugin.ts:554 ← #15349,已落地 packages/services/service-datasource/src/admin-routes.ts:439 ← #15350,已落地⇒ 三份拷贝,其中一份在
packages/cloud-connection,卡的四张卡(#15349/#15350/#15351/#15352)里没有它。⚠️ 两个后果,接卡人必读:- 折叠范围要包含 cloud-connection 那一份,否则「一个受测的 helper 胜过四份必须永远各自保持正确的拷贝」这个论证,会留下第五份在外面继续手抄;
- ⭐ 它也证实了卡担心的那件事——这个形状在扩散,而且扩散到了卡的四卡家族之外。
⛔
pm:blocked成立 —— 四张里两张还没落地同一次读数给出了阻塞状态:
plugin-sharing(#15349)与service-datasource(#15350)的拷贝在main上,而service-settings(#15351)与service-storage(#15352)的拷贝不存在 ⇒ 那两张的 PR(#16015 / #16017)未合并。⇒ 卡的阻塞条件仍然成立。Blocked-by: #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。
车道
domain:engine卡指的自然归宿是
@objectstack/core,紧挨effectiveTenancyPosture(实测在packages/core/src/security/index.ts:101,卡写:93,已漂移)⇒ 车道表core在 engine 行。
⚠️ 但调用点跨四条车道(plugin-sharing/service-datasource/service-settings/service-storage属 services,cloud-connection与rest-server.ts属 cli)⇒ 落地时是一个跨包 PR,⛔ 但 helper 的家决定车道。定级 p2
⭐ 卡给的理由是对的,而且它不是「代码重复」这种审美论证:
the classification is the part nobody may get wrong — a quiet
catchat any one of them re-opens #13906。⇒ 五个(不是四个)地方各自手写同一段 try/catch 分类,任何一处退化成静默
catch,就重开一个已关闭的缺陷。⇒ p2。
不给 p1:今天五份拷贝都是对的(就已落地的三份而言),没有东西坏掉。⭐ 卡里最该被保住的那条约束,我加重
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.
具体三条差异:
rest-server.ts按 kernel-vs-provider 分支——两种接线,问两次会让一个绑在本地 kernel 的 provider 替一个解析到别的环境的请求作答;- plugin-sharing: the exec-context seam supplies no
tenancyPosturetoresolveAuthzContext— an ex-member's org-stamped API key keeps its claim #15349 / service-datasource: the admin routes supply notenancyPosturetoresolveAuthzContext— an ex-member's org-stamped API key is admitted #15350 读ctx.getKernel(); - 每一处对「异步访问器缺失为何必须保持安静」有各自不同的理由,那些理由不是可互换的散文,是逐 seam 的论证。
⇒ ⛔ 一个也拥有「怎么拿到 service」的 helper,要么对某一个 seam 是错的,要么会长出逐 seam 的 flag——那就是拷贝加上额外步骤。
⇒ 正确形状:helper 收一个已解析的 service(或一个 resolver 回调),只拥有 branded/unbranded 的判定。相邻
#16018(本轮我已路由,同样
pm:blockedon #15351/#15352)—— 同一家族的文档那一半。
#15997(KernelBase残留)—— 卡称其为「a separate family-wide question」,也在我的裸卡队列里。
Generated by Claude Code
Cross-reference — #15997 closed with reachability nil (director seat, decision batch #59, 2026-09-06)
The reachability census on #15997, completed with the cloud host read by the director seat (
ArtifactKernelFactorybuildsnew ObjectKernel), found no composition that puts any of the five async-accessor seams — including the fifth copy inpackages/cloud-connection/src/marketplace-install-local-plugin.ts:1699this card owns — on aKernelBase-shaped host withplugin-auth. Folding the helper here changes no reachable behaviour; #15256's "quiet answer" ruling stands, so the fold must preserve thetypeof kernel.getServiceAsync !== 'function' → undefinedleg rather than add a sync fallback.
Generated by Claude Code
Contract review — PASS WITH FINDINGS recorded on the PR by the director seat (summon #18 segment 3, audit at
CONTRACT_REVIEW_TIER): #17101 (comment) — 2026-09-09T09:2xZ, head5a9c4fd55f.- Reviewed-by: isolated
claude-fable-5-1subagent, transcript-verified (73 stamps, no other model value), adopted verbatim bysession_017Js5kTpTtxieBjPyScgxJ3(huangyiirene). Implemented-by:os-musk/session_01ADLdAs2pVcH17h9tZKWMBg, branchclaude/issue-16013-fold-admission-tenancy-posture-classification. - Outcome: nothing blocking — no admission decision moved at any of the six folded seams (per-input-class table on the PR), the two new
@objectstack/coreexports are declared on both carriers and in the changeset (core: minor), every per-seam pin survives. Non-blocking: F1 the last commit'spackages/spectsup-bundle test flake fix is outside the card and not listed in the PR body (split it out, or list it with its reproduction); F2 the dev report pins readings to the previous head803fad5d— add a one-line addendum for5a9c4fd5; F3 a tautologicalifbranch in the "SCOPED without a scope id" pin; F4 two more hand-written copies remain (resolve-execution-context.ts:206-214,mcp/plugin.ts:90-105) — acceptance note, not a card. - CI on the head at posting: 30 success / 3 skipped / 1 in progress (
Lint & Repo Gates) / 0 failure. The PR carriesprotocol:system⇒ maintainer-only merge: thedomain:engineseat adopts, resolves F1/F2, clears both carriers, and moves this card topm:awaiting-maintainerwith the PR left draft. ⛔ This seat cleared no carrier and touched no PR state.
Generated by Claude Code
- Reviewed-by: isolated
Pointer addendum: the PR head moved to
bdd62f15(a clean merge oforigin/maininto5a9c4fd5, pushed 08:49Z) before the verdict above was posted; the verdict is re-pinned tobdd62f15at #17101 (comment) — the PR's own hunks are byte-identical across the merge, findings unchanged, F2 now asks the dev-report addendum to namebdd62f15. CI on the new head was 12 success / 16 in progress / 0 failure at 09:3xZ.
Generated by Claude Code
Pointer correction: the addendum is #17101 (comment) (the id written above pre-dated the comment and is wrong). Content of the pointer stands.
Generated by Claude Code
- added a commit that references this issue
on Oct 7, 2026
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