Defer V3-08/V3-09, add V3-17 to investigate self-hosted OSRM

Per request: V3-08's routing-engine direction is decided (self-hosted OSRM over a hosted API or the public demo instance) but standing one up is split into its own ticket, V3-17, since provisioning a server is different work from the app code that calls it. V3-08 and V3-09 are marked Deferred pending V3-17.

V3-17 also names a real tension worth flagging rather than quietly ignoring: this backlog's own organizing principle is 'v3 is everything buildable with no server,' and a self-hosted OSRM instance is a server -- so V3-08/V3-09 sit oddly under docs/v3/ once V3-17 exists. Left unresolved by design (a documentation call for later), noted in both V3-17 and BACKLOG.md's v4 section rather than silently renumbering tickets that are already cross-referenced throughout the docs.
This commit is contained in:
2026-08-17 19:56:44 -05:00
parent 1bcc6f1c5a
commit e2ccd4b250
5 changed files with 117 additions and 6 deletions

View File

@@ -0,0 +1,88 @@
# V3-17 — Self-hosted OSRM: investigate and stand one up
**Phase** Infrastructure · **Depends on** nothing · **Size** M · **Blocks** V3-08, V3-09 ·
**Status** Not started
## Goal
Get a self-hosted OSRM instance running somewhere, so V3-08 (road-snapped routing and
ETA) has a real backend to build against instead of a deferred decision.
## Context
V3-08 named the choice of routing engine as "a decision that cannot be deferred," and
[the conversation that spawned this ticket](../v3/README.md) picked a direction without
picking a provider: **self-hosted OSRM**, over a hosted API (GraphHopper, Mapbox
Directions) or the public OSRM demo (explicitly not for production use).
**This ticket exists because that decision itself has a wrinkle worth naming up front:**
this whole v3 backlog's organizing principle, stated in `docs/BACKLOG.md`, is *"v3 is
everything that can be built with no server. v4 is everything that cannot."* A
self-hosted OSRM instance is a server. Strictly, that makes V3-08 and V3-09 — anything
that depends on this ticket — v4 work by the project's own definition, not v3, even
though they're filed under `docs/v3/` today and the routing itself has nothing to do
with the group-rides/accounts/backup programme that currently defines v4. Whether to
formally renumber them is a documentation decision for whoever picks this up next; this
ticket does not resolve it, only flags it so it isn't silently glossed over.
## Design
Two separable questions:
1. **Where does it run?** A small VPS (the same shape of box that would eventually host
the v4 group-ride server, so this could double as an early step toward that) versus
something serverless/managed. OSRM's own Docker image is the standard path either way.
2. **What data does it need?** A regional OSM extract, not the planet — start with
whatever region actually gets ridden (per `docs/LAUNCH.md`, this is presently a
friends-and-family app, so the region is small and known). [Geofabrik](https://download.geofabrik.de/)
publishes regional `.osm.pbf` extracts sized for exactly this.
Profiles matter for this app specifically (see V3-08's Design section): a motorcycle
route and a bicycle route between the same two pins should genuinely differ. OSRM ships
car/bike/foot profiles out of the box; a motorcycle profile is closer to car (mostly
avoids the walk-only restrictions bike profiles impose) but might want the twisty-road
preference a stock car profile doesn't have reason to express. Confirming that is part of
this ticket's investigation, not something to guess at now.
## Implementation
1. Pick and provision a host (see Design's first question)
2. Download and preprocess a regional extract with OSRM's own toolchain
(`osrm-extract` → `osrm-partition` → `osrm-customize`, or the older
`osrm-contract` pipeline depending on the OSRM version chosen)
3. Run `osrm-routed` behind whatever the host offers for TLS termination — the app will
be calling this over the public internet from riders' phones, so plain HTTP is not
an option
4. Confirm at least a car-equivalent and a bike profile both return sane routes for a
handful of real local pin pairs, by hand, before writing any app code against it
5. Write the resulting base URL and auth (if any) down for V3-08 to consume — as
configuration, never a hardcoded value, matching V3-08's own "no API key committed to
the repository" acceptance criterion, which applies here too even though there's no
third-party vendor to protect a key from — an open, unauthenticated routing endpoint
is still worth not publishing in a public repo
6. A basic uptime check of some kind — this becomes a real dependency the app relies on,
not a fire-and-forget script
## Acceptance criteria
- [ ] An OSRM instance is reachable over HTTPS from outside the host network
- [ ] Returns a road-following route for a real pin pair in the region actually ridden
- [ ] At least two distinct profiles (car-equivalent, bike) both work
- [ ] The endpoint and any credentials live in configuration, not source
- [ ] Documented: what's running, where, how to update the extract when it goes stale,
and what it costs (if anything) to keep running
## Tests
Infrastructure, not app code — no `flutter test` coverage belongs to this ticket
directly. V3-08's own `FakeRoutingService`-driven tests are what verify the app's
behavior; this ticket's job is only to make the real thing exist for that fake to stand
in for.
## Risks
- **Ongoing hosting cost and maintenance**, however small — this is the first piece of
always-on infrastructure this project has taken on. Worth being honest that "no
server" stopped being true the moment this ticket is picked up, regardless of which
numbering bucket it ends up filed under.
- **OSM extracts go stale.** A road that didn't exist at extract time won't route.
Needs a refresh cadence, not a one-time setup.
- Regional extracts are cheap; do not reach for a planet-wide extract preemptively.
## Out of scope
Actually building V3-08/V3-09 against this once it exists — that's their ticket, not
this one. Turn-by-turn navigation, traffic-aware routing, anything beyond what stock OSRM
gives you.