Skip to content

Architecture decisions

The backend records every significant design choice as a numbered Architecture Decision Record (ADR). This page is a map, not a replacement: it groups the records by theme and gives a one-line decision for each so you can find the right one fast. The records themselves are the source of truth and live in the backend repo under NexisOmni/docs/adr/ (files 0001-*.md through 0023-*.md).

Each file follows the same shape: a status line (Accepted, Proposed, or superseded-by), the date and decider, the context that forced a choice, the decision itself, and the alternatives rejected. A Status of “superseded by ADR-00xx” means part of that record has been overtaken - always follow the pointer forward to the current decision.

The database-per-tenant foundation, how tenants are placed and scaled, and how schema changes reach every tenant database.

ADR Title Decides
0001 Adaptive multi-vertical API model One API drives supermarket, bakery, cafe, and boutique terminals via a per-outlet BusinessType plus capability flags.
0012 Pragmatic layering Business services live in Infrastructure as concrete classes with a near-empty Application ring; EF Core is the unit of work (no MediatR, no per-service interfaces).
0013 Per-tenant module entitlements Whole modules are enabled or disabled per tenant from a central Tenant.Plan plus overrides, enforced by authorization policy, no tenant-DB migration needed.
0020 Tenant connection-pool bounds and manual-context audit A shared context provider stamps bounded connection pools on every tenant context and defines which admin paths are audited.
0021 Tenant migration fan-out runner An admin-plane runner applies pending migrations to every tenant database in-process; once a first production tenant exists, InitialCreate is frozen and changes become additive forward-only.
0022 Tenancy scaling strategy Per-tenant isolation tiers (dedicated vs shared schema-per-tenant), a connections-based capacity ceiling, multi-server placement, and a safe graduation path between tiers.

The two authentication planes, how tokens are signed and secrets protected, and the permission and account-lifecycle model.

ADR Title Decides
0014 Auth and secret hardening RS256 JWT signing keys with rotation, and tenant connection strings encrypted at rest in the central database.
0016 Enterprise security model Verb-based permissions resolved per request (never baked into the token), per-user branch scoping, an audit trail, lockout, and 2FA.
0017 Bounded role tiers and role management Three seeded roles - Owner (the only holder of the global.admin override), a bounded Manager, and Cashier - plus tenant-managed roles.
0018 Transactional email and email-2FA A swappable email transport (Resend) with a no-op fallback, enforced email confirmation on the tenant plane, enumeration-safe password reset, and email as an opt-in second factor.

The cash-drawer backbone, the offline-first sales layer, returns after settlement, and the read-only reporting layer.

ADR Title Decides
0002 Operations and cash Register, CashSession, and a typed CashMovement ledger - the accountable open-float-count-reconcile cash lifecycle, universal across all verticals.
0003 Sales and offline sync The Order / OrderLine / Payment aggregate with frozen price and stacked-levy tax snapshots, per-branch receipt numbers, and idempotent offline POS replay.
0008 Returns and refunds Single-shot post-settlement returns that refund pro-rata of the snapshotted sale and reverse money, stock, loyalty, and promotion effects, with a race-safe over-return guard.
0007 Reporting and analytics Read-only, computed-on-read reports over snapshotted figures, with a per-request IANA timezone parameter and Manager-gated financial reads.

How stock is costed, depleted, and moved between branches.

ADR Title Decides
0010 FIFO inventory costing and COGS Exact FIFO depletion via a per-consumption ledger that captures COGS on sale and reverses precisely on void or return.
0011 Inter-branch stock transfers A Draft-Dispatched-Received transfer lifecycle that moves the exact FIFO cost layers with the goods, preserving the on-hand invariant at both branches.

The inbound supply side that feeds inventory and costing.

ADR Title Decides
0009 Purchasing and goods receipt Supplier - Purchase Order - Goods Receipt, where a PO is intent and only a receipt moves stock, recording actual lot cost as the valuation basis.

Discounts and loyalty at the register, and the credit and installment model with its ceiling.

ADR Title Decides
0004 Credit (the Singer model) First-class Customer and CreditAccount with hire-purchase and layaway, flat financing interest, an installment schedule, and layaway stock reservation.
0005 Marketing - discounts, promotions, loyalty Manual discounts plus a rule-based promotion/coupon/BOGO engine and loyalty points and tiers, with a configurable, default discount-before-tax treatment.
0023 Owner-governed credit ceiling Moves the per-tenant credit ceiling to its own Owner-only CreditSettings, enforced at both grant time and lending time.

The wire contract both frontends generate from, and email decisions that span planes.

ADR Title Decides
0006 Post-roadmap feature roadmap (Phases 7-10) Sequences reporting, returns, purchasing, and stock transfers, fixing scope and dependencies for each.
0015 Frontend API contract Money and decimals are quoted JSON strings on the wire, the OpenAPI document declares the two bearer planes and the Tenant-ID header per operation, and sync acks carry the server receipt number and totals.
0018 Transactional email and email-2FA The platform email transport and the account-email lifecycle (also listed under Auth and security).
0019 Tenant customer email A backlogged plan for owner-configurable, business-branded customer email (transactional and marketing) - recorded but not yet built.

Most records are Accepted and implemented. A few carry pointers you should follow:

  • ADR-0016’s original single-role model is superseded by ADR-0017 (Owner / Manager / Cashier), and its authenticator-only 2FA by ADR-0018 (email confirmation and email-2FA).
  • ADR-0014’s “email deferred” item is superseded by ADR-0018.
  • ADR-0019 (tenant customer email) is Proposed and backlogged - a settled design, not built.

The canonical files are in the backend repo at NexisOmni/docs/adr/, one Markdown file per record, named by number and slug (for example NexisOmni/docs/adr/0014-auth-and-secret-hardening.md). For the broader backend orientation see the developer guide at NexisOmni/docs/developer-guide.md, and for how the contract binds the web and POS clients see the API contract.