Commit graph

8 commits

Author SHA1 Message Date
Ullrich Schäfer
ed7f6ce153
Session-bind /api/route and /api/overpass
Today both proxies are effectively open to anyone who can set an
Origin header for trails.cool — a third party can use us as a free
BRouter/Overpass relay. Require a live planner session on every call
so abuse traffic costs the scraper a session row (observable,
revocable) before they can issue a single query.

Server:
- New `requireSession(id)` helper — returns the session row or a 401
  Response. Reused by both route handlers.
- `/api/route`: `sessionId` in body is now required and verified;
  rate-limit key always falls back to the session id.
- `/api/overpass`: new `X-Trails-Session` header, verified. Header
  keeps the session out of the request body so the body-keyed cache
  is unaffected.

Client plumbing:
- `useRouting(yjs, sessionId)` — sessionId goes into the /api/route
  body.
- `usePois(sessionId)` → `queryPois(..., sessionId)` → `X-Trails-Session`
  on the proxy call.
- `PlannerMap` + `YjsDebugPanel` gain a `sessionId` prop from
  `SessionView`.

Journal server-to-server:
- Demo-bot and `/api/v1/routes/compute` now POST `/api/sessions` to
  mint a throwaway planner session, then cite it on the forwarded
  `/api/route` call. Planner's `expire-sessions` cron cleans these up
  (7d window) so nothing needs explicit teardown.

Tests:
- 5 unit tests for `requireSession` covering missing / empty /
  non-string / unknown-session / valid-session cases.
- Two integration E2E tests document the 401 for missing session on
  each proxy.
- Pre-existing `/api/route` integration tests updated to mint a
  session first.

Caveat: existing browser tabs lose their /api/route ability until
reload (the old JS doesn't know to send sessionId). Acceptable for
an anonymous planner.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 22:18:45 +02:00
Ullrich Schäfer
f94020a93a
Block unmocked external requests in E2E tests
Surface net for the class of bug we hit in #282 — a POI test silently
relied on a live Overpass server for months because its `page.route`
mock was targeting a URL the browser no longer hit directly. CI stayed
green on coincidence (real OSM data happened to satisfy the "any
marker renders" assertion) until upstream behaviour drifted.

Add a shared Playwright fixture (e2e/fixtures/test.ts) that installs a
catch-all `page.route("**", ...)` before each test. Requests to
localhost + known tile CDNs pass through via `route.continue()`;
anything else is aborted and accumulated. At test teardown, a non-empty
blocked list throws, failing the test with the offending URLs and a
pointer to the fixture.

All seven e2e *.test.ts files updated to import test/expect (+ types)
from ./fixtures/test.

Full suite passes with this fixture in place (50/50 at --workers=2;
catch-all never fires, meaning no test currently relies on an
unallowlisted external service).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 22:42:29 +02:00
Ullrich Schäfer
2970a460f8
Add E2E tests, Journal map coloring, and remaining unit tests
- planner.test.ts: E2E test for overnight toggle → day breakdown in sidebar,
  and GPX import with overnight metadata
- integration.test.ts: E2E test for isDayBreak preservation through GPX import
- RouteMapThumbnail: Per-day route coloring with alternating colors
- overnight.test.ts: Y.Doc-aware tests for isOvernight/setOvernight
- daybreaks-extraction.test.ts: GPX → dayBreaks index extraction tests

All 28 tasks complete.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:14:08 +02:00
Ullrich Schäfer
b080a15fb1
Add route interactions: click-to-split, drag-to-reshape, colored route rendering
- Enrich BRouter response with per-point 3D coordinates and segment boundary
  tracking (EnrichedRoute interface)
- ColoredRoute component: plain, elevation gradient (green→yellow→red), and
  surface color modes with invisible wide polyline for click targeting
- Click-to-split: click on route polyline inserts waypoint at nearest point,
  mapped to correct segment via boundary indices
- MidpointHandles: draggable CircleMarkers at route segment midpoints for
  reshaping, hidden below zoom 12, opaque on hover
- Color mode toggle (select) synced via Yjs routeData
- i18n keys for color mode labels (en + de)
- Unit tests for segment boundary tracking (13 tests)
- E2E tests for enriched route response and color mode toggle

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:15:55 +01:00
Ullrich Schäfer
0a8dd0b766
Add transactional emails (SMTP) and planner features (no-go areas, notes, crash recovery)
Transactional emails:
- Add nodemailer SMTP email module with dev-mode console logging
- Magic link template and welcome template with HTML + plain text
- Wire sendMagicLink into login flow, sendWelcome into registration
- Update privacy page and deploy docs for SMTP configuration

Planner features:
- No-go areas: draw polygons on map (leaflet-geoman), synced via Yjs,
  passed to BRouter as nogos parameter, route recomputes on change
- Session notes: collaborative Y.Text textarea in sidebar tab
- Crash recovery: periodic localStorage save of Yjs state, restore on reconnect
- Rate limit session creation (10/IP/hour) in /new route

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 01:00:42 +01:00
Ullrich Schäfer
b71117e4ca
Add PostgreSQL + BRouter to CI E2E tests
CI now runs the full stack for E2E tests:
- PostgreSQL as a service container + schema push via drizzle
- BRouter JAR + Berlin segment (E10_N50) with caching
- Both cached across runs (BRouter JAR + segment)

Removed all skip/workaround logic from tests — all 20 E2E tests
now run in CI with real services.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 23:58:01 +01:00
Ullrich Schäfer
7d273b73c0
Fix CI E2E: check Planner DB, add Playwright HTML report
- Integration test DB check now hits Planner API (not Journal)
  so it correctly skips when no PostgreSQL in CI
- Playwright uploads HTML report artifact on all runs (not just failures)
- Install Chromium with --with-deps for CI compatibility
- Report retained for 30 days

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 23:47:43 +01:00
Ullrich Schäfer
79e6ae6ea2
Add E2E and integration tests (Group 11)
Journal tests (6):
- Home page, auth pages render correctly
- No password fields on register/login
- Protected routes redirect to login

Planner tests (9):
- Session creation via API
- Map loads in session
- Yjs WebSocket connects (Connected status)
- Profile selector, export button, waypoint sidebar
- Session with initial GPX waypoints
- Expired session returns 404

Integration tests (5):
- GPX import returns parsed waypoints
- BRouter computes Berlin routes
- Routes pass through all waypoints (segment by segment)
- Rate limit headers present
- Rejects < 2 waypoints

Total: 32 unit tests + 20 E2E tests, all passing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 23:20:04 +01:00