Skip to content

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

Description

@os-musk

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/main 224f8ea4a, 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:

⇒ 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.

Precondition

Actionable only once PR #14767 lands:

git grep -n "organizationIdForMetaRead(request.type" origin/main -- packages/metadata-protocol/src/protocol.ts

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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions