You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Decision] #16712's position-name refusal reads the position catalog of every organization: scope it to the writer's organization, or keep the ruled literal reading #20297
On a deployment where organizations are walled off from one another, an assignment naming a position that exists only in another organization is accepted and silently grants nothing. The same accept-or-refuse answer tells any organization admin whether some other organization has a position by that name.
Filed by the domain:services seat (#6021, session_01TEah6PeJGjxJfbHaySJjLQ). This question arose while executing #16712's ruling (5582062659, confirmed 5582244791) on PR #20292, so it gets its own card, linked back to that ruling; #16712 is not re-labelled needs-user-decision. The implementing dev raised it as an open question (5858844438), and the seat re-measured it on the PR head. ⛔ Not a claim.
Background
The ruling, verbatim: «⛔ The predicate is exactly "no catalog row carries this name" — never "this assignment cannot take effect": ADR-0049 keeps a deactivated position's assignment while it stops granting».
The ⛔ rules out deactivated positions (shape E).
It does not say which organization's catalog the predicate reads.
namesWithoutCatalogRow reads sys_position under const SYSTEM_CTX = { isSystem: true }, a bare system context with no tenant (position-catalog-refusal.ts:108).
The walled test pins "a name only ANOTHER organization's catalog carries is ACCEPTED" (position-catalog-refusal.test.ts:419).
single posture: every catalog row is organization-less, so every reading below gives the same answer. hotcrm, hotclm and the showcase run this posture, per the dev's report.
That work is on the v18 line (D14). Until C2/C3 land, the fork is live on every walled deployment.
Who can reach the check. A caller who may not write sys_user_position is refused 403 on authority and never sees the catalog verdict. The middleware runs inside the security middleware; ablation A2 turns that pin red. So the probe is open to authorized writers of assignments, meaning organization admins, not to members.
No non-test writer stores a name this refusal could newly refuse.
The in-repo census on 4d7e740d3b was EMPTY (dev report 5858844438).
The seat re-ran the catalog-less-name leg on e6b7d8c861: git grep -nE "position:\s*['\"](org_member|everyone|org_owner|org_admin|authenticated|guest|anonymous|platform_admin)['\"]" -- 'packages/**/*.ts' 'examples/**/*.ts' ':!**/*.test.ts' → 0 hits. Control, the same pattern in **/*.test.ts → 3 hits.
Out-of-repo: hotcrm and hotclm are EMPTY (5857658468).
Question
On a walled deployment, a writer in organization A stores an assignment whose position name exists only in organization B's catalog. Does the platform accept it (201) or refuse it (400)?
The catalog is read across every organization; a name any organization carries is accepted.
The assignment saves and grants nothing, silently. Organization A's admin can tell "some other organization has this position" (201) from "no one has it" (400), measured in the PR's walled test.
B: the writer's organization plus organization-less rows
The read takes the engine lookup probe's spelling, { ...context, isSystem: true }. A name only another organization carries is refused like a name that exists nowhere, with the same envelope and the same message. A writer with no organization in context (a platform-level caller) still reads every organization, as the engine does.
A loud 400 that names the fix; the two cases answer identically. The dev estimates one line in namesWithoutCatalogRow plus reversing one pin.
C: the assignment row's own organization_id plus organization-less rows
The check matches exactly where the resolver will look.
Same as B for an organization admin. A platform admin writing for organization B is judged against B's catalog. A row with no organization_id needs its own rule, which nobody has asked for.
A in business terms: an HR system that lets you assign someone the job title "Plant Manager" because some other customer on the same server has that title. The assignment does nothing, and the answer tells you the other customer exists.
B in business terms: a job title must exist in your company's title list. This is how Salesforce roles and Workday job profiles behave per tenant.
C in business terms: the same as B, except that the platform operator acting on a customer's behalf is checked against that customer's list.
namesWithoutCatalogRow reads with { ...opCtx.context, isSystem: true }, the engine's spelling.
The walled pin at :419 is reversed into a refusal pin. It is reversed, not deleted, and asserts the same envelope as the "exists nowhere" case.
The module docblock, the changeset line and the system-context.mdx row are rewritten.
Then the contract review, CI and landing. Clause-②: yes stays.
C. The same patch round, reading the row's own organization_id plus organization-less rows. It needs a stated rule for a row without organization_id (the dev's proposal: fall back to the writer's organization) and a pin for a platform-level cross-organization write.
Dedupe: GitHub semantic issue search in this repository, closed included:
«sys_user_position position name refused when no sys_position catalog row, scoped to the writer's organization, cross-tenant existence oracle» → 16 hits.
«position catalog per-organization name existence probe tenant wall isSystem bare context» → 7 hits.
On a deployment where organizations are walled off from one another, an assignment naming a position that exists only in another organization is accepted and silently grants nothing. The same accept-or-refuse answer tells any organization admin whether some other organization has a position by that name.
Filed by the
domain:servicesseat (#6021,session_01TEah6PeJGjxJfbHaySJjLQ). This question arose while executing #16712's ruling (5582062659, confirmed5582244791) on PR #20292, so it gets its own card, linked back to that ruling; #16712 is not re-labelledneeds-user-decision. The implementing dev raised it as an open question (5858844438), and the seat re-measured it on the PR head. ⛔ Not a claim.Background
cbdd0e70b7) applies the words literally.namesWithoutCatalogRowreadssys_positionunderconst SYSTEM_CTX = { isSystem: true }, a bare system context with no tenant (position-catalog-refusal.ts:108).position-catalog-refusal.test.ts:419).singleposture: every catalog row is organization-less, so every reading below gives the same answer. hotcrm, hotclm and the showcase run this posture, per the dev's report.per-organization-catalog.ts, The Layer-0 tenant wall's strict equality annihilates the driver's platform bucket: #2734's fix is defeated on every walled read, and the org-less RBAC catalog reads ZERO for every principal #10103 option C). The readings differ in exactly one case, a name that only another organization's copy carries.sys_positionretires (D3/D13, card C2 = feat(core,objectql,plugin-security,plugin-sharing): the catalog is read from the registry; assignment tables reference it by name (ADR-0131 D2/D3/D4) #15196). There is then one namespace and every option is identical.sys_user_positionis refused403on authority and never sees the catalog verdict. The middleware runs inside the security middleware; ablation A2 turns that pin red. So the probe is open to authorized writers of assignments, meaning organization admins, not to members.Governing text
priority:p1,security) → PR fix(objectql): scope the lookup existence probe to the caller's organization #19836.packages/objectql/src/engine.tsassertReferencesResolvedocblock, on the engine's own existence probe for lookup columns:sudo()-shaped —{ ...context, isSystem: true }… not a bare{ isSystem: true }([finding] a lookup's existence check reads under a bare system context with no tenant — an org-bound caller can store a reference to another organization's row, and tell "exists elsewhere" from "missing" #19808). The bare spelling carried notenantId, so the probe spanned every organization: an org-bound caller could store a reference to another organization's row, and could tell "exists in another organization" (the write committed) from "exists nowhere" (refused) — a cross-tenant existence oracle.»sys_positionby NAME across organizations in two authority decisions — the sibling half #19775 did not repair #19819 (closed,priority:p0,security) → PR fix(plugin-security): the delegated-admin gate resolves a position name inside the caller's own organization #19859 «the delegated-admin gate resolves a position name inside the caller's own organization». This is the closest precedent: the same plugin, the same object, and a position name resolved across organizations.sys_user_positionrow — self-delegation rule 4 reads holdings by (user, position NAME) under a bare system context #19860 (closed,priority:p0,security) → PR fix(plugin-security): the delegated-admin gate counts a holding only in the organization the runtime grants it #19866: the delegated-admin gate read position holdings by name under a bare system context, across organizations. It now counts a holding only in the organization the runtime grants it in.sys_user_positionrow whosepositionnames nosys_positioncatalog row — 201 with nothing resolvable (RE-CUT: the originally reported resolution-path defect is disproved, see the 2026-09-09 measurement) #16712 ruling5582062659, quoted above.origin/maine6b7d8c861:git grep -n "cross-tenant existence" -- packages/objectql/src/engine.ts→ 1 hit (:7402).git grep -n -i -E "existence oracle|existence probe" -- docs/adr AGENTS.md→ 1 hit (ADR-0120:206).git grep -c -i tenant -- AGENTS.md→ 1.This card changes no protocol file and no
packages/specsource under any answer.Premises, each with its re-check
git show <PR head>:packages/plugins/plugin-security/src/position-catalog-refusal.ts | grep -n "^const SYSTEM_CTX"→{ isSystem: true } as const.grep -n "export async function namesWithoutCatalogRow"→ 1 hit.git grep -n "cross-tenant existence" origin/main -- packages/objectql/src/engine.ts→ 1 hit.git grep -c "assertReferencesResolve" origin/main -- packages/objectql/src/engine.ts→ ≥1.packages/platform-objects/src/pages/sys-user.page.tspickers readsys_positionwithvalueField: 'name'under the caller's context.git grep -n "valueField: 'name'" origin/main -- packages/platform-objects/src/pages/sys-user.page.ts→ 2 hits (:176comment,:191the picker).4d7e740d3bwas EMPTY (dev report5858844438).e6b7d8c861:git grep -nE "position:\s*['\"](org_member|everyone|org_owner|org_admin|authenticated|guest|anonymous|platform_admin)['\"]" -- 'packages/**/*.ts' 'examples/**/*.ts' ':!**/*.test.ts'→ 0 hits. Control, the same pattern in**/*.test.ts→ 3 hits.5857658468).Question
On a walled deployment, a writer in organization A stores an assignment whose position name exists only in organization B's catalog. Does the platform accept it (
201) or refuse it (400)?Options
201) from "no one has it" (400), measured in the PR's walled test.{ ...context, isSystem: true }. A name only another organization carries is refused like a name that exists nowhere, with the same envelope and the same message. A writer with no organization in context (a platform-level caller) still reads every organization, as the engine does.400that names the fix; the two cases answer identically. The dev estimates one line innamesWithoutCatalogRowplus reversing one pin.organization_idplus organization-less rowsorganization_idneeds its own rule, which nobody has asked for.四维分析(业务立场)
sys_positionby NAME across organizations in two authority decisions — the sibling half #19775 did not repair #19819、[finding] the delegated-admin gate answers "you already hold this position" from ANOTHER organization'ssys_user_positionrow — self-delegation rule 4 reads holdings by (user, position NAME) under a bare system context #19860)的修法同一口径。sys_user_positionrow whosepositionnames nosys_positioncatalog row — 201 with nothing resolvable (RE-CUT: the originally reported resolution-path defect is disproved, see the 2026-09-09 measurement) #16712 要消灭的"静默成功",只是换到了隔离部署上。Prior rulings read:
cross-tenant existence/existence oracle|existence probe→ 1 + 1 hits; ADR-0120 (the oracle class), ADR-0131 D3/D13/D14 (end state); thread: #167125582062659,5582244791,5857658468,5858844438; #19808; #19819; #19860.推荐 B(回退项:A,仅当维护者认定裁决字面优先且接受该探测口;⛔ C 不单独推荐)。只看①选 B;②③④ 是否翻转:否。
置信缺口:
Execution per answer
sys_user_positionrow whosepositionnames nosys_positioncatalog row — 201 with nothing resolvable (RE-CUT: the originally reported resolution-path defect is disproved, see the 2026-09-09 measurement) #16712.namesWithoutCatalogRowreads with{ ...opCtx.context, isSystem: true }, the engine's spelling.:419is reversed into a refusal pin. It is reversed, not deleted, and asserts the same envelope as the "exists nowhere" case.system-context.mdxrow are rewritten.Clause-②: yesstays.organization_idplus organization-less rows. It needs a stated rule for a row withoutorganization_id(the dev's proposal: fall back to the writer's organization) and a pin for a platform-level cross-organization write.sys_user_positionrow whosepositionnames nosys_positioncatalog row — 201 with nothing resolvable (RE-CUT: the originally reported resolution-path defect is disproved, see the 2026-09-09 measurement) #16712 ispm:blockedon this card withUnlock-action: re-check PR #20292.position-catalog-refusal.tsas a new reader ofsys_positionthat must move to the registry. The seat records that on feat(core,objectql,plugin-security,plugin-sharing): the catalog is read from the registry; assignment tables reference it by name (ADR-0131 D2/D3/D4) #15196 once this card is ruled.Related: #16712 · PR #20292 · #19808 / PR #19836 · #19819 / PR #19859 · #19860 / PR #19866 · #15196 · #17247 · ADR-0131 · ADR-0120.
Dedupe: GitHub semantic issue search in this repository, closed included:
sys_user_positionrow whosepositionnames nosys_positioncatalog row — 201 with nothing resolvable (RE-CUT: the originally reported resolution-path defect is disproved, see the 2026-09-09 measurement) #16712 (the parent), [finding] a lookup's existence check reads under a bare system context with no tenant — an org-bound caller can store a reference to another organization's row, and tell "exists elsewhere" from "missing" #19808, [finding] the delegated-admin gate still resolvessys_positionby NAME across organizations in two authority decisions — the sibling half #19775 did not repair #19819 and [finding] the delegated-admin gate answers "you already hold this position" from ANOTHER organization'ssys_user_positionrow — self-delegation rule 4 reads holdings by (user, position NAME) under a bare system context #19860 (the precedents).