Skip to content

ADR-008-F: Flutter Mobile (One App, Four Roles)

Status: Accepted Date: 2026-04-16 Decision Makers: Gautham Chellappa

Context

The existing ASG mobile strategy consists of four separate apps (aCMS employee, aAMS asset, aTask task, aTeam team). Four App Store listings, four codebases, four sets of App Store reviews, four installation steps per worker. Field workers who wear multiple hats carry four icons.

Finnest replaces them with one app. The question is which framework, and whether to adapt the existing Flutter v5.0.4 codebase or rewrite.

Decision

One Flutter mobile app (separate repo: finnest-mobile) with role-based feature visibility. Adapt the existing Flutter v5.0.4 codebase rather than rewrite from scratch.

One app, four (five) roles

Role Screens Primary interaction
Field Worker ~5 (home/agent, roster, timecard, leave, notifications) Agent chat, NFC clock
Supervisor ~10 (above + team view, approvals, shifts, tasks, incident) Notifications + agent chat
Asset Manager ~10 (above + equipment, maintenance, fleet) Quick actions + agent chat
Client Contact ~5 (assigned workers, roster, placements, billing) Client portal

Role is derived from the JWT claim returned by the server — same user can have different roles in different orgs.

Framework: Flutter

  • Existing codebase proves NFC, GPS, push, biometric, offline capable
  • Bounded polyglot cost (~5-10K LOC of Dart vs 150K+ LOC of Elixir backend)
  • Single codebase → iOS + Android builds
  • Mature native capabilities for every field-work requirement

Architecture summary

  • BLoC state management (existing, CQM-08)
  • GoRouter navigation with role-based guards
  • SQLite offline event queue (drift or sqflite) mirroring server event shape
  • Phoenix Channels over WSS for real-time (notifications + agent chat streaming)
  • REST /api/v1/* for CRUD and sync
  • JWT + biometric-unlocked refresh token (SE-18)
  • FCM push with encrypted payload (no PII in notification body)

Full detail in ../architecture/mobile.md.

Alternatives Considered

Framework Rejected because
LiveView Native NFC, offline SQLite, background location not production-ready; experimental
React Native Ecosystem churn risk; bridge architecture brittle; fourth language in the stack (JS)
KMP + Compose No code sharing with Elixir backend; iOS Compose still maturing; duplicate UI code
PWA Can't do NFC; weak enterprise MDM; no App Store presence for defence Intune
Rewrite Flutter from scratch Throws away proven NFC / GPS / push implementations; 8-10 weeks to same capability
Keep four separate apps Four apps to maintain, four store listings, four reviews per release, installation friction

Consequences

Positive:

  • 4× reduction in mobile codebase maintenance surface
  • One App Store listing — one review per release
  • Role-based visibility: field workers not overwhelmed; asset managers have what they need
  • Existing Flutter proves production viability for NFC / GPS / push / offline
  • Bounded polyglot cost — Dart is isolated to the mobile tier
  • Clean REST + Channels API layer keeps mobile client swappable (LiveView Native re-evaluation trigger at 2027)

Negative:

  • Dart is a second language in the stack alongside Elixir
  • Separate repo means separate CI / release / test tooling
  • App Store submission process is separate from backend deployment
  • Role-based UI adds complexity over single-role app — feature flags per role

Migration effort (B07):

Work item Duration
API migration (v2 CodeIgniter → Finnest Phoenix) 2 weeks
Offline sync engine 2 weeks
Agent chat interface 1 week
Role-based navigation 1 week
Asset management screens 1 week
UI refresh (Finnest design system) 1 week
Testing + App Store submission 1 week
Total ~8-10 weeks (Phase 2, Weeks 13-20)

IRAP flavor (IR-15, IR-16):

  • Separate Flutter flavor (flutter build apk --flavor irap) produces distinct APK/IPA
  • Microsoft Intune MDM distribution only — not public App Store
  • Firebase Analytics disabled; FCM kept with encrypted payload only
  • Mandatory biometric + PIN; 5-min idle lock

Tipping points for re-evaluation:

  • LiveView Native matures for NFC / offline / background location (2027 review per main architecture OI-08)
  • Flutter 4.x introduces breaking changes that cost more than a rewrite would — unlikely
  • Team grows such that a native iOS + Android split team is affordable — unlikely at current scale

Relationship to Guardrails

Enforces / is enforced by: CQM-01 through CQM-12 (12 Flutter mobile guardrails), SE-17, SE-18 (mobile security), IR-15, IR-16 (IRAP mobile).