Measured on main = 8f1d995ef447 while converging MarkdownSchema for #6172.
The fact
MarkdownSchema declares two members that no renderer reads:
| member |
declared at |
read by |
sanitize?: boolean (@default true) |
packages/types/src/data-display.ts |
nothing |
components?: Record<string, any> |
same |
nothing |
The Zod mirror carries both as well (packages/types/src/zod/data-display.zod.ts).
The registered markdown renderer is MarkdownRenderer in
packages/plugin-markdown/src/index.tsx. It forwards exactly two values to the
implementation — content and className:
LazyMarkdown content={schema.content || ''} className={schema.className}
MarkdownImplProps accepts only those two. Nothing anywhere destructures or
indexes schema.sanitize or schema.components.
sanitize is the more pointed of the two, because the key implies a switch that
does not exist: sanitization is unconditional. rehypeSanitize is a fixed
link in the rehype chain in MarkdownImpl.tsx, documented there as "the final
gate". Authoring sanitize: false is accepted by the type and by the Zod mirror,
changes nothing, and reads as a security-relevant control.
Why it is worth a card
ADR-0049 enforce-or-remove: declared = enforced. This is the same class as #6942
(TextSchema.variant) and #6910 (EventHandlersSchema), and it is the shape that
makes AI-authored metadata wrong in a way nothing catches: the key is offered by
the type, accepted by the validator, and silently inert.
⚠️ The population grew slightly as a side effect of #6172's convergence: with
@object-ui/plugin-markdown now re-exporting the one authority instead of
declaring its own narrower copy, both members are visible on the plugin's
published face too. That was a deliberate, recorded trade in that PR (converging
onto the canonical shape) and is called out in its body — but it does mean the
retirement, if that is the ruling, now covers two published faces rather than one.
Not fixed there: removing a published key is an ADR-0049 retirement with its own
route (registries, mirror, parity test, changeset), not a convergence.
Reproduce
grep -rn "sanitize\|components" packages/plugin-markdown/src/index.tsx packages/plugin-markdown/src/MarkdownImpl.tsx
grep -rn "schema.sanitize\|schema.components" packages/ apps/ --include=*.ts --include=*.tsx
Refs: #6172 (where this was measured), #6942 / #6910 (same class).
Generated by Claude Code
Measured on
main = 8f1d995ef447while convergingMarkdownSchemafor #6172.The fact
MarkdownSchemadeclares two members that no renderer reads:sanitize?: boolean(@default true)packages/types/src/data-display.tscomponents?: Record<string, any>The Zod mirror carries both as well (
packages/types/src/zod/data-display.zod.ts).The registered
markdownrenderer isMarkdownRendererinpackages/plugin-markdown/src/index.tsx. It forwards exactly two values to theimplementation —
contentandclassName:MarkdownImplPropsaccepts only those two. Nothing anywhere destructures orindexes
schema.sanitizeorschema.components.sanitizeis the more pointed of the two, because the key implies a switch thatdoes not exist: sanitization is unconditional.
rehypeSanitizeis a fixedlink in the rehype chain in
MarkdownImpl.tsx, documented there as "the finalgate". Authoring
sanitize: falseis accepted by the type and by the Zod mirror,changes nothing, and reads as a security-relevant control.
Why it is worth a card
ADR-0049 enforce-or-remove: declared = enforced. This is the same class as #6942
(
TextSchema.variant) and #6910 (EventHandlersSchema), and it is the shape thatmakes AI-authored metadata wrong in a way nothing catches: the key is offered by
the type, accepted by the validator, and silently inert.
@object-ui/plugin-markdownnow re-exporting the one authority instead ofdeclaring its own narrower copy, both members are visible on the plugin's
published face too. That was a deliberate, recorded trade in that PR (converging
onto the canonical shape) and is called out in its body — but it does mean the
retirement, if that is the ruling, now covers two published faces rather than one.
Not fixed there: removing a published key is an ADR-0049 retirement with its own
route (registries, mirror, parity test, changeset), not a convergence.
Reproduce
Refs: #6172 (where this was measured), #6942 / #6910 (same class).
Generated by Claude Code