fix(metadata-admin): DatasourcePreview reads only keys DatasourceSchema accepts (#4131) - #4226
Merged
Merged
Conversation
…ma accepts (#4131) `retryPolicy`, `healthCheck` and `capabilities` were removed from the datasource document by objectstack#4583 under ADR-0049 enforce-or-remove: connection retry and health probing belong to the runtime driver, and pushdown is decided by that driver's own `supports.*`, never by datasource metadata. `DatasourceSchema` is `.strict()`, so it refuses all three by name — while this preview kept painting a `Retry Policy` SideBlock, a `Health Check` SideBlock and a `Capabilities` chip strip for them. An author who typed any of the three saw the designer confirm a draft that cannot be saved, and the preview was the only surface acknowledging the keys at all, so it was also the strongest signal they worked. Deleted: both SideBlocks, the chip strip, `enabledCapabilities()`, the reads at `d.retryPolicy` / `d.healthCheck` / `d.capabilities`, and the now unused `RotateCcw` import. `pool` and `ssl` are still declared and still render. This is the third wave of the same defect on this one file (#3275 deleted `d.type`, `isDefault` and the `Array.isArray(capabilities)` branch; #3143 deleted the read-replica pill), and the removals sat in `main` for eight days because nothing compared the two halves of the contract. They are compared mechanically now: `DatasourcePreview.spec-keys.test.ts` derives the preview's read set from the component's own AST — every key reached off the `draft` prop, through dot access, optional chain, bracket or destructure, following a renamed prop and alias chains — and derives the accepted set from the schema object's `.keyof()`. Neither side is written down as a list, so a key added or removed in `@objectstack/spec` moves the pin on the next dependency bump instead of leaving it stale. The pin also asserts things about itself, because a derivation that silently returned nothing would satisfy a subset check forever: that it still finds this file's real reads, and that every use of the draft binding is a read form it understands, so it fails loudly rather than going blind if the preview is refactored. Reverse-verified both ways — restoring the pre-fix file turns it red naming all three keys at their exact lines, and a freshly planted `d.readReplicas` read turns it red naming that one. The AST is load-bearing rather than a grep: the header comment now names all three removed keys in prose, so a text scan would report violations that do not exist. Fixes #4131 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This was referenced Aug 11, 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.
Fixes #4131
What was wrong
retryPolicy,healthCheckandcapabilitieswere removed from the datasource document by objectstack#4583 under ADR-0049 enforce-or-remove — connection retry and health probing belong to the runtime driver, and pushdown is decided by that driver's ownsupports.*, never by datasource metadata.DatasourceSchemais.strict(), so it refuses all three by name, whileDatasourcePreviewkept painting aRetry PolicySideBlock, aHealth CheckSideBlock and aCapabilitieschip strip for them.An author who typed any of the three saw the designer confirm a draft that cannot be saved. And, as objectui#3275's own header comment put it about the read-replica pill it deleted, the preview was "the only surface that acknowledged the key at all, [so] it was the strongest signal an author had that it worked".
Premise re-verified on the branch point, against the installed
@objectstack/spec17.0.0-rc.6 — parse probes, not grep:What changed
Deleted, on the objectui#3275 route: both SideBlocks, the chip strip,
enabledCapabilities(), the reads atd.retryPolicy/d.healthCheck/d.capabilities, and the now-unusedRotateCcwimport.poolandsslare still declared and still render. The file's #3275 header comment is extended to record this second wave in the same convention — what was deleted and why.The console's datasource sample was already clean (
apps/console/src/preview-samples.tscarries a comment saying so), so the sample and the renderer had drifted apart; this closes that gap from the renderer side.The pin is the point
Third occurrence of this shape on one file (#3275 deleted
d.type/isDefault/ theArray.isArray(capabilities)branch; #3143 deleted the read-replica pill), and objectstack#4583 landed 2026-08-02 while the preview still carried the keys eight days later. Nothing compared the two halves of the contract.DatasourcePreview.spec-keys.test.tsnow compares them mechanically, deriving both sides so neither can go stale:DatasourcePreview.tsx's own AST: every key reached off thedraftprop, through dot access, optional chain, bracket access or destructure, following a renamed prop ({ draft: raw }) and alias chains (const d = draft as …) to a fixpoint;DatasourceSchema.keyof()), so a key added or removed in@objectstack/specmoves the pin on the next dependency bump.The AST is load-bearing rather than a grep: the header comment now names
d.retryPolicy,d.healthCheck,d.capabilitiesandd.typein prose to record why they are gone, so a text scan reports four violations that do not exist.Two assertions the pin makes about itself, because a derivation that quietly returned nothing would satisfy a subset check forever: that it still finds this file's real reads, and that every use of the draft binding is a read form it understands — so it fails loudly instead of going blind if the preview is refactored into a shape it cannot follow.
Scope note: this is a top-level key pin, matching what
.strict()rejects by name. It says nothing about nested value shapes.Reverse verification — red both ways
Predicted RED, confirmed RED, in two independent directions.
git checkout origin/main -- DatasourcePreview.tsx) — the guard names all three keys at their exact lines, which are the lines the issue's measured table recorded:const plantedReplicas = d.readReplicas) — red, naming that one:Restored after both; the working tree was byte-compared against a saved patch to confirm.
Tests
Render pins alongside the read pin: a draft of declared keys only renders
PoolandSSLand their contents; a draft carrying all three removed groups renders none of their titles and none of their values. Both fixtures are asserted againstDatasourceSchemaitself rather than described as valid in a comment, so they cannot drift into the state they exist to rule out.Changeset:
@object-ui/app-shellpatch.The three red CI jobs are
main's rc.6 remainder, not this PRThis PR's four files are all under
packages/app-shell/src/views/metadata-admin/previews/plus one changeset. None of the three failing jobs touches them, and all three reproduce locally on this branch and on a cleanorigin/main@a9a67ec5bworktree:Type Checkcheck:spec-symbols— the objectstack#4115 collision guard, beforepnpm type-checkis ever reachedTest (shard 2/4)apps/console/src/__tests__/registry-inputs-spec-parity.test.ts— 12 stale exemptions, andrecord_pickerpublishingsort/limit/emptyTextTest (shard 3/4)packages/plugin-detail/src/__tests__/recordDetailsInputs.spec-parity.test.ts— "the spec really takes OBJECT sections"Root cause for all three:
38ab5054f(#4169) bumped@objectstack/specrc.5 to rc.6 at 03:30 today. The last pull request to run a full gate set before that (#4218, checks at 03:24) was green on every one of these jobs.A fourth consequence of the same bump is visible only locally, because
Type Checkdies atcheck:spec-symbolsbefore reaching it:pnpm --filter @object-ui/app-shell type-checkreports threeTS2322errors insrc/utils/resolveActionParams.test.ts(a file listed intsconfig.typetests.json), because rc.6 widenedActionParamSchema.labeltoI18nLabeland app-shell's localRawActionParam.label?: stringdid not follow. Not filed as a twin — #4163 is being worked right now and its branch already carries exactly that fix (label?: I18nLabel, plus a newresolveActionParams.i18nLabel.test.ts).Nothing here is fixed in this PR: each belongs to a card that is already dispatched (#4167 / #4189, #4163), and two parallel agents are in those files.
Generated by Claude Code