**Note** from Bead: Incident Viewer Epic 5 · [canonical source](https://redfish.acequia.io/guerin/.agents/84395793-e621-4739-81e4-fe247b9e6003/2026-06-25/notes/03-elevation-assertion-ship.md) · session 2026-06-25 · discussion: Talk: Incident Viewer Epic 5
**2026-06-25.** Built Epic-5 todos #2 (STAC pose-elevation assertion) and #3 (height-reference modes) together, per Stephen's pick. Implements [a55f5270 note 04](https://redfish.acequia.io/guerin/.agents/a55f5270-1767-475b-924a-1ef59ee09e90/2026-06-15/notes/04-elevation-as-a-soft-uri-assertion.md).
## What shipped - **One central resolver `camGroundElev(c)`** replaces the three duplicated `geo.heightAt → elev` sites (`buildCamCard`, `camPoseWorld`, `configureCamProjector`). Returns `{ elev, agl, ref }`. - **Height-reference modes** (`elevation_msl = height_AGL + DEM`, Google-Earth altitude modes): - `msl` — absolute: use the asserted value, **skip the DEM** (the "don't need the DEM every time" case once harvested/calibrated). No re-drape (it's a fixed assertion; recalibration supersedes it). - `dem` — above-terrain: sample the DEM + AGL. **Default** (today's behaviour). - `dsm` — above-surface: DEM + surface-object height; **DSM source stubbed to DEM** until a lidar DSM exists. - Global default `dem`; **per-item STAC override** via `pose:height_ref`. - **Assertion read (step 1)** from inline STAC item properties (read-side safe, no behaviour change until assertions exist): `pose:elevation_msl_m`, `pose:height_agl_m`, `pose:height_ref`, `pose:elevation_href`, `pose:elevation_method`. (The linked-asset JSON form — `assets.elevation` → its own URI — is the next step.) - **Harvest (step 2):** DEM-relative cards record the stable post-LOD DEM ground elev (`demHarvest`) in the re-drape sentinel — the same value the re-drape fix stabilises, now captured to persist. - **`__misb` API:** `heightRef(mode?)` gets/sets the mode and rebuilds cards; `elevations()` exports per camera the **asserted + harvested** assertion JSON (decomposed `AGL + DEM`, `method:'dem-sample'`, `supersedes`) — ready to PUT to the commons. The viewer *offers*; the human/commons owns the write.
## Verify - `npm run build` clean → `index-D9Zt3pFf.js`. **tsc (via taos-engine toolchain): zero NEW type errors** (the two remaining — `ToaData[].mat`, `frame` implicit-any — are pre-existing in HEAD). - CDP (local `dist/` + Sandy catalog): **no render regression** ([`tools/_e5-elev-load.png`] — terrain, imagery, layer tree, timeline identical). New API live: `heightRef()` → `'dem'`, setter cycles `msl`/`dem`/`dsm`, `elevations()` returns the 10 Sandy cameras with the correct schema (`asserted` all-null — catalog has none yet; `harvested` null headless because frames are auth-gated so cards never drape). [`tools/_e5-elev-api.png`, `tools/_e5-elev-detail.png`]. - **Owed (authed browser):** the MSL-skip-DEM render, the AGL offset, and the harvest only exercise once cameras drape — auth-gated, headless loads `0` frames. Confirm in an authed browser alongside the camera re-drape fix. Default `dem` ⇒ behaviour is identical until assertions exist, so the deploy is low-risk.
## Deploy — BOTH hosts together - Branch `feat/elevation-assertion` `7117906` (off reconciled `reconcile/epic5`). - redfish [apps/incident-viewer/](https://redfish.acequia.io/guerin/apps/incident-viewer/) + santafe [/](https://santafe.live/): PUT `index-D9Zt3pFf.js` (201) + `index.html` (204); DELETE old `index-BR1bSKpa.js` (204). **Both serve `D9Zt3pFf`.**
## Next - Through-the-lens calibration writes a `method:'through-the-lens'` assertion that `supersedes` the dem-sample one (note 04 step 3) — the pose factor-graph treats it as one more soft node. - Linked-asset (own-URI) assertion form + a `?stac=` round-trip that PUTs harvested elevations back. - Remaining Epic-5: look-through roll-fix, `<stac-layer-tree>`/`<stac-timeline>` adoption, union-browser URL cleanup (Image Cache Manager already recovered by Stephen to [santafe.live/set-space-time/](https://santafe.live/set-space-time/index.html)).
## References (bead cross-links) - Bead: Nuke Geo Camera · [canonical](https://redfish.acequia.io/guerin/.agents/a55f5270-1767-475b-924a-1ef59ee09e90/)