Release summaries
billingos-data-fetching-admission-gate
Add the BillingOS pre-engine admission gate (submitBillingMutation) — the single safe caller of the data-fetching engine's mutate(), fail-closed for every approval-gated and unknown BillingActionKind — and make InvoiceWorkspace QueryState-aware via the design-system DataViewList plus a pending-approval affordance.
maintainer
module.billing-os gains a submitBillingMutation admission gate (the only permitted engine.mutate caller) plus isEngineEligibleBillingAction and ENGINE_ELIGIBLE_BILLING_ACTION_KINDS, exported from the root and a new ./lib/submit-billing-mutation subpath, with types BillingMutationEngine, SubmitBillingMutationOutcome, and SubmitBillingMutationRequest. The gate is fail-closed: only read/draft_quote/draft_invoice reach the engine (optimistic + offline queue + auto-replay); all 11 approval-gated kinds and any unknown/future kind route to composeBillingOsCompanyOsReview with no optimistic write. New deps @lssm-tech/lib.contracts-runtime-core and @lssm-tech/lib.contracts-spec are used for engine/protocol types only — the pure billing libs gain no data-fetching dependency.
integrator
All changes are additive — existing imports resolve unchanged. To drive BillingOS mutations through the engine, call submitBillingMutation(request, engine) instead of engine.mutate directly; approval-gated actions return a pending_approval outcome (no optimistic write) routed to the operator inbox. InvoiceWorkspace accepts two new optional props: queryState (canonical QueryState; renders loading/error/offline/ stale/conflict/empty/auth-expired via the design-system DataViewList) and pendingApproval (a pending-approval affordance). The component remains I/O-free.
i18n-readiness-billing-formatting
Make BillingOS money/number formatting locale-correct at every call site by removing the silent en-US fallback from formatCurrency and requiring a locale on PaymentCard.
integrator
formatCurrency(amount, currency, locale) now requires locale (no en-US default), and the PaymentCard organism requires a locale prop. Pass the active locale from useI18n() or the host i18n context at every call site.
customer
Invoices, quotes, and payment amounts now render with locale-correct currency, grouping, and symbol placement (for example 1 234,56 € in French instead of en-US formatting).
monorepo-i18n-readiness
Make the monorepo i18n-ready. Each in-scope package now ships a public `./i18n` subpath with `createI18nFactory`-backed en/fr/es catalogs (real translations), consumed in React via `@lssm-tech/lib.design-system`'s `useI18n`/`LocaleProvider`. No public API removals; every change is additive. Blocking CI gates (hardcoded-string scan, en/fr/es parity, JSX-text/attribute Grit rules, no module-scope translation calls) enforce the contract repo-wide via a shrinking `unmigratedPackages` allowlist.
maintainer
Every migrated package gains a public `./i18n` subpath exporting `create<Pkg>I18n(locale?)`, `getDefault<Pkg>I18n()`, `reset<Pkg>I18nRegistry()`, a `<Pkg>MessageKey` type, and `<PKG>_I18N_KEYS` / `<PKG>_I18N_KEY_LIST`, backed by `defineTranslation` specs keyed `<pkg>.messages` with en/fr/es real translations. The canonical pattern is `createI18nFactory` from `@lssm-tech/lib.contracts-spec/translations` consumed in React via `useI18n` from `@lssm-tech/lib.design-system/i18n` (the app/bundle root mounts one `LocaleProvider` per render tree; modules and libs never mount it). M1 exception: libs that design-system depends on (presentation-runtime-react, contracts-runtime-client-react) resolve via their own factory inside the component to avoid a build cycle. The deprecated `@lssm-tech/lib.translation-runtime` is retained only for ICU/override/SSR edge cases. CI gates: `bun run i18n:ci` aggregates `lint:i18n` (no module-scope translation calls), `i18n:check-hardcoded` (DocBlock-aware scanner, shrinking `unmigratedPackages` allowlist with non-growth guard), and `i18n:check` (en/fr/es parity); Grit plugins enforce typography-wrapped JSX text and ban hardcoded `aria-label`/`placeholder`/`title`/`alt` literals.
integrator
All changes are additive — existing imports resolve unchanged. To consume translations from a migrated package in React, import `useI18n` from `@lssm-tech/lib.design-system/i18n` and call `t('<pkg-namespace>.<area>.<element>')`; the host app must mount a `<LocaleProvider>` once at the root with a `createRuntime` that aggregates the catalogs of every rendered package (see `LocaleProviderAdapter` in `apps/web-application-monolith` and `MobileI18nProvider` in `apps/mobile-monolith` for the verbatim pattern). For non-React emit (notification templates, surfaced error descriptions), call `create<Pkg>I18n(locale).t(...)` directly, threading `locale` from the caller. `data-exchange-client` now depends on `@lssm-tech/lib.design-system` at runtime (web + native both consume `useI18n`). `presentation-runtime-react`'s `WorkflowStepRenderer` accepts an optional `locale?` prop. ui-kit and examples packages remain string-agnostic (out of scope).
