Commit Graph
139 Commits
Author SHA1 Message Date
Said Turksever 40be3bc54d Merge branch 'main' into fix/nyc-cctv-pack 2026-10-14 12:52:49 +01:00
Said TurkseverandClaude Opus 5.5 e9a4dbb062 fix(street-level): KartaView marker and camera direction; remaining review P4s
Marker and direction (reported on the PR):
- KartaView has its own marker, a purple view cone (Street View's is
  blue), not GEV's default pin that Mapillary uses.
- The camera direction (marker, cones, FOLLOW, a panorama's centre) is
  the direction of travel to the next photo a few metres on. KartaView's
  heading is the device compass: whole drives read 0 (no compass) and
  others sit a steady ~110° off. Until the drive loads the compass stands
  in (0 = unknown), and the pose is sent again once the course is known.

Remaining P4s from the review of #1121:
- Segment chaining is linear (a per-point cursor) and capped at 20,000
  segments a tile and 5,000 points a line: a hostile tile of 60k segments
  sharing one point took 1.5 s, now tens of ms.
- Decoded tiles are dropped when KartaView is switched off.
- No network / a refused request says so and is not retried as a timeout;
  an unreadable answer says so.
- A docked flat photo skips the 2,560 px download until the viewer grows.
- The panel counts the drive's photos (countActivePhotos), not the thinned
  page of cones (2,250, not 217).
- After a GPU reset the viewer redraws the photo itself, so a lookup the
  user started is not cancelled; a failure is still reported.
- The gate's keyless page lights KartaView and checks it draws with no key;
  the fixture answers the sequence count; the line-click step checks the
  camera looks along the drive when the compass says 200°.
- README/CHANGELOG show the share-link form the app writes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 12:17:33 +01:00
Said TurkseverandClaude Opus 5.5 128a689a56 fix(cctv): make the NYC DOT pack opt-in and carry DOT's disclaimer
NYC DOT asks developers who use its camera feed to sign a data-sharing
agreement, and this project does not hold one that covers downstream
installs. The pack now loads only when CCTV_NYC_ENABLED=1; unset, empty
or any other value makes no request to webcams.nyctmc.org (tested).

The NYC credit carries NYC DOT's requested application disclaimer
verbatim, and DATA_SOURCES, README, CHANGELOG, CURRENT-STATE and
.env.example describe the prerequisite.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 11:44:25 +01:00
ulihhhh b57f2ded7f Merge remote-tracking branch 'upstream/main' into pr595-sync
# Conflicts:
#	README.md
2026-10-14 10:14:36 +02:00
Cliff Flood 51b89d3e4a feat(cctv): add the City of Toronto RESCU camera pack
The province's 511 pack covers Ontario's highways; this adds the municipal
network underneath it — roughly 336 cameras across downtown arterials plus
the Gardiner, DVP, Allen and Lake Shore, from the City's own open data.

The list is keyless and carries no frame URL, so frame URLs are built from
the convention the dataset documents (`CameraImages/loc####.jpg`) and a
camera number validated as plain digits. The frame proxy is therefore
pinned to the portal origin by construction rather than by trusting a
field. The list fetch refuses redirects, bounds the body it buffers, and
releases the transport on every rejection path.

The dataset publishes no camera facing. `D1`-`D4` look like a compass and
map trivially onto one, but they describe the *comparison* images — static
reference stills captured in 2016 and served from a different path — not
the live pan-tilt-zoom frame. A heading derived from them would be
confidently wrong for every camera in the city, so every camera takes the
shared id-hash fallback at low confidence, as headingless Austin, TfL,
Fintraffic and Calgary cameras do. A test pins that down so it is not
"fixed" later.

Names stay verbatim: the feed's labels are upper-case, and title-casing
would mangle MCCOWAN RD and ST HELEN'S AVE more often than it helped.

Carries the Open Government Licence – Toronto attribution the licence
requires. Disable with `CCTV_TORONTO_ENABLED=0`.
2026-10-13 18:54:59 -04:00
Said TurkseverandClaude Opus 5.5 bd0bbf5134 fix(street-level): IC8 review of KartaView — cones on the right page, pano sizing
P1s from the correctness review, each with a regression test:
- Cones showed the wrong page of a long sequence (cache keyed by
  sequence; no re-centre after a close or a same-drive line click):
  KartaView always reselects, and re-centres whenever a photo of the
  selected sequence opens on another page.
- A 360° photo's first frame was one colour: the canvas was sized while
  hidden (1×1). It is shown first, and re-measured every frame.

P2/P3s: a storage timeout or 5xx is not remembered as archived (only
403/404/409/410 are); dense z13 tiles draw up to 1,600 lines (a third of
downtown Detroit was cut); decoded tiles are kept 10 min; a timed-out tile
is asked once more; pages are 250 photos and the newest page request goes
first; a photo far past deleted ones, or unlisted at a page edge, still
finds its neighbours; a step that gets no answer is not the end; a lost
WebGL context redraws the photo, and a failed one is retried on the next
mount; the first flat image comes from the proxy (KartaView's own can be
1.7 MB); fileurl fallbacks must be https storage hosts; oversized answers
are refused; keyboard (Shift+← →, ↑ ↓, + −) and pinch look around a
panorama; focus stays in the viewer when a step button disables. Docs:
share links with 0.m.0, keyless count, CURRENT-STATE matched to the code.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 20:08:23 +01:00
Said TurkseverandClaude Opus 5.5 310984ff0b test(street-level): KartaView in the hermetic browser gate; docs
The fixture gate answers api.kartaview.org, cdn.kartaview.org and
*.openstreetcam.org from fixtures (a drive with a 360° photo, stored on
storage2 while the API names storage1) and adds three steps: keyless
coverage with its credit and hidden filters, a line click opening the
nearest photo with cones and ›, and a 360° photo on the panorama without
FIT / FILL. The Street View share-link check reads the switch field instead
of one exact entry, since a chip click records every provider's switch.

README, DATA_SOURCES, CHANGELOG and CURRENT-STATE describe KartaView.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 18:42:36 +01:00
Said TurkseverandClaude Opus 5.5 b1efd22f02 feat(street-level): one imagery source at a time; IC8 review fixes
- One provider is lit at a time: lighting a chip darkens the others, and a
  chip click records every registered provider's switch in one update so
  the share link keeps the swap (also off Google 3D, where Street View is
  not listed). The layer starts with the first default-on provider
  (Mapillary, free); params that light several keep the one already on,
  so reapplying them never flips (litByParams). The now-unreachable
  "several lit" chip paths are gone.
- Leaving Google 3D during a Street View lookup ends it without an error
  or a stuck loading state (openImage's early return resets it; the
  lookup loop rechecks availability).
- A source swap during a lookup no longer reports "no imagery".
- Street View lit off Google 3D says the panel needs the Google 3D map.
- Comments trimmed to the why; keySetupCore.test.mjs back to upstream's
  formatting plus the one new test (was a 551-line reformat).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 15:10:58 +01:00
Said TurkseverandClaude Opus 5.5 64d939f3d2 feat(street-level): Street View polish — name, filters, legend, marker
- The chip reads GOOGLE STREET VIEW (and its caption link likewise).
- Providers declare the imagery filters they honour (`filters`, default
  pano + since). Street View declares none: every panorama is 360° and it
  draws no coverage to thin, so its lookups ignore the filters and the
  panel hides IMAGERY and SINCE while it is the only lit provider.
- The legend lists only providers that draw coverage lines, with
  Selected only beside one: Street View alone shows no legend.
- Providers may pick their on-globe marker (`marker`); Street View's is a
  Google-blue field-of-view cone from a white-ringed dot, in place of
  GEV's amber pin, and switches back for a Mapillary photo.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 14:05:57 +01:00
German KhokhlovandClaude Fable 5.1 c29ccd55d6 Merge origin/main: keep the provider registry, slim it
main grew the Street Level provider registry while this branch removed it
(#982–#985: injected providers, an empty composition, the `r` switch field).
The registry, params, uiState and pick router come back as main has them and
the slimmed layer sits behind the provider contract:

- The core (index.js) drives providers as on main, without surface modes,
  ground casting, FOLLOW, prewarm and nearest-image lookups. A provider's key
  status is asked with a 10 s timeout and asked again on a switch-on while no
  key is known.
- Mapillary is mapillaryProvider.js over the slim coverage, sequences and
  viewer modules, which read the filter and the active flag from the provider
  context.
- The viewer host mounts one provider adapter at a time, no prewarm.
- The panel has a chip per provider again (the pill switches the layer);
  no legend, EXPAND stays the Fullscreen API.
- The contract drops what no provider implements: groundCaster, meshSampler,
  getSurface/setSurface, nearestImage, prewarm, reportError, the legend and
  surface fields of the UI snapshot.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-10-13 13:24:25 +04:00
Matt Van Horn 3cf9a8d65d feat(cctv): add NYC DOT Traffic Management Center camera pack
Register the keyless webcams.nyctmc.org catalog as a live CCTV source,
synthesize frame URLs from validated camera UUIDs, and keep the nearest
cameras to the five borough cores under the existing catalog ceiling.
2026-10-12 19:18:45 +00:00
ulihhhhandClaude Opus 5.5 97492e28fe docs: list the Catalonia pack under Unreleased and in the README
The changelog entry sat below the 0.2.0/0.2.1 release headings after those
were cut; move it to [Unreleased] beside the Norway pack. Name Catalonia in
the README's CCTV Mesh row the way the other packs are listed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 13:04:55 +02:00
Said TurkseverandClaude Opus 5.5 76db4114ff Merge upstream/main into pr/google-street-view
Conflicts with upstream's Street Level provider composition and share-state
codec, resolved:

- Street View's switch moves from its own share option (`g`) to upstream's
  provider-switch field (`r`, e.g. `0.r.google-1`); a link without it keeps
  Street View off. Docs and the browser gate follow.
- createApplicationStreetLevel keeps upstream's injectable provider list;
  its default, once the application supplies its Street Level source, is
  Mapillary plus Google Street View. Without that source there are none, as
  upstream intends.
- The coverage hint keeps upstream's empty-composition message and joins
  every switched-on provider's hint otherwise.
- CHANGELOG, README and SECURITY keep both sides' entries.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 11:32:05 +01:00
cj-vana 11bc2ec0ae feat(search): resolve two-dimensional geo URIs offline 2026-10-11 20:58:02 -06:00
SM-26andClaude Opus 5.5 3ade710ce0 docs(docker): say where data lives, and fix the UID/GID commands
The Path 3 section assumed readers already knew how a bind-mounted container
persists state (14traits, #208). It now lists what the app saves and where,
with the NAS and reverse-proxy detail in the collapsed block that was already
there, so the open part stays about the same length.

It also fixes two commands that did not do what they said in bash, confirmed
in bash and dash by PoBruno: `UID=1026 GID=100 docker compose up` prints
"UID: readonly variable" and still runs as the caller's UID, and
`export UID GID` exports an empty GID because bash does not define one. Both
are now `env UID=... GID=...`, which `docker compose config` resolves to the
requested ids.

Suggested-by: 14traits
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 19:48:02 +02:00
1c6c291774 fix(docker): let Provider Settings admit the host through the published port
Docker delivers the host's own browser to the container from the container
network's gateway, never from 127.0.0.1, so the loopback-only admission gate
answered every POWER UP request with 403 and no key could be saved. The README
and CHANGELOG claimed otherwise; both are corrected here.

- keySetupCore: GEV_KEY_SETUP_TRUSTED_PEERS, an exact-address list (no
  wildcards, prefixes or hostnames) admitted alongside loopback. Unset trusts
  nothing, and the sharing, Host, Origin, Content-Type and proxy-header checks
  all still apply to a listed address. Twelve assertions pin each refusal.
- scripts/docker-start.mjs: the container entry point, shaped after
  scripts/pinokio-start.mjs. It reads the default gateway from /proc/net/route,
  trusts exactly that address, and starts Vite. No gateway (--network none)
  trusts nothing. The pure helpers are unit-tested and a contract test pins the
  Dockerfile CMD and the loopback-only publish.
- Dockerfile: install git. `npm test` builds fixtures with `git init`, so the
  suite failed 71 tests inside the image and the README's claim that it runs in
  the container was wrong.
- SECURITY.md and .env.example document the setting and why it is safe only
  behind a 127.0.0.1 publish; README gains the Linux/NAS id note and .dockerignore
  drops macOS AppleDouble sidecars, both reported on the PR.

Verified in Docker on a clean build: saving a key from the panel writes the
bind-mounted .env (0600 in the container), it survives `compose down`/`up`, and
REMOVE comments it back out. A foreign Origin, a foreign Host, a proxy header
and a sibling container on the same network are each refused. `npm run doctor`,
`npm test` (5067 passed, 1 skipped, 0 failed) and `npm run build` are green
inside the container.

Reported-by: @jklaze
Co-Authored-By: Bogdan Petrut <[email protected]>
Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-10 19:48:02 +02:00
SM-26andClaude Opus 5 2e50836b08 feat: add a Docker install path
Vite's dev server is the whole app here — it serves the client and runs every
API proxy as middleware — so one container running `npm run dev` covers it, and
HOST/PORT are already env-driven.

Three details are deliberate:

- The port publishes to 127.0.0.1. Docker's usual "4173:4173" binds every host
  interface, which would silently make the README's LAN warning the default for
  a server that brokers configured provider keys.
- The repo is bind-mounted, so keys saved from Provider Settings, .gev-cache
  and .gev-logs persist on the host exactly as they do under `npm run dev`.
  node_modules stays in the image so a host install cannot shadow the
  Linux-built native deps.
- The container runs as the host user, since everything it writes lands in
  that bind mount. Vite's dep optimizer still needs to write inside the image's
  node_modules, hence the two loosened directories.

Puppeteer's Chromium download is skipped: it is only needed by `npm run
test:track`, which the README points at the host.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-10 19:48:02 +02:00
Sameh Khamis 8979d159bb docs(voice): note the Windows Codex login workaround 2026-10-08 11:03:18 -07:00
Sameh Khamis fb1596d2f1 Merge main into PR #621 (ChatGPT OAuth for Realtime voice)
Resolve conflicts with the voice-core captions, panel resize and MCP
panel key changes by keeping both sides.
2026-10-08 11:00:54 -07:00
bassem chagra b7d25f4c69 Merge origin/main into feat/wsdot-camera-pack
Resolve the source-pack conflicts with Statens vegvesen (keep both packs).
The Norway pack's 900 default pushed the per-pack defaults to 5,204, past
the 4,500 catalog cap this PR enforces, so raise DEFAULT_CCTV_MAX_SOURCES
to 5,500 and CCTV_MAX_SOURCES_CEILING to 6,000.
2026-10-08 15:59:09 +02:00
bassem chagra 054f1cc198 Merge remote-tracking branch 'origin/main' into feat/king-county-camera-pack
# Conflicts:
#	.env.example
#	CHANGELOG.md
#	DATA_SOURCES.md
#	README.md
#	docs/CURRENT-STATE.md
#	server/providers/cctv/catalog.js
#	server/providers/cctv/sources.js
#	src/data/dataCredits.js
2026-10-08 15:52:38 +02:00
German KhokhlovandClaude Opus 5.5 35bfe203a6 Merge remote-tracking branch 'origin/main' into german/street-level-slim
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 16:04:02 +04:00
Said TurkseverandClaude Opus 5.5 ef396655fc feat(street-level): OPEN STREET VIEW, and Street View only on Google 3D
- OPEN STREET VIEW in the PROVIDERS row opens Street View's nearest
  panorama at the ground under the middle of the screen, without moving
  the camera: Street View no longer needs a pointer. It is disabled (and
  says so) until the camera is at street zoom.
- Off the Google 3D map Street View does not appear at all: no chip,
  legend swatch, globe credit, layer source or button, and Google's script
  is not loaded (the viewer has no prewarm; the script loads on first use).
  The share option keeps the user's choice for when Google 3D returns.
- A ground click measures the camera height at the click rather than
  reading the cached flag.
- A chip without a usable key explains it instead of lighting; it darkens
  beside a lit chip, and the other chips keep switching, so a refused
  Street View key cannot lock Mapillary out.
- The gate checks that nothing of Street View shows off Google 3D even when
  a share link switches it on, presses OPEN STREET VIEW on Google 3D, and
  asserts that each chip it switches really switched.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 12:55:08 +01:00
German KhokhlovandClaude Opus 5.5 94049c5667 refactor(street-level): drop openNearest; QA opens a photo by clicking a line then a cone
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 15:01:42 +04:00
Said TurkseverandClaude Opus 5.5 7bfcf177ac fix(street-level): IC8 review of the Street View provider
Google's Maps Platform terms forbid Street View imagery beside non-Google
maps, so the provider declares requiresMapStack: 'photoreal': off Google
3D its chip is dashed with the reason, lookups and opens skip it, and
leaving Google 3D closes its panorama.

- Ground clicks: only a click on the map itself (scenePick.isSurfacePick:
  nothing picked or Google 3D tile content) at street zoom opens Street
  View, and the camera stays put; higher up the hint says to zoom in.
  scenePick.pickGroundPosition replaces the copy in Directions.
- Viewer: poses go out at once and again when the date and address
  arrive, so an open never hangs on that lookup; one lookup per panorama,
  seeded by the nearest lookup; a close settles a pending open; failed
  lookups are asked again; poses follow position changes, not pano_changed.
- Loader: the gm_authFailure handler is installed once, so a retried load
  reports a refusal once.
- Viewer host: a prewarm that lands after another provider took the host
  is released; FIT/FILL availability is set on every open.
- Provider: a refusal while switched off reports no error over another
  photo; SINCE compares against the end of Google's month; messages name
  the referrer and network causes; FLAT says Street View is 360° only.
- The layer row names the key of the providers that are on; the MCP panel
  CSP admits Street View's tiles, control images and photos.
- Tests for each, against fakes that now follow Google's event order; the
  browser gate restores its state, waits instead of sleeping, aims its
  panel clicks and corner drags, and asserts the camera stays put.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 02:59:51 +01:00
Said TurkseverandClaude Opus 5.5 22b0009138 feat(street-level): Google Street View as the second imagery provider
Google Street View registers beside Mapillary as provider `google`. It runs
on the Maps JavaScript API with the browser GOOGLE_MAPS_API_KEY, loaded on
first use (mapsLoader.js), and uses Google's own StreetViewPanorama as its
viewer adapter, emitting provider-neutral poses (address and month in the
caption, a link to Google Maps, steps along Google's arrows, FOLLOW on
Google 3D). Its chip starts off because every panorama is billed to the
key; the share option is `g`.

Google offers no coverage layer for other maps, so the provider draws
none: with it on, a click on bare ground at street zoom opens its nearest
Google-collected outdoor panorama (groundClick.js). A key Google refuses
reads KEY REJECTED and fails a pending open at once; a lookup Google never
answers fails after 10 s.

Core: providers may declare `groundClick` and `defaultOn`; poses may carry
`capturedAtPrecision` and `title`; the coverage line keeps every
provider's hint; opening one provider's image releases another's
prewarmed viewer; FIT/FILL hides for viewers without render modes. CSP
script-src admits https://maps.googleapis.com. The browser gate gains two
Street View steps (the keyed one skips as 'no Google key' in CI).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 02:32:06 +01:00
Sameh Khamis 1594db9497 Merge main into feat/voice-core and reconcile layer capabilities 2026-10-07 13:14:31 -07:00
German KhokhlovandClaude Opus 5.5 ad58a0bdc4 refactor(street-level): trim QA, tests, styles and docs
The browser gate is one pass over the remaining flows: rail strip and
expand, coverage with fixtures, the ON/OFF pill, 360° and SINCE filters,
KEY REJECTED, nearest photo with caption, × close, phone fit, keyless
KEY REQUIRED on a second page and no page errors. Panel controls are
pressed through the DOM; pick-point search, line/cone clicks, the
framing-cancel, reload/share and status-route probes, the second
viewport and pointer-settling retries are gone (unit tests cover them).

Tests that pinned constants, copy, CSS or source text, or repeated
another test, are removed or merged. CSS loses an unused variable and
duplicate rules. Docs describe the slimmed feature; unused exports and
the layer's dead setCoverageFilter/refreshCoverage surface are removed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 22:41:29 +04:00
German KhokhlovandClaude Opus 5.5 37a96072fa refactor(street-level): one provider, no orbit overview, no prewarm, simpler tile choice
The layer now owns its Mapillary parts directly: the provider registry,
pick router, multi-provider UI summary, params codec helper and provider
context are gone. createStreetLevelLayer({ source }) builds coverage,
sequences, the nearest-image lookup and the MapillaryJS viewer itself; a
single providerOn switch keeps the share link's `mapillary` option (off
draws nothing), and getParams/setParams keep { mapillary, pano, sinceDays }.

No z0-5 overview points: above 60 km nothing is drawn and the panel says to
zoom in; the proxy now serves only coverage z11-14. Tiles come from the
visible ground within range of the camera, ranked from the ground under it
(no line-of-sight ranking or near-range padding). MapillaryJS loads on the
first photo; viewer prewarm is removed. Key status, a rejected key and a
rate limit share one `blocked` state on coverage.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 22:19:24 +04:00
German KhokhlovandClaude Opus 5.5 7dec7883aa refactor(street-level): simpler panel — native fullscreen, no FOLLOW button, no provider chips
EXPAND now uses the browser's Fullscreen API on the viewer element, which
stays in the panel; the hand-built modal (re-parenting to <body>, inert
siblings, focus trap, document-level Esc/Tab, Clean View/recording/cockpit
hide rules) is gone. The button is hidden where the API is missing.

The FOLLOW button and the PROVIDERS chip row are removed. The header pill is
the only layer switch and re-enables a provider switched off elsewhere; under
KEY REQUIRED the error line says which key to add. Chip colour support in
chipGroup, dead CSS and tests pinning the removed behaviour go with them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 21:50:11 +04:00
German KhokhlovandClaude Opus 5.5 fbbc4cda5c refactor(ui): remove floating, resizable rail panels
PR #768 bundled a portable-panel windowing system with the Street Level
layer. Remove it so CCTV and Street Level are ordinary docked right-rail
panels again, as on main before the merge.

Removed:
- header drag to float, 8-way edge/corner resize, double-press snap-back,
  dockOnCollapse, command-dock clearance, float hint toast, floating z floor,
  persisted floating geometry and ResizeObserver re-clamping
  (panelPositionControls.js restored to its pre-#768 version)
- src/ui/panelResize.js and its tests, panelDock.test.mjs
- onPanelResized/dockPanel wiring in PanelChrome, the application shell and
  StreetLevelControls (EXPAND/SHRINK no longer docks)
- :not(.panel-floating) guards and .panel-floating/.panel-portable/resize CSS
- qa:panel-resize, qa-panel-resize.mjs, qa-panelDrag.mjs, their tests, the
  CI "Portable panel gate" step, QA_FAIL_ON_RETRY, and the Street Level
  gate's float/resize/dock steps
- floating-panel docs in README, CHANGELOG, CURRENT-STATE, KNOWN-ISSUES

Kept: the Street Level panel as a docked rail panel (share/cockpit/rail
lists, layout controller, rail and Cyber CSS, EXPAND viewer), and the
independent right-rail alignment fix (settledLeftRailTop, 9dde7b4).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 21:39:33 +04:00
Said TurkseverandClaude Opus 5.5 4ea6631425 docs(street-level): shorten docs and comments before merge
Trim the doc text this PR adds (README, CHANGELOG, CURRENT-STATE,
KNOWN-ISSUES, SECURITY, DATA_SOURCES, .env.example, the CI job comment),
drop code comments that restate the code, cut design-note JSDoc to a line
or two, and drop review tags from test names. Comments only; no code
changes.

Also: README key count (seven keys, two metered), CURRENT-STATE's gate
paragraph (CI runs a production build with a dummy token), the stacked
doc above meshBoxInRange and the orphaned inMeshRange line in
coverage.js, and a duplicate ALPR row in DATA_SOURCES that a merge had
brought back.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-06 21:59:12 +01:00
devv-shayan 26f125c57c Merge remote-tracking branch 'upstream/main' into codex/chatgpt-realtime-oauth 2026-10-06 20:07:36 +05:00
Said Turksever bb88a8b034 Merge branch 'main' of https://github.com/bilawalsidhu/gods-eye-view into pr/mapillary-layer
# Conflicts:
#	README.md
2026-10-05 17:06:24 +01:00
Soma Froghyar 9ba1b345e6 Merge branch 'main' into fix-tomtom-link 2026-10-05 17:48:49 +02:00
Said Turksever 91d8bba4a3 Merge branch 'main' of https://github.com/bilawalsidhu/gods-eye-view into pr/mapillary-layer
# Conflicts:
#	CHANGELOG.md
#	README.md
2026-10-05 13:47:54 +01:00
Soma FroghyarandClaude Sonnet 5.5 ee7a5fb30b fix: link TomTom key setup to /keys and terms to docs.tomtom.com
Address review feedback on #903: the DATA_SOURCES terms link now points
at the actual terms page instead of a sign-in page, key-creation links
go straight to my.tomtom.com/keys, and the README table row is realigned.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-05 09:34:55 +02:00
Soma FroghyarandClaude Sonnet 5.5 491a856a6b fix: point remaining developer.tomtom.com links to my.tomtom.com
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-05 09:34:55 +02:00
Soma Froghyar 19d8ed5867 fix: MyTomTom link to the new one 2026-10-05 09:34:39 +02:00
H4ldenandClaude Opus 5.5 10d10eab6b fix: address review on the Statens vegvesen CCTV pack
- Lower the Vegvesen default cap to 900, still above the ~850 working
  cameras, so the per-pack defaults stay closer to the catalog default.
- Name the flat ground-elevation prior as a known limitation: the feed
  is 2D, and mountain-pass cameras can sit below terrain where neither
  the point-height prior nor the ground snap resolves.
- README: ~3,900 public cameras.
- Use one HLS figure (~135 working) in CHANGELOG and DATA_SOURCES.
- DATA_SOURCES: list the frame and HLS hosts alongside the catalog host.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 05:47:50 +02:00
manjunath22466 ae3612a356 fix voice debug-log privacy and docs drift
omit tool arguments unless content logging is enabled
correct the remaining current tool-count references
2026-10-05 05:46:47 +05:30
H4ldenandClaude Opus 5.5 d43478a547 feat: add Statens vegvesen (Norway) road cameras as a CCTV pack
Norway's ~850 working road cameras load from one keyless GeoJSON request
to the agency's OGC API view of its DATEX 3.1 CCTV table, so no DATEX
account is needed. Faulty cameras are dropped, every camera sits under a
"Norway" category, and the ~135 that publish HLS play as live video
through the existing in-memory relay with the still as fallback. Frames
and manifests are pinned to each camera's own path on the agency hosts.

CCTV_VEGVESEN_ENABLED=0 disables the pack, CCTV_VEGVESEN_MAX_SOURCES
caps it (nearest the largest cities first) and CCTV_VEGVESEN_VIDEO=0
keeps stills only. Attributed under NLOD 2.0.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-04 22:23:16 +02:00
devv-shayan 8f5710e7cb fix(voice): track OAuth login lifecycle and storage readiness 2026-10-04 17:24:30 +05:00
devv-shayan 6c88b78140 Merge upstream main into ChatGPT Realtime OAuth 2026-10-04 12:29:54 +05:00
Said TurkseverandClaude Opus 5.5 5a7ce5785e Merge upstream/main (v0.2.1) into pr/mapillary-layer
Brings in 123 commits from main, including the v0.2.0 and v0.2.1 releases
(MCP server and tool catalog, server security hardening, build hygiene).

Conflicts:
- package.json: kept main's script order and added this PR's
  qa:panel-resize and qa:street-level; exports keep both sides (main's
  tools/view entries and this PR's street-level and Mapillary entries).
- src/tooling/viteBuild.test.mjs: kept this PR's Mapillary-token define
  assertion and main's new wildcard-host allowedHosts assertions.
- CHANGELOG.md: main now has release sections; this PR's entries go under
  [Unreleased].

Checks after the merge: doctor, format:check, check:boundaries,
layer-token:check (28 published, 1 new: street-level 0), npm test (5726
pass), build, the Windows job's focused tests (70 pass), qa:panel-resize,
and the keyless street-level gate. The new CSP allows Mapillary (https:
connect/img, blob workers). The keyed gate stops at coverage locally
because the dev .env Mapillary token is invalid (upstream 403), not because
of the merge.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-03 13:29:32 +01:00
98b8c6c581 fix(server): keep the Host-header check when binding to all interfaces
Binding HOST=0.0.0.0 no longer sets Vite's allowedHosts to true. The dev and
preview servers accept IP addresses, localhost and the LAN hostnames listed
in GEV_ALLOWED_HOSTS; suffix and wildcard entries are ignored. The
configuration factory takes the resolved list as an input, so build/vite.js
still reads no environment.

Ported from #97 to the current build/vite.js layout. Fixes #21.

Co-authored-by: Sameh Khamis <[email protected]>
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-02 19:59:02 -07:00
bb74071dc2 fix(server): throttle the cost-bearing proxies by default
The OpenAI endpoints (/api/realtime/token, /api/openai/hud-summary) now
allow 30 requests per minute per client IP and the Google Places endpoints
120, the caps the Pinokio build already ships. GEV_RATELIMIT_OPENAI_PER_MIN
and GEV_RATELIMIT_GOOGLE_PER_MIN still override them and exactly 0 disables
them; an unreadable value falls back to the default rather than to
unlimited.

Salvaged from #683 onto current main.

Co-authored-by: Sameh Khamis <[email protected]>
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-02 19:57:29 -07:00
Sameh Khamis bcbc350354 docs: add a one-page MCP setup for Claude and Codex
Steps people and coding agents can follow to run the app, add the MCP
server to Claude Code, Claude Desktop, the Codex CLI and the Codex and
ChatGPT desktop apps, and check it works, linked from the README and the
tools guide.
2026-10-02 18:29:42 -07:00
rileygramlich 8887ca47eb feat(air-quality): add the Air quality layer to the Weather group
Reworks #568 to the shape asked for in review.

Generalized from "AQHI" to a provider-backed Air quality layer, with ECCC's
AQHI as the first registered provider. Readings are carried as
{ provider, scale, value, band } rather than a bare number, because
air-quality indices are not interchangeable: AQHI runs 1-10+ on health risk,
the US AQI runs 0-500 on concentration breakpoints, and Europe's EAQI is a
five-step category. Naming the index a value belongs to is what lets another
network be added without inventing a shared numeric meaning. Coverage is
stated as "Canada only" on the provider, the layer row and the card.

Adds the WEATHER panel readout (readout: true) carrying the band legend and
the worst readings currently in view, with getRowControls/setRowControlsListener
following the wind and cyclone cards. An unresolvable view rectangle degrades
to the worst readings overall rather than to a blank card, and a rectangle
crossing the antimeridian is handled.

update() now takes the earthquakes layer's abort-and-guard shape: it aborts any
in-flight request, passes the signal through to the source, and refuses to
touch the scene when the request was superseded, aborted, or the layer was
disabled while it was outstanding. disable() and destroy() abort too. Tests
cover the late-response, superseded-refresh and disabled-update paths.

Rebased on main: the source is registered in src/sources/reference.js, and the
allocation profile was re-measured against the current worker — median 3,900
B/frame, max 4,114, 85.7 B/candidate, inside the shared 154 ceiling, budgeted
at 5,200 for 26% headroom. The earlier figures no longer held.

Freshness is now judged on the observation time rather than on when the last
response arrived. lastUpdate only says the feed answered; a station that keeps
returning a reading from four hours ago would otherwise be narrated as live by
the HUD and the voice provenance envelope. getStats() reports observedAt and
stale, so layerFeedState() calls the layer stale past two missed hourly
publications, and degraded when a refresh fails over readings that are still
good.

The share-link token is 0, which is what layer-token:next allocates. Taking it
moves the ledger fixtures that had hard-coded 0 as the free digit and 3 as the
one after; those shift to 3 and 4. The pinned equality between the reservation
ledger and LEGACY_LAYER_STATE_TOKENS also had to become "the closed legacy set
plus air-quality", since that set is documented as never growing. Happy to
re-pin this differently if you would rather the fixtures derive the provisional
digits from nextLayerStateToken() so the next layer does not move them again.

The layer and its source are registered as ./layers/air-quality and
./layers/air-quality/source, each with its own boundary group, following the
perimeters pair. check:boundaries requires the package exports and the group
exports to be the same set, so a layer that ships a source needs both.
2026-10-02 15:12:37 -06:00
bassem chagra 0cfb795845 Merge remote-tracking branch 'origin/main' into feat/wsdot-camera-pack
# Conflicts:
#	CHANGELOG.md
#	docs/CURRENT-STATE.md
2026-10-01 12:23:41 +02:00