# Map — Recipe (per FVW v8 §11.1)

**Module ID:** `oscar.map` v0.2.0

## A. Product Description

Vector map module for arboriculture site surveys. Supports 3 geometry types (point, line, polygon), layer drawing/editing/selection/export, court-grade document generation, and forward-compatible cloud-sync data shapes. Operates as a sovereign SPA — no server dependency at runtime.

The map is the canonical source of truth for in-the-field geometry. Documents (PDF / PNG / SVG / GeoJSON / KML) are snapshots of layer state at a specific version. Layer version is bumped on significant edits; documents record the version they were generated against.

## B. Structural Contract

- **Mode:** Sovereign SPA Mode (per DO-001)
- **Runtime renderer:** Leaflet (lifted from prior SVG-only constraint; see §C1 / rules.md §1)
- **Persistence:** IndexedDB, `map_layers` store (DB v18+), `documents` store (added v0.2.0), `layer_versions` store (added v0.2.0 Item 6 — DB v19, audit trail for significant edits), `annotations` store (added v0.2.0)
- **State:** Shared selection state lives in component-level state, surfaced to both map and layer list via the same source

## C. Reconstruction Notes

- `app/src/map/MapView.tsx` — map container + Leaflet renderer + vertex-drag handlers + version bump on save
- `app/src/map/SidePanel.tsx` — selection side panel (added v0.2.0) with v{n} badge
- `app/src/map/FilterChips.tsx` — kind/date/name filters (added v0.2.0)
- `app/src/map/ExportMenu.tsx` — export-format picker + PDF/PNG/SVG/GeoJSON/KML/Print generators (added v0.2.0). Persists Document record with real version numbers in `layerVersions`.
- `app/src/views/Documents.tsx` — saved documents index (added v0.2.0), shows version per layer
- `app/src/data/models/MapLayer.ts` — MapLayer shape (now carries `version`, `syncState`, `syncedAt`, `serverVersion`)
- `app/src/data/models/Document.ts` — Document shape (added v0.2.0)
- `app/src/data/models/LayerVersion.ts` — LayerVersion shape (added v0.2.0 Item 6): `{id, layer_id, version, coords, created_at, updated_at}`. One row per significant edit.
- `app/src/data/models/Annotation.ts` — Annotation shape (added v0.2.0)
- `app/src/data/persistence/idb.ts` — IDB store registration (DB v19 for v0.2.0 additions; v18 → v19 in Item 6 to add `layer_versions` store with `by-layer-id` + `by-created-at` indexes)

## D. Doctrine Surfaces (v0.2.0)

| Surface | Purpose | Fragment |
|---|---|---|
| Map canvas | Leaflet-rendered geometry + selection | oscar.map.view.001 |
| Layer list | Filtered, grouped list of layers | oscar.map.view.001 |
| Filter chips | Kind/date/name filters + clear-all | oscar.map.filter-chips.002 |
| Side panel | Selected layer details + actions | oscar.map.side-panel.002 |
| Selection state | Two-way map↔list shared state | oscar.map.selection-shared.002 |
| Export menu | Format picker + per-format generators + Document write path | oscar.map.export-menu.002 |
| Documents view | Saved exports index + re-download + delete | oscar.map.documents-view.002 |
| Vertex editor | Drag-vertex handlers on map | oscar.map.vertex-editing.002 |
| Version ledger | Version bump rules | oscar.map.versioning.002 |
| Report type picker | Site visit / client / planning / expert-witness templates | oscar.map.report-types.002 |
| Annotation store | PDF annotation persistence (stub) | oscar.map.annotation-stub.002 |
| Cloud-sync fields | Forward-compat sync state fields (stub) | oscar.map.cloud-sync-stub.002 |
| Base-layer toggle | Map / Satellite / Hybrid switcher in toolbar top row | oscar.map.view.001 (base layer is a sub-case of view) |

## E. Backward Compatibility

- v0.1.0 fragment set (`oscar.map.model.001`, `oscar.map.view.001`, `oscar.map.store.001`, `oscar.map.geometry-types.3.001`, `oscar.map.tree-integration.001`) remains SHIPPED and authoritative for their respective surfaces.
- v0.2.0 additive only: no v0.1.0 behaviour is removed or altered.
- Existing layers without `version` field default to `version: 1` on read.

## END OF RECIPE.MD