Skip to content

ADR-007-F: Three-Layer IRAP Architecture (AWS + Go Proxy + Elixir)

Status: Accepted Date: 2026-04-16 Decision Makers: Gautham Chellappa Depends on: ADR-001-F (Elixir), ADR-006-F (Hexagonal ports) Related: ADR-0010 (AU data residency for AI — inherited)

Context

Finnest must serve defence clients at OFFICIAL:Sensitive (architected for PROTECTED). The Australian Government Information Security Manual (ISM) provides a recommended list of memory-safe languages. BEAM is not explicitly listed. This is a SHOULD, not a MUST, but creates assessor friction.

The decision: redesign Finnest in an ISM-listed language (months of rework, loses BEAM concurrency), negotiate BEAM acceptance directly (possible but slow and risky), or put an ISM-listed boundary language in front of the Elixir app so the assessor's primary scrutiny focuses on 500 lines of Go rather than 150K+ LOC of Elixir.

Decision

Three-layer deployment for IRAP:

LAYER 1: AWS infrastructure (ap-southeast-2, IRAP-assessed)
  Dedicated VPC, Multi-AZ RDS, S3 Object Lock, CloudHSM,
  CloudWatch, CloudTrail, GuardDuty, Security Hub, WAF.
  No peering to commercial; no internet egress except allowlist.

LAYER 2: Security Boundary (Go proxy, ~500 LOC, ISM-listed language)
  TLS termination (FIPS cipher suites), request validation,
  auth verification (JWT + MFA + FIDO2), classification header injection,
  audit logging, rate limiting, W3C traceparent propagation, response filtering.
  NO business logic. NO database access. NO state.

LAYER 3: Application (Finnest Elixir, same codebase as commercial)
  config/runtime.exs branches to :irap — Bedrock Sydney only,
  15-min sessions, FIDO2 mandatory, IP allowlist, restricted integrations,
  Microsoft Entra SSO only.

One codebase, dual deployment. The commercial and IRAP deployments run the same Elixir release; behaviour branches on FINNEST_ENV=commercial vs FINNEST_ENV=irap in config/runtime.exs (AR-19).

Sixteen IRAP-specific guardrails (IR-01 through IR-16) enforce the restrictions — see ../10-GUARDRAILS.md §12.

Full architecture detail in ../architecture/irap.md.

Alternatives Considered

Alternative Rejected because
Rewrite Finnest in Go or Rust for IRAP Loses BEAM concurrency + supervision + hot reload; 6+ months of rework; different codebase for commercial vs IRAP violates single-codebase principle
Negotiate BEAM acceptance directly with assessor Possible but slow and risky; assessor-dependent; if rejected late, months of remediation
Put Elixir at the boundary, no proxy Assessor scrutiny lands on 150K+ LOC of Elixir + BEAM VM; BEAM not ISM-listed is a blocker
Node.js or Python boundary proxy Neither is ISM-listed at the boundary role; defeats the purpose
Rust boundary proxy More complex than needed for 500 LOC of request-handling; Go is simpler, well-audited HTTP server ecosystem

See ../brainstorms/brainstorm-06-irap-strategy.md for full analysis.

Consequences

Positive:

  • Assessment surface minimised — AWS already assessed, Go proxy is ~500 LOC auditable in isolation, Elixir inherits the boundary
  • ISM-listed language (Go) at the security boundary satisfies the assessor regardless of application language behind
  • Pre-assessment in Phase 0 validates the approach before committing to full build ($25K de-risks months of work)
  • Feature flags make the IRAP restrictions config, not code fork (AR-19)
  • Commercial benefits from IRAP-driven hardening (audit, encryption, access control)

Negative:

  • Extra hop adds ~5ms latency
  • Go proxy is an additional component to monitor, maintain, and version
  • Team must maintain two deployment pipelines (commercial + IRAP CI/CD separate per IR-12)
  • Need Go expertise for proxy maintenance (minimal — 500 LOC is tractable)

Risk mitigations:

  • Pre-assessment meeting in Phase 0 Week 1-2 validates assessor acceptance before proxy development commits
  • Proxy code size capped by design — grows past 1000 LOC triggers review
  • Proxy has zero state, zero DB access, zero business logic — reduces blast radius if compromised
  • W3C traceparent propagation keeps observability continuous across proxy (Part 7 decision)

Tipping points for re-evaluation:

  • ISM adds BEAM to the listed languages — proxy becomes optional (keep for defense-in-depth or remove for simplicity)
  • IRAP program fundamentally changes (e.g. post-quantum mandates) — re-architect per new requirements

Relationship to Guardrails

Enforces: IR-01 through IR-16 (16 IRAP-specific guardrails), AR-19 (IRAP as config variant), ADR-0010 (AU data residency for AI — inherited).