Filed by the domain:devx dev seat while porting dashboard-widget-options for #12810. The port is correct as landed; this records a drift hazard it necessarily leaves behind, so it is findable rather than living only in a file header.
The hazard
checkDashboardWidgetOptions warns on any widget options key outside CONSUMED_WIDGET_OPTION_KEYS. That array has two halves:
- the five DECLARED keys —
dateGranularity, sortBy, sortOrder, limit, stageOrder — which are exactly the five properties DashboardWidgetOptionsSchema declares in packages/spec/src/ui/dashboard.zod.ts; description — undeclared, but written into options by translateDashboard (documented on WidgetLike.options in packages/spec/src/system/i18n-resolver.ts).
In objectui, the array is re-derived every test run against the installed spec and against the renderer's read sites. In this repo it is a literal pin. So the failure mode is specific and one-directional: someone adds a declared key to DashboardWidgetOptionsSchema — a change entirely inside THIS repo, since the spec ships from here — and does not touch the parser. The new key is then spec-legal, renderer-consumed on the objectui side, and warned about here. A false positive on legal metadata, which is the shape that gets a diagnostic deleted by the next person who hits it.
Why the existing test does not catch it
The test added with the port asserts the array equals the six expected strings and names the two spec files to re-read. That pins the parser against ITSELF. Adding a key to the spec does not fail it — the test stays green and becomes wrong, which is precisely the "closure claim nothing re-derives" pattern this repo treats as a defect elsewhere.
Why the port did not just derive it
@objectstack/sdui-parser takes no dependency on @objectstack/spec — it is dependency-free and hoistable by design, and its package.json devDependencies are only typescript and vitest. Adding the spec as a test input is not a one-line change: it pulls the package into check:cross-package-test-inputs (a turbo.json inputs declaration) and into check:test-source-alias (a vitest alias or a KNOWN_UNALIASED_TEST_IMPORTS registration). That is a real design decision about the package's purity, well outside a port's scope, so it was not taken unilaterally.
Options, none chosen here
- Derive in a gate script instead of a test — a
scripts/check-*.mjs reading both files by source text keeps the package dependency-free and puts the claim where the repo already keeps cross-package claims. Probably the cheapest honest answer. - Take the devDependency and derive in-package like objectui does, accepting the two gate registrations.
- Accept the pin and rely on the header note. Cheapest, and the option that decays — worth choosing explicitly rather than by default.
Note the whole class is currently latent for a second reason, recorded separately: validateTree is not reached from the production gate at all (#12924). A false positive here would surface only once that wiring lands, which is an argument for settling this before it does, not after.
Filed by the
domain:devxdev seat while portingdashboard-widget-optionsfor #12810. The port is correct as landed; this records a drift hazard it necessarily leaves behind, so it is findable rather than living only in a file header.The hazard
checkDashboardWidgetOptionswarns on any widgetoptionskey outsideCONSUMED_WIDGET_OPTION_KEYS. That array has two halves:dateGranularity,sortBy,sortOrder,limit,stageOrder— which are exactly the five propertiesDashboardWidgetOptionsSchemadeclares inpackages/spec/src/ui/dashboard.zod.ts;description— undeclared, but written intooptionsbytranslateDashboard(documented onWidgetLike.optionsinpackages/spec/src/system/i18n-resolver.ts).In objectui, the array is re-derived every test run against the installed spec and against the renderer's read sites. In this repo it is a literal pin. So the failure mode is specific and one-directional: someone adds a declared key to
DashboardWidgetOptionsSchema— a change entirely inside THIS repo, since the spec ships from here — and does not touch the parser. The new key is then spec-legal, renderer-consumed on the objectui side, and warned about here. A false positive on legal metadata, which is the shape that gets a diagnostic deleted by the next person who hits it.Why the existing test does not catch it
The test added with the port asserts the array equals the six expected strings and names the two spec files to re-read. That pins the parser against ITSELF. Adding a key to the spec does not fail it — the test stays green and becomes wrong, which is precisely the "closure claim nothing re-derives" pattern this repo treats as a defect elsewhere.
Why the port did not just derive it
@objectstack/sdui-parsertakes no dependency on@objectstack/spec— it is dependency-free and hoistable by design, and itspackage.jsondevDependencies are onlytypescriptandvitest. Adding the spec as a test input is not a one-line change: it pulls the package intocheck:cross-package-test-inputs(a turbo.jsoninputsdeclaration) and intocheck:test-source-alias(a vitest alias or aKNOWN_UNALIASED_TEST_IMPORTSregistration). That is a real design decision about the package's purity, well outside a port's scope, so it was not taken unilaterally.Options, none chosen here
scripts/check-*.mjsreading both files by source text keeps the package dependency-free and puts the claim where the repo already keeps cross-package claims. Probably the cheapest honest answer.Note the whole class is currently latent for a second reason, recorded separately:
validateTreeis not reached from the production gate at all (#12924). A false positive here would surface only once that wiring lands, which is an argument for settling this before it does, not after.