Status
Maintainer decision (2026-08-13): scheduled for v18.
Context
Surfaced while scoping a solution for an overseas port/terminal customer (2026-08): billing / reconciliation / invoicing must run in multiple currencies, with consolidated reporting in one home currency.
What the platform has today
currency field type with currencyConfig — currencyMode: 'dynamic' (per-record currency) or 'fixed', defaultCurrency, precision (packages/spec/src/data/field.zod.ts).- ISO 4217 fraction-digit consistency validation at publish time (
packages/spec/src/data/currency-fraction-digits.ts — JPY 0, KWD 3, CLDR 48.0 snapshot). - Tenant default currency in Localization settings (
packages/services/service-settings/src/manifests/localization.manifest.ts, valueDomain: 'iso_4217_currency'). - Analytics currency labeling resolution chain (ADR-0053): measure
currency → field currencyConfig.defaultCurrency → ctx.currency (packages/services/service-analytics/src/analytics-service.ts).
What is missing
- No exchange-rate table / object, no dated-rate history.
- No conversion engine:
formula / summary roll-ups and analytics aggregations over a dynamic-currency field combine nominal values as if they were one currency — a sum across USD + EUR rows is numerically meaningless. - No "record currency + home-currency shadow amount" projection (Salesforce ACM-style) for consolidated reporting.
Grep evidence: exchange rate / fx_rate / currency_conversion have zero implementation hits under packages/. The one prose mention ("Money with exchange rates", content/docs/protocol/objectql/index.mdx) does not match the shipped field.zod.ts behavior and reads as a doc leftover.
Possible scope sketch (for discussion)
- M1 —
sys_exchange_rate platform object (base currency, quote currency, rate, effective date) + settings for the org home currency (already exists in Localization). - M2 — CEL stdlib conversion function(s) (e.g.
convertCurrency(amount, from, to, date?)) usable in formula fields. - M3 — opt-in converted projection for
summary roll-ups and analytics measures over dynamic currency fields (aggregate in home currency; keep per-currency breakdown available). - Guard rails: refuse (or warn on) cross-currency
sum/avg over a dynamic currency field when no conversion is configured — today it fails silently into wrong numbers.
Workaround today
App-level customization: model an exchange-rate object, snapshot the rate onto each billing record via hook, and compute home-currency amounts with formula. Works, but every implementation reinvents it and the naive-aggregation foot-gun above remains for anyone who doesn't.
Status
Maintainer decision (2026-08-13): scheduled for v18.
Context
Surfaced while scoping a solution for an overseas port/terminal customer (2026-08): billing / reconciliation / invoicing must run in multiple currencies, with consolidated reporting in one home currency.
What the platform has today
currencyfield type withcurrencyConfig—currencyMode: 'dynamic'(per-record currency) or'fixed',defaultCurrency,precision(packages/spec/src/data/field.zod.ts).packages/spec/src/data/currency-fraction-digits.ts— JPY 0, KWD 3, CLDR 48.0 snapshot).packages/services/service-settings/src/manifests/localization.manifest.ts,valueDomain: 'iso_4217_currency').currency→ fieldcurrencyConfig.defaultCurrency→ctx.currency(packages/services/service-analytics/src/analytics-service.ts).What is missing
formula/summaryroll-ups and analytics aggregations over adynamic-currency field combine nominal values as if they were one currency — asumacross USD + EUR rows is numerically meaningless.Grep evidence:
exchange rate/fx_rate/currency_conversionhave zero implementation hits underpackages/. The one prose mention ("Money with exchange rates",content/docs/protocol/objectql/index.mdx) does not match the shippedfield.zod.tsbehavior and reads as a doc leftover.Possible scope sketch (for discussion)
sys_exchange_rateplatform object (base currency, quote currency, rate, effective date) + settings for the org home currency (already exists in Localization).convertCurrency(amount, from, to, date?)) usable informulafields.summaryroll-ups and analytics measures overdynamiccurrency fields (aggregate in home currency; keep per-currency breakdown available).sum/avgover adynamiccurrency field when no conversion is configured — today it fails silently into wrong numbers.Workaround today
App-level customization: model an exchange-rate object, snapshot the rate onto each billing record via hook, and compute home-currency amounts with
formula. Works, but every implementation reinvents it and the naive-aggregation foot-gun above remains for anyone who doesn't.