**Note** from Bead: Incident Viewer Taos Engine App · [canonical source](https://redfish.acequia.io/guerin/.agents/cbf8b027-e80c-4b9f-8eb3-91d40af072d5/2026-06-11/notes/01-taos-hosting-and-token-percolation.md) · session 2026-06-11 · discussion: Talk: Incident Viewer Taos Engine App
Decisions from Stephen, 2026-06-11. Captured as project state; the PR itself is not yet written.
## Hosting decisions 1. **incident-viewer stays put for now.** Keep it where it is — the engine is **bundled into the app** (per [note 00](https://redfish.acequia.io/guerin/.agents/cbf8b027-e80c-4b9f-8eb3-91d40af072d5/2026-06-11/notes/00-session-mount-table.md) / the build wiring). Do **not** refactor it onto the shared `/taos` engine host yet. - ⚠️ Path nuance to confirm: it currently lives at `https://redfish.acequia.io/guerin/apps/incident-viewer/` (under `guerin`). Stephen wrote "redfish.acequia.io/apps" — unclear if that signals a future move to a top-level `/apps`, or is shorthand for the current path. Left as-is ("keep for now"); flag on next touch. 2. **`redfish.acequia.io/taos` is the intended shared engine host** (the `engine-lib/` standalone-bundle target). **Status now: public, and it has CORS.** So the public phase of shared-hosting is unblocked — the earlier CORS concern is resolved. 3. **Later: privatize `/taos` behind an API token.** When `/taos` goes private, every consumer (incident-viewer, realtime.earth) must present a token to fetch the engine bundle **and its sibling subresources**. That is the motivation for the engine PR below.
## The token-percolation PR (to TaosEngine — Brendan's repo) **Problem.** When the engine is served from a *private* origin, the hard part is not tile data — it's the engine's **own** assets, fetched by URL with no header attachable: - **Module workers** — `new Worker(new URL('./<x>_worker.ts', import.meta.url), { type: 'module' })` at: - `src/geo/terrain_bake_pool.ts:95` (terrain bake) - `src/geo/tile_worker_pool.ts:87` (quantized-mesh decode) - `src/geo/vector_tile_pool.ts:82` (vector tiles) - `src/third_party/meshopt/meshopt_decoder.mjs:85` (`new Worker(url)`) - **wasm by `?url`** — `src/assets/gltf_decoders.ts:12,14` (`draco_decoder.wasm?url`, `basis_transcoder.wasm?url`); jolt physics has an explicit `locateFile`-style override already (`src/physics/jolt_backend.ts:18-30`). A `Worker` constructed from a `new URL(...)` and a `fetch`-of-`?url` wasm cannot attach `Authorization`. So a private `/taos` cannot be served by header auth for these; the token has to ride another way. **Two viable percolation mechanisms** (the PR should enable at least one; ideally make it pluggable): 1. **Asset-base + `locateFile` hook** (engine change) — add an engine-config option, e.g. `Engine.create({ assetBase, locateAsset(url) })`, that *every* worker-spawn and wasm-load routes its URL through. The consumer supplies a function that appends `?token=…` (acequia capability JWT) or rewrites to a SW-proxied path. Mirrors the existing `jolt_backend` `locateFile` precedent — generalize that one pattern across `terrain_bake_pool` / `tile_worker_pool` / `vector_tile_pool` / `gltf_decoders` / `meshopt`. 2. **Service-worker ambient auth** (no engine change) — the acequia SW intercepts subresource GETs and injects the bearer (per generate-acequia-access-token: "SW ambient-auth covers worker/wasm subresources"). Works today *if* the consuming origin has the SW registered; the PR-worthy gap is consumers that don't. **Why the PR regardless of #2.** The SW path only covers origins that registered it. A library meant to be hosted at a private `/taos` and consumed by arbitrary apps (incl. realtime.earth, non-acequia embeds) needs an **in-engine** token hook so it's self-sufficient. That hook is the PR: thread a single `locateAsset(url) → url'` (and reuse the existing `DataSource.authHeaders()` for any header-able tile fetch that targets `/taos`) through the five spawn/load sites above. **Token shape.** Per the acequia model, a scoped PS256 capability JWT (`scope.paths` covering `/taos/**`, `writePaths:[]` = read-only), passed as `?token=` / Bearer. Minting is client-side (signing key / dashboard).
## Sequencing - **Now (public /taos):** no token needed; `engine-lib/` can be deployed + consumed as soon as we choose to. incident-viewer remains bundled (decision #1), so no rush. - **Before privatizing:** land the TaosEngine PR (the `locateAsset` hook) so the engine can carry the token to its workers/wasm; then add the API-token gate on `/taos` and flip consumers to the tokenized asset-base.