P1 — self-hosted OSRM replaces ALL paid Mapbox routing in the SPA:
- hub: POST /roster/osrm-route (geometry + total + per-leg km/min) and
/roster/osrm-table (durations/distances matrix, Mapbox-shaped) proxying
the local OSRM; osrmGet helper.
- SPA: loadRealRoutes (review map), kanban travel matrix, day-editor
matrix, day-map route geometry → all via hub OSRM. 0 paid
directions/matrix calls left (tiles + geocoding only).
Review usability (evaluate whether times fit):
- Click a job → the SAME job-detail dialog as the grid (address, ticket
thread, duration, team). openEntryDetail maps the pool job.
- Per-task time is editable (q-popup-edit on the "X.Xh"): updates the
plan live, survives Ré-optimiser (durOverride), persists duration_h
via patchJob (hub whitelist extended, 0-24h).
- Real travel time BETWEEN stops: one OSRM route per tech×day (cached)
→ "🚗 X min" rows between entries + "domicile → 1er arrêt";
haversine ≈ fallback when coords missing.
Verified: OSRM proxies live (route 7.8km/12min with legs 7+6min, table
3x3); review shows 10 real leg rows; detail dialog shows address;
duration popup opens/cancels cleanly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>