docs(street-level): README, DATA_SOURCES, CURRENT-STATE, SECURITY, CHANGELOG

Describe the provider-neutral layer, the PROVIDERS chip row, the shared
filter and its share-link options, and how a new provider registers.
Drop every mention of the removed plain-English query and Anthropic key.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Said TurkseverandClaude Fable 5.1 committed 2026-09-25 18:37:42 +01:00
1 parent 28e6a1faa7
commit 33ee9bf23e
5 files changed
+44 -27

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
# Changelog
- Street Level (Mapillary): a new layer draws Mapillary coverage on the globe from orbit down to a single street, opens photos and 360° panoramas in an embedded MapillaryJS viewer beside the CCTV panel, and answers plain-English questions ("show me all fire hydrants in Sacramento") with Mapillary's detected objects and traffic signs when an Anthropic key is present; the layer needs a free Mapillary client token and credits CC BY-SA 4.0 imagery on the globe.
- Street Level: a provider-neutral street-level imagery layer modelled on the iD editor's photo overlay. One panel in the right rail carries a chip per imagery provider, shared 360°/flat and captured-since filters, coverage drawn on the globe from orbit down to a single street, image cones per sequence, and one embedded viewer whose adapter follows the provider of the open image; each active provider credits its imagery on the globe, and share links carry the provider switches and the filter. Mapillary is the first provider (free client token; CC BY-SA 4.0 imagery); Google Street View, KartaView and Panoramax are next.
- CCTV cameras whose bearing is a guess now say so. Packs mark bearings derived
from a hash of the camera id as `headingConfidence: 'low'`, but nothing read the
+1 -2
View File
@@ -21,8 +21,7 @@ How to read this:
| **NOAA nowCOAST lightning density** (`nowcoast.noaa.gov/geoserver/observations/lightning_detection/ows`) | Lightning density: 15-minute accumulated strike density on an approximately 8 km grid, Americas and Pacific. Keyless; layer metadata refreshed every 10 minutes, exact-time images cached for up to 24 hours | NOAA Level-5 derived product from Vaisala NLDN/GLD360; the [product description](https://ocean.weather.gov/lightning/lightning_pdd.php) permits public distribution of this density product, not of raw Vaisala detections | "NOAA/NWS nowCOAST; derived from Vaisala NLDN/GLD360" |
| **NOAA NHC / CPHC advisories** (`www.nhc.noaa.gov/CurrentStorms.json` + the `mapservices.weather.noaa.gov` tropical weather summary MapServer) | Cyclone advisories: storm positions, forecast tracks, points and cones for the Atlantic and eastern/central North Pacific. Keyless through `/api/cyclones`; cached for 5 minutes | [NWS public-data terms](https://www.weather.gov/disclaimer); no endorsement implied | "NOAA/NWS NHC / CPHC" |
| **OpenStreetMap ALPR camera locations** (including DeFlock community mapping) | Optional mapped automatic license-plate-reader camera layer | [ODbL 1.0](https://opendatacommons.org/licenses/odbl/1-0/); commercial use permitted with applicable attribution and database share-alike obligations | [© OpenStreetMap contributors](https://www.openstreetmap.org/copyright); [DeFlock](https://deflock.org) community mapping |
| **Mapillary** (vector tiles, Graph API, MapillaryJS) | Street Level layer: coverage, image cones, embedded viewer, and the map features / traffic signs behind the plain-English query box | Imagery and derived data [CC BY-SA 4.0](https://www.mapillary.com/terms); API use under the Mapillary Platform Terms with a client token; tiles are cached locally for 24 h | "Imagery © Mapillary contributors, CC BY-SA 4.0" — shown on the globe while the layer is on, and by the embedded viewer's attribution component |
| **mapillary_sprite_source** (icons) | Map-feature icons on the globe | [MIT](https://github.com/mapillary/mapillary_sprite_source/blob/master/LICENSE) | Copyright (c) 2015 mapillary |
| **Mapillary** (vector tiles, Graph API, MapillaryJS) | Street Level layer, Mapillary provider: coverage lines, image cones and the embedded viewer | Imagery and derived data [CC BY-SA 4.0](https://www.mapillary.com/terms); API use under the Mapillary Platform Terms with a client token; coverage tiles are cached locally for 24 h | "Street Level: imagery © Mapillary contributors, CC BY-SA 4.0" — shown on the globe while the provider is on, and by the embedded viewer's attribution component |
| **Google Map Tiles API** (Photorealistic 3D Tiles) + Places/Geocoding | The 3D globe, voice scene context, and on-demand nearby installation search | Google Maps Platform ToS (proprietary, your own key + billing) | "Google" / "Google Maps" logo — **shown in-app**, required |
| **OpenSky Network** | Primary worldwide live-flight snapshot | Non-commercial research/education license | Schäfer et al., _"Bringing Up OpenSky"_, IPSN 2014 + opensky-network.org |
| **adsb.lol point API** | Bounded live-flight fallback when OpenSky has no usable snapshot | ODbL 1.0 | adsb.lol contributors; `api.adsb.lol/v2/lat/{lat}/lon/{lon}/dist/{radius}` |
+10 -10
View File
@@ -290,7 +290,7 @@ Twenty layers and map sources. **Seventeen have a keyless path.** Some offer add
| 🚗 **Traffic** | Simulated vehicles on OSM roads. With TomTom, live flow speeds drive the simulation and congestion colors below ~8 km; individual vehicle positions are not live observations | TomTom + OSM | 🟢 simulation · 🟡 live flow speeds |
| 📹 **CCTV Mesh** | ~3,600 public cameras projected _into_ the 3D space — Austin · Texas (TxDOT) · California (Caltrans) · London (TfL) · Ontario (511) · Finland (Fintraffic) · British Columbia (DriveBC) · Estonia (Tallinn, Tarktee) · Delaware (DelDOT live video) · New South Wales (Live Traffic NSW) · Calgary. Positions are published; poses are estimated priors **you calibrate by dragging a gizmo on the camera itself** | City APIs | 🟢 |
| 📷 **Mapped ALPR Cameras** | License-plate-reader camera locations tagged by OpenStreetMap contributors, loaded one city-sized view at a time, with **SHOW NEAREST**. Locations and tags only: no plate data, no video | OpenStreetMap (incl. DeFlock mapping) | 🟢 |
| 📷 **Street Level** | Mapillary coverage drawn onto the streets from orbit down to a single road, image cones per sequence, an embedded MapillaryJS viewer with a **CAMERA FOLLOWS VIEW** mode, and a plain-English query box (_"show me all fire hydrants in Sacramento"_) that streams Mapillary's detected objects and traffic signs onto the globe with Mapillary's own icons | Mapillary (+ Anthropic for the query box) | 🟡 Mapillary client token · 🔴 Anthropic key for plain-English queries only |
| 📷 **Street Level** | Street-level imagery from several providers behind one panel, modelled on the iD editor's photo overlay: a chip per provider, shared 360°/flat and captured-since filters, coverage drawn onto the streets from orbit down to a single road, image cones per sequence, and an embedded viewer with a **CAMERA FOLLOWS VIEW** mode. Mapillary ships in this build; Google Street View, KartaView and Panoramax are planned | Mapillary | 🟡 Mapillary client token |
| 📻 **Radio** | Geolocated world radio with an **analog tuner** — drag the needle across up to 750 stations and the globe flies to each broadcaster | Radio Browser / broadcasters | 🟢 |
| 🚌 **Transit** | Live buses, trams, metros, trains and ferries with delayed playback between reports, selected-vehicle trails, and mode-coloured DETECT labels — Boston, Austin, Minneapolis, Helsinki, the Netherlands, Norway, South East Queensland | Operator GTFS-Realtime feeds | 🟢 |
| 🚲 **Bikeshare** | Live station availability | GBFS | 🟢 |
@@ -326,18 +326,19 @@ _The Space Missions layer replaying a Falcon 9 ascent — labeled `RECONSTRUCTED
---
## 📷 Street Level (Mapillary)
## 📷 Street Level
> Needs a free **Mapillary client token**; the plain-English query box additionally needs an **Anthropic key**. Both go in POWER UP.
> One panel for street-level imagery from any provider. This build registers **Mapillary**, which needs a free **Mapillary client token** in POWER UP; Google Street View, KartaView and Panoramax are the next providers.
**Getting the keys**
Setup for Mapillary:
1. **Mapillary client token (required, free).** Sign in at [mapillary.com/dashboard/developers](https://www.mapillary.com/dashboard/developers), choose **Register application**, give it any name and website, tick **Read** access, and copy the **Client Token** (it starts with `MLY|`). Paste it into **POWER UP → Mapillary**, or set `MAPILLARY_CLIENT_TOKEN` in `.env` and restart `npm run dev`.
2. **Anthropic key (optional).** Create one at [console.anthropic.com](https://console.anthropic.com/settings/keys) and add it in **POWER UP → Anthropic** or as `ANTHROPIC_API_KEY` in `.env`. It stays on the server; only the plain-English query box uses it.
1. **Mapillary client token (free).** Sign in at [mapillary.com/dashboard/developers](https://www.mapillary.com/dashboard/developers), choose **Register application**, give it any name and website, tick **Read** access, and copy the **Client Token** (it starts with `MLY|`). Paste it into **POWER UP → Mapillary**, or set `MAPILLARY_CLIENT_TOKEN` in `.env` and restart `npm run dev`.
Without the Mapillary token the STREET LEVEL panel reads **KEY REQUIRED** and its controls stay greyed out; without the Anthropic key everything except the query box works.
Without the token the STREET LEVEL panel reads **KEY REQUIRED**, the Mapillary chip turns amber and the controls stay greyed out.
Turn on **Street Level (Mapillary)** under DATA LAYERS → Cameras, or open the STREET LEVEL strip in the right rail. Mapillary's coverage draws as ground-hugging lines (recent captures bright green, older ones dim, 360° panoramas magenta); click a line for its image cones and a cone to open the photo in the embedded MapillaryJS viewer. **EXPAND** grows the viewer to most of the screen and **CAMERA FOLLOWS VIEW** drives the globe camera from the panorama. With an Anthropic key, type a request such as _"stop signs in downtown Detroit"_ and the matching detections stream onto the globe tile by tile with Mapillary's own icons; click one to see the photo with the detection outlined. Mapillary blurs faces and licence plates before publishing imagery, and the globe credits "© Mapillary contributors, CC BY-SA 4.0" while the layer is on.
Turn on **Street Level** under DATA LAYERS → Cameras, or open the STREET LEVEL strip in the right rail. The **PROVIDERS** row has one chip per registered provider; switch a provider off and its coverage, its on-globe credit and its share-link bit go with it. The **IMAGERY** filter (ALL / 360° / FLAT) and the **SINCE** window apply to every provider at once. Mapillary's coverage draws as ground-hugging lines (recent captures bright green, older ones dim, 360° panoramas magenta); click a line for its image cones and a cone to open the photo in the embedded viewer, or press **OPEN NEAREST PHOTO** for the closest image to the view centre. **EXPAND** grows the viewer to most of the screen and **CAMERA FOLLOWS VIEW** drives the globe camera from the panorama; the caption links to the image on the provider's own site. Mapillary blurs faces and licence plates before publishing imagery, and the globe credits "© Mapillary contributors, CC BY-SA 4.0" while the provider is on.
Share links carry the layer's provider switches and filter (`3.m.0` turns Mapillary off, `3.p.p` keeps only panoramas, `3.s.365` shows the last year). Adding a provider means implementing the contract in `src/layers/streetLevel/registry.js` and registering it in `src/app/layers/streetLevel.js`; the chip, credit and share bit follow.
## 🎖️ Field Missions
@@ -430,8 +431,7 @@ Eight keys. Five have a free tier, and the three 🔴 ones are metered:
| 🟡 | **AISStream** | 🚢 Live global ships | [aisstream.io](https://aisstream.io) — free signup |
| 🟡 | **NASA FIRMS** | 🔥 Live active fires | [firms.modaps.eosdis.nasa.gov](https://firms.modaps.eosdis.nasa.gov/api/map_key/) — free |
| 🟡 | **TomTom** | 🚦 Live flow speeds and congestion colors for the simulated traffic layer | [developer.tomtom.com](https://developer.tomtom.com) — free tier available |
| 🟡 | **Mapillary** | 📷 Street-level coverage, photos and detected objects on the globe. A public client token by design (see SECURITY.md) | [mapillary.com/dashboard/developers](https://www.mapillary.com/dashboard/developers) — register an app, copy its Client Token |
| 🔴 | **Anthropic** | 💬 Plain-English questions in the Street Level panel, turned into Mapillary queries server-side. Coverage, photos and filters work without it | [console.anthropic.com](https://console.anthropic.com/settings/keys) — metered, roughly a cent per question |
| 🟡 | **Mapillary** | 📷 Street-level coverage and photos on the globe (the Street Level layer's Mapillary provider). A public client token by design (see SECURITY.md) | [mapillary.com/dashboard/developers](https://www.mapillary.com/dashboard/developers) — register an app, copy its Client Token |
![Diving from city-scale live congestion straight into an intersection's public camera](docs/media/05-traffic-to-cctv.gif)
+1 -1
View File
@@ -28,7 +28,7 @@ These are designed to be used directly in the browser (like a Mapbox public toke
1. **Google Maps API key** — loads Photorealistic 3D Tiles directly and powers GEV place search. **Restrict it** (HTTP referrer + API restriction to the required Google APIs) in the Google Cloud Console. An unrestricted key in a public deployment can be abused and billed to you.
2. **Cesium ion token** (`CESIUM_ION_TOKEN`, optional — for ion-hosted Google Photorealistic 3D Tiles, Bing world imagery, and world terrain) — used as `Cesium.Ion.defaultAccessToken` client-side. Use a public **`assets:read`** token with **URL restrictions** for any hosted deployment. The Community plan has eligibility and usage limits; a public token is not a secret, but it can still consume the account's quota.
3. **Mapillary client token** (`MAPILLARY_CLIENT_TOKEN`, optional — street-level imagery, coverage tiles and the plain-English query box) — used by the embedded MapillaryJS viewer and for Graph API lookups client-side. Mapillary client tokens are designed for browser use and can be scoped per application in the Mapillary developer dashboard; the dev server uses the same token for cached vector-tile fetches. The Anthropic key behind the query box never leaves the server.
3. **Mapillary client token** (`MAPILLARY_CLIENT_TOKEN`, optional — the Street Level layer's Mapillary provider: street-level imagery and coverage tiles) — used by the embedded MapillaryJS viewer and for Graph API lookups client-side. Mapillary client tokens are designed for browser use and can be scoped per application in the Mapillary developer dashboard; the dev server uses the same token for cached coverage-tile fetches.
> The explicit browser `define` block in `build/vite.js` controls exactly what reaches the client: only these three keys. Everything else stays server-side.
+31 -13
View File
@@ -2766,24 +2766,42 @@ its criteria cannot be silently ignored.
| Dams ▰ | OpenInfraMap/OSM extract (bundled) | `src/data/localLayers.js` | — | static |
| Submarine Cables ◠ | TeleGeography public map (bundled) | `src/data/telegeographySubmarineCables.js` | — | static |
| FIRMS Active Fires ▲ | NASA FIRMS live (VIIRS ×3 NRT + MODIS NRT, trailing 24h) | `src/data/firmsHeatmap.js` | `/api/firms` (`FIRMS_MAP_KEY`) | 10 min (proxy TTL 30 min) |
| Street Level 📷 | Mapillary vector tiles + Graph API + MapillaryJS (optional Claude planner, server-side key) | `src/layers/mapillary/` via `src/app/layers/mapillary.js` | `/api/mapillary/status`, `/tiles`, `/features` (NDJSON), `/plan`, `/sprite` (`MAPILLARY_CLIENT_TOKEN`; `ANTHROPIC_API_KEY` optional) | camera-driven (320 ms debounce, ≤9 coverage tiles); queries on demand (≤600 tiles, cached 24 h) |
| Street Level 📷 | Provider-neutral street-level imagery; Mapillary registered (vector tiles + Graph API + MapillaryJS) | `src/layers/streetLevel/` (core) + `src/layers/streetLevel/providers/mapillary/` via `src/app/layers/streetLevel.js` | `/api/mapillary/status`, `/api/mapillary/tiles/coverage/{z}/{x}/{y}` (`MAPILLARY_CLIENT_TOKEN`) | camera-driven (320 ms debounce, ≤9 coverage tiles, cached 24 h) |
| Wind 🌬 | NOAA GFS 10 m wind (keyless, 0.25°→1° grid; animated particles) | `src/data/wind.js` | `/api/wind` | 1 h (forecast cycle) |
| Fire Perimeters 🔥 | NIFC WFIGS current interagency perimeters (keyless, paged past the 2000-record cap); InciWeb catalog + incident page origin and update time checks for verified incident-page links | `src/layers/perimeters/` via `src/app/layers/perimeters.js` | `/api/fire-perimeters` + `/api/fire-perimeters/inciweb/*` | 5 min (server caches: catalog 1 h; publication 30 min) |
Fire Perimeters uses capped, timed server reads with stale-on-error caching and a per-client limit. Unchanged snapshots retain geometry; link checks cancel on disable or selection change, and the row legend shows reported containment.
Street Level (Mapillary) lives in the right context rail next to CCTV as an
ordinary collapsible panel and starts collapsed. Without `MAPILLARY_CLIENT_TOKEN`
the header status reads KEY REQUIRED and the controls stay disabled (key setup
is documented in the README's Street Level section); with it, coverage
draws as ground-clamped sequence lines (z0–5 overview points from orbit,
z11–14 sequences below 60 km) and the proxy strips the unused `image` point
layer from z14 tiles in transit (12 MB → ~80 KB). The plain-English query box
is only live with `ANTHROPIC_API_KEY` (server-side; the browser posts the
sentence to `/api/mapillary/plan`). While enabled the layer adds an on-globe
Cesium credit ("Imagery © Mapillary contributors, CC BY-SA 4.0"). Follow-ups
kept out of the first landing: procedural 3D objects for results, a Google 3D
map-stack shortcut, and portable/resizable rail panels.
Street Level lives in the right context rail next to CCTV as an ordinary
collapsible panel (`#street-level-panel`, share token `3`, option owner
`street-level`) and starts collapsed. It is modelled on the iD editor's photo
overlay: one panel, a PROVIDERS chip per registered imagery provider, shared
360°/flat and captured-since filters (stored as relative days so a link keeps
its meaning), one viewer host, and one on-globe credit per active provider.
Share options: `m` (Mapillary on/off), `p` (a/p/f panorama mode), `s`
(since, days). Only Mapillary is registered in this build. Without
`MAPILLARY_CLIENT_TOKEN` the header reads KEY REQUIRED, the Mapillary chip
turns amber and the controls stay disabled; with it, coverage draws as
ground-clamped sequence lines (z0–5 overview points from orbit, z11–14
sequences below 60 km) and the proxy strips the unused `image` point layer
from z14 tiles in transit (12 MB → ~80 KB).
Street-level providers implement the contract documented in
`src/layers/streetLevel/registry.js`: a definition (`id`, `name`, `label`,
`requiresKeyId`, `pickPrefix`, `colors`, `credit`, `capabilities`, `legend`,
`externalUrl`, `create`) whose `create(context)` returns an instance with
`status`, `init`/`activate`/`deactivate`/`destroy`, `refreshCoverage`,
`setFilter`, `coverageStats`, `handlePick`, optional sequence selection,
`nearestImage`, and a viewer adapter (`mount`/`open`/`close`/`unmount`/
`resize`/`onPose`) that emits a provider-neutral pose. The core routes clicks
by pick prefix, swaps viewer adapters in the one host, adds and removes each
provider's Cesium credit, and fans the filter out to every provider. Adding a
provider: implement the definition, register it in
`src/app/layers/streetLevel.js`, add its boolean option to the `street-level`
group in `src/data/layerState.js` and its modules to
`scripts/package-boundaries.json`; the chip, credit and legend follow. Once a
keyless provider registers, `requiresKeyId` on the layer becomes null and the
key gate moves to the chips, by design.
Directions is a keyless front end to the routing the voice agent already
uses. Its row chips are the whole interface: DRIVE / WALK / BIKE pick the