**Note** from Bead: Incident Cataloging · [canonical source](https://redfish.acequia.io/guerin/.agents/c38c1239-bfd3-44dd-8d97-1a0aa39ac8da/2026-06-10/notes/stac-as-catalog-substrate.md) · session 2026-06-10 · discussion: Talk: Incident Cataloging
> Stephen, 2026-06-10: "consider STAC." STAC = SpatioTemporal Asset Catalog (https://stacspec.org), a mature, widely-adopted open standard for exactly the noun half of this bead's mission: cataloging spatiotemporal assets. This note considers adopting it.
## The short version STAC already is "the catalog" (the noun), battle-tested. Most of our [event-catalog-format-design](event-catalog-format-design.md) requirements are STAC features. So: **adopt STAC as the catalog substrate, and spend our originality on the two things STAC does not give us: the cataloging (verb / connect-to-layers interface), and a pose-stream extension for FMV.**
## STAC in one screen - **Item** = the atomic unit: a GeoJSON Feature with `geometry`+`bbox` (footprint), `properties.datetime` (or `start_datetime`/`end_datetime`), `assets` (a dict of `{href, type, roles}` pointing at the actual files), `links`, and a `collection` id. Extensible via **extensions** (`view`, `eo`, `proj`, `sar`, `datacube`, ...). - **Collection** = a group of Items with a spatial+temporal `extent`, `summaries`, `item_assets`, `providers`, `license`. - **Catalog** = a node of `links` (root → child catalogs/collections → items): the recursive grouping tree. - **STAC API** = OGC-API-Features `/search`: filter by `bbox`, `datetime`, `collections`, and CQL2 property `filter`; returns a GeoJSON FeatureCollection. The **Transactions** extension adds POST/PUT/DELETE (ingest).
## Requirement crosswalk (ours → STAC) | Our requirement (event-catalog-format-design) | STAC mechanism | |---|---| | Entry `{id, media-by-URL, ...}` | **Item**; media = `assets[].href` | | media roles (source/thumbnail/video) | `assets[].roles` = `data`/`thumbnail`/`overview`/`visual` | | Time = instant / range | `datetime` / `start_datetime`+`end_datetime` (native) | | recursive typed grouping tree (#8) | **Catalog** → **Collection** → Item links | | a "layer" (L1, mission note) | a **Collection** | | normalize at edge; type tag + adapter (#6) | `stac_extensions` URIs + the extension mechanism | | content-addressed id | `Item.id` (any string; SHA-256 fine) | | spatial ∩ temporal browse (map-bounds ∩ timeline) | `/search` `bbox` + `datetime` | | proximity / embedding query (T6) | not native (emerging similarity extensions) | | the cataloging *verb* / connect-to-layers | **not in STAC** (see gaps) | So requirements #5 (media-by-reference), #6 (edge-normalize via extensions), #8 (tree), L1 (layer=Collection), L2 (timeline=datetime), and the map∩time browse all land on existing STAC. That is most of the catalog noun, already standardized and tooled (pystac, stac-fastapi, titiler, QGIS/leaflet STAC plugins).
## Where STAC stops (our value-add) 1. **STAC is the noun, not the verb.** It describes and searches assets; it does not define an interface for *connecting / composing / subscribing* layers ("where people go to make connections"). The Transactions extension is CRUD ingest, not the connect-the-layers cataloging interface. **The cataloging interface is ours to build, on top of a STAC catalog.** 2. **Pose is footprint-centric (subject), thin on platform/look stream.** STAC `geometry` is the asset's ground footprint = our **subject** pose. The `view` extension adds scalar sensor/sun geometry (`view:azimuth`, `view:off_nadir`, `view:sun_*`), but there is no native time-varying 6-DOF **platform+look** track. MISB FMV (per-frame sensor pose) does not fit a single Item's static `view`. Fit: one Item per clip (geometry = footprint hull over the clip, datetime = the interval) carrying a **video asset + a telemetry-track asset** (our `poseTrack`), described by a small **custom FMV/pose extension**. That extension is the one piece of format we genuinely add. 3. **Time-as-stream / datacube.** STAC datetime is instant or interval. A continuous FMV stream or an animated fire progression is either many Items (one per timestep) or the `datacube` extension. Native STAC handles discrete; the streaming/animation lives in the assets + the interface.
## Sandy fire, expressed in STAC (answers L1 + L2) ``` Catalog: "incident: CA-VNC-SANDY (Sandy fire, 2026)" ├─ Collection: "MISB FMV" ← a LAYER │ ├─ Item: N42Z clip 18:13:41Z (geometry=footprint hull, datetime=[start,end], │ │ assets:{ video:{href,roles:[data]}, telemetry:{href,roles:[metadata]}, │ │ thumbnail:{...} }, ext: fmv-pose + view) │ └─ Item: N42Z clip 22:20:21Z ... └─ Collection: "fire progression" ← a LAYER ├─ Item: perimeter/raster @ t0 (geometry=perimeter, datetime=t0, assets:{ raster, perimeter-geojson }) └─ Item: ... @ t1 ... (a time sequence; or datacube) ``` - **A layer = a STAC Collection** (L1 resolved as a candidate answer). - **The shared timeline = STAC `datetime`/intervals** across both Collections (L2): FMV intervals and fire-progression timesteps are both placed on one axis by their datetime. - **The cataloging interface** connects/toggles/sequences the two Collections over that axis; taos-engine renders FMV Items as projectors and fire-progression Items as terrain overlays (L3 = the render-kind is chosen by the interface from asset media-type + roles, not by STAC).
## Recommendation 1. **Adopt STAC as the catalog (noun).** Map Entry→Item, layer→Collection, grouping→Catalog, media→assets, time→datetime, per-type→extensions. Do not reinvent it; inherit the tooling and the lingua franca. 2. **Expose the cataloging (verb) as the catalog's dual** (corrected per [catalog-cataloging-duality](catalog-cataloging-duality.md) — it is NOT a layer "on top"). The connect-to-layers interface is STAC's own operations dualized on the same Items: `search ↦ subscribe/connect`, `GET ↦ observe`, read-edge `#` ↦ write-edge `@`. Same Items, reverse the arrows. 3. **Define one small extension: FMV / 6-DOF pose-stream** (platform+look telemetry track as an asset), since that is where our domain exceeds vanilla STAC + `view`. 4. **Re-express the existing surfaces as a check:** map alertLive `imageMeta`+`imagePoses` and the MISB `incidents.json` into STAC Items/Collections; if they fit cleanly (they should: posed photo = Item with `view`; FMV clip = Item with fmv-pose ext), STAC is validated for us. Open: STAC's geometry-as-footprint means we carry the subject/platform/look split (mission note, catalog design) partly in extensions, partly in geometry. Worth a follow-up: exactly which of subject/platform/look goes to `geometry` vs `view` vs the new fmv-pose extension.
## Provenance Stephen 2026-06-10 ("consider STAC"). Feeds [event-catalog-format-design](event-catalog-format-design.md) and the [bead mission](bead-mission-catalog-and-cataloging.md). STAC spec: https://stacspec.org , extensions: https://stac-extensions.github.io .