Fix all OpenSpec validation failures (36/36 passing)
- Add ## Purpose sections and convert delta headers to ## Requirements on all 25 specs - Add SHALL keywords to requirements missing them (gpx-import, planner-session, planner-journal-handoff) - Convert prose GPX format section to proper scenarios (no-go-areas) - Create specs/ delta files for 7 changes that were missing them (activity-photos, local-dev-stack, multi-day-routes, route-discovery, route-sharing, visual-redesign, waypoint-notes) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c6949e9490
commit
0b9b99984e
32 changed files with 414 additions and 35 deletions
|
|
@ -1,4 +1,8 @@
|
|||
## MODIFIED Requirements
|
||||
## Purpose
|
||||
|
||||
User account settings page with connected services management, profile editing, and security controls.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Connected Services section
|
||||
The settings page SHALL include a "Connected Services" section for managing external integrations.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
## ADDED Requirements
|
||||
## Purpose
|
||||
|
||||
Activity creation, chronological feed, detail views, and route linking in the Journal app.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Create activity
|
||||
The Journal SHALL allow authenticated users to create an activity by uploading a GPX trace and adding a description.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
## ADDED Requirements
|
||||
## Purpose
|
||||
|
||||
Route computation between waypoints via the BRouter HTTP API, including routing host election, result broadcasting via Yjs, profile selection, and rate-limited proxying.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Route computation from waypoints
|
||||
The Planner SHALL compute a route between ordered waypoints by calling the BRouter HTTP API with tiledesc enabled and returning the result as an EnrichedRoute, preserving per-point elevation, surface data, and segment boundary indices.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
## Purpose
|
||||
|
||||
Browser crash resilience via localStorage-based Yjs state persistence and recovery on reconnect.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: localStorage crash recovery
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
## ADDED Requirements
|
||||
## Purpose
|
||||
|
||||
GPX file import in the Planner via home page file picker and in-session drag-and-drop, with client-side parsing and waypoint extraction.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Import GPX from home page
|
||||
Users SHALL be able to import a GPX file from the planner home page to start a new planning session.
|
||||
|
|
@ -30,7 +34,9 @@ Users SHALL be able to drag a GPX file onto the map in an existing session.
|
|||
- **WHEN** a user drops a GPX file and the confirmation dialog appears
|
||||
- **THEN** clicking "Cancel" leaves the session unchanged
|
||||
|
||||
### Requirement: Non-GPX files are rejected
|
||||
### Requirement: Non-GPX file rejection
|
||||
The Planner SHALL reject non-GPX files dropped on the map.
|
||||
|
||||
#### Scenario: Drop non-GPX file
|
||||
- **WHEN** a user drops a non-GPX file on the map
|
||||
- **THEN** the file is ignored with a brief error toast
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
## ADDED Requirements
|
||||
## Purpose
|
||||
|
||||
Server provisioning on Hetzner, Docker Compose deployment, CI/CD pipelines, database and BRouter management, TLS, Sentry, Grafana, and monitoring stack for the flagship instance.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Terraform Hetzner provisioning
|
||||
Infrastructure SHALL be provisioned on Hetzner Cloud using Terraform with the Hetzner provider.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
## MODIFIED Requirements
|
||||
## Purpose
|
||||
|
||||
Authentication for the Journal app, including OAuth token storage for external services in the sync_connections table.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Store external service tokens
|
||||
The journal auth system SHALL store OAuth tokens for external services alongside user credentials.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
## ADDED Requirements
|
||||
## Purpose
|
||||
|
||||
One-command local development setup with PostgreSQL, BRouter, automatic schema migration, and segment downloading.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: One-command dev startup
|
||||
The project SHALL provide a single command that starts all services needed for local development.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
## ADDED Requirements
|
||||
## Purpose
|
||||
|
||||
Interactive map rendering with Leaflet and OSM tiles, waypoint editing, route visualization, elevation profiles, multiplayer cursors, and polygon drawing for both Planner and Journal apps.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Map rendering with OSM tiles
|
||||
The Planner and Journal SHALL render interactive maps using Leaflet with OpenStreetMap tiles as the default base layer.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
## Purpose
|
||||
|
||||
Polygon-based route avoidance areas drawn on the map, synced via Yjs, sent to BRouter as constraints, and persisted in GPX extensions.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Draw no-go areas
|
||||
|
|
@ -35,22 +39,16 @@ No-go areas SHALL be preserved when saving to the journal or exporting a plan.
|
|||
- **AND** the file is compatible with any GPX-consuming application
|
||||
|
||||
### Requirement: GPX extensions format
|
||||
No-go areas are stored in GPX using a custom XML namespace:
|
||||
No-go areas SHALL be stored in GPX using the `trails:planning` custom XML namespace with point-based polygon representation.
|
||||
|
||||
```xml
|
||||
<gpx xmlns:trails="https://trails.cool/gpx/1">
|
||||
<extensions>
|
||||
<trails:planning>
|
||||
<trails:nogo>
|
||||
<trails:point lat="52.5" lon="13.3"/>
|
||||
<trails:point lat="52.4" lon="13.4"/>
|
||||
<trails:point lat="52.3" lon="13.2"/>
|
||||
</trails:nogo>
|
||||
</trails:planning>
|
||||
</extensions>
|
||||
</gpx>
|
||||
```
|
||||
#### Scenario: Valid no-go area in GPX
|
||||
- **WHEN** a GPX file contains a `<trails:nogo>` element with 3+ `<trails:point>` child elements
|
||||
- **THEN** the parser creates a no-go area polygon from the point coordinates
|
||||
|
||||
- Each `<trails:nogo>` element contains 3+ `<trails:point>` elements
|
||||
- Parser accepts both namespaced (`trails:nogo`) and non-namespaced (`nogo`) elements
|
||||
- Areas with fewer than 3 points are rejected on parse
|
||||
#### Scenario: Namespace-agnostic parsing
|
||||
- **WHEN** a GPX file contains non-namespaced `<nogo>` elements instead of `<trails:nogo>`
|
||||
- **THEN** the parser accepts them identically
|
||||
|
||||
#### Scenario: Invalid no-go area rejected
|
||||
- **WHEN** a GPX file contains a no-go area with fewer than 3 points
|
||||
- **THEN** the parser rejects it
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
## Purpose
|
||||
|
||||
Health endpoints, Prometheus metrics, structured logging, Grafana dashboards, and alerting for both apps and the flagship instance.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Health endpoints
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
## MODIFIED Requirements
|
||||
## Purpose
|
||||
|
||||
Round-trip GPX exchange between Planner and Journal, including JWT-scoped callbacks for saving routes and GPX reimport in the Planner.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Export Plan reimport
|
||||
The "Export Plan" GPX can now be reimported directly in the planner via the file upload UI, completing the round-trip without needing the journal.
|
||||
The Planner SHALL support reimporting an exported plan GPX via the file upload UI, completing the round-trip without needing the journal.
|
||||
|
||||
#### Scenario: Reimport exported plan
|
||||
- **WHEN** a user exports a plan and later imports it via the planner's GPX upload
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
## MODIFIED Requirements
|
||||
## Purpose
|
||||
|
||||
### Requirement: Session initialization
|
||||
Sessions can now be initialized from a GPX file upload in addition to URL parameters and the journal handoff.
|
||||
Collaborative planning session management with Yjs CRDT synchronization, supporting initialization from URL parameters, journal handoff, and GPX file upload.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Session initialization from GPX
|
||||
The Planner SHALL support initializing sessions from a GPX file upload in addition to URL parameters and the journal handoff.
|
||||
|
||||
#### Scenario: Session created from GPX upload
|
||||
- **WHEN** a session is created via GPX file upload on the home page
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
## Purpose
|
||||
|
||||
Request rate limiting for Planner session creation and BRouter API calls to prevent abuse.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Session creation rate limit
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
## Purpose
|
||||
|
||||
Multi-mode route visualization (plain, elevation gradient, surface type) with session-synced color mode selection.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Route color modes
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
## Purpose
|
||||
|
||||
Ghost marker drag interaction for reshaping routes by inserting new waypoints mid-segment.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Ghost marker on route hover
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
## ADDED Requirements
|
||||
## Purpose
|
||||
|
||||
Route CRUD operations, GPX import/export, sequential versioning, PostGIS spatial storage, and route metadata in the Journal app.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Create route
|
||||
The Journal SHALL allow authenticated users to create a new route with a name and optional description.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
## ADDED Requirements
|
||||
## Purpose
|
||||
|
||||
Map thumbnails on route and activity list pages, and interactive maps with zoom and layer switching on detail pages.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Route map preview on list pages
|
||||
Route and activity list pages SHALL show a small map thumbnail for each item that has geometry.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
## Purpose
|
||||
|
||||
Waypoint insertion by clicking the ghost marker on the route polyline, splitting a segment into two.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Insert waypoint by clicking on route
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
## Purpose
|
||||
|
||||
SOPS-encrypted secrets stored in the repository, split into app and infra files, decryptable with a single age key at deploy time.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Encrypted secrets in repository
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
## Purpose
|
||||
|
||||
Security headers, scanner path blocking, secret scanning, dependency auditing, non-root containers, and vulnerability disclosure policy.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Security response headers
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
## Purpose
|
||||
|
||||
Collaborative text notes in Planner sessions, synced in real-time via Yjs.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Collaborative session notes
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
## ADDED Requirements
|
||||
## Purpose
|
||||
|
||||
Shared TypeScript packages (@trails-cool/types, gpx, map, ui, i18n) used by both Planner and Journal apps.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Shared types package
|
||||
The `@trails-cool/types` package SHALL export TypeScript interfaces for Route, Activity, Waypoint, RouteVersion, and RouteMetadata used by both apps.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
## Purpose
|
||||
|
||||
Transactional email sending with HTML and plain-text templates for magic links and welcome messages, using SMTP in production and console logging in dev.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Email sending interface
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
## ADDED Requirements
|
||||
## Purpose
|
||||
|
||||
Provider-agnostic activity sync framework with Wahoo as the first provider, supporting OAuth connection, webhook-based automatic sync, manual import, and FIT-to-GPX conversion.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Provider-agnostic sync framework
|
||||
The system SHALL provide a common interface for external activity sync providers.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue