Skip to content

fix(spec,data): the five RPC query aliases resolve by one fold — spec table, not per-reader prose (#3795) - #4323

Merged
os-zhuang merged 2 commits into
mainfrom
claude/protocol-rpc-alias-precedence-1fc2cd
Jul 31, 2026
Merged

fix(spec,data): the five RPC query aliases resolve by one fold — spec table, not per-reader prose (#3795)#4323
os-zhuang merged 2 commits into
mainfrom
claude/protocol-rpc-alias-precedence-1fc2cd

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes #3795. The sweep's live-and-inverted cluster: RpcQueryOptionsSchema stated its five alias precedences in prose only, so both readers re-implemented them — protocol.ts had four of five backwards (canonical consulted last), and disagreed with the runtime dispatcher's copy on three, so the same request resolved differently per path (?select=a&fields=b[a] or [b] depending on which route served it).

What changed

The mapping lives once, in the spec. packages/spec/src/data/data-engine.zod.ts now exports RPC_QUERY_ALIAS_SLOTS (the five pairs) and foldQueryAliasSlots (the fold), and both consumers run the same table:

  1. Schema transformsRpcQueryOptionsSchema (find/findOne) and the four RpcLegacyFilterMixin options (update/delete/count/aggregate requests) fold at parse. Parsed output speaks canonical QueryAST keys only; the alias keys are dropped from the output type, so a TS consumer reading parsed.query.populate fails to compile instead of silently reading undefined — the fix(action): one precedence for target vs deprecated execute — lower the alias, then drop it (#3713) #3742/fix(field): fold deprecated conditionalRequired into requiredWhen and drop the alias (#3754) #3764 shape one layer down, hence the minor for @objectstack/spec.
  2. protocol.ts findData — the four inverted open-coded folds are gone; the wire fold runs the spec table extended with the wire-only spellings (filters, $filter, $expand — the last settling the $expand ?? expand inversion the issue flagged "worth settling in the same pass").
  3. runtime/domains/data.ts — the dispatcher's second copy of the fold (opposite precedence on three pairs) is deleted, not fixed in place. GET-list wire params ride to findData verbatim; one fold, one answer.

The rule (per slot)

#4181 had already replaced "pick a winner" with "refuse ambiguity" for the filter pair, with rationale that applies verbatim to the other four ("picking one is the silent drop itself"). This PR generalizes that rule rather than implementing the doc block's silent canonical-wins, and rewrites the doc block to match:

Behavior changes (deliberate, all toward one answer)

request before after
?filter=X&where=Y (GET list) Y silently (dispatcher) 400 — matches what POST /query already did (#4181)
{select: a, fields: b} [a] — alias clobbered canonical 400
{skip: 10, offset: 0} 10 — alias clobbered canonical 400
{populate: [a], expand: b} populate won, canonical only as fallback 400
{sort: a, orderBy: b} b silently 400 (consistency — one rule for all five slots)
any alias alone worked unchanged ✔
both spellings, identical value passed unchanged ✔
{expand: ['a','b']} on POST /query latent bug: array survived the block whole, #4226 gate read its indices400 Unknown field '0' (or raw array reached the driver registry-less) lowers to {a: {…}, b: {…}} like populate always did

Callers mixing vocabularies with different values were already getting a wrong/ambiguous answer on at least one path — nothing that worked consistently before stops working.

Pins

  • spec: per-pair fold-to-canonical + alias-absent-from-output, record-sort lowering, identical-tolerated/conflict-refused, all five conflict pairs (data-engine.test.ts).
  • protocol: it.each over all five slots × {fold, conflict, redundant-identical}; rejection message quotes wire spellings incl. OData; canonical-only untouched; null-withdrawal; expand-array lowering (protocol-data.test.ts). The REST 列表:无法解析的 filter JSON 被静默忽略 —— 返回未过滤整页(#4134/#4164 家族第三员) #4181 suite passes unchanged — the shared fold preserves its semantics exactly.
  • runtime: dispatcher test now pins verbatim pass-through (http-dispatcher.test.ts).

Verification

  • spec 7132 / objectql 1365 / runtime 954 / metadata-protocol 122 tests green.
  • Full pnpm test: 131/132 tasks green; the one failure was dogfood/two-factor-lockout timing out at 5s under parallel load — passes standalone, untouched by this PR.
  • check:generated all 8 gates green; api-surface.json (+4 exports) and content/docs/references regenerated via --fix.
  • Changeset: minor @objectstack/spec, patch @objectstack/metadata-protocol + @objectstack/runtime.

Scope notes

Per the issue: $top/$select/$orderby/$skip (the OData rewrite loop) and the engine-level toplimit alias are left as-is; visibleWhen family already correct; the remaining @deprecated spec markers are renamed exports with no key-precedence risk.

🤖 Generated with Claude Code

… table, not per-reader prose (#3795)

RpcQueryOptionsSchema documented its alias precedence in prose only, so both
normalizers re-implemented it: protocol.ts had four of five pairs BACKWARDS
(canonical consulted last) and disagreed with the runtime dispatcher's copy on
three, so ?select=a&fields=b answered [a] or [b] depending on the path.

The mapping now lives once in the spec (RPC_QUERY_ALIAS_SLOTS +
foldQueryAliasSlots), applied as a parse transform on the RPC schemas and as
the wire fold in findData, under #4181's rule generalized to all five slots:
alias alone folds and is dropped from parsed output, identical duplicates
collapse, different values are refused, an explicit null spelling is a
withdrawal. The dispatcher's second copy of the fold is deleted. Also lowers
a direct expand:[names] array to the expand record instead of reading its
indices as relation names.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 31, 2026 6:16am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation protocol:data tests tooling size/l labels Jul 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/metadata-protocol, @objectstack/runtime, @objectstack/spec.

114 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via packages/runtime, @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/api/wire-format.mdx (via @objectstack/runtime)
  • content/docs/automation/approvals.mdx (via @objectstack/spec)
  • content/docs/automation/connectors.mdx (via @objectstack/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via @objectstack/runtime, packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via @objectstack/metadata-protocol, packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/runtime, packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/index.mdx (via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/deployment/vercel.mdx (via @objectstack/runtime)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authentication.mdx (via @objectstack/runtime)
  • content/docs/permissions/authorization.mdx (via packages/runtime, @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/runtime)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit a2266a6 into main Jul 31, 2026
18 checks passed
@os-zhuang
os-zhuang deleted the claude/protocol-rpc-alias-precedence-1fc2cd branch July 31, 2026 06:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:data size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P2] protocol.ts implements 4 of the 5 documented RPC alias precedences backwards — and disagrees with http-dispatcher.ts on three of them

1 participant