Measured by the #11992 dev (fable, 2026-08-26, head 3986bafe) during reverse verification, handed to the PM to file (its dispatch barred label writes). Filed unassigned for triage's first-touch grading; recording only.
What was measured
A planted unknown key on a plugin action-param literal — carryOverX: true in packages/plugins/plugin-security/src/objects/sys-permission-set.object.ts — passed pnpm --filter @objectstack/plugin-security typecheck CLEAN. The compile layer does not police this surface: the params array flows into ObjectSchema.create(...) through a shape where TypeScript's excess-property checking does not bite (the literal is not directly contextually typed against ActionParamSchema's input type at the point where the extra key would be flagged).
The enforcement that DOES catch it: ActionParamSchema is a strictObject, and the parse runs at ObjectSchema.create module load — the planted key failed clone-carryover.test.ts at import time with unrecognized_keys and the alias suggestion naming carryOver. Evidence: PR #12614 verification section (reverse verification: tsc GREEN, strict parse RED, both mutations disk-confirmed and restore hash-proven).
Why it is worth recording
- The protection is real but conditional: an unknown key on an action-param literal is caught only where the object module is parse-validated at import by some test or boot path. A plugin object module that no test imports would carry the typo silently until first runtime load.
- An author (human or AI) writing
readonly:/disabled:/any misspelled key gets zero editor/CI signal from the type layer — the first signal is a runtime/parse refusal. That is later than the platform's usual declared-=-enforced posture wants, and it is the inverse of the usual expectation that tsc is the first line. - Possible directions for whoever grades this (not prejudged): a lint rule contextually typing action-param literals; asserting
satisfies on params arrays in plugin object modules; or accepting the current parse-at-import posture and recording it as the intended enforcement point (in which case a note in the authoring docs is the fix).
Dedup: MCP search_issues for the tsc/unknown-key/action-param shape returned zero on 2026-08-26 (this card's own filing search).
Measured by the #11992 dev (fable, 2026-08-26, head
3986bafe) during reverse verification, handed to the PM to file (its dispatch barred label writes). Filed unassigned for triage's first-touch grading; recording only.What was measured
A planted unknown key on a plugin action-param literal —
carryOverX: trueinpackages/plugins/plugin-security/src/objects/sys-permission-set.object.ts— passedpnpm --filter @objectstack/plugin-security typecheckCLEAN. The compile layer does not police this surface: the params array flows intoObjectSchema.create(...)through a shape where TypeScript's excess-property checking does not bite (the literal is not directly contextually typed againstActionParamSchema's input type at the point where the extra key would be flagged).The enforcement that DOES catch it:
ActionParamSchemais astrictObject, and the parse runs atObjectSchema.createmodule load — the planted key failedclone-carryover.test.tsat import time withunrecognized_keysand the alias suggestion namingcarryOver. Evidence: PR #12614 verification section (reverse verification: tsc GREEN, strict parse RED, both mutations disk-confirmed and restore hash-proven).Why it is worth recording
readonly:/disabled:/any misspelled key gets zero editor/CI signal from the type layer — the first signal is a runtime/parse refusal. That is later than the platform's usual declared-=-enforced posture wants, and it is the inverse of the usual expectation that tsc is the first line.satisfieson params arrays in plugin object modules; or accepting the current parse-at-import posture and recording it as the intended enforcement point (in which case a note in the authoring docs is the fix).Dedup: MCP
search_issuesfor the tsc/unknown-key/action-param shape returned zero on 2026-08-26 (this card's own filing search).