Commit Graph
515 Commits
Author SHA1 Message Date
Sameh Khamis 4adeae0afe Merge branch 'main' into feat/transit-ontario
# Conflicts:
#	CHANGELOG.md
2026-10-15 19:14:21 -07:00
Sameh Khamis ed00f7af30 Merge branch 'main' into feat/transit-ontario 2026-10-15 19:09:40 -07:00
Sameh Khamis a4888d7846 Merge branch 'main' into feat/cctv-model-spec-enrichment
# Conflicts:
#	CHANGELOG.md
2026-10-15 19:08:55 -07:00
Sameh Khamis d7918d66f2 Merge branch 'main' into feat/brazil-gbfs-cities 2026-10-15 19:03:42 -07:00
Sameh Khamis 419a7afc04 Merge branch 'main' into feat/webapp-icons
# Conflicts:
#	CHANGELOG.md
2026-10-15 18:58:11 -07:00
Sameh Khamis 265c8a1cc0 Tighten datasheet model matching and keep given fields of view
Codec, product and resolution words never identify a model; generation suffixes such as Mk II no longer fall back to the base model; a mismatched manufacturer never matches, and brand-only numeric names need the brand. The datasheet FOV only fills when the source and seed give none and the pose is not curated, and DATASHEET is shown only while no calibration offset applies. Adds the CC0 extract to DATA_SOURCES.
2026-10-15 17:27:55 -07:00
Sameh Khamis 687a94c9df Document Bike Itaú (Tembici) and test the Brazilian cities
The seven feeds publish no licence, operator or attribution fields, so DATA_SOURCES records that and credits the operator. Adds a registry test per city: allowed host and path, provider, and activation over its outermost live station.
2026-10-15 17:27:55 -07:00
Cliff Flood a7fc5ea7c5 feat(transit): add Burlington, switch Barrie and YRT on
Burlington's route ids are internal keys with a trap in them: `351` is
route 1 while `3510` is route 10, so no prefix trim is correct and the
table is a real join against the City's own published GTFS. Its licence is
the same 2011 municipal template as Mississauga — revocable, and the terms
must travel with the data, so licenseUrl is the terms document itself.
Plain http:// has no listener at all, so https is mandatory, not preferred.

Barrie and YRT ship on. Both operators invite acceptance of their licence
through a form, and both licences also state that use is itself acceptance
("By using Barrie Transit Data, you agree to be bound by these terms";
"Your Use of Information indicates Your acceptance"). This deployment
relies on that clause, and both entries record it so the reasoning does not
have to be re-derived.

Nine Ontario feeds now, all verified live against their upstreams.
2026-10-15 20:18:15 -04:00
Cliff Flood 8ccb0cd895 feat(transit): register YRT/Viva off, named by Viva colour
York Region's feed is first-party infrastructure under an open licence that
permits commercial use and does not even require attribution. It is the one
feed that fills the gap north of Toronto, and it is switched off anyway.

The operator asks that its licence be accepted through a form collecting a
name, company, phone and email. No credential is issued and nothing gates
the endpoint — the licence body says use is itself acceptance — but a form
asking for contact details is close enough to the registration this registry
refuses that a person should decide it, not a poller. Barrie is off for the
same reason. Both are one line from on.

Viva route ids get labels: YRT publishes `601` where every station sign says
Viva Blue. The numeric local routes already read correctly and carry no
entry, so the table is six lines, not 125.

No vehicle in this feed carries a bearing; heading comes from observed
movement, as with Durham.
2026-10-15 20:18:15 -04:00
Cliff Flood 11dd914c2f feat(transit): add Guelph and Kingston, register Barrie off
Guelph's feed publishes the internal database key of a route (`2991`)
where the rider sees the number on the bus (`1`), which would have put
"Route 2991" on the label a person reads. So a feed may now carry its own
`routeLabel`, the same way it may carry its own `modeWords`. Guelph's table
is its 33 routes, taken from the City's own published GTFS; an id missing
from it renders unchanged, because a raw id you can compare against the bus
beats a blank. Every other feed is identity and carries no table.

Kingston is catalogued by the City against this exact URL. Its licence PDF
link is pinned to the canonical location rather than the legacy path that
currently redirects there — Durham's entry records what happens when such a
redirect is eventually dropped.

Barrie ships REGISTERED AND OFF. The City offers its licence for acceptance
behind a click-through gate, and nobody on this project has accepted it.
Whether to accept is a person's decision, not an assumption a poller should
make, so the feed is visible, documented, and one line from enabled.
2026-10-15 20:18:15 -04:00
Cliff Flood 849cb80375 feat(transit): add MiWay, Hamilton HSR and Durham Region Transit
Three keyless GTFS-Realtime feeds around Toronto, each verified live: all
vehicles carry real coordinates, and each is polled only near its own
region rather than across the Golden Horseshoe.

The licences differ in ways the registry now records rather than flattens:
Hamilton PRESCRIBES its attribution wording, so the credit is that exact
sentence; Durham makes credit optional and its catalogued licence PDF is
dead after a site relaunch, so licenseUrl points at the live page where the
v.1.0 text was actually read; Mississauga's licence is revocable and asks
that the terms travel with the data, so licenseUrl is the terms themselves.

All three are bus-only and set no route hint, so their modes default rather
than resolve. Durham publishes no bearing on any vehicle — heading comes
from observed movement, as with any feed that omits it.

GO Transit / Metrolinx stays out: its feed requires an API key.
2026-10-15 20:18:15 -04:00
Cliff Flood c5f7fe285b feat(transit): add the TTC Toronto surface feed
TTC BusTime publishes keyless GTFS-Realtime VehiclePositions with real
coordinates for the surface network: ~1,180 buses and streetcars with
bearing and per-vehicle timestamps. Registering it is one registry row.

The subway is deliberately absent. BusTime covers surface vehicles only
and the subway publishes no positions, so Lines 1/2/4 are left out rather
than inferred from schedules — the same rule that keeps NYCT out.

Route numbers establish the mode: the three-digit 500-series is streetcar,
as are the four Blue Night routes on streetcar trackage. A leading 5 alone
would misclassify bus routes 50-59, so the rule is anchored and tested.

Licensing is the portal-wide Open Government Licence - Toronto; the CKAN
record for the BusTime NVAS dataset leaves its own licence field blank,
and the terms note says so rather than overstating the grant.

Refs #70
2026-10-15 20:18:15 -04:00
Mazeyar Moeini FeizabadiandClaude Opus 5.5 6d6ce364c6 docs(cyclones): document the early-advisory window and pin its bounds
Maintainer follow-up for #741, no runtime change.

- CURRENT-STATE: advisory issue and position times up to and including
  90 minutes ahead of the server clock are accepted because NHC can release
  advisories before their nominal time; 90 minutes is the app's tolerance,
  not an NHC limit. Later, non-canonical and over-12-hour-old times still
  reject the snapshot.
- Tests: pin exact 90-minute acceptance and +1 ms rejection, and exact
  12-hour acceptance and +1 ms rejection, for issuance and lastUpdate
  independently; the early-publication test now asserts
  invalid_cyclone_data.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 02:03:16 +02:00
Mazeyar Moeini FeizabadiandClaude Opus 5.5 2e4beb9418 Merge main (82022306) into fix/flights-unpositioned-rows-complete
Resolve conflicts with main by keeping both sides:
- CHANGELOG.md: keep this PR's flights entry above main's newer entries.
- src/layers/flights/records.test.mjs: keep this PR's position-less
  retention test alongside main's civil emergency-status test.

src/sources/live/aircraft.js merged cleanly: openSkySnapshot keeps main's
emergencyByIcao normalizer and passes openSkyUnpositionedId to admitRecords.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 01:30:21 +02:00
Sameh Khamis a478f26eb9 Merge branch 'main' into feat/webapp-icons 2026-10-15 16:26:06 -07:00
Sameh Khamis 59d375cc8b Merge branch 'main' into feat/cctv-model-spec-enrichment
# Conflicts:
#	CHANGELOG.md
2026-10-15 16:25:46 -07:00
Sameh Khamis 7366a46eba Merge branch 'main' into feat/wsdot-camera-pack 2026-10-15 16:17:22 -07:00
Sameh Khamis 05d8529edc Merge branch 'main' into feat/wsdot-camera-pack 2026-10-15 16:10:59 -07:00
Sameh Khamis ee10b2ce1c Merge branch 'main' into feature/catalonia-cctv-cameras 2026-10-15 16:10:47 -07:00
Sameh Khamis 52d26b0577 Merge branch 'main' into feat/wsdot-camera-pack 2026-10-15 16:05:47 -07:00
Sameh Khamis a800d28ddf Merge branch 'main' into feature/catalonia-cctv-cameras 2026-10-15 16:05:20 -07:00
Sameh Khamis d3cedbaaaf Merge branch 'main' into feat/lithuania-cctv 2026-10-15 16:04:24 -07:00
Sameh Khamis a75550024d Merge branch 'main' into feat/king-county-camera-pack 2026-10-15 15:57:27 -07:00
Sameh Khamis 248a658713 fix(cctv): serve only live feeds on /media
/api/cctv/media relayed still-image cameras with an ordinary fetch: it followed
redirects to any host, passed through any content type and had no body cap.
Stills are served by /api/cctv/frame, which keeps redirects on the registered
origin, accepts only image/* and caps the body, and no client requests a still
through /media. /media now answers 404 for anything but HLS, MP4/WebM and
MJPEG, before any upstream request.
2026-10-15 15:53:09 -07:00
Sameh Khamis bcfba77196 fix(cctv): make the Lithuania pack opt-in until its licence is confirmed
The camera endpoints are the eismoinfo.lt website backend, which the Via
Lietuva open-data statement does not list, so the pack now follows the NYC
opt-in pattern (CCTV_LITHUANIA_ENABLED=1) and the docs say why. A failed
catalog request now aborts its sibling instead of leaving it open until the
timeout, and a redirect is logged as not followed.
2026-10-15 15:17:31 -07:00
Sameh Khamis 7b1032bfc7 docs(cctv): document the Toronto pack and the shared camera cap
Adds the Toronto settings to .env.example and a current-state section for the
pack, restores an approximate camera count in the README, and corrects the
claim that adding a pack never trims another region: with the shared
4,000-camera cap, the largest packs give way round-robin. Fixes two stale
comments about the list's refresh and the ground-height sidecar.
2026-10-15 15:15:49 -07:00
Sameh Khamis 7561a5ab82 Merge branch 'main' into feat/cctv-toronto 2026-10-15 14:23:19 -07:00
Sameh Khamis 24f14a77a3 Merge branch 'main' into feat/wsdot-camera-pack
Keeps main's 4,000 catalog-wide camera cap, which main pins in tests; WSDOT
shares it round-robin with the other packs. The branch's earlier cap raise and
its removal of main's cap tests are reverted in this merge.
2026-10-15 14:22:22 -07:00
Sameh Khamis dca24996d5 Merge branch 'main' into feat/king-county-camera-pack 2026-10-15 14:21:10 -07:00
Sameh Khamis b4d852587a Merge branch 'main' into feat/lithuania-cctv 2026-10-15 14:21:07 -07:00
Sameh Khamis e8b6ffd196 Merge branch 'main' into feature/catalonia-cctv-cameras
# Conflicts:
#	CHANGELOG.md
2026-10-15 14:18:47 -07:00
Sameh Khamis ac13acfe3d Merge branch 'main' into feat/aqhi
# Conflicts:
#	CHANGELOG.md
2026-10-15 13:47:21 -07:00
Sameh Khamis 48ee073469 Merge branch 'main' into feat/bikeshare-toronto-and-failure-fix 2026-10-15 13:34:50 -07:00
Sameh Khamis 51e32a30f2 fix(bikeshare): scope city failures to range and report partial outages
A failure now ends when its city leaves range or the camera rises above the
activation gate, so an empty map no longer reads LOAD FAILED. Late activation
and status rejections are ignored like late successes. Partial failure reads
DEGRADED, every in-range city failing over cached points reads STALE, and
freshness advances only on a refresh that succeeded. Behavioural tests drive
the real proximity, update and enable paths. Docs say no licence is published
for Toronto and list Social Bicycles and PBSC. The merge also restored the #61
GBFS v3 changelog entry that an earlier merge on main dropped.
2026-10-15 13:08:45 -07:00
Sameh Khamis a02f729191 fix(opensky): cool down before reading a 429, and test the six caps
A 429 now starts the credit cooldown from its headers and drops the body
unread, so a stalled or oversized 429 cannot skip the governor; an oversized
snapshot is not retried. A 429 without retry-after now waits the intended
2 minutes (headers.get() returns null, which Number() read as 0 s). Adds
oversized-stream tests for OpenSky, adsb.lol, CelesTrak and TomTom that fail
on main, names the six reads in the changelog, and corrects the docs on
what was already bounded.
2026-10-15 13:08:37 -07:00
Sameh Khamis 046126eb36 Merge branch 'main' into feat/aqhi
Port to current main: main reserved layer-state token 0 for street-level, so
air-quality takes the next free token, 4 (registry, ledger, and the allocation
tests shift by one). Main moved source contracts into sourceComposition.js, so
air-quality registers its getSnapshot contract there. Package boundaries keep
main's lists plus this branch's air-quality modules and packages.
2026-10-15 12:39:00 -07:00
Sameh Khamis c9f43e8517 Merge branch 'main' into feat/bikeshare-toronto-and-failure-fix
# Conflicts:
#	CHANGELOG.md
#	DATA_SOURCES.md
#	docs/CURRENT-STATE.md
2026-10-15 12:35:18 -07:00
Sameh Khamis 1bb8643a28 Merge branch 'main' into fix/cap-remaining-upstream-reads
# Conflicts:
#	CHANGELOG.md
2026-10-15 12:34:49 -07:00
Said Turksever ab14f48360 Merge branch 'main' into pr/panoramax 2026-10-15 20:17:28 +01:00
Said TurkseverandClaude Opus 5.5 56b113397d Merge upstream main into pr/panoramax
CHANGELOG: kept both Unreleased entries (satellite cloud filter #1084 and
Panoramax).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 20:07:26 +01:00
Said Turksever 09bdc105a6 Merge branch 'main' into feat/bikeshare-norway 2026-10-15 20:04:57 +01:00
Mazeyar Moeini Feizabadi 8959b5b71a fix(weather): preserve filter drag previews across panel refreshes 2026-10-15 20:52:22 +02:00
NotProniss 86b7dc8d3c feat(weather): add satellite cloud filter strength slider
Blend the existing infrared brightness key from Full (0%) to Clouds only (100%), preserving Soft/Vivid as independent opacity presets. Commit filter changes on slider release and retain legacy share-link mode codes.
2026-10-15 20:52:22 +02:00
Sameh Khamis c42b072e99 fix(overpass): tag caches by the sorted upstream set and cover installations
Uses a full SHA-256 of the sorted instance list, so reordering the same
instances for failover keeps the cache. Adds the installation-cache repoint
test (tagged, reordered, repointed, untagged, unconfigured) and the changelog
and current-state notes.
2026-10-15 10:48:38 -07:00
Said Turksever eeb8bc83fd Merge branch 'main' into feat/bikeshare-norway 2026-10-15 17:56:23 +01:00
Said Turksever 42d3c0c0d2 Merge branch 'main' into feat/bikeshare-norway 2026-10-15 17:32:25 +01:00
SaidandClaude Opus 5.5 7056fa113e Merge main into fix/radio-mirror-null-body
Resolve the CHANGELOG conflict by keeping every entry from main and
adding the radio entry on top; the previous main merge (cebd870)
had dropped 19 of main's entries.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 17:30:20 +01:00
Said Turksever 9e6ecc2ca6 Merge branch 'main' into fix/363-geocode-proxy 2026-10-15 17:02:14 +01:00
Said TurkseverandClaude Opus 5.5 b5de533567 Merge upstream main into pr/panoramax
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 16:56:15 +01:00
Said TurkseverandClaude Opus 5.5 b645a767c8 Street Level: Panoramax review follow-ups (gekh, #1134)
Image loading (photoViewer.js)
- One AbortController per open: a new open, close or unmount stops the
  previous photo's first and sharper downloads (an <img> by src = '').
  A collapsed viewer never falls back to the original; Panoramax's flat
  fallback is the thumbnail. A superseded open resolves quietly.
- Flat HD tracked as "loading" and "shown" apart: a discarded response no
  longer blocks later upgrades, and resizes while it loads ask once.
- No upgrade of the photo still shown while another opens.
- Size limits before decoding: imageSize.js reads JPEG/PNG/WebP/GIF
  headers; more than 64 MP or 16,384 px a side is refused undecoded, an
  <img> that decodes larger is refused and let go, flat HD needs a known
  width of at most 8,192 px, and panoramas always decode with a resize.

Panoramax provider
- Retry-After parsed as seconds or an HTTP date; the browser cannot read
  it here, so busy answers back off 5 s doubling to 300 s, reset once
  answered.
- Headers timed, then the body by an idle timeout (15 s of silence), so a
  slow link still gets its megabyte tiles.
- Cones centre only on the picture shown (onShowing), never on a late
  lookup; lookups nobody waits for are aborted (shared, refcounted).
- onReopen: a GPU reset redraws in the viewer, not through the core.
- Cones draw the home z15 tile at once and add neighbours as they arrive;
  a neighbour that failed is not counted as drawn.
- Coverage tiles decode in ~8 ms slices (a 2 MB z10 tile over Paris was
  one ~85-200 ms task); sorted by measured length without a Map.
- Box search asks for 20, not 100 (the API returns them nearest first).
- looksLikeEmail checks every '@'; creatorOf de-duplicates with a Set.

lineCoverage.js
- A redraw while a swap still builds keeps what is on screen (the swap's
  old lines and its ready new ones) and drops only the unready ones.

Tests for each (mutation-checked), two vacuous tests made real, the
cones' pictures lane and readable()'s busy/timeout paths covered; the
fixture's box search is nearest first. Docs: README filters and share
links, CHANGELOG HD wording, CURRENT-STATE.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 16:55:59 +01:00