Skip to content

8. Crosscutting Concerns

Concerns that touch every domain. Each is implemented once; every domain inherits the behaviour.

Authentication

Mechanism: phx.gen.auth scaffold with Argon2 password hashing + TOTP MFA. FIDO2 WebAuthn for IRAP deployment.

Where: finnest_core + finnest_web session stack.

Status: Implementation in flight (Sprint 2, STORY-F-006).

Multi-tenant isolation

Mechanism: org_id foreign key on every tenant-scoped row. Enforced by:

  1. Finnest.Repo.prepare_query/3 — every query is rewritten to inject WHERE org_id = ? from the current process dictionary.
  2. Finnest.Tenant plug — HTTP request pipeline sets the org context before any Repo call.
  3. Agent process isolation — agents are never reused across tenants; each agent GenServer is bound to an org_id at spawn.

Status: STORY-F-008 in Sprint 2.

Event store & audit

Mechanism: Append-only Postgres table, trigger-enforced immutability, SHA-256 hash-chained per-org. Doubles as the IRAP audit trail.

Retention: 7 years (Fair Work + tax law).

Where: finnest_core — one table, many writers, per-domain readers.

Status: STORY-F-016 in Sprint 4.

Compliance gate

Mechanism: Compliance.check/2 is the sole synchronous cross-domain call. Invoked before writes in roster, timekeep, payroll, clients, assets. Returns :ok | {:error, reasons} — callers refuse the write on error.

Ratified: ADR-011-F.

Observability

Mechanism: OpenTelemetry traces + correlation IDs propagated via Logger.metadata/1 and Phoenix request context. Sentry for error aggregation. Structured logs in JSON.

Origin: D19 architectural driver — "if you can't see it, you can't maintain it."

Accessibility

Mechanism: WCAG 2.1 AA as hard requirement. DaisyUI primitives (when STORY-F-017 lands), semantic HTML, ≥44 px touch targets, keyboard-only navigation supported everywhere.

Origin: D18 architectural driver + Commonwealth procurement requirements.

Internationalisation

Out of scope for v1. Australian English only. Structure-ready via Phoenix gettext should a second market open.

Financial precision

Mechanism: ex_money + DECIMAL(12,4) columns. No floats in any pay, billing, margin, or award calculation.

Origin: D17 architectural driver; violations are a 42-Commandments non-starter.

Security headers

Mechanism: put_secure_browser_headers on every Phoenix pipeline. Applied automatically during Sprint 1 (STORY-F-004).

AI budget guard

Mechanism: BudgetGuard GenServer in finnest_agents — per-org token and dollar ceiling, circuit-breaker when exceeded. Hard-stops the agent swarm before it can run up a bill.

Status: STORY-F-012 in Sprint 3.

Origin: D5 architectural driver — "70 %+ of queries handled at $0; per-org budget circuit-breaker."