Guardrails Reference — Finnest¶
Status: Active Date: 2026-04-16 Purpose: Authoritative enforcement reference for all Finnest project guardrails. Maps every rule to its philosophical principle from
42-COMMANDMENTS.md. Hierarchy:42-COMMANDMENTS.mdis the philosophy. This document is the enforcement matrix.CLAUDE.md(in each repo) is the operational checklist. Adapted from:AgenticAI-app/docs/architecture/10-GUARDRAILS.md(Laravel/PHP) — rewritten for Elixir/Phoenix backend and Flutter mobile.
Enforcement Tiers¶
| Tier | Symbol | Meaning |
|---|---|---|
| Automated (CI) | CI |
Enforced in GitHub Actions pipeline. Violations block merge. |
| Automated (Pre-commit) | PRE |
Enforced by local tooling before code reaches the repo. |
| Code Review | REV |
Required in PR review; human or Review Agent responsibility. |
| Advisory | ADV |
Documented best practice. Not enforced by tooling. |
1. Code Quality¶
1a. Elixir/Phoenix Backend (finnest repo)¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| CQ-01 | Code passes mix format --check-formatted |
CI + PRE |
Active | #5 Consistency |
| CQ-02 | All tests pass before merge (mix test) |
CI |
Active | #39 Full test suite |
| CQ-03 | Test-first development: failing test before implementation | REV |
Active | #9 Tests prove behaviour |
| CQ-04 | Unit + integration tests for every context function and LiveView | REV |
Active | #9 Tests prove behaviour |
| CQ-05 | Ecto preloads explicit (Repo.preload/2 or from ... preload:); no lazy loading |
REV |
Active | #1 Code is liability |
| CQ-06 | No SELECT *; specify schema fields explicitly in Ecto queries |
REV |
Active | #10 Surface area is a cost |
| CQ-07 | Input validation via Ecto.Changeset; never in controllers/LiveView directly | REV |
Active | #5 Consistency |
| CQ-08 | Conventional Commits format: type(scope): description |
REV |
Active | #5 Consistency |
| CQ-09 | Static analysis via Dialyzer (mix dialyzer) — zero warnings tolerated |
CI |
Active | #3 Understand every line |
| CQ-10 | ExUnit syntax; ExMachina factories for test data | REV |
Active | #5 Consistency |
| CQ-11 | Reversible migrations: all must implement down/0 (or be change/0 with reversible ops) |
REV |
Active | #36 Migrations reversible |
| CQ-12 | Indexes on columns used in WHERE, ORDER BY, JOIN clauses | REV |
Active | #16 Data models outlive everything |
| CQ-13 | Repo.transaction/1 for multi-table write operations |
REV |
Active | #12 One error philosophy |
| CQ-14 | Use Ecto.Repo.stream/2 for large datasets; never Repo.all on unbounded data |
REV |
Active | #1 Code is liability |
| CQ-15 | Idempotent Oban workers: safe to process more than once | REV |
Active | #38 Idempotent jobs |
| CQ-16 | No speculative abstractions: no behaviours/protocols until 2+ implementations | REV |
Active | #2 No speculative abstractions |
| CQ-17 | Constants over config: if a value doesn't change per environment, hardcode it | REV |
Active | #33 Constants over config |
| CQ-18 | Match gold-standard files: new modules must follow existing OTP app patterns | REV |
Active | #32 Gold-standard files |
| CQ-19 | Tests prove behaviour, not implementation: tests must survive internal refactoring | REV |
Active | #9 Tests prove behaviour |
| CQ-20 | Credo strict mode (mix credo --strict); zero design issues tolerated |
CI |
Active | #1 Code is liability |
| CQ-21 | No Process.sleep/1 in production code; use GenServer messages or Oban timers |
REV |
Active | #15 Prefer boring technology |
| CQ-22 | Pattern matching over conditionals where both are natural | ADV |
Active | #5 Consistency |
1b. Flutter Mobile (finnest-mobile repo)¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| CQM-01 | Code passes dart format --set-exit-if-changed |
CI + PRE |
Active | #5 Consistency |
| CQM-02 | All tests pass (flutter test unit + widget + flutter test integration_test/) |
CI |
Active | #39 Full test suite |
| CQM-03 | Test-first for BLoC and services | REV |
Active | #9 Tests prove behaviour |
| CQM-04 | Widget tests for all reusable widgets; integration tests for critical flows | REV |
Active | #9 Tests prove behaviour |
| CQM-05 | flutter analyze passes with zero warnings |
CI |
Active | #3 Understand every line |
| CQM-06 | Flutter build succeeds for both iOS and Android | CI |
Active | #39 Full test suite |
| CQM-07 | Null safety throughout (no ! null assertion on nullable values) |
REV |
Active | #1 Code is liability |
| CQM-08 | BLoC pattern consistent across features; no inline state management | REV |
Active | #5 Consistency |
| CQM-09 | Feature modules are self-contained (no cross-feature imports) | REV |
Active | #34 Isolate volatility |
| CQM-10 | Accessibility: WCAG AA, 44px touch targets, screen reader support | REV |
Active | — |
| CQM-11 | Golden tests for critical screens (update deliberately) | REV |
Active | #9 Tests prove behaviour |
| CQM-12 | Battery-conscious: careful with background location, polling intervals, FCM frequency | REV |
Active | — |
2. Architecture¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| AR-01 | No AWS service lock-in: Lambda, DynamoDB, SQS, SNS, Cognito, Aurora, ECS, Fargate excluded. Bedrock permitted via hexagonal AI provider adapter | REV |
Active | #30 No vendor lock-in |
| AR-02 | No Cloudflare lock-in: Workers, KV, D1, Durable Objects excluded | REV |
Active | #30 No vendor lock-in |
| AR-03 | OTP app structure: each domain is its own OTP application under apps/{finnest_domain}/ |
REV |
Active | #34 Isolate volatility |
| AR-04 | Cloud services accessed only through hexagonal ports (behaviours) | REV |
Active | #30 No vendor lock-in |
| AR-05 | External DB connections (admin_central, admin_atslive during migration) are read-only | REV |
Active | #28 External data read-only |
| AR-06 | Supervised Modular Monolith retained; no premature extraction to microservices | ADV |
Active | #21 Build for your team |
| AR-07 | Cross-domain communication via events ONLY — no direct function calls between domain apps | CI + REV |
Active | #34 Isolate volatility |
| AR-08 | Domain boundary enforcement via Boundary library (or equivalent); violations block merge |
CI |
Active | #31 Boundaries by tooling |
| AR-09 | No JS frameworks (React, Vue, Svelte) on web; LiveView + DaisyUI + vanilla JS only | REV |
Active | #15 Prefer boring technology |
| AR-10 | Authentication via phx.gen.auth; external identity only through SSO integration (OAuth) |
REV |
Active | #15 Prefer boring technology |
| AR-11 | Job queue: Oban (PostgreSQL-backed), not SQS or Cloud Tasks | REV |
Active | #30 No vendor lock-in |
| AR-12 | File storage via hexagonal FileStorage behaviour; S3 default, swappable via config |
REV |
Active | #13 Exit path |
| AR-13 | Standard PostgreSQL 17; no vendor-specific extensions beyond standard contrib | REV |
Active | #15 Prefer boring technology |
| AR-14 | AI inference uses Australian-region endpoints only (Bedrock ap-southeast-2 / Vertex australia-southeast1) | REV |
Active | #23 PII classification |
| AR-15 | AI providers accessed only through AiProvider behaviour; no direct Claude SDK calls in domain code |
REV |
Active | #30 No vendor lock-in |
| AR-16 | MCP at every domain boundary for agent tool access | REV |
Active | #34 Isolate volatility |
| AR-17 | Event store is append-only: UPDATE/DELETE forbidden at DB trigger level | CI + REV |
Active | #36 Migrations reversible |
| AR-18 | Compliance auto-blocking: Compliance.check/2 called synchronously before roster/timekeep/payroll writes |
REV |
Active | #27 Never disable security defaults |
| AR-19 | IRAP deployment is a config variant, not a code fork | REV |
Active | #30 No vendor lock-in |
3. Security¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| SE-01 | CSRF protection enabled (Phoenix :protect_from_forgery plug); never disable |
REV |
Active | #27 Never disable security defaults |
| SE-02 | HEEx templates escape by default; raw/1 forbidden on user content |
REV |
Active | #27 Never disable security defaults |
| SE-03 | Server-side validation via Ecto.Changeset required; client-side is UX only | REV |
Active | #27 Never disable security defaults |
| SE-04 | Security headers via Phoenix :put_secure_browser_headers + CSP: HSTS, X-Content-Type-Options, X-Frame-Options, CSP |
REV |
Active | #27 Never disable security defaults |
| SE-05 | Rate limiting on all public endpoints (Hammer library or equivalent) | REV |
Active | #25 Rate limit public endpoints |
| SE-06 | config :logger, level: :info in production; no :debug |
REV |
Active | #26 Secrets never in code |
| SE-07 | Environment secrets via System.get_env + runtime.exs; never hardcoded | REV |
Active | #26 Secrets never in code |
| SE-08 | Use Plug.Crypto, Argon2, Comeonin for crypto; never roll custom |
REV |
Active | #15 Prefer boring technology |
| SE-09 | CORS configured explicitly in Phoenix endpoint for API routes | REV |
Active | #10 Surface area is a cost |
| SE-10 | No stack traces, debug info, or runtime config exposed in production | REV |
Active | #26 Secrets never in code |
| SE-11 | Dependency vulnerability scanning: mix deps.audit + mix sobelow in CI |
CI |
Active | #14 Dependencies age |
| SE-12 | Secret scanning: gitleaks pre-commit + CI | PRE + CI |
Active | #26 Secrets never in code |
| SE-13 | PII handling: data classification tiers (Restricted/Sensitive/Internal/Public) | REV |
Active | #23 PII classification |
| SE-14 | Non-root user in Docker containers (app user) |
REV |
Active | #27 Never disable security defaults |
| SE-15 | PostgreSQL TLS required in production (ssl: true) |
REV |
Active | #26 Secrets never in code |
| SE-16 | Supply chain: exact version pinning in mix.lock, Renovate soak, harden-runner on CI |
CI + REV |
Active | #14 Dependencies age |
| SE-17 | Mobile: no hardcoded secrets in APK/IPA; use flutter_dotenv + CI-injected secrets | REV |
Active | #26 Secrets never in code |
| SE-18 | Mobile: biometric unlock for stored JWT tokens | REV |
Active | #27 Never disable security defaults |
| SE-19 | IRAP: FIDO2 MFA mandatory, 15-min session timeout, IP allowlist | REV |
Active | #27 Never disable security defaults |
| SE-20 | IRAP: AES-256 at rest, TLS 1.2+ in transit, CloudHSM key management for PROTECTED | REV |
Active | #27 Never disable security defaults |
| SE-21 | Audit log is tamper-evident (hash chain on event sequence) | REV |
Active | #24 Log by ID, never PII |
4. Frontend — LiveView Web¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| FE-01 | HTML First: native HTML before CSS, CSS before JS hooks | REV |
Active | #35 Start simple (Gall's Law) |
| FE-02 | Progressive Enhancement: LiveView handles interactivity; JS hooks only when necessary | REV |
Active | #35 Start simple |
| FE-03 | DaisyUI components for all UI elements; no custom CSS without approval | REV |
Active | #5 Consistency |
| FE-04 | No dynamic Tailwind class construction; compiler must find complete strings | REV |
Active | #5 Consistency |
| FE-05 | Touch targets >= 44px on all interactive elements | REV |
Active | — |
| FE-06 | Contrast ratios: normal text >= 4.5:1, large text >= 3:1 (WCAG 2.2 AA) | REV |
Active | — |
| FE-07 | user-scalable=yes in viewport meta; never block zoom |
REV |
Active | — |
| FE-08 | Dark mode default; both themes via DaisyUI semantic colour tokens only | REV |
Active | #5 Consistency |
| FE-09 | Semantic HTML mandatory: <form novalidate>, <fieldset>, <legend>, ARIA |
REV |
Active | #15 Prefer boring technology |
| FE-10 | LiveView over JS hooks: use phx-click/phx-change over custom JS where possible |
REV |
Active | #35 Start simple |
| FE-11 | Alpine.js for local interactive state only; no global app state in Alpine | REV |
Active | #15 Prefer boring technology |
| FE-12 | Animate only transform, translate, opacity; motion-safe: prefix required |
REV |
Active | — |
| FE-13 | Playwright visual regression tests before committing visual changes | CI |
Active | #9 Tests prove behaviour |
| FE-14 | Alt text on every image; alt="" with role="presentation" for decorative |
REV |
Active | — |
| FE-15 | Command bar (Cmd+K) accessible on every page for power users | ADV |
Active | — |
| FE-16 | Three paths to every action: agent, notification, navigation | ADV |
Active | — |
5. Infrastructure & Deployment¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| IN-01 | Debian-based Elixir Docker images (not Alpine — musl causes issues with NIFs) | REV |
Active | #15 Prefer boring technology |
| IN-02 | Non-root user in containers | REV |
Active | #27 Never disable security defaults |
| IN-03 | Multi-stage Docker builds: build stage (with dev deps) + slim runtime | REV |
Active | #1 Code is liability |
| IN-04 | Elixir releases (mix release): compiled, self-contained, no deps at runtime |
REV |
Active | #30 No vendor lock-in |
| IN-05 | PostgreSQL slow query log enabled (log_min_duration_statement = 1000) |
REV |
Active | #18 Can't see it, can't maintain it |
| IN-06 | Production compile: MIX_ENV=prod mix compile --warnings-as-errors |
CI |
Active | — |
| IN-07 | mix deps.get --only prod and mix deps.clean --unused in production builds |
CI |
Active | #1 Code is liability |
| IN-08 | Health check endpoint at /health; automatic rollback on failure |
REV |
Active | #18 Can't see it, can't maintain it |
| IN-09 | Backups: daily automated, encrypted, with restore tests | ADV |
Active | #16 Data models outlive everything |
| IN-10 | BEAM tuning: +sbwt none +sbwtdcpu none for container environments |
ADV |
Active | — |
| IN-11 | Squash merges to main; delete feature branches after merge |
REV |
Active | #6 Delete before you add |
| IN-12 | Feature branches: feature/, fix/, chore/ naming; short-lived |
REV |
Active | #22 Ship smallest change |
| IN-13 | All CI checks pass before merge to main |
CI |
Active | #39 Full test suite |
| IN-14 | At least one human review required before merge | REV |
Active | #3 Understand every line |
| IN-15 | Database migration safety: reversible, non-destructive, human-reviewed | REV |
Active | #36 Migrations reversible |
| IN-16 | Monitoring and alerting thresholds defined (Telemetry + Prometheus or equivalent) | ADV |
Planned | #18 Can't see it, can't maintain it |
| IN-17 | IRAP deployment: separate CI/CD pipeline, two-person approval, security review gate | REV |
Active | #27 Never disable security defaults |
| IN-18 | Mobile: versioned app releases; rollout via staged Play/App Store releases | REV |
Active | #22 Ship smallest change |
6. Data & Database¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| DA-01 | External DB Ecto repos are read-only: priv: "priv/external_repo", no migrations |
REV |
Active | #28 External data read-only |
| DA-02 | External DB schemas: @primary_key false if no primary key, explicit fields only |
REV |
Active | #28 External data read-only |
| DA-03 | Repo.transaction/1 or Multi for operations modifying multiple tables |
REV |
Active | #12 One error philosophy |
| DA-04 | Repeated query patterns extracted to context functions (3+ uses rule) | REV |
Active | #7 Three is a pattern |
| DA-05 | utf8 encoding and en_AU.UTF-8 collation as PostgreSQL defaults |
REV |
Active | #15 Prefer boring technology |
| DA-06 | PostgreSQL shared_buffers at 25% of RAM, work_mem tuned for query load |
ADV |
Active | — |
| DA-07 | Composite indexes matching query patterns; use EXPLAIN ANALYZE before shipping |
REV |
Active | #16 Data models outlive everything |
| DA-08 | Backups encrypted (AWS native encryption + separate backup key) | ADV |
Active | #26 Secrets never in code |
| DA-09 | Backup retention: 30 daily, 12 monthly, 5 yearly (7 years for IRAP PROTECTED) | ADV |
Active | #16 Data models outlive everything |
| DA-10 | Monthly automated restore tests against staging | ADV |
Active | #16 Data models outlive everything |
| DA-11 | Every table has org_id for multi-tenancy (except public.organisations itself) |
REV |
Active | #27 Never disable security defaults |
| DA-12 | Every table has inserted_at, updated_at, soft-delete deleted_at |
REV |
Active | #16 Data models outlive everything |
| DA-13 | UUIDs for primary keys (distributed-ready, no auto-increment) | REV |
Active | #16 Data models outlive everything |
| DA-14 | Event store partitioned by month for query performance | ADV |
Active | #18 Can't see it, can't maintain it |
| DA-15 | Financial precision: all monetary values use ex_money + Postgres DECIMAL(12,4) (or DECIMAL(19,8) for unit prices). No native Float, no bare 0.0 literals in finnest_payroll, finnest_clients, finnest_compliance.awards. Custom Credo rule enforces |
CI + REV |
Active | #16 Data models outlive everything |
| DA-16 | Event store hash chain: every event computes hash = sha256(prev_hash || id || org_id || domain || event_type || payload) via DB trigger; monthly integrity verification script |
REV |
Active | #16 Data models outlive everything |
7. Queue & Jobs (Oban)¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| QJ-01 | All Oban workers must be idempotent — safe to process more than once | REV |
Active | #38 Idempotent jobs |
| QJ-02 | Retry logic with exponential backoff (backoff: [5, 30, 120]) |
REV |
Active | #12 One error philosophy |
| QJ-03 | Dead-letter strategy: max_attempts exceeded → DLQ table + alert |
REV |
Active | #18 Can't see it, can't maintain it |
| QJ-04 | Separate Oban queues per domain (scout_queue, verify_queue, etc.) + priority | REV |
Active | #34 Isolate volatility |
| QJ-05 | Monitor all queues via Oban Web dashboard | REV |
Active | #18 Can't see it, can't maintain it |
| QJ-06 | Unique constraints on time-sensitive jobs (unique: [fields: [:aggregate_id]]) |
REV |
Active | #38 Idempotent jobs |
| QJ-07 | Workflow agents (Tier 2) use Oban job chaining for multi-step processes | REV |
Active | #12 One error philosophy |
8. Agent Workflow¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| AW-01 | Plan before code: Analyse → Plan → Test → Implement → Verify → Review | REV |
Active | #20 Human decides what |
| AW-02 | Read and update sprint-status.yaml at session start and end | REV |
Active | #19 Documentation is a product |
| AW-03 | No new dependencies without explicit human approval | REV |
Active | #15 Prefer boring technology |
| AW-04 | Infrastructure files (Dockerfile, CI, Kamal config) require human review | REV |
Active | #20 Human decides what |
| AW-05 | No git push --force, git rebase on shared branches, or git reset --hard |
REV |
Active | #6 Understand before you delete |
| AW-06 | One branch per agent; no overlapping file edits | REV |
Active | #34 Isolate volatility |
| AW-07 | Review Agent has veto power; code failing checklist does not merge | REV |
Active | #3 Understand every line |
| AW-08 | Stick to defined story scope; log adjacent discoveries in retro notes | ADV |
Active | #4 Solve problem you have |
| AW-09 | .env*, _build/, deps/, node_modules/, signing keys are off-limits |
REV |
Active | #26 Secrets never in code |
| AW-10 | Commit to feature branches only; never directly to main |
REV |
Active | #22 Ship smallest change |
| AW-11 | Agent scope budgets: target max 10 files modified, 20 per PR | ADV |
Active | #22 Ship smallest change |
| AW-12 | AI agents in production follow confidence framework: GREEN/AMBER/RED thresholds | REV |
Active | #27 Never disable security defaults |
| AW-13 | AI agents in production respect budget limits with circuit breaker | REV |
Active | #27 Never disable security defaults |
| AW-14 | AI agent audit trail: every LLM call + tool call logged to event store | REV |
Active | #24 Log by ID, never PII |
9. Performance¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| PF-01 | Response time targets: LiveView mounts <300ms, APIs <200ms, agent chat <2s | ADV |
Active | #18 Can't see it, can't maintain it |
| PF-02 | Slow query threshold: 1 second; target zero in normal operation | ADV |
Active | #16 Data models outlive everything |
| PF-03 | Oban job duration targets: investigate any job exceeding 5 minutes | ADV |
Active | #38 Idempotent jobs |
| PF-04 | Load testing required before production launch (k6 or Gatling) | ADV |
Active | #37 Measure code health |
| PF-05 | Mobile: app launch < 2s cold, < 500ms warm | ADV |
Active | — |
| PF-06 | Mobile: offline sync reconciliation < 10s for 100 queued events | ADV |
Active | — |
10. Operational Strategy¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| OP-01 | Structured logging: JSON format (logger_json), correlation IDs, PII-free, level-appropriate | REV |
Active | #24 Log by ID, never PII |
| OP-02 | Feature flag lifecycle: create → develop → test → flip → cleanup within 1 sprint | ADV |
Active | #17 Flags are debt with timer |
| OP-03 | Telemetry spans on every context function + LiveView mount | REV |
Active | #18 Can't see it, can't maintain it |
| OP-04 | Error tracking (Sentry or similar) in production | REV |
Active | #18 Can't see it, can't maintain it |
11. AI-Specific Guardrails (Finnest-Unique)¶
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| AI-01 | Local-first routing: pattern-match + DB query before Claude API call | REV |
Active | #4 Solve the problem you have |
| AI-02 | Deterministic guardrails for compliance: pay rates, awards, credentials = rules engines. AI queries, never overrides | REV |
Active | #27 Never disable security defaults |
| AI-03 | Tenant isolation at MCP tool level: org_id injected by infrastructure, not agent | REV |
Active | #27 Never disable security defaults |
| AI-04 | Agent processes never reused across tenants: session end = process termination | REV |
Active | #23 PII classification |
| AI-05 | Correlation IDs on every event to prevent infinite agent loops; max 10 events per chain | REV |
Active | #12 One error philosophy |
| AI-06 | Tier 3 autonomous agents are PROPOSE-only: no destructive actions without human approval | REV |
Active | #20 Human decides what |
| AI-07 | AI provider failover chain: primary (Bedrock) → fallback (Vertex or Anthropic direct) → manual review | REV |
Active | #12 One error philosophy |
| AI-08 | AI cost budgets: per-org daily/weekly/monthly limits with 80% warning, 100% circuit breaker | REV |
Active | #27 Never disable security defaults |
| AI-09 | Prompt-cache-optimal structure: system prompts + MCP tool schemas ordered stable-first for 90% Anthropic cache discount. Dashboard tracks hit rate; alert if <50% for 1 hour | REV |
Active | #1 Code is liability |
12. IRAP-Specific Guardrails¶
These apply ONLY to the IRAP deployment variant.
| ID | Guardrail | Enforcement | Status | Principle |
|---|---|---|---|---|
| IR-01 | AI provider: AWS Bedrock Sydney ONLY (no direct Anthropic API) | REV |
Active | #23 PII classification |
| IR-02 | All data in ap-southeast-2 (Sydney): primary, backups, logs, metadata, caches | REV |
Active | #23 PII classification |
| IR-03 | Separate PostgreSQL instance (no data co-residency with commercial) | REV |
Active | #27 Never disable security defaults |
| IR-04 | Separate VPC with no peering to commercial infrastructure | REV |
Active | #27 Never disable security defaults |
| IR-05 | Go boundary proxy in front of Phoenix (ISM-listed language security boundary) | REV |
Active | #27 Never disable security defaults |
| IR-06 | FIDO2 MFA mandatory on every login (no "remember me") | REV |
Active | #27 Never disable security defaults |
| IR-07 | 15-minute session timeout, 10-minute idle lock | REV |
Active | #27 Never disable security defaults |
| IR-08 | IP allowlist (client network ranges only) | REV |
Active | #27 Never disable security defaults |
| IR-09 | CloudHSM key management (FIPS 140-2 Level 2+ for PROTECTED) | REV |
Active | #27 Never disable security defaults |
| IR-10 | Audit retention: 7 years, tamper-evident (hash chain), immutable storage | REV |
Active | #24 Log by ID, never PII |
| IR-11 | JIT admin access via AWS SSM Session Manager; zero standing access | REV |
Active | #27 Never disable security defaults |
| IR-12 | Two-person approval required for IRAP production deployments | REV |
Active | #20 Human decides what |
| IR-13 | Disabled integrations: SEEK, Indeed, LinkedIn, Calendly, WhatsApp, Google/Apple OAuth | REV |
Active | #23 PII classification |
| IR-14 | Dependency audit includes SBOM generation and CVE monitoring | CI |
Active | #14 Dependencies age |
| IR-15 | Mobile: separate IRAP build with feature flags; no Firebase Analytics | REV |
Active | #23 PII classification |
| IR-16 | Mobile: MDM (Intune) enrollment required for defence tenant users | REV |
Active | #27 Never disable security defaults |
Summary Statistics¶
| Category | Count | CI | PRE | REV | ADV |
|---|---|---|---|---|---|
| Code Quality — Elixir (CQ) | 22 | 4 | 1 | 16 | 1 |
| Code Quality — Flutter (CQM) | 12 | 3 | 1 | 8 | 0 |
| Architecture (AR) | 19 | 2 | 0 | 16 | 1 |
| Security (SE) | 21 | 2 | 1 | 18 | 0 |
| Frontend — LiveView (FE) | 16 | 1 | 0 | 13 | 2 |
| Infrastructure (IN) | 18 | 4 | 0 | 12 | 2 |
| Data & Database (DA) | 16 | 1 | 0 | 10 | 5 |
| Queue & Jobs (QJ) | 7 | 0 | 0 | 7 | 0 |
| Agent Workflow (AW) | 14 | 0 | 0 | 12 | 2 |
| Performance (PF) | 6 | 0 | 0 | 0 | 6 |
| Operational (OP) | 4 | 0 | 0 | 3 | 1 |
| AI-Specific (AI) | 9 | 0 | 0 | 9 | 0 |
| IRAP-Specific (IR) | 16 | 1 | 0 | 15 | 0 |
| Total | 180 | 18 | 3 | 139 | 20 |
Key Changes from AgenticAI-app Version¶
This document adapts the original AgenticAI-app guardrails (113 rules) for the Finnest stack. Notable changes:
Replaced¶
mix formatreplaces PintDialyzer + Credoreplaces PHPStan + PHPMDBoundarylibrary replaces DeptracExUnit + ExMachinareplaces Pest + factoriesEcto.Changesetreplaces Form RequestsObanreplaces Laravel Queue/HorizonLiveView + HEExreplaces BladePhoenixreplaces Laravel
Added (New to Finnest)¶
- Section 1b: Flutter Mobile (CQM) — 12 rules for mobile code quality
- Section 11: AI-Specific (AI) — 8 rules covering agent architecture (local-first routing, deterministic guardrails, tenant isolation, confidence framework, cost budgets)
- Section 12: IRAP-Specific (IR) — 16 rules for IRAP deployment variant
- AR-16, AR-17, AR-18, AR-19 — MCP boundaries, event store immutability, compliance auto-blocking, IRAP as config variant
- DA-11, DA-12, DA-13, DA-14 — multi-tenancy, soft deletes, UUIDs, event store partitioning
Removed (Laravel-specific, not applicable)¶
- OPcache (PHP-specific)
composer.json/composer.lockconventions- Laravel Horizon (replaced by Oban Web)
- Blade-specific rules (replaced by HEEx equivalents)
This document is the enforcement reference. 42-COMMANDMENTS.md is the philosophy. CLAUDE.md (in each code repo) is the operational checklist. All three must stay aligned.