Commit Graph

4563 Commits

Author SHA1 Message Date
Maurice ec8df01f85 feat(shared): name the Valhalla costing of each profile and the providers that route every day
VALHALLA_COSTING maps driving, walking and cycling to auto, pedestrian and
bicycle once for the planner and the server. valhallaRoutesEveryDay says
whether the resolved provider carries every day: the TREK services and an
own Valhalla do, FOSSGIS and no Valhalla leave the days to OSRM.
2026-10-29 13:34:28 +01:00
Maurice 79260ad737 fix: name the routing and allowance labels where the key check finds them and keep the new tests within the lint baselines 2026-10-29 13:34:28 +01:00
Maurice 0426ce7f01 docs(server): name TREK_PHOTON_URL in the services config and the alternates limit of the TREK Valhalla 2026-10-29 13:34:28 +01:00
Maurice f76b8d5d9c fix(server): put a Photon house number before its street as Nominatim does 2026-10-29 13:34:28 +01:00
Maurice 8c11833fb1 fix(server): ask Nominatim when Photon finds nothing and keep bulk lookups off Photon
An empty Photon search, or one without a hit that has an OpenStreetMap id, is asked again at Nominatim as the reverse lookup already was. The background lane goes to Nominatim alone, a reverse lookup leaves Nominatim half of the caller's deadline, and a 429 with Retry-After pauses Photon for that long.
2026-10-29 13:34:28 +01:00
Maurice 45727b3d3b fix(client): ask FOSSGIS when the routing relay times out, refuses the body or is missing
A route or height question through the relay now gives up after 12 s. A 400 without Valhalla's error_code and a 404 or 405 count as the relay unable to answer instead of no way or no Valhalla, and a Retry-After sets how long the tab leaves the relay alone.
2026-10-29 13:34:28 +01:00
Maurice 686592437a fix(server): rest the routing relay after a failure and keep it under the installation's minute
A hung TREK Valhalla cost every leg, height chunk and trace the full 30 s before FOSSGIS answered. The relay now waits 10 s for a route or heights, rests a minute after an error or timeout and answers 503 at once meanwhile, follows a 429's Retry-After (an hour at most), passes that header on to the browser, and holds the installation to 100 questions a minute below the gate's 120 (60 per user).
2026-10-29 13:34:28 +01:00
Maurice 1da7d0627a fix(server): judge the address search in the admin status by TREK_PHOTON_URL and an own NOMINATIM_URL
The status asked a fixed Photon origin and compared NOMINATIM_URL with the public address, so a moved Photon or an explicitly set public Nominatim showed the wrong service as in use. It now reads the same photonUrl and nominatimOwn the Photon client decides by. TREK_VALHALLA_URL joins the commented compose variables.
2026-10-29 13:34:28 +01:00
Maurice bc62eb0d6f feat(admin): show the allowance of place search, address search and routing in the TREK API card
GET /api/admin/service-identity lists places, photon and valhalla, each with
today's allowance read fresh from /v1/quota of its own host (cached for 20
seconds per host) and whether this instance asks it right now: Photon only
beside the public Nominatim, the TREK Valhalla only where the routing choice
comes to it. Photon and Valhalla are asked only with a key and only while
TREK_SERVICES_HOSTS lists them. The last allowance an answer stated is kept
per host for when a host does not answer.

The card lists the three services under each other in the look it had,
a service this instance does not ask dimmed and named as such.
2026-10-29 13:34:28 +01:00
Maurice 091ebed8e4 feat(routing): let the admin pick FOSSGIS, the TREK services or an own Valhalla
routing_valhalla_provider (fossgis, trek or custom) sits beside the routing
URLs under Admin, Default user settings, admin only and locked on a managed
install. Without a choice an own Valhalla is custom, an own OSRM alone asks
no Valhalla, and otherwise the TREK services answer.

The planner asks them through the same-origin relay, so no connect-src
changes. A relay that answers 401 (a shared page without a sign-in), 403,
413, 429 or 5xx sends the question to FOSSGIS without a word and is left
alone for ten minutes. A long line to describe goes as a polyline.
2026-10-29 13:34:28 +01:00
Maurice 80183bc986 feat(server): relay Valhalla routing to the TREK services with the installation key
POST /api/routing/valhalla/route, /trace_attributes and /height ask the
Valhalla at TREK_VALHALLA_URL (default https://valhalla.liketrek.com) for a
signed-in user. The body is held to the shared contract (64 KB, at most 20
locations), every question counts against 120 a minute per user, and the
installation key goes along only to a host TREK_SERVICES_HOSTS lists.
Valhalla's answer is passed on as it came, refusals included.

The road trip router asks the same relay when the routing choice lands on
the TREK services, so the MCP road trip, city walk and hike tools share its
limits, and hands a question it cannot answer to FOSSGIS.
2026-10-29 13:34:28 +01:00
Maurice 250a7d4eb7 docs(wiki): describe the Photon address search and TREK_PHOTON_URL 2026-10-29 13:34:28 +01:00
Maurice 256f8c08e2 feat(server): ask the TREK services' Photon before Nominatim for search and reverse lookups
An installation that holds a key for the TREK services and has no
NOMINATIM_URL of its own now sends the OpenStreetMap search and the
reverse lookups to photon.liketrek.com first. The answers are read into
Nominatim's shape, so the place records stay the same, and every miss
(refused key, allowance spent, timeout, error, foreign body) falls back
to Nominatim, with a one minute pause after four misses in a row.

TREK_PHOTON_URL points at another copy, and the default of
TREK_SERVICES_HOSTS now lists photon.liketrek.com and
valhalla.liketrek.com beside places.liketrek.com.
2026-10-29 13:34:28 +01:00
Maurice 4ab3244f8f fix(server): mark the identity reset as writing its new key on its own
Regenerating clears the stored key at once and writes the new one only after the issuer answered in the background, so the two writes cannot share a transaction.
2026-10-29 13:34:28 +01:00
Maurice cb546e4a72 refactor(server): move the identified Places request into a file of its own
The instance token and the request that carries the installation key leave trek-places.client.ts, which had grown past the 1000-line limit.
2026-10-29 13:34:28 +01:00
Maurice eeae904867 fix(server): solve the proof of work and read the revocation notice without awaiting in a loop
The proof of work and the bounded read of a 403 body recurse instead of looping, the background-work checks compare against null instead of testing a promise, and the tests repeat their requests through oneByOne. The renewal test loads the stored key before its first request, and the panel test picks the last confirm button without Array.prototype.at.
2026-10-29 13:34:28 +01:00
Maurice 414a7ad98f fix(server): fetch a refused registration challenge once more instead of backing off 2026-10-29 13:34:28 +01:00
Maurice 58e006cfd9 docs(wiki): say that requests are counted per installation and per network 2026-10-29 13:34:28 +01:00
Maurice 476dbef7dc fix(server): renew service keys on the next request and stop sending expired ones
An expired key is no longer sent; the request goes through the shared pool
while a due key, or an expired one within its grace, is renewed in the
background. Refusals in one burst count once, a refused renewal counts like
a refused search, and a Places request whose key is refused is sent once
more without it.
2026-10-29 13:34:28 +01:00
Maurice b53751344b fix(server): ask the issuer for the allowance of a key only when TREK_SERVICES_HOSTS lists it 2026-10-29 13:34:28 +01:00
Maurice 01c0f8b64c fix(server): rotate the stored service key with ENCRYPTION_KEY and pin every encrypted app setting 2026-10-29 13:34:28 +01:00
Maurice 44add57109 fix(client): hide the new identity action on a managed install 2026-10-29 13:34:28 +01:00
Maurice afacf00c9f docs: document TREK_SERVICES, TREK_SERVICES_KEY and the daily allowance
docker-compose.yml and the Helm chart name the switch and the key (the key in the Secret, never the ConfigMap), and the wiki explains the installation key, what it carries, where it goes and the admin view of the allowance.
2026-10-29 13:34:28 +01:00
Maurice baf69da27f feat(client): show the TREK services allowance on the TREK API card
A calm panel under the card's facts: a dot with the state, the tier, a bar of today's use against the limit, what is left and the local time the count starts again. It reads when the card comes into view and every 30 seconds while it stays there and the tab is in front, says why when the services are off, revoked or cannot be read, and offers a new identity behind a confirmation unless the key comes from the environment.
2026-10-29 13:34:28 +01:00
Maurice 01ae91c939 feat(server): give each installation a key for the TREK services and report its allowance
A new service-identity domain registers the installation with places.liketrek.com on its first Places request, in the background and behind a light scrypt proof of work, keeps the key encrypted in app_settings, renews it from day 60 through a daily job, drops it after three 401s in a row with up to six hours of jitter, and freezes it on a revocation until an admin starts over. TREK_SERVICES_KEY wins and turns registration off; TREK_SERVICES=off sends no key; a mirror set with TREK_PLACES_URL never registers and never sees the key, which goes only to the hosts in TREK_SERVICES_HOSTS over https.

The Places client takes its headers from the identity port, sends a TREK/<version> User-Agent and keeps the instance token. A 401 or 403 does not open its breaker. GET /api/admin/service-identity reports the state, tier and today's allowance, asking the issuer at most every 20 seconds; POST .../regenerate starts a new identity.
2026-10-29 13:34:28 +01:00
Maurice f19f0a33b2 feat(shared): add the service identity contract and the allowance texts of the TREK API card
Zod schemas for what the key issuer answers (challenge, key grant, quota) and for GET /api/admin/service-identity. The card no longer claims there is no quota: every locale now says there is no key to enter, a fair daily allowance per installation, and that only the number of requests is counted.
2026-10-29 13:34:28 +01:00
Maurice e5fc735e13 docs(readme): close the gap above the sponsor line 2026-10-29 11:38:54 +01:00
Maurice d2ec9eabde docs(readme): describe TREK as the trip ecosystem it has become 2026-10-29 11:38:54 +01:00
Maurice 9128039c38 docs(readme): let the four status badges continue the badge row 2026-10-29 11:38:54 +01:00
Maurice dd6f41f768 docs(readme): give the license, release, pulls and stars badges the style of the row above 2026-10-29 11:38:54 +01:00
Maurice 1a73b22810 docs(readme): show the TREK logo alone at the top 2026-10-29 11:38:54 +01:00
Maurice c1d413f31a docs(readme): set the sponsor logo right under its line and the server hint right under the button 2026-10-29 11:38:54 +01:00
Maurice 8316119293 docs(readme): thank dataforest cloud as infrastructure sponsor, drop the third showcase and the star history 2026-10-29 11:38:54 +01:00
Maurice 74abaa9d7c test(unsplash): check both refusals without awaiting in a loop 2026-10-28 16:30:54 +01:00
Maurice 091505d17c fix(unsplash): tell a server Unsplash turns away that the free key helps
Without an Access Key the image search goes through Unsplash's web endpoint,
which refuses datacenter addresses with a 401 or 403 or answers with a
challenge page. The search then said only "Unsplash search unavailable",
although an admin can already enter a free key in the settings. Such a
refusal now answers 502 with that hint and the code unsplash_key_needed, and
the cover search shows it in the user's language.

Closes #1449
2026-10-28 16:30:54 +01:00
Maurice aee275e2b0 fix(places): read an imported row for the dedup set in one helper
The candidate a GPX or KML row is checked as is built in lineCandidate, so
places.service.ts stays within its size baseline, and the atomic import test
imports the same Ridge line it later expects to be skipped.
2026-10-28 15:43:52 +01:00
Maurice ef86bf2660 fix(places): keep two different tracks of the same name apart on import
Two GPX tracks a watch named alike (two "Afternoon Hike"s) were taken for one:
the import compared a track only by its name, so the second was skipped as
already in the trip. A track now matches a track of that name only when it
also starts, ends and reaches as far as that one, to about a hundred metres,
so the same file imported again is still skipped. The GPX, KML and tour
imports and the tour preview all read the same rule.

Closes #2870
2026-10-28 15:43:52 +01:00
Maurice 0139c46fb4 test(i18n): count the new planned total key in the tours locales 2026-10-28 15:18:07 +01:00
Maurice a0a7fcdbb9 fix(tours): say why a tour over a day cannot be saved
A tour whose walking time and breaks came to more than 24 hours a stage
only greyed out Save, with nothing saying why. The planner now marks the
planned total and says what to do: make it a multi-day tour by ending a
stage at a stop, or enter a shorter planned total. The details section
opens by itself so the reason is in sight.

Closes #2869
2026-10-28 14:52:01 +01:00
Maurice 186dd94b61 fix(assistant): chat with an own server entered without /v1 at /v1
The assistant sent an own server's chat to the address as entered plus
/chat/completions. Ollama, entered as http://host:11434 the way its own docs
write it, answers that with a 404, so every message ended in "something went
wrong" while connecting had worked: the model list is found under the root
at /api/tags. A bare server address now chats under /v1, where Ollama, LM
Studio, vLLM, llama.cpp and LiteLLM all answer; an address with a path, such
as https://api.groq.com/openai/v1, is used as entered.
2026-10-28 12:17:54 +01:00
Maurice ad721a1ac6 test(studio): the auto layout lays out a long journey whole 2026-10-28 12:26:06 +01:00
Maurice 87441f269d fix(studio): lay out a book as long as its journey, with no page limit
A book held at most 150 spreads. The auto layout cut everything past that
without a word, so a long journey's book ended about three quarters of the
way through, with its last page and back cover gone, and adding, copying or
applying a designed page to a full book was refused.

The spread cap is gone from the book schema, the page operations, the
design composer and its apply, the assistant's book card and the design tool
contracts. A design's own page budget (pages.max) still bounds what it lays
out. The save route's 8 MB body still bounds a book's size, which at two to
five kilobytes an auto laid page is a few thousand pages.

The templated design digests move because their counter ids shift by two;
the pages, their order and their elements are unchanged.
2026-10-28 12:06:50 +01:00
github-actions[bot] a0943f8226 chore: bump version to 5.0.1 [skip ci] v5.0.1 2026-10-28 10:43:52 +00:00
Maurice 6741e8ca0d fix(help): give the close button a row of its own
A wider gutter left the button floating in the corner over the first card and the scrollbar. It now sits in its own row above the scrolling content, level with the Help title, and the content keeps symmetric padding.
2026-10-28 10:24:08 +01:00
Maurice c14f179e39 fix(help): keep the help center's content clear of its close button
The close button floats over the scrolling content, which only kept a 40px gutter on the end side while the button reaches 52px in, so the first card ran right up to it. The content now keeps a wider gutter on that side.
2026-10-28 10:24:08 +01:00
Maurice 3bfef73a46 refactor(maps): move the place clusters out of MapViewGL
The cluster source, its layers, the expansion zoom and the DOM bubbles
now live in placeClusterLayers.ts with their own tests, which brings
MapViewGL back under its size baseline instead of growing it. Lowers the
size and eslint baselines that this change made smaller.
2026-10-28 10:11:56 +01:00
Maurice 7e790c3fb7 fix(maps): draw the GL cluster bubbles like the Leaflet ones
The MapLibre and Mapbox maps painted their place clusters as a canvas
circle plus a symbol layer, so the count used whatever glyphs the map
style ships and the bubble had no hover. They are now DOM pins built by
the same markup and CSS as the Leaflet bubbles, with the same sizes,
font and hover scale. The canvas layers stay, invisible, as the hit
area the track and route layers check a click against.
2026-10-28 10:11:56 +01:00
Maurice 228db8541c chore(notices): show 5.0.1 in the release popup
The release popup still named 5.0.0 and linked the 5.0.0 release notes. It now names 5.0.1 and links its tag.
2026-10-28 09:52:18 +01:00
Maurice a729a6935f fix(journey): keep the photo picker's calendar inside the screen
The date picker of the external photo picker hung absolutely under its
trigger, inside a dialog that clips its content. The last week of a
six-week month fell below the dialog, and for the end date in the
right-hand column the calendar opened past the dialog's right edge, so
the last weekday and the next-month arrow could not be reached.

The calendar now opens in a portal, pinned to its trigger through
useAnchoredPosition: it flips above the trigger when below is too short,
scrolls when neither side holds it, and is kept inside the viewport
sideways.

Closes #2858
2026-10-28 09:25:53 +01:00
Maurice 6c0e39e287 fix(transit): name and record the backend that answered, not always Transitous
With Google as the transit provider, the result list still credited
Transitous, and a route added from the panel or through
create_transit_journey was saved with provider 'transitous'. The panel
now credits "Google Maps" (untranslated, as Google's terms ask) or
Transitous after the backend that answered and saves that one; the MCP
journey records the backend that plans routes for the caller, and
search_transit_routes reports it.
2026-10-27 21:30:18 +01:00