Skip to content

STORY-F-001: Elixir umbrella scaffold (21 OTP app skeletons)

Epic: Foundation Priority: Must Have Story Points: 3 Status: Completed Assigned To: Gautham Chellappa Created: 2026-04-17 Completed: 2026-04-17 Sprint: 1


User Story

As the Lead Developer, I want an Elixir umbrella project with 21 OTP app skeletons matching the architectural layout, so that all subsequent stories have a consistent place to add code and the Supervised Modular Monolith pattern (ADR-002-F) is real from day one.


Description

Background

ADR-001-F (Elixir/Phoenix stack) and ADR-002-F (Supervised Modular Monolith with 21 OTP apps) commit to a specific repository shape. The umbrella layout in architecture.md §System Components is authoritative — every domain has its own apps/finnest_<domain>/ directory, and they communicate via events only (AR-07). Scaffolding this correctly on day one prevents an expensive restructure later.

This is foundation-only — no business logic lives in these apps yet. The goal is that every subsequent story has the right place to land.

Scope

In scope:

  • finnest/ umbrella root with mix.exs, mix.lock, config/ (config.exs, runtime.exs, dev.exs, test.exs, prod.exs, commercial.exs, irap.exs)
  • 21 OTP app subdirectories under apps/:
  • Infrastructure (2): finnest_core, finnest_agents
  • Tier 1 Core (7): finnest_people, finnest_recruit, finnest_onboard, finnest_roster, finnest_timekeep, finnest_reach, finnest_pulse
  • Tier 2 Essential (4): finnest_payroll, finnest_clients, finnest_safety, finnest_assets
  • Tier 3 Growth (3): finnest_quotes, finnest_learn, finnest_benefits
  • Tier 4 Industry (3): finnest_compliance, finnest_fatigue, finnest_clearance
  • Tier 5 People Excellence (1): finnest_performance
  • Edge (1): finnest_web
  • Each app has: lib/finnest_<domain>/application.ex (OTP entry), lib/finnest_<domain>.ex (facade), mix.exs with :finnest_core as only dep (AR-07), test/ folder with minimal smoke test, README.md
  • Umbrella root .formatter.exs, .tool-versions (Elixir 1.17+, Erlang 27+)
  • mix test passes for the umbrella (all smoke tests green)

Out of scope:

  • Boundary library configuration (STORY-F-002)
  • Ecto Repo, tenant, correlation ID (STORY-F-003)
  • Phoenix endpoint scaffolding (STORY-F-004)
  • Docker / CI (STORY-F-005)

Technical Notes

  • Use mix new finnest --umbrella as the seed command, then cd apps && mix new finnest_<domain> for each app
  • Each app is a bare OTP application with a blank supervision tree — content gets added in later stories
  • config/runtime.exs should branch on FINNEST_ENV per irap.md §Config branching, but for this sprint a single commercial env is sufficient — IRAP path can land later
  • Adopt mise (.tool-versions) for Elixir/Erlang version pinning — carry-forward pattern from AgenticAI-app
  • Reference AgenticAI-poc-elixir repo for umbrella patterns if stuck
  • Domain dependency rule: in each mix.exs, declare only {:finnest_core, in_umbrella: true} — NOT other domain apps (AR-07 — enforced in STORY-F-002)

Dependencies

  • None (this is the seed story)

Acceptance Criteria

  • mix compile succeeds at umbrella root with zero warnings (IN-06 --warnings-as-errors used by CI)
  • mix test runs all app test suites; all smoke tests pass
  • mix format --check-formatted passes (CQ-01)
  • 21 apps listed under apps/ with correct names
  • Each app has a lib/finnest_<domain>/application.ex defining use Application
  • Each app's mix.exs declares only {:finnest_core, in_umbrella: true} as internal dep — no other domain apps
  • finnest_core itself has NO internal deps
  • finnest_web declares all domain apps as deps (edge-exception per AR-07)
  • finnest_agents declares all domain apps as deps (agent-tier exception per AR-07)
  • .tool-versions pins Elixir ≥1.17, Erlang/OTP ≥27
  • .formatter.exs at umbrella root configures Elixir formatter for all subdirectories
  • Each app has a minimal README.md stating purpose (one paragraph, linking to architecture.md §System Components)

Testing Requirements

  • Smoke test per app: each finnest_<domain>/test/finnest_<domain>_test.exs asserts the app's Application module starts (e.g. assert {:ok, _} = Application.ensure_all_started(:finnest_<domain>))
  • Full umbrella mix test must run all 21 suites
  • No architecture tests yet (these land in STORY-F-007 — tenant isolation test)

References