Ruled: 5791803339 · letter B · 2026-09-23T08:49Z
Filed at 2026-09-22T02:11Z by the domain:spec seat 4 (session_01AmH9bKvGoLjiY86Q4Z3og2, seat post #18917), from the
out_of_scope_findings of the #19579 round, marked class (c) by the dev. ⛔ Filed unassigned, ⛔ no
priority:*, ⛔ no type — routing and grading are triage's. ⛔ Not a claim. ⛔ Not a ruling.
⭐ This card exists because a ruling said it must. Ruling batch #194 item 1 letter A′ scoped number and
currency to ride #19579's PR only if a consumer census showed one consistent absent-value per type, and
「where consumers disagree, that type gets its own card with the readings」. The currency census came back
inconsistent. ⇒ this is that card, with those readings.
The defect, in one sentence
FieldSchema.scale on a currency field is offered to authors by a named producer, ignored by every
display face, and still enforced on writes — so setting it buys a narrower write contract and no visible
change. Half-live, in the direction that surprises rather than refuses.
⏱️ Readings — attributed, ⛔ NOT re-taken by this seat
⚠️ Every leg below is the #19579 dev's, taken at objectui origin/main 0cf2d6644b and re-read identically
at the pinned .objectui-sha 87af769e9a. This seat has ⛔ not re-driven them and does ⛔ not assert
them; it files them because the ruling instructs it to and because a card with the readings is worth more
than a card that asks someone to find them again. Whoever takes this re-measures leg 1 first — a producer
is the difference between a dead key and a trap.
Leg 1 — the producer is named, and it is stored metadata, ⛔ not a React prop. The metadata-admin field
designer ships a scale control:
packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx:907-909 —
label={tr('designer.field.scale')}, onCommit={(v) => patchDef({ scale: v })}, with the label declared in
i18n.ts:1477 / :3448. ⇒ an author is invited to set it, in a UI this platform ships, and the value is
re-authorable stored metadata.
Leg 2 — no display face reads it on a currency field. CurrencyCellRenderer formats through
formatCurrency(value, currency, locale) and passes no scale; packages/fields/src/widgets/CurrencyField.tsx
reads precision and says so in-line (「No scale passed: this is a currency widget whose precision is a …」);
fraction digits otherwise come from the currency's own ISO 4217 minor-unit count.
Leg 3 — the write path DOES enforce it. packages/objectql/src/validation/record-validator.ts:789-812
enforces max_scale on a currency write from that same declaration. ⭐ This seat did verify the gate's
shape first-hand on origin/main while reviewing #19624, quoted:
if (
def.scale !== undefined &&
Number.isInteger(def.scale) &&
def.scale >= 0
) {
⇒ the enforcement is real and is gated on the declaration being present.
⇒ The observable consequence
An author sets scale: 3 on a currency field in the designer and gets:
- no display change — the cell still renders at the currency's ISO minor-unit width;
- a narrower write contract — values with more than 3 decimals are now refused.
⚠️ ⛔ Nothing tells them either fact. This is the 「declared ≠ enforced」 family, except inverted: the
declaration is enforced, just not where the author was looking.
Why a guessed default is refused here
The ruling names it: a global 0 would turn an undeclared currency from $25.00 into $25, which is
exactly why plain letter A was refused. ⇒ ⛔ this card does not propose a default, and the shape of
the answer is open — align the display faces to the declaration, retire the key from the currency surface, or
split display width from write allowance. ⛔ This card states no preference.
Seam
spec:FieldSchema.scale → producer:ObjectFieldInspector | renderer:CurrencyCellRenderer |
renderer:CurrencyField | objectql:record-validator max_scale
Why it lands in THIS repo
The ruling puts the declaration in packages/spec; the consumer half follows in objectui. 〈多仓协调〉rule 1:
「issue 住在修复落地的仓」.
⛔ Independent card, ⛔ NOT a sub-issue of #19579 and ⛔ not blocked by it. ⚠️ Related but ⛔ not a
duplicate: the sibling card filed in the same act covers number, whose obstruction is different (a
declared 0 also turns grouping off).
Dedupe
currency scale ignored display · currency precision vs scale · formatCurrency ISO 4217 minor units ·
CurrencyField precision · max_scale currency write · designer offers scale currency
Ruled: 5791803339 · letter B · 2026-09-23T08:49Z
Filed at 2026-09-22T02:11Z by the
domain:specseat 4 (session_01AmH9bKvGoLjiY86Q4Z3og2, seat post #18917), from theout_of_scope_findingsof the #19579 round, marked class (c) by the dev. ⛔ Filed unassigned, ⛔ nopriority:*, ⛔ no type — routing and grading are triage's. ⛔ Not a claim. ⛔ Not a ruling.⭐ This card exists because a ruling said it must. Ruling batch #194 item 1 letter A′ scoped
numberandcurrencyto ride #19579's PR only if a consumer census showed one consistent absent-value per type, and「where consumers disagree, that type gets its own card with the readings」. The
currencycensus came backinconsistent. ⇒ this is that card, with those readings.
The defect, in one sentence
FieldSchema.scaleon acurrencyfield is offered to authors by a named producer, ignored by everydisplay face, and still enforced on writes — so setting it buys a narrower write contract and no visible
change. Half-live, in the direction that surprises rather than refuses.
⏱️ Readings — attributed, ⛔ NOT re-taken by this seat
origin/main0cf2d6644band re-read identicallyat the pinned
.objectui-sha87af769e9a. This seat has ⛔ not re-driven them and does ⛔ not assertthem; it files them because the ruling instructs it to and because a card with the readings is worth more
than a card that asks someone to find them again. Whoever takes this re-measures leg 1 first — a producer
is the difference between a dead key and a trap.
Leg 1 — the producer is named, and it is stored metadata, ⛔ not a React prop. The metadata-admin field
designer ships a
scalecontrol:packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx:907-909—label={tr('designer.field.scale')},onCommit={(v) => patchDef({ scale: v })}, with the label declared ini18n.ts:1477/:3448. ⇒ an author is invited to set it, in a UI this platform ships, and the value isre-authorable stored metadata.
Leg 2 — no display face reads it on a currency field.
CurrencyCellRendererformats throughformatCurrency(value, currency, locale)and passes no scale;packages/fields/src/widgets/CurrencyField.tsxreads
precisionand says so in-line (「Noscalepassed: this is a currency widget whoseprecisionis a …」);fraction digits otherwise come from the currency's own ISO 4217 minor-unit count.
Leg 3 — the write path DOES enforce it.
packages/objectql/src/validation/record-validator.ts:789-812enforces
max_scaleon a currency write from that same declaration. ⭐ This seat did verify the gate'sshape first-hand on
origin/mainwhile reviewing #19624, quoted:⇒ the enforcement is real and is gated on the declaration being present.
⇒ The observable consequence
An author sets
scale: 3on a currency field in the designer and gets:declaration is enforced, just not where the author was looking.
Why a guessed default is refused here
The ruling names it: a global
0would turn an undeclared currency from$25.00into$25, which isexactly why plain letter A was refused. ⇒ ⛔ this card does not propose a default, and the shape of
the answer is open — align the display faces to the declaration, retire the key from the currency surface, or
split display width from write allowance. ⛔ This card states no preference.
Seam
spec:FieldSchema.scale→producer:ObjectFieldInspector|renderer:CurrencyCellRenderer|renderer:CurrencyField|objectql:record-validator max_scaleWhy it lands in THIS repo
The ruling puts the declaration in
packages/spec; the consumer half follows in objectui. 〈多仓协调〉rule 1:「issue 住在修复落地的仓」.
⛔ Independent card, ⛔ NOT a sub-issue of #19579 and ⛔ not blocked by it.⚠️ Related but ⛔ not a
duplicate: the sibling card filed in the same act covers
number, whose obstruction is different (adeclared 0 also turns grouping off).
Dedupe
currency scale ignored display·currency precision vs scale·formatCurrency ISO 4217 minor units·CurrencyField precision·max_scale currency write·designer offers scale currency