liberusoftware/currency-context
A Laravel package for managing currency context across your application. Detect and set the active currency per request, user, or session, then resolve it consistently for pricing, formatting, and conversion so monetary values display correctly everywhere.
Architecture fit. The package is a Laravel "module" (repo name module-currency-context), which almost always implies an opinionated host: a module loader, a service-provider contract, possibly a directory convention (Modules/CurrencyContext/...). That is the first architectural question a TPM must resolve, because it determines whether this is a drop-in library or a dependency on someone else's monolith scaffold. The functional scope described — ISO 4217 metadata, precise money values, currency roles (base/display/settlement/reporting), locale formatting, and effective-dated FX contracts — is a coherent bounded context, not a grab bag. The "context" framing (an ambient current-currency per request/tenant/user) is the differentiator versus moneyphp/money, which is deliberately context-free. The trade-off is symmetry: context objects are typically container-scoped singletons, which is exactly the pattern that leaks across requests under Octane/Swoole and bleeds into queued jobs and console commands. A TPM should require an explicit answer on how context is set, scoped, and reset before this touches a checkout path.
Integration feasibility. Low-to-moderate effort in greenfield, high in brownfield. Greenfield: composer require, auto-discovery, publish config/migrations, seed ISO data, done in a day. Brownfield: existing schema almost certainly stores amounts as decimal/float with a currency string column and computes conversions ad hoc — retrofitting means either dual-writing or accepting a read-path adapter, and historical rows must not be recomputed (an invoice's rate and timestamp are facts, not derived state). The package will also collide conceptually with whatever money abstraction already exists; expect name clashes around Money, Currency, Converter and a period of two coexisting representations. The ISO dataset is a live liability, not a constant: currency redenominations and accessions (HRK→EUR, SLL→SLE, ZWG) mean any bundled metadata needs a versioned refresh path or you will silently format wrong.
Technical risk. The dominant risk is not code quality — it is adoption and provenance. Zero stars, zero dependents, zero external users means zero field-testing: no Stack Overflow corpus, no issue history to read as a defect map, no third party who has hit the Octane bug before you. That is a bus-factor-of-one situation. The listed last release of 2026-10-27 is future-dated relative to the present, which is a metadata anomaly worth verifying directly against the tag and commit history — it may be a scheduled/pre-release tag, a fabricated datapoint in the scoring pipeline, or a clock issue. Treat the score (19.89) and opportunity (44.88) as "interesting domain, unproven artifact." MIT is permissive and removes legal friction; it does not remove the maintenance obligation, it merely grants you the right to assume it.
Key questions.
moneyphp/money / brick/money, or reimplement minor-unit arithmetic? Integer minor units + BCMath is table stakes; floats are disqualifying.Stack fit. Presumed Laravel (auto-discovered provider) with PHP 8.1+. The critical compatibility checks are: (1) the module loader dependency — if it requires liberusoftware's own module framework, the real cost is adopting that framework; (2) Laravel major-version constraint, since an unmaintained package pinned to L10 blocks an L12 upgrade; (3) Octane compatibility. If it is storage-agnostic and provider-light, fit is good. If it drags in a scaffold, evaluate it as a framework decision, not a package decision.
Migration path. Do not let the package's types become your domain's public API. Insert your own thin interfaces — CurrencyConverter, RateProvider, MoneyFormatter, CurrencyContext — and implement them with the package. This costs a day and buys you the ability to swap to moneyphp/money + a bespoke rate table without touching call sites. Then: introduce alongside existing columns rather than replacing them; backfill with a reversible migration; dual-write during a shadow period; compare outputs in logs; cut reads over per-bounded-context. Freeze historical rows — store amount_minor, currency_code, rate, rate_effective_at, rate_source on the transaction and never re-derive them. The FX source is the real coupling: you need an ingestion job, a staleness policy, and an audit trail of which rate was used on which document, independent of whatever the package ships.
Compatibility. Coexistence with an existing money library is feasible via adapters but will be confusing for the team for a quarter — pick one representation per layer and document it. Watch for Money/Currency class-name collisions under the same namespace root. Verify the bundled ISO metadata vintage against the current ISO 4217 amendment list, and confirm there is a mechanism to override or refresh the dataset without forking.
Sequencing. (1) Two-day spike in a scratch branch: prove precision, rounding, allocation, and Octane context isolation. (2) Vendor-risk decision: adopt-as-is, adopt-and-fork under MIT with an internal maintainer named, or rebuild the 200 lines you actually need on top of moneyphp/money. (3) Pilot in one bounded context with the lowest blast radius — a reporting/display path, not checkout. (4) Harden: rate staleness alerts, missing-rate behavior, overlap constraints. (5) Expand to pricing/checkout only after a finance sign-off on rounding. Do not pilot on the payment path.
Maintenance. With zero dependents, you are the only production user and therefore the de facto maintainer. Assume fork-and-own from day one: mirror the repo internally, tag your own releases, and budget roughly one to two engineer-days per quarter for security patches, Laravel-version drift, and ISO 4217 updates. Pin the version exactly; do not use a floating constraint on a single-maintainer package. The MIT license makes this legitimate, but the TPM must make the ownership explicit in writing — "we depend on it" without a named internal owner is the failure mode.
Support. No community, no maintainer SLA, no issue-tracker history to mine. Your support story is internal: a runbook, a documented money-rules policy, and a decision log. Escalation is to your own team. If the upstream repo is abandoned, the cost is not zero but it is bounded — the domain surface (ISO tables, minor-unit math, date-ranged rates) is small enough to reimplement or fork.
Scaling. Rate tables grow unbounded over time; index on (base_currency, quote_currency, effective_from, effective_to) with an explicit exclusion/overlap guard, and cache hot pairs with a TTL tied to your staleness tolerance. Context resolution per request is cheap; formatting large collections is not — naive per-row rate lookups in a listing endpoint produce N+1 storms. Money arithmetic at scale is CPU-cheap but error-prone; the scaling risk is correctness at volume, not throughput.
Failure modes. Ranked by severity: (1) missing or stale rate on a transaction — decide fail-closed (block the transaction) versus fail-open (use last known, flag it), and encode that decision in code, not convention; (2) rounding drift accumulating across allocations and aggregates — mitigate with property-based tests asserting the parts sum to the whole; (3) overlapping or gapped effective-date ranges silently selecting the wrong contract, aggravated by UTC/local ambiguity; (4) Octane or queue context leakage — a job running with the previous request's currency; (5) silent ISO metadata staleness after a redenomination; (6) a composer update pulling an unreviewed change from a one-person upstream.
Ramp-up. The package is small, so mechanical ramp-up is hours. Domain ramp-up is the real cost: engineers reliably get minor units, rounding modes, allocation remainders, and FX direction wrong, and those errors surface as financial discrepancies rather than exceptions. Plan for a short internal briefing, a documented "money rules" decision record signed off by finance, and a test suite that encodes those rules as executable specs before the first pricing path ships. Expect two to three weeks from first spike to a trustworthy pilot, most of it spent on policy rather than code.
How can I help you explore Laravel packages today?