github dawarich-app/atlas v0.4.0

latest releases: v0.6.2, v0.6.1, v0.6.0...
one month ago

Fixed

  • Directions now has a Get directions button, including for endpoints selected on the map. Transit dispatches to OpenTripPlanner and decodes its polyline5 geometry; empty or failed routes clear the old line instead of displaying a misleading "Route ready" message (#45, #47).
  • Directions preserves typed endpoints when changing travel mode and fits the map to the resulting route. Trips outside the loaded region show a coverage hint. On mobile screens the controls and map share the viewport, keeping the map and point picker accessible.
  • Placeholder installs its official prebuilt database automatically on first start. Its data directory honours PUID/PGID; downloads stream to a temporary file, are checked against the pinned service's schema, and only then replace the database. Invalid previous databases are backed up; valid databases are reused offline. This removes the manual WhosOnFirst import from normal Search setup (#26).
  • The catalog generator runs without starting the database or control plane, fixing the monthly refresh on a clean CI checkout.
  • The docker socket group was read from the wrong place. compose.yml exports DOCKER_GID into the app container, defaulting to 999, while the socket on macOS is gid 0 — so preferring that variable granted a group the daemon does not answer on and left the control plane degraded anyway. The socket's own gid now decides; DOCKER_GID is honoured as an additional group, which is the only lever available when the socket is not visible from inside the container.
  • Dokploy deployments never gave Valhalla its region. /work/data/valhalla had no volume there, so the staged PBF landed in the container's ephemeral layer and Valhalla crash-looped exactly as it did elsewhere.
  • Service status ignored every parser. The status guards matched atom phases while all parsers emit strings, so downloading, building and error were unreachable and any enabled service that was not ready collapsed to "starting" — a crashed geocoder reported itself as still starting up, and a multi-GB index download showed no phase for its whole run.
  • An apply announced itself finished while its sidecars were still ingesting. A sidecar that had not logged in the seconds before the applier returned was written off as absent. Services the apply actually restarts now hold the timeline open until they report; only ones it deliberately skipped settle early.
  • Failures during the restart step went unrecorded: a docker compose restart that failed was discarded and reported as a successful apply, and when it followed a failed conversion it vanished entirely — leaving the sidecar rows to turn green on log lines from the containers that never received the new data. Every service is now attempted, and every failure is named.
  • A finished apply stayed on screen forever — the Region tab and /admin/apply kept rendering the last run until another one started. It can now be dismissed.
  • A failed restart no longer reports the Overpass conversion as broken, a completed stage is no longer reddened by a later crash, and a progress bar can no longer exceed 100% when an upstream under-reports its Content-Length.
  • The control plane came up permanently degraded. The entrypoint re-added DOCKER_GID after dropping to uid 65534, but compose's group_add: never exports that value into the container, so the dropped process ran with an empty supplementary group list and could not reach the docker socket; the socket's own gid is now read instead. Separately, HOME=/root is unreadable by 65534, which made the docker CLI abort plugin discovery and report unknown flag: --short rather than a permission error — DOCKER_CONFIG now points somewhere readable.
  • Valhalla crash-looped after every apply, and lost its tiles on restart. The gis-ops image scans its own /custom_files for *.osm.pbf and exits with "No local PBF files... Nothing to do" without one, but the applier only ever wrote to osm/. The region PBF is now staged where Valhalla actually looks, and its tile directory has a bind mount, so a rebuilt graph survives docker compose restart.
  • Applying more than one region always failed, in milliseconds. osmium infers its output format from the file extension, and the applier merges to current.osm.pbf.partial so an interrupted run leaves a file the partial sweep can recognise; osmium rejects that name outright without an explicit -f pbf.
  • OpenTripPlanner never reported itself ready. The log parser watched for four phrases OTP does not emit — it logs Started listener bound to, not Started listening, and Grizzly server running, not Grizzly server started — so transit sat at saving-graph 90% until something happened to call the API and a fallback pattern rescued it. The fixture that covered this was written to match the regex rather than the program; it is now a verbatim capture, alongside an unedited full container start that the phase-order test runs against.
  • OTP silently discarded every time-based restriction. Without osmDefaults.timeZone it logs "time-restricted entities will not be created" and drops opening hours and conditional access from the street graph. Atlas wrote no OTP config at all; it now pins the zone when the selected regions agree on one, and removes a stale config when they do not, since a zone outliving its extract shifts every restriction by whole hours without saying so. The country table is generated from the IANA database: a country qualifies only when all of its zones hold the same UTC offset all year, so Berlin + Vienna resolve while Berlin + London stay ambiguous, and the US, Canada, Australia, Brazil and Russia are excluded by construction.
  • Region subdivisions had no country. Geofabrik publishes country_code only at country level, so gf:berlin and two thirds of the shipped catalog arrived as nil. The catalog now inherits it up the parent chain (523 of 796 regions resolve a zone, up from 265).
  • The apply progress bar sat at exactly 50% for the whole Valhalla build. building-tiles was treated as a measured phase, but the parser assigns it a flat 0.5 on sight of "Running valhalla_build_tiles" and its only real-progress pattern matches OpenTripPlanner's wording. Sidecar stages for services that never started now settle as skipped with a reason instead of spinning indefinitely.
  • Search answered every failure with an empty panel, so a geocoder that was never installed, one that had crashed, and a misspelt place name were indistinguishable from a dead button. The panel now names the service and the reason — "Photon is not installed" is actionable where "unavailable" is not, and it is the ordinary state of a fresh instance — and separates not installed from still downloading its dataset from installed but not responding.
  • Hovering and keyboard-highlighting a search result had no visible effect: both painted the row bg-base-200, the colour the panel already sits on.
  • A malformed value in any upstream tuning knob (PHOTON_TIMEOUT, VALHALLA_TIMEOUT, *_OPEN_TIMEOUT, …) no longer takes down every request that reads it. env_int/2 used String.to_integer/1, so VALHALLA_TIMEOUT=10s raised on each call; it now falls back to the default and logs a warning naming the variable.
  • The Protomaps daily-planet basemap targets the previous day’s build, which is already published, instead of a build that may not exist yet (#2)
  • Transit planning now uses OpenTripPlanner's GraphQL API instead of the removed legacy REST endpoint (#25).
  • Region apply no longer stalls or silently serves stale POI data: the PBF→bz2 convert is no longer bounded by a 30-minute wall-clock timeout (a genuinely hung osmium is now caught by a stall watchdog instead), orphaned .partial files are swept from osm/, osm/sources/ and gtfs/, and a failed conversion fails the apply loudly instead of leaving overpass on a weeks-old snapshot (#34, #28). The convert now runs after OTP staging, so a broken overpass source no longer withholds fresh data from valhalla and OTP.
  • Reverse-proxy deployments no longer loop on HTTPS redirects when TLS terminates before Caddy (#20)
  • The app no longer crash-loops when the data dir is owned by another uid: PUID/PGID are honoured, the entrypoint takes ownership before dropping privileges, and an unwritable dir reports a clear error instead of a bare Permission denied (#23)
  • Headless LAN deployments work over plain HTTP on a non-standard port: PHX_SCHEME, PHX_PORT, FORCE_SSL and PHX_CHECK_ORIGIN are now configurable, and PHX_SCHEME=http turns the HTTPS redirect off by default (#19)
  • The in-app control plane now reads the project .env, so region, UID/GID and heap settings reach control-plane-launched services instead of silently falling back to compose defaults (#22). Note: if your .env sets a different COUNTRY_CODE than the compose default, the next service start will now honour it and re-download that region's data.
  • Valhalla now starts with a safe default worker cap and file-descriptor limit on multi-core hosts (#24)
  • Overpass diff updates are now opt-in so POIs can serve after an initial import without waiting on Geofabrik catch-up (#27)
  • Dokploy's minimal compose file no longer starts or exposes Overpass by default; the Overpass service and /overpass proxy are now commented out together as optional poster-sidecar configuration.

Added

  • Search markers, dismissal and shareable queries behave as one thing. Picking a result, pressing Escape and clearing the box all clear the pins with the list; flying to a result no longer re-runs the query that put it there; and a shared ?q= link reproduces the sender's results instead of being re-scoped to wherever the viewer's map happened to open.
  • Type-as-you-go search. Results now arrive while typing (200 ms debounce, two-character minimum) instead of only on Enter, with arrow-key navigation, Enter to pick the highlighted result and Escape to dismiss. Search is scoped to the visible map again and asks for up to 40 results, re-querying as you pan — so searching a chain name answers "which of these can I see" rather than returning a handful from across the country.
  • Every search result is now a marker, not just the one you click, so you can see where the matches are before choosing. Clicking a pin opens a popup with the place's category, a one-line address, its coordinates and a link to the OpenStreetMap object. Results carry a category icon and label in the list as well.
  • Searches are shareable. The query lives in the URL as ?q=… and is applied when such a link is opened, so a search reproduces what the sender saw. The same path serves typing, a pasted link and the back button.
  • A copy button on both log viewers, so reading a crash-looping sidecar no longer means selecting hundreds of lines by hand. It reports failure inline rather than silently succeeding, because clipboard writes are blocked on insecure origins — which a LAN deployment over plain HTTP is.
  • The region-apply timeline reports what it is actually doing: which file is downloading, from which URL, and how many bytes of how many; which stage is running and which are still pending; and it continues past the applier's return through Valhalla, Overpass and OTP ingest, since an apply that finished but left Valhalla hours from serving a route has not finished in any sense that matters. Stages whose progress nothing measures show their phase rather than an invented percentage.
  • Map matching — POST /api/v1/map-match snaps a recorded GPS trace onto the road network via Valhalla's Meili matcher, the inverse of /api/v1/route: routing invents a path between two points, matching takes a path you already walked and decides which edges you were on. Post a shape of {lat, lon} points (optionally with time and accuracy); mode, shape_match and Valhalla's search_radius / gps_accuracy / breakage_distance are accepted. format=polyline6 (default) returns Valhalla's legs verbatim, matching what /api/v1/route already returns; format=geojson stitches them into one decoded LineString, so callers need no polyline decoder of their own. A trace Valhalla rejects is reported as invalid input rather than as an upstream failure, relaying Valhalla's own reason and error_code — whether the trace fell outside the loaded region, was too sparse or noisy, or exceeded a service limit such as the 200 km max_distance. Trace length is capped by MAP_MATCH_MAX_POINTS (default 10000), and matching gets its own VALHALLA_MATCH_TIMEOUT (default 60000 ms) separate from the routing timeout, since it is superlinear in point count and holds a Valhalla worker for the whole request. Both knobs are read from .env.

Changed

  • Release publication and image builds now run Phoenix and deployment tests first, then build and boot the actual image on native amd64 and arm64 runners. Stable image tags are published only after both architectures pass. Release notes must match the application version; Unreleased cannot accidentally select an older release, and an interrupted publication can be resumed on the same commit.
  • ghcr.io/dawarich-app/atlas/app:latest now means "newest stable release", not "tip of main". Images are cut from published GitHub releases; pushing to main no longer publishes one. Pin a version tag if you were relying on latest tracking every merge — and note that a fresh docker compose pull will now hold at the last release rather than moving with development.
  • Releases are tagged and published automatically from this file: when the top heading is a version with a date (rather than Unreleased), CI tags it, creates the GitHub release, and builds the image. Per-commit builds continue on the OneDev registry for testing.
  • mix credo --strict is clean and enforced in CI, with the project's ruleset checked in at app-phoenix/.credo.exs. It previously failed on main and ran ahead of the test step, so the test suite had never actually executed for a pull request.
  • The deployment-config assertions in test/deployment_config.test.mjs now run in CI, on a workflow that triggers when Caddyfile or a compose*.yml changes. They had no runner, so the reverse-proxy and sidecar defaults they guard could regress silently.

Don't miss a new atlas release

NewReleases is sending notifications on new releases.