Surfaced by #17768's dev as a class-(c) out_of_scope_findings entry; the domain:devx seat verified two of its three legs and names the third as unverified. ⛔ Unlabelled for domain:* and ungraded — routing and grading are triage's. ⛔ The filer did not dedupe; dedupe words at the bottom.
Class (c) — authorable metadata that the runtime silently drops
A messages id containing a dot is writable, schema-valid, and resolves to nothing. Nothing refuses it at either door.
Verified by the seat
1 — messages is a FLAT record, so a dotted id is a key that merely contains a dot, ⛔ not a path:
packages/spec/src/system/translation.zod.ts:670
messages: z.record(z.string(), z.string()).optional()
.describe('UI message translations keyed by message ID')
control: 163 occurrences of `z.` in that file ⇒ the grep discriminates
2 — the spec's own docblock @example teaches the trap, and it does so TWICE — ⚠️ the dev reported one site; there are two:
packages/spec/src/system/translation.zod.ts:577 "messages": { "common.save": "Save" }
packages/spec/src/system/translation.zod.ts:1430 messages: { 'common.save': '保存' }
⭐ That is the load-bearing part. A docblock @example on the schema is the doorway an authoring agent copies from — so the trap is not merely possible, it is demonstrated to the author by the contract itself. It will keep being minted until this is fixed.
⛔ NOT verified by the seat — establish it before acting
The dev reports that "both t() implementations walk the key segment by segment, so a dotted id is unreachable". The seat did not confirm this. It looked in packages/spec/src/system/i18n-resolver.ts and found the only split('.') there (:3263) is a schema-title helper, unrelated to translation lookup — so the t() implementations are elsewhere and were not located.
⇒ ⛔ Do not treat the unreachability mechanism as measured. Find both t() implementations, show what a dotted id does at each, and say whether the two agree — if one resolves it and the other does not, that is a bigger finding than this card describes.
Corroboration already in the tree
packages/plugins/plugin-audit/src/translations/messages.ts:3-10 is reported to document this rule privately, for its own bundle — i.e. a team already hit it and wrote themselves a local note instead of the rule reaching the contract. Worth reading as evidence of the class, ⛔ not as a second measurement.
Suggested shape (⛔ a proposal, not a prescription)
Two independent halves; ⛔ do not assume one implies the other:
- Fix the doorway — the two
@example blocks must stop demonstrating an id that cannot resolve. This is cheap and is the half that stops new instances.
- Decide whether the door should refuse — a single-segment constraint on
messages keys would make the trap unauthorable rather than merely undocumented. ⚠️ That narrows an accept set on a published schema ⇒ it is a Clause-②: yes shape and owes the contract-review path; it is ⛔ not a drive-by addition to the docs fix.
Acceptance
- The
t() behaviour is measured at both implementations, with a firing control (an id that does resolve).
- The
@example blocks teach only ids that resolve, verified by running one through the real lookup rather than by eye.
- If the schema is narrowed, that rides its own card with a Clause-② declaration — ⛔ not folded into the example fix.
Dedupe words
messages dotted key · translation message id segment · resolveKey dot walk · TranslationItemSchema example · single-segment message id
Generated by Claude Code
Surfaced by #17768's dev as a class-(c)
out_of_scope_findingsentry; thedomain:devxseat verified two of its three legs and names the third as unverified. ⛔ Unlabelled fordomain:*and ungraded — routing and grading are triage's. ⛔ The filer did not dedupe; dedupe words at the bottom.Class (c) — authorable metadata that the runtime silently drops
A
messagesid containing a dot is writable, schema-valid, and resolves to nothing. Nothing refuses it at either door.Verified by the seat
1 —
messagesis a FLAT record, so a dotted id is a key that merely contains a dot, ⛔ not a path:2 — the spec's own docblock⚠️ the dev reported one site; there are two:
@exampleteaches the trap, and it does so TWICE —⭐ That is the load-bearing part. A docblock
@exampleon the schema is the doorway an authoring agent copies from — so the trap is not merely possible, it is demonstrated to the author by the contract itself. It will keep being minted until this is fixed.⛔ NOT verified by the seat — establish it before acting
The dev reports that "both
t()implementations walk the key segment by segment, so a dotted id is unreachable". The seat did not confirm this. It looked inpackages/spec/src/system/i18n-resolver.tsand found the onlysplit('.')there (:3263) is a schema-title helper, unrelated to translation lookup — so thet()implementations are elsewhere and were not located.⇒ ⛔ Do not treat the unreachability mechanism as measured. Find both
t()implementations, show what a dotted id does at each, and say whether the two agree — if one resolves it and the other does not, that is a bigger finding than this card describes.Corroboration already in the tree
packages/plugins/plugin-audit/src/translations/messages.ts:3-10is reported to document this rule privately, for its own bundle — i.e. a team already hit it and wrote themselves a local note instead of the rule reaching the contract. Worth reading as evidence of the class, ⛔ not as a second measurement.Suggested shape (⛔ a proposal, not a prescription)
Two independent halves; ⛔ do not assume one implies the other:
@exampleblocks must stop demonstrating an id that cannot resolve. This is cheap and is the half that stops new instances.messageskeys would make the trap unauthorable rather than merely undocumented.Clause-②: yesshape and owes the contract-review path; it is ⛔ not a drive-by addition to the docs fix.Acceptance
t()behaviour is measured at both implementations, with a firing control (an id that does resolve).@exampleblocks teach only ids that resolve, verified by running one through the real lookup rather than by eye.Dedupe words
messages dotted key·translation message id segment·resolveKey dot walk·TranslationItemSchema example·single-segment message idGenerated by Claude Code