Skip to content

[rest] record the #8039 ruling in DATA_RECORD_READ_PARAMS's docblock - #8510

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-8039-alias-ruling-comment
Aug 13, 2026
Merged

[rest] record the #8039 ruling in DATA_RECORD_READ_PARAMS's docblock#8510
os-zhuang merged 1 commit into
mainfrom
claude/issue-8039-alias-ruling-comment

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes#8039

What changed

Prose only. The docblock above DATA_RECORD_READ_PARAMS in
packages/rest/src/rest-server.ts described the fields / populate alias-table
spellings on GET {basePath}/data/:object/:id as an open question ("Tracked as #8039
rather than widened here"). It has been settled by maintainer ruling on 2026-08-12:
option 2 — keep the narrow select / expand accepted set, refuse the alias-table
spellings loudly instead of folding them. The comment now records that ruling instead of
pointing at a decided question:

  • narrow set kept deliberately (select / expand)
  • fields / populate refused by name via refuseUnknownQueryParams, not silently
    dropped
  • option 1 (folding RPC_QUERY_ALIAS_SLOTS onto this one route) explicitly rejected,
    and why — surface expansion on a public route with no measured pull, and doing it for
    this route alone would leave every other data route's ingress inconsistent in the
    opposite direction
  • what would have to change: a ruling that declares the alias table universal across
    all data routes, landed as one card, never a quiet per-route widening here

No route logic changed.

Why this is the correct delivery, not a thin one

The assignment explicitly warned against inheriting a previous round's measurement that
"the code half is already done." I re-verified it myself rather than trusting that
comment, per the instructions:

  1. Read the actual gate.refuseUnknownQueryParams (packages/rest/src/query-allowlist.ts)
    builds Set(allowed) from DATA_RECORD_READ_PARAMS = ['select', 'expand'] and rejects
    any query key outside it with a 400 VALIDATION_ERROR before the handler ever
    destructures { select, expand } — so fields / populate cannot reach getData
    silently.
  2. Drove it through the real handler, not just read the source. Ran the existing
    pinned suite rest-server-closed-query-params.test.ts (see Tests below), which boots a
    real RestServer, drives GET /data/:object/:id through its actual registered route
    handler with { fields: 'title' } and { populate: 'owner' }, and asserts:
    • status === 400, nested body.error.code === 'VALIDATION_ERROR'
    • the located message names select / expand as what the route accepts
    • getData was never called (the defect this whole policy exists to prevent —
      "still 200" is exactly what silent widening looks like)

Both spellings are refused today, exactly as option 2 requires. No ablation applies
here — there is no behavioural change to reverse-verify, so instead of a predict/run
ablation pair this PR shows the direct measurement above, taken against origin/main
before this change, proving the behaviour already holds. This makes shipping the prose-only
change the correct delivery, per the task's own instruction: "If it is genuinely complete,
then shipping only the prose change is the correct delivery, not a thin result."

Symbol drift note

Every line number on this card was stale (ruling: :1779-1780; a later round measured
:1515 / :6834; PR #8487 moved both again). Located everything by symbol instead:
DATA_RECORD_READ_PARAMS is now at rest-server.ts:1539, and the by-id handler's
refuseUnknownQueryParams(req, res, DATA_RECORD_READ_PARAMS) call is at rest-server.ts:7007.

Tests

Build closure for the package first (per lane convention):

pnpm --filter '@objectstack/rest^...' build

Typecheck, clean:

cd packages/rest && npx tsc --noEmit

Targeted suite, before AND after the docblock edit (comment-only change, so identical
either way — confirms the rewrite didn't alter behaviour):

npx vitest run rest-server-closed-query-params.test.ts --maxWorkers=2
Test Files 1 passed (1)
Tests 27 passed (27)

including, specifically:

✓ #7606 §1 — GET /data/:object/:id refuses what it would have dropped
> ?fields= is refused — the CANONICAL spelling this route never implemented
✓ #7606 §1 — GET /data/:object/:id refuses what it would have dropped
> ?populate= — the expand slot's unimplemented alias — is refused the same way

Whole-package sanity pass (pre-edit, unaffected by a comment-only diff):

pnpm --filter '@objectstack/rest' test
Test Files 113 passed (113)
Tests 1870 passed (1870)

Local gate families run

Derived via node scripts/pm/dispatch-gates.mjs packages/rest/src/rest-server.ts .changeset/data-record-read-alias-ruling-comment.md
(one extra family the dispatch prompt didn't name: check:authz-resolver, matched because
it globs the whole rest-server.ts file — included below since the diff touches that file).
All green:

  • pnpm check:authz-resolver
  • pnpm check:route-envelope
  • pnpm check:meta-type-normalized
  • pnpm check:filter-alias-parity
  • pnpm check:changeset-gate-self-tests
  • pnpm check:objectui-changeset
  • pnpm check:cross-package-test-inputs
  • node scripts/check-empty-changeset.mjs --base origin/main
  • node scripts/check-changeset-no-major.mjs --base origin/main
  • node scripts/check-adr-0087-registration.mjs --base origin/main
  • node scripts/check-nul-bytes.mjs

One derived family (check:objectui-pin-fresh) reports the objectui pin as stale — this
is pre-existing on origin/main, unrelated to this diff (nothing here touches
.objectui-sha or console files; the matcher fired only because this PR adds a file under
.changeset/), and that gate is release.yml-scoped / advisory on ordinary code PRs per its
own message ("advisory mode does not block on a stale pin").

Changeset

packages/rest gets a patch changeset (non-empty frontmatter, following the
comment-gate-own-depth-contract.md precedent for doc-only contract clarifications —
check-empty-changeset.mjs rejects a newly-introduced empty-frontmatter changeset, so the
empty-frontmatter pattern some older comment-only PRs used is not available for a new
file).

Note on scope

packages/rest/src/rest-server.ts is a named hot-file serial queue for this lane; this PR
touches only the DATA_RECORD_READ_PARAMS docblock, nothing else in the file.


Generated by Claude Code

The docblock above DATA_RECORD_READ_PARAMS (GET /data/:object/:id's closed
query-parameter set) described the fields/populate alias-table spellings as
an open question tracked by #8039. Maintainer ruling, 2026-08-12, settled it:
option 2 - keep the narrow select/expand set, refuse the alias spellings
loudly instead of folding them. Option 1 (folding RPC_QUERY_ALIAS_SLOTS onto
this one route) was explicitly rejected as surface expansion with no measured
pull, and would leave other data routes' ingress inconsistent in the
opposite direction.
No code change. refuseUnknownQueryParams(req, res, DATA_RECORD_READ_PARAMS)
already refuses `?fields=` / `?populate=` with a located 400 VALIDATION_ERROR
- measured directly against origin/main before this commit by running
rest-server-closed-query-params.test.ts (27/27 passing), including the two
cases that drive both spellings through the real by-id handler and assert
the refusal plus that getData is never called. The behavioural half of the
ruling was already shipped; this commit is the prose half the ruling asked
for.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P7vaLs7bhBPi9m3JyzkhDj
@vercel

vercelBot commented Aug 13, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 13, 2026 4:34pm

Request Review

@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation tooling labels Aug 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/rest.

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

  • content/docs/ai/connect-mcp.mdx(via @objectstack/rest)
  • content/docs/api/error-handling-server.mdx(via @objectstack/rest)
  • content/docs/api/index.mdx(via @objectstack/rest)
  • content/docs/permissions/authentication.mdx(via @objectstack/rest)
  • content/docs/permissions/system-context.mdx(via packages/rest)
  • content/docs/plugins/index.mdx(via @objectstack/rest)
  • content/docs/plugins/packages.mdx(via @objectstack/rest)
  • content/docs/protocol/kernel/http-protocol.mdx(via @objectstack/rest)
  • content/docs/protocol/kernel/i18n-standard.mdx(via packages/rest)

3 release-owned page(s) also reference the affected code. These are read-only:

  • content/docs/releases/implementation-status.mdx(via @objectstack/rest)
  • content/docs/releases/v12.mdx(via @objectstack/rest)
  • content/docs/releases/v17.mdx(via @objectstack/rest)

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

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 marked this pull request as ready for review August 13, 2026 19:28
@os-zhuang
os-zhuang added this pull request to the merge queueAug 13, 2026
Merged via the queue into main with commit 0a515c8Aug 13, 2026
26 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-8039-alias-ruling-comment branch August 13, 2026 19:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/stooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[rest] GET /data/:object/:id folds no query aliases — the CANONICAL fields spelling is dropped while the alias select works

2 participants

@os-zhuang@claude