fix(rest): strip read decorations before validating a dataset query - #4879
Merged
Conversation
Every widget on every dataset-bound dashboard failed with "Dataset query failed: 400 Bad Request — Invalid dataset definition." POST /analytics/dataset/query resolves a saved `datasetName` through `getMetaItems`, and the metadata READ path stamps its spec-validation verdict `_diagnostics` onto every document it serves. Since #4001 closed the metadata schemas, `DatasetSchema.parse()` rejects unrecognized keys rather than dropping them — so the route handed a served document back to the schema that produced it and got `unrecognized_keys: ["_diagnostics"]`. The 400 blamed the author for a key the server had just added. This is exactly what `stripReadDecorations` exists to prevent, and the failure `spec/kernel/metadata-read-decorations.ts` already documents from the cold-boot flow bind (cloud#971). Strip before validating. Applied on BOTH branches, not only the `datasetName` read: the Studio dataset preview posts its draft inline, and that draft is the document the designer GET-loaded, decorations included. A hand-authored draft never carries these keys, so the strip is a no-op there. The ADR-0010 provenance envelope (`_packageId`, `_provenance`, …) is not a read decoration and still survives. Regression coverage for the saved-dataset path was the gap that let this ship — every existing case passed the dataset inline, so nothing exercised the read. Tests now cover resolve-by-name, the inline decorated draft, the 404, and a genuinely malformed saved dataset (still 400). Also bumps the vendored console pin to objectui@f5bc4c78be76 via scripts/bump-objectui.sh, with the changeset it generates. Verified in a real browser against the showcase app: before, all 8 widgets of showcase_ops_dashboard rendered the 400; after, all 8 render live data, with zero failed responses and zero console errors. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QuQBvLsJWuYFAYdkqDbM4N
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 11 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This was referenced Aug 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
Every widget on every dataset-bound dashboard failed:
Reproduced in a real browser at
/_console/apps/com.example.showcase/dashboard/showcase_ops_dashboard— all 8widgets, KPI tiles and charts alike.
Root cause
POST /analytics/dataset/queryresolves a saveddatasetNamethroughgetMetaItems, and the metadata READ path stamps its spec-validation verdict_diagnosticsonto every document it serves. Since #4001 closed the metadataschemas,
DatasetSchema.parse()rejects unrecognized keys instead ofdropping them — so the route handed a served document straight back to the
schema that produced it and got
unrecognized_keys: ["_diagnostics"].The 400 blamed the author for a key the server itself had just added. The
dataset was never wrong.
This is precisely the failure
stripReadDecorationsexists to prevent, and theone
spec/kernel/metadata-read-decorations.tsalready documents from thecold-boot flow bind (cloud#971): a served body is not a valid input to the
schema that produced it. That module's guidance simply hadn't been applied on
this route.
The fix
Strip read decorations before validating.
Applied on both branches, not only the
datasetNameread: the Studiodataset preview posts its draft inline, and that draft is the document the
designer GET-loaded — decorations and all. A hand-authored draft never carries
these keys, so the strip is a no-op there.
The ADR-0010 provenance envelope (
_packageId,_provenance,_lock, …) isdeliberately not a read decoration and still survives the round-trip — the
tests pin that.
Why it shipped
Regression coverage for the saved-dataset path was the gap: every existing case
in
analytics-routes.test.tspassed the dataset inline, so nothing everexercised the read. The route's tests now cover resolve-by-name, the inline
decorated draft, the 404, and a genuinely malformed saved dataset (still 400).
Confirmed the new test fails without the fix and passes with it.
Verification
Browser-verified against the showcase app (
os dev --ui --seed-admin), signingin through the real form:
showcase_ops_dashboard,showcase_chart_galleryandshowcase_revenue_pulseall render live data after the fix.
pnpm --filter @objectstack/rest test— 577 passed (38 files).Also in this PR
chore: bump objectui to f5bc4c78be76(requested alongside the fix) viascripts/bump-objectui.sh, including the@objectstack/consolechangeset itgenerates from objectui's own declared changesets, and a rebuild of the vendored
console dist at the new pin.
Generated by Claude Code