# FireWatch

Satellite-led wildfire detection and perimeter monitoring, designed to deploy as a Cloudflare Pages application.

## What is included

- A responsive incident dashboard with monitored fires, new hotspots, estimated acreage, scene freshness, and a fire-tagging workflow.
- A live dashboard feed from D1: `/api/fires` returns tagged monitoring areas, their latest Earth Engine result, FIRMS candidate clusters, and the past-24-hour hotspot count. It never exposes provider credentials.
- Cloudflare Pages configuration (`wrangler.jsonc`) and local/deploy scripts.

When D1 is unavailable (including a fresh local database before migrations), the interface deliberately falls back to marked **demonstration data**. Live estimates remain satellite-derived estimates, not official agency perimeters.

## Production data pipeline

1. A scheduled Cloudflare Worker requests new VIIRS/MODIS hotspots (NASA FIRMS) and creates candidate incidents after spatial clustering. **Implemented:** [`workers/firms-ingestion.js`](workers/firms-ingestion.js) polls NOAA-20 VIIRS for the Santa Fe region every 15 minutes, keeps nominal/high-confidence detections, deduplicates them in D1, and makes a candidate from two or more detections within 7 km during the prior 24 hours.
2. For each user-tagged area of interest, queue a processing job when a new Sentinel-2/Landsat scene becomes available. **Implemented:** [`workers/scene-orchestrator.js`](workers/scene-orchestrator.js) stores AOIs, creates one durable scene job per AOI/day, and sends it through Cloudflare Queues. Jobs wait safely until the protected Earth Engine processor is configured.
3. The processor runs server-side imagery analysis: cloud masking, NBR `(NIR - SWIR2) / (NIR + SWIR2)`, then differenced NBR against a pre-fire baseline. Convert qualifying burn pixels to polygons and geodesic acreage.
4. Store incidents and observation history in D1; store perimeter GeoJSON/raster outputs in R2. Return simplified GeoJSON plus summary properties from `/api/fires`.

Google Earth Engine is a suitable analysis engine for step 3, but keep its service-account credentials and Earth Engine calls in a Worker or a separate trusted processing service—never in the browser. Earth Engine exports can be written to Cloud Storage/R2-compatible staging and ingested by the worker. Sentinel Hub, AWS SageMaker, or a container job are viable alternatives for that processing tier.

## Deployment

```sh
npm install
npm run dev
npm run deploy
```

The first `npm run deploy` requires a Pages project. This workspace now uses
`firewatch`; create it once with `npx wrangler pages project create firewatch
--production-branch main` if it does not already exist. The Pages configuration
binds the production `firewatch` D1 database as `DB`, which is what
`functions/api/fires.js` uses for the live dashboard feed.

### Enable FIRMS ingestion

1. Request a free NASA FIRMS `MAP_KEY` from the [FIRMS map-key page](https://firms.modaps.eosdis.nasa.gov/api/map_key/). FIRMS’s area API takes a product, `west,south,east,north` bounding box, and a 1–5 day range; the worker defaults to the Santa Fe region. [NASA FIRMS API documentation](https://firms.modaps.eosdis.nasa.gov/api/area/)
2. Create the D1 database: `npx wrangler d1 create firewatch`. Copy its ID into `wrangler.ingestion.jsonc`.
3. Apply the schema: `npm run db:migrate`.
4. Set the required secrets: `npx wrangler secret put FIRMS_MAP_KEY --config wrangler.ingestion.jsonc` and `npx wrangler secret put INGESTION_TOKEN --config wrangler.ingestion.jsonc`.
5. Deploy the cron worker: `npm run ingestion:deploy`. Test a run with `POST /run` and `Authorization: Bearer <INGESTION_TOKEN>`.

### Enable Google Earth Engine scene orchestration

1. Enable Earth Engine for a Google Cloud project and create a service account for the processor. Google recommends application-default credentials for unattended Google runtimes; grant the service account Earth Engine Resource Viewer and, when required, Service Usage Consumer. [Earth Engine service-account guidance](https://developers.google.com/earth-engine/guides/service_account)
2. Create queues: `npx wrangler queues create firewatch-scene-jobs` and `npx wrangler queues create firewatch-scene-jobs-dlq`.
3. Copy the same D1 database ID into `wrangler.scene-orchestrator.jsonc`, then run `npm run db:migrate`.
4. Set `ORCHESTRATOR_TOKEN` using `npx wrangler secret put ORCHESTRATOR_TOKEN --config wrangler.scene-orchestrator.jsonc`.
5. Deploy with `npm run scenes:deploy`. Until the Google processor exists, new jobs are recorded as `awaiting_processor` rather than dropped.

The protected Google Cloud Run Earth Engine processor now lives in [`gee-processor/`](gee-processor/). It receives a queued AOI, runs a Sentinel-2 dNBR estimate, and reports acreage through the authenticated completion endpoint. Configure its URL and token in the Worker as `GOOGLE_EE_PROCESSOR_URL` and `EE_PROCESSOR_TOKEN` only after deployment.

Before turning on live ingestion, add API secrets with Wrangler (for example, the FIRMS MAP_KEY and Earth Engine service credentials), create D1/R2/Queue bindings, and set the dashboard’s API base URL. Validate output against incident agency perimeters; satellite-derived acreage is an estimate and must communicate acquisition time, cloud coverage, confidence, and methodology.
