Fire Path AI - Developer Documentation
Last reviewed against the codebase: 2026-07-25.
Private developer documentation for Fire Path AI, an Australian bushfire
prediction and asset-protection system. This site is for authorised technical
reviewers and developers; it is access-controlled (Cloudflare Access) and not
search-indexed (noindex), so it can be published while sections are still
being filled in.
This landing page is the 10-minute orientation: what the system is, how it is put together, where the code lives, the five mechanics you must understand before touching anything, and where to go next. It is deliberately shallow - it links into the deeper pages rather than duplicating them, so there is a single source of truth for each topic.
What it is
Fire Path AI is a situational-awareness and decision-support system for Australian bushfires. It turns live satellite fire detections, weather, terrain and a property’s own details into property-specific risk, spread estimates, time-to-impact, and alerts - for residents and landholders today, with an operations view for wider situational awareness. It complements official agency warnings; its predictions are physics-based estimates, not authoritative agency products. See Overview & architecture for the full system context, the fire-science model, and the capability-status table.
Architecture in one diagram
Mobile + Web app ──HTTPS──▶ API server ──▶ PostGIS (Postgres) (Expo / MapLibre) (Node/Express) ▲ │ ▲ │ │ └─▶ Redis queue ──▶ Wind-worker │ │ │ (WindNinja, terrain wind) └────── push/alerts ◀──────┤ │ ├─ Ingest scheduler ─▶ FIRMS / DEA / OpenMeteo (external feeds) └─ Alert evaluator ──▶ push (FCM/APNs) + SMS/email fallbackThe client is a universal Expo app (iOS, Android, web SPA). It talks only to the API server, which owns all business logic and is the only thing that touches the PostGIS database. A scheduled ingest loop pulls external feeds; terrain-wind computation is offloaded to a separate wind-worker over a Redis/BullMQ queue so a slow WindNinja run never blocks an HTTP request. Full narrative, tiers, and external-feed detail live in Overview & architecture; the hosting topology (which of these run where, and what hibernates) is in Infrastructure.
The technology stack
| Layer | Choice |
|---|---|
| Client | Expo / React Native (iOS, Android, web SPA), MapLibre |
| API | Node.js / Express, TypeScript, Drizzle ORM |
| Database | PostgreSQL + PostGIS (spatial) |
| Queue / cache | Redis (BullMQ) |
| Terrain wind | WindNinja (containerised worker) |
| Package manager | pnpm (workspaces monorepo) |
| Infra | AWS ECS Fargate, ALB, RDS, ElastiCache, Terraform (IaC) |
| Static sites | Cloudflare Pages / Workers (marketing, docs, web app shell) |
Repository map
The code is a pnpm-workspaces monorepo rooted at Fire-Path-AI/
(packageManager: pnpm@11, packages under artifacts/*, lib/*, and
scripts). The workspace name in the root package.json is literally
workspace, and packages reference each other as @workspace/<name>.
| Path | What it is |
|---|---|
artifacts/api-server | The Node/Express API - routes, ingest, alert evaluator |
artifacts/firepath-ai | The Expo / React Native app (iOS, Android, web SPA) |
artifacts/docs-site | This documentation site (Astro + Starlight) |
artifacts/marketing-site | The public marketing site (Astro) |
lib/db | Drizzle schema + the push migration scripts (@workspace/db) |
lib/api-zod | Zod request/response schemas shared by server + client |
lib/api-spec | The OpenAPI spec, derived from the Zod schemas |
lib/api-client-react | Typed React Query client generated from the spec |
lib/spread-model | The McArthur-based fire-spread math |
lib/web-brand | Shared brand tokens for the web surfaces |
scripts | Repo tooling (typechecked as a workspace package) |
infra/ · .github/ | Terraform + wake/hibernate scripts · CI workflows |
The Repository guide has the full generated tree and a one-liner for every package; Where everything is maps common tasks (“I want to change a route / a table / a screen”) to the exact directory.
The five things to know
Understand these five and the rest of the docs will make sense.
1. Auth and RBAC
Every non-public route is authenticated with a JWT, and authorisation is
role-based. There are four roles, defined in the schema
(lib/db/src/schema/enums.ts): homeowner, agency_officer,
council_admin, and system_admin. Ownership is enforced on top of roles - a homeowner can only
see their own org’s assets (IDOR protection), not just “any authenticated
user’s”. The auth model, the RBAC matrix, and the endpoints that are still
503 stubs (Microsoft SSO, phone-OTP) are documented in the generated
API reference and the Security page.
2. The ingest → predict → alert flow
This is the core life-safety pipeline:
- Ingest - a scheduled, overlap-guarded loop pulls FIRMS (NASA
satellite fire detections), DEA Hotspots (Digital Earth Australia), and
OpenMeteo weather, writing an
ingest_cyclesrow per source per run. - Predict - a clustering pass tracks fires over time; the spread path
(
lib/spread-model) computes footprint + ETA; terrain wind runs asynchronously on the wind-worker via the Redis queue. - Alert - an evaluator matches active fires to a user’s assets and raises alerts, delivered by push (FCM/APNs) with SMS/email fallback. A threat registry is the single writer for fire↔asset threats, so alerts can’t be double-raised by two concurrent runs.
The Operations page covers the runtime behaviour and alarms for this pipeline.
3. COLD / WARM / HOT - the cost model
Only the AWS API backend costs real money to run, so it is deliberately hibernated between work sessions. The three Cloudflare surfaces (marketing, docs, web-app shell) are static and always on for ~$0.
- COLD - AWS torn down to ~$0; the web app loads but shows a
“Service is paused” banner because
api.resolves to nothing. - WARM / HOT - the data tier or the full stack is awake and billable.
The topology, the Terraform module map, and the exact wake/hibernate mechanics are in Infrastructure and Operations.
4. Config is env-driven, not hard-coded
There are no config literals scattered through the code. Every setting -
database URL, secrets, feature flags, contact identity - is an environment
variable or a Terraform variable, with a single place to change it per
environment. Third-party keys (FIRMS, OAuth, Resend, Twilio) can stay blank
locally; those features degrade gracefully when unset. Feature flags such as
enable_data_tier, enable_compute, and dev_mode gate whole tiers. The full,
generated table of every variable, its default, and whether it is
required/optional is the Configuration reference.
5. CI gates keep the docs and code honest
Quality is enforced in CI, not by convention: a coverage ratchet (CI floors today ~59% statements / 50% branches / 62% functions / 61% lines, ratcheting up toward the ≥85% statements-lines / ≥90% route-integration resale target - never allowed to regress), typecheck, the test suites, and - specific to this site - the doc-drift gate (generated reference must match the source) and the redaction gate (no paths, account IDs, resource IDs, or names in the published build). CI never receives real production secrets; tests must pass with them unset. See Testing & quality and Contributing & release.
Run it in three commands
Full setup (env file, keys, device builds) is in Run it locally; the short version, from the repo root:
docker compose up -d postgres # Postgres/PostGIS on :5432cd Fire-Path-AI && set -a; source .env; set +a # after: cp .env.example .envpnpm --filter @workspace/api-server run dev # builds + starts API on :3000Then, in a second terminal, start the app:
pnpm --filter @workspace/firepath-ai run web # Expo web on :8081Verify it’s alive - the API exposes two health endpoints:
curl -s localhost:3000/healthz # {"status":"ok"} - liveness, dependency-freecurl -s localhost:3000/readyz # readiness - 200 only if Postgres is reachable/healthz intentionally never touches the database (a transient DB blip must
not make the orchestrator kill a healthy task); /readyz actually pings
Postgres and reports ingest freshness, returning 503 when the DB is down.
The full verification checklist (typecheck, vitest, health) is in
Verify.
Reference (generated)
These sections are generated directly from the codebase on every build and drift-checked, so they cannot silently fall out of sync:
- Repository guide - every workspace package.
- API endpoints - every route the server exposes.
- Data model - every table and column, from the live database schema.
- Configuration - every environment variable.
Where to go next
- New here? Start with Overview & architecture, then the Get-started guides: where everything is, run it locally, and verify.
- Operating the platform? Infrastructure, Operations, and Security.
- Contributing code? Testing & quality and Contributing & release.