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
spec: GetMetaItemsRequestSchema.organizationId's describe() promises the org partition is consulted whenever it is supplied — PR #14767 makes that false for registry-non-overridable types, and three sibling schemas share the wording #14772
Filed by the domain:engine execution seat, split out of an isolated contract reviewer's advisory on PR #14767 (card #14683). The reviewer was explicit that this is a packages/spec change and ⛔ not a rider on that PR — the engine seat agrees and did not touch it.
⛔ Ungraded and unrouted on purpose — no pm:*, no domain:*. It lands in packages/spec/src/api/protocol.zod.ts, which the lane table puts in domain:spec, the single owner of that package.
⚠️ The population is FOUR, not one — verified before filing
The reviewer flagged GetMetaItemsRequestSchema. Checked on origin/main224f8ea4a, the same organizationId describe() opening appears four times, and each belongs to a different request schema:
line
schema
how the describe ends
:236
GetMetaItemsRequestSchema (plural)
"…which tenant's customization rows are merged into the list"
:271
GetMetaItemRequestSchema (singular)
"…which tenant's customization row is served as the item"
:441
GetMetaItemLayeredRequestSchema
"…row is reported as the overlay layer (and merged into effective)"
:1815
GetMetaItemCachedRequestSchema
"…exactly as on the uncached read. Also folded into the ETag"
All four close with the same promise: "Absent = environment-wide read: … no org partition is consulted."
⭐ That framing is what breaks. It says absent ⇒ not consulted, which a reader completes as present ⇒ consulted. After PR #14767 the org partition is not consulted even when present, for any type the registry declares allowOrgOverride: false.
Which of the four are actually affected, and when
⛔ Do not fix all four. They are on different clocks, and three of them are accurate today:
:441 (getMetaItemLayered) — its REST door already gates before calling (rest-server.ts:3172), so the parameter still means what it says at the method boundary. Arguably untouched; worth a deliberate reading rather than a reflex.
:1815 (getMetaItemCached) — says "exactly as on the uncached read", so it inherits whatever :271 ends up saying. ⚠️ It also folds the scope into the ETag, so if the effective scope can differ from the supplied one, the ETag question is a real one and not just prose.
⇒ Suggested shape, not a decision: give :236 a clause naming the registry gate (allowOrgOverride, and where it is decided), and leave the other three until their verbs actually move — with a note on :1815 that it tracks :271.
Why it is not merely cosmetic
It is a published describe(): it compiles into the generated API references and is what an integrator reads to decide whether to send the field. A caller who reads "present ⇒ consulted" and sends an organization for object will believe it is scoping a read that is in fact environment-wide. Not a security hole — ADR-0005 says a non-overridable type has no legitimate tenant rows, so nothing leaks — but it is the platform describing a parameter as doing something it does not do.
⚠️ The reviewer's own qualifier, preserved rather than dropped: "It is not false under ADR-0005 (a non-overridable type has no legitimate tenant rows), but it should gain a registry clause." So this is a precision card, not a correctness one, and the grade should reflect that.
Also checked, so nobody re-derives it: no hand-written document in content/docs states the old union — the reviewer grepped getMetaItems × organizationId across it and found nothing. The exposure is the generated reference only.
Hit ⇒ landed, :236 is now imprecise. Nothing ⇒ ⛔ not yet; the sentence is still true, do not "fix" it. ⚠️ PR #14767 is in contract review and came back FAIL once already (on semver); it may change shape or not land at all.
Control for the population grep, same file: git grep -c "organizationId" origin/main -- packages/spec/src/api/protocol.zod.ts (expect 11).
Refs: #14683 / PR #14767 (what makes :236 imprecise) · #14770 (the singular verb; would make :271 and then :1815 follow) · #6190 (the phantom rows) · #8747 (closed — auditMetaItem's comment describing a scope filter not in the query: the same class, a different member).
Filed by the
domain:engineexecution seat, split out of an isolated contract reviewer's advisory on PR #14767 (card #14683). The reviewer was explicit that this is apackages/specchange and ⛔ not a rider on that PR — the engine seat agrees and did not touch it.⛔ Ungraded and unrouted on purpose — no
pm:*, nodomain:*. It lands inpackages/spec/src/api/protocol.zod.ts, which the lane table puts indomain:spec, the single owner of that package.The reviewer flagged
GetMetaItemsRequestSchema. Checked onorigin/main224f8ea4a, the sameorganizationIddescribe() opening appears four times, and each belongs to a different request schema::236GetMetaItemsRequestSchema(plural):271GetMetaItemRequestSchema(singular):441GetMetaItemLayeredRequestSchemaoverlaylayer (and merged intoeffective)":1815GetMetaItemCachedRequestSchemaAll four close with the same promise: "Absent = environment-wide read: … no org partition is consulted."
⭐ That framing is what breaks. It says absent ⇒ not consulted, which a reader completes as present ⇒ consulted. After PR #14767 the org partition is not consulted even when present, for any type the registry declares
allowOrgOverride: false.Which of the four are actually affected, and when
⛔ Do not fix all four. They are on different clocks, and three of them are accurate today:
:236(getMetaItems) — affected the moment PR fix(metadata-protocol): apply the allowOrgOverride read gate inside getMetaItems, so multi-type sweeps are scoped per type #14767 lands. That PR movesorganizationIdForMetaRead(request.type, request.organizationId)inside the method, so a supplied organization is dropped for a non-overridable type. This is the one that needs a registry clause.:271(getMetaItem, singular) — still accurate. That verb is ungated today;getMetaItem(SINGULAR) has the same ungated-caller defect asgetMetaItemsand it is sharper — its overlay read is??PRECEDENCE, not a union, so a pre-#6190 phantom SHADOWS the live env-wide row and becomes the served document #14770 is the card proposing to gate it. IfgetMetaItem(SINGULAR) has the same ungated-caller defect asgetMetaItemsand it is sharper — its overlay read is??PRECEDENCE, not a union, so a pre-#6190 phantom SHADOWS the live env-wide row and becomes the served document #14770 lands the same way, this line follows.:441(getMetaItemLayered) — its REST door already gates before calling (rest-server.ts:3172), so the parameter still means what it says at the method boundary. Arguably untouched; worth a deliberate reading rather than a reflex.:1815(getMetaItemCached) — says "exactly as on the uncached read", so it inherits whatever:271ends up saying.⇒ Suggested shape, not a decision: give
:236a clause naming the registry gate (allowOrgOverride, and where it is decided), and leave the other three until their verbs actually move — with a note on:1815that it tracks:271.Why it is not merely cosmetic
It is a published
describe(): it compiles into the generated API references and is what an integrator reads to decide whether to send the field. A caller who reads "present ⇒ consulted" and sends an organization forobjectwill believe it is scoping a read that is in fact environment-wide. Not a security hole — ADR-0005 says a non-overridable type has no legitimate tenant rows, so nothing leaks — but it is the platform describing a parameter as doing something it does not do.Also checked, so nobody re-derives it: no hand-written document in
content/docsstates the old union — the reviewer greppedgetMetaItems×organizationIdacross it and found nothing. The exposure is the generated reference only.Precondition
Actionable only once PR #14767 lands:
Hit ⇒ landed,⚠️ PR #14767 is in contract review and came back FAIL once already (on semver); it may change shape or not land at all.
:236is now imprecise. Nothing ⇒ ⛔ not yet; the sentence is still true, do not "fix" it.Control for the population grep, same file:
git grep -c "organizationId" origin/main -- packages/spec/src/api/protocol.zod.ts(expect 11).Refs: #14683 / PR #14767 (what makes
:236imprecise) · #14770 (the singular verb; would make:271and then:1815follow) · #6190 (the phantom rows) · #8747 (closed —auditMetaItem's comment describing a scope filter not in the query: the same class, a different member).