You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
finding(types): BaseSchema closes with [key: string]: any (packages/types/src/base.ts:467), so NO annotation on any node schema can catch a misspelled metadata key — measured green by a planted probe while the type, optionality and payload-member probes all went red #7927
Finding (observation, awaiting first grading). Measured by the os-dev seat working objectui#5174 batch 13 (PR to follow). ⛔ Deliberately NOT fixed there: removing or narrowing an index signature on the base type every node schema extends is a public-contract change on @object-ui/types with a blast radius across every package, not a rider on a documentation-ledger batch. Unassigned and bare — domain:* and grading are triage's.
What is true today (measured at origin/maindb2c20d08)
/** * Additional properties specific to the component type. * This index signature allows type-specific extensions. */[key: string]: any;
Every authored node schema in the system extends BaseSchema. The consequence is that no TypeScript annotation anywhere — in source, in tests, or in a documentation snippet — can catch a misspelled or invented metadata key. The annotation checks the key's type and never its name.
The measurement, not an inference
Batch 13 annotated packages/plugin-calendar/README.md's authored-surface listing against the shipped CalendarViewSchema and then ran seven planted probes, each with its direction predicted in writing beforehand. Six were predicted RED and came back RED. One was predicted GREEN, and came back GREEN:
P5 — inside the annotated block, rename the key titleField to titleFieldd. check:doc-snippetsexit 0, Semantic phase: 477 of 477 block(s) judged, 0 failed, nothing reported.
The complement bounds it from the other side, so this is not a claim that nothing is checked:
P1 — view?: CalendarViewMode narrowed to view?: 'agenda' (a mode retired by objectui#5740): exit 1, TS2322 in both assignment directions.
P7 — data?: any made required: exit 1, TS2322: Property 'data' is optional in type 'CalendarViewSchema' but required in type 'CalendarViewNode'.
P6 — event.title misspelled event.titel on the contextually-typed CalendarEvent payload: exit 1, TS2551. CalendarEvent is a plain interface with no index signature, which is exactly why that one IS caught.
⇒ Types are checked. Optionality is checked. Members of payload types that do not inherit the index signature are checked. Key spelling on any BaseSchema descendant is not, and cannot be.
Why this is worth a card rather than a footnote
It is the reason a whole class of gate is structurally blind. objectui#5174's ledger burn-down is making documentation snippets compile against the shipped types; this signature caps what that green can ever mean for metadata literals. Batch 10 hit the same wall on DashboardComponentSchema; batch 13 hit it on CalendarViewSchema. Neither is one type's defect — both inherit it.
The repo already ruled on this exact shape one level down. objectui#7497 is QueryParams carrying [key: string]: any, filed because it "let the published testing guide teach a test that could never pass." BaseSchema is the same mechanism on the most central type in the product.
It runs against AGENTS.md §5 #0.1 and Fix documentation deployment for www.objectui.org #6. #0.1 wants one strict contract and rejection at the producer rather than tolerance at the consumer; Fix documentation deployment for www.objectui.org #6 is "type safety over magic — no any". A blanket [key: string]: any is the most permissive possible consumer-side tolerance, and it is precisely the surface an AI writing metadata gets wrong in bulk and silently.
The strict @objectstack/spec zod twins already refuse unknown keys — several CalendarViewSchema members carry docblocks saying exactly that ("the zod twin refuses this key by name"). So the two faces of the same contract disagree: the zod face is strict, the TypeScript face accepts anything. Whichever is right, they should not differ silently.
Scope, if this is graded for work
Measure first, do not delete first: git grep every site that relies on an undeclared key riding BaseSchema's passthrough. objectui#7780 records one such read (ObjectKanban reading an undeclared inline data), so the population is non-empty and the removal is not free.
Decide the direction deliberately per AGENTS.md §5 #0.1 — the honest options are removing the signature and declaring the real extension keys, or keeping it and stating in the docblock that key-level validity is the zod twin's job and not TypeScript's (which is what batch 13's README note now says locally, for one page).
Whatever lands, the pin is a compile-fail test: a fixture with a misspelled key must stop type-checking.
Related: objectui#7497 (the same mechanism on QueryParams), objectui#7912 and objectui#7483 (bare-any props with the same "a wrong value raises nothing" consequence), objectui#5138 (schema-key validity as the snippet gate's stated non-goal), objectui#5174 (the ledger burn-down that measured it).
Finding (observation, awaiting first grading). Measured by the
os-devseat working objectui#5174 batch 13 (PR to follow). ⛔ Deliberately NOT fixed there: removing or narrowing an index signature on the base type every node schema extends is a public-contract change on@object-ui/typeswith a blast radius across every package, not a rider on a documentation-ledger batch. Unassigned and bare —domain:*and grading are triage's.What is true today (measured at
origin/maindb2c20d08)packages/types/src/base.ts:467closesBaseSchema(lines 70–468) with:Every authored node schema in the system extends
BaseSchema. The consequence is that no TypeScript annotation anywhere — in source, in tests, or in a documentation snippet — can catch a misspelled or invented metadata key. The annotation checks the key's type and never its name.The measurement, not an inference
Batch 13 annotated
packages/plugin-calendar/README.md's authored-surface listing against the shippedCalendarViewSchemaand then ran seven planted probes, each with its direction predicted in writing beforehand. Six were predicted RED and came back RED. One was predicted GREEN, and came back GREEN:titleFieldtotitleFieldd.check:doc-snippetsexit 0,Semantic phase: 477 of 477 block(s) judged, 0 failed, nothing reported.The complement bounds it from the other side, so this is not a claim that nothing is checked:
view?: CalendarViewModenarrowed toview?: 'agenda'(a mode retired by objectui#5740): exit 1,TS2322in both assignment directions.data?: anymade required: exit 1,TS2322: Property 'data' is optional in type 'CalendarViewSchema' but required in type 'CalendarViewNode'.event.titlemisspelledevent.titelon the contextually-typedCalendarEventpayload: exit 1,TS2551.CalendarEventis a plain interface with no index signature, which is exactly why that one IS caught.⇒ Types are checked. Optionality is checked. Members of payload types that do not inherit the index signature are checked. Key spelling on any
BaseSchemadescendant is not, and cannot be.Why this is worth a card rather than a footnote
DashboardComponentSchema; batch 13 hit it onCalendarViewSchema. Neither is one type's defect — both inherit it.QueryParamscarrying[key: string]: any, filed because it "let the published testing guide teach a test that could never pass."BaseSchemais the same mechanism on the most central type in the product.any". A blanket[key: string]: anyis the most permissive possible consumer-side tolerance, and it is precisely the surface an AI writing metadata gets wrong in bulk and silently.@objectstack/speczod twins already refuse unknown keys — severalCalendarViewSchemamembers carry docblocks saying exactly that ("the zod twin refuses this key by name"). So the two faces of the same contract disagree: the zod face is strict, the TypeScript face accepts anything. Whichever is right, they should not differ silently.Scope, if this is graded for work
git grepevery site that relies on an undeclared key ridingBaseSchema's passthrough. objectui#7780 records one such read (ObjectKanbanreading an undeclared inlinedata), so the population is non-empty and the removal is not free.Related: objectui#7497 (the same mechanism on
QueryParams), objectui#7912 and objectui#7483 (bare-anyprops with the same "a wrong value raises nothing" consequence), objectui#5138 (schema-key validity as the snippet gate's stated non-goal), objectui#5174 (the ledger burn-down that measured it).Generated by Claude Code