From 38617ce0aa070571cba434e554f6d7e7998b28b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ullrich=20Sch=C3=A4fer?= Date: Sun, 24 May 2026 11:20:57 +0200 Subject: [PATCH] Fix OpenSpec validation failures on medium-severity specs - komoot-import: add SHALL to Credential storage requirement body - local-dev-environment: add SHALL to Mobile app dev requirement body - multi-day-routes: demote ### Note heading to plain paragraph to avoid validator treating it as a requirement Co-Authored-By: Claude Sonnet 4.6 --- openspec/specs/komoot-import/spec.md | 2 +- openspec/specs/local-dev-environment/spec.md | 2 +- openspec/specs/multi-day-routes/spec.md | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/openspec/specs/komoot-import/spec.md b/openspec/specs/komoot-import/spec.md index affc9e9..16fd386 100644 --- a/openspec/specs/komoot-import/spec.md +++ b/openspec/specs/komoot-import/spec.md @@ -81,7 +81,7 @@ Each import run SHALL be tracked as a batch with status and statistics. - **THEN** the batch shows: totalFound, importedCount, duplicateCount, and duration ### Requirement: Credential storage -Both connection modes store credentials in `connected_services` with `credential_kind = 'web-login'`. Public mode stores only the verified Komoot username; authenticated mode stores an encrypted email + password in the `credentials` JSONB blob. The Komoot provider uses a noop `CredentialAdapter` — it does not go through `ConnectedServiceManager`'s `withFreshCredentials` lifecycle (no token refresh needed for web-login credentials). Credential decryption for API calls happens inside the Komoot importer directly. +Both connection modes SHALL store credentials in `connected_services` with `credential_kind = 'web-login'`. Public mode stores only the verified Komoot username; authenticated mode stores an encrypted email + password in the `credentials` JSONB blob. The Komoot provider uses a noop `CredentialAdapter` — it does not go through `ConnectedServiceManager`'s `withFreshCredentials` lifecycle (no token refresh needed for web-login credentials). Credential decryption for API calls happens inside the Komoot importer directly. The four Komoot-specific routes (`/api/sync/komoot/connect`, `/api/sync/komoot/verify`, `/api/sync/komoot/import`, `/api/sync/komoot/import-status`) intentionally bypass the generic `/api/sync/connect/:provider` / `/api/sync/callback/:provider` framework — Komoot's bio-verification flow is too different from OAuth to fit the generic shape. diff --git a/openspec/specs/local-dev-environment/spec.md b/openspec/specs/local-dev-environment/spec.md index 54bd08f..f3e6e97 100644 --- a/openspec/specs/local-dev-environment/spec.md +++ b/openspec/specs/local-dev-environment/spec.md @@ -81,7 +81,7 @@ The dev environment SHALL provide a command to tear down and recreate the local - **THEN** all Docker volumes are removed and containers are recreated ### Requirement: Mobile app dev (Expo) -The `apps/mobile` React Native app (Expo) requires its own dev commands separate from the web stack. +The project SHALL provide dedicated dev commands for the `apps/mobile` React Native app (Expo), separate from the web stack. #### Scenario: iOS development - **WHEN** a developer runs `pnpm dev:ios` from `apps/mobile` diff --git a/openspec/specs/multi-day-routes/spec.md b/openspec/specs/multi-day-routes/spec.md index dcde5cf..8f76e2c 100644 --- a/openspec/specs/multi-day-routes/spec.md +++ b/openspec/specs/multi-day-routes/spec.md @@ -60,6 +60,4 @@ Day structure SHALL be preserved in GPX exports via waypoint type elements. Note: the single-track export (without `splitByDays`) is the default. The per-day split is available as an option on the GPX generator and is the recommended format for multi-day exports to head units. -### Note on overnight vs isDayBreak naming - -The Yjs wire format stores the flag as `overnight: true` on the waypoint Y.Map entry. The TypeScript interface exposes it as `isDayBreak` (a comment in `waypoint-ymap.ts` documents `overnight` as the legacy wire name). Spec scenarios use `overnight` to refer to the wire-level concept; TypeScript code uses `isDayBreak`. +Note on overnight vs isDayBreak naming: The Yjs wire format stores the flag as `overnight: true` on the waypoint Y.Map entry. The TypeScript interface exposes it as `isDayBreak` (a comment in `waypoint-ymap.ts` documents `overnight` as the legacy wire name). Spec scenarios use `overnight` to refer to the wire-level concept; TypeScript code uses `isDayBreak`.