Merge branch 'worktree-agent-a7f7c229' into Develop

# Conflicts:
#	.planning/REQUIREMENTS.md
#	.planning/ROADMAP.md
#	.planning/STATE.md
#	tests/routes/auth.test.ts
#	tests/services/auth.service.test.ts
This commit is contained in:
2026-04-04 20:56:29 +02:00
12 changed files with 368 additions and 423 deletions

View File

@@ -19,9 +19,9 @@ Requirements for this milestone. Each maps to roadmap phases.
- [x] **AUTH-01**: User can register an account via external OIDC auth provider
- [x] **AUTH-02**: User can log in via external auth provider and access their data
- [x] **AUTH-03**: API keys remain functional for programmatic access (MCP, scripts)
- [ ] **AUTH-03**: API keys remain functional for programmatic access (MCP, scripts)
- [ ] **AUTH-04**: Auth provider runs self-hosted alongside the application
- [ ] **AUTH-05**: E2E tests authenticate via API keys without depending on the auth provider
- [x] **AUTH-05**: E2E tests authenticate via API keys without depending on the auth provider
### Multi-User Data Model
@@ -123,9 +123,9 @@ Which phases cover which requirements. Updated during roadmap creation.
| DB-05 | Phase 14 | Pending |
| AUTH-01 | Phase 15 | Complete |
| AUTH-02 | Phase 15 | Complete |
| AUTH-03 | Phase 15 | Complete |
| AUTH-03 | Phase 15 | Pending |
| AUTH-04 | Phase 15 | Pending |
| AUTH-05 | Phase 15 | Pending |
| AUTH-05 | Phase 15 | Complete |
| MULTI-01 | Phase 16 | Pending |
| MULTI-02 | Phase 16 | Pending |
| MULTI-03 | Phase 16 | Pending |

View File

@@ -189,7 +189,7 @@ Plans:
| 12. Comparison View | v1.3 | 1/1 | Complete | 2026-03-17 |
| 13. Setup Impact Preview | v1.3 | 0/2 | Not started | - |
| 14. PostgreSQL Migration | v2.0 | 0/? | Not started | - |
| 15. External Authentication | v2.0 | 2/1 | Complete | 2026-04-04 |
| 15. External Authentication | v2.0 | 1/1 | Complete | 2026-04-04 |
| 16. Multi-User Data Model | v2.0 | 0/? | Not started | - |
| 17. Object Storage | v2.0 | 0/? | Not started | - |
| 18. Global Items & Public Profiles | v2.0 | 0/? | Not started | - |

View File

@@ -3,14 +3,14 @@ gsd_state_version: 1.0
milestone: v1.3
milestone_name: Research & Decision Tools
status: planning
stopped_at: Completed 15-02-PLAN.md
last_updated: "2026-04-04T18:47:52.641Z"
stopped_at: Completed 15-03-PLAN.md
last_updated: "2026-04-04T18:55:48.924Z"
last_activity: 2026-04-03 — v2.0 roadmap created (Phases 14-18)
progress:
total_phases: 8
completed_phases: 7
total_plans: 13
completed_plans: 12
completed_plans: 11
percent: 0
---
@@ -54,8 +54,8 @@ Key decisions made during v2.0 planning:
- Structured UGC only — ratings and predefined fields, no freeform text until moderation
- Separate globalItems table — not a flag on user items table
- Single-user SQLite mode diverges at v2.0 boundary
- [Phase 15]: OIDC routes at root level (/login, /callback, /logout), API key routes under /api/auth
- [Phase 15]: Three-way auth order: API key -> MCP Bearer -> OIDC session
- [Phase 15]: Login page redirects to Logto OIDC (no credential form), useLogout uses redirect not mutation
- [Phase 15]: E2E tests use static API key for auth, no dependency on Logto provider
### Pending Todos
@@ -68,6 +68,6 @@ None active.
## Session Continuity
Last session: 2026-04-04T18:47:52.639Z
Stopped at: Completed 15-02-PLAN.md
Last session: 2026-04-04T18:55:48.922Z
Stopped at: Completed 15-03-PLAN.md
Resume file: None

View File

@@ -0,0 +1,143 @@
---
phase: 15-external-authentication
plan: 03
subsystem: auth
tags: [oidc, logto, react, tanstack-query, e2e, api-keys]
# Dependency graph
requires:
- phase: 15-external-authentication (plan 02)
provides: OIDC middleware, refactored auth routes, stripped auth service
provides:
- OIDC-aware login page (redirect to Logto, no credential form)
- Updated auth hooks matching new API response shape (string user id)
- E2E seed using API keys instead of user table
- Auth middleware tests for three-way auth (API key, Bearer, OIDC)
- Auth route tests with mocked OIDC session
affects: [16-multi-user-data-model, e2e-tests]
# Tech tracking
tech-stack:
added: []
patterns:
- "OIDC redirect login via window.location.href to server route"
- "useLogout returns plain function (not mutation) for redirect-based logout"
- "E2E tests authenticate via API key header, bypassing auth provider"
- "Mock @hono/oidc-auth getAuth in tests with bun:test mock.module"
key-files:
created: []
modified:
- src/client/hooks/useAuth.ts
- src/client/routes/login.tsx
- src/client/routes/settings.tsx
- src/client/components/UserMenu.tsx
- e2e/seed.ts
- tests/middleware/auth.test.ts
- tests/services/auth.service.test.ts
- tests/routes/auth.test.ts
key-decisions:
- "Login page renders redirect button rather than credential form"
- "useLogout returns { logout } function (not useMutation) since it is a redirect"
- "Removed ChangePasswordSection from settings (passwords managed by Logto)"
- "E2E seed uses static API key string for deterministic test auth"
patterns-established:
- "OIDC login: client redirects to server /login which triggers Logto redirect"
- "Test mocking: mock.module for @hono/oidc-auth before importing middleware"
- "E2E auth: API key in X-API-Key header, no dependency on auth provider"
requirements-completed: [AUTH-05, AUTH-01, AUTH-02]
# Metrics
duration: 4min
completed: 2026-04-04
---
# Phase 15 Plan 03: Client Auth UI, E2E Seed, and Test Updates Summary
**OIDC login redirect page, cleaned auth hooks (string user id, no credential forms), API-key E2E seed, and three-way auth test coverage**
## Performance
- **Duration:** 4 min
- **Started:** 2026-04-04T18:50:52Z
- **Completed:** 2026-04-04T18:54:28Z
- **Tasks:** 3 (2 auto + 1 checkpoint auto-approved)
- **Files modified:** 8
## Accomplishments
- Login page redirects to Logto via server-side OIDC instead of showing username/password form
- Auth hooks match new OIDC API response shape (user.id is string, no setupRequired)
- E2E seed creates API key for test authentication instead of inserting into removed users table
- Auth middleware and route tests validate all three auth paths with proper mocking
## Task Commits
Each task was committed atomically:
1. **Task 1: Rewrite login page and auth hooks for OIDC** - `79b27b6` (feat)
2. **Task 2: Update E2E seed script and auth-related tests** - `689a56b` (feat)
3. **Task 3: Verify OIDC login flow** - auto-approved checkpoint (no commit)
## Files Created/Modified
- `src/client/hooks/useAuth.ts` - Removed useLogin/useSetup/useChangePassword, updated AuthState to string id
- `src/client/routes/login.tsx` - Replaced credential form with OIDC redirect button
- `src/client/routes/settings.tsx` - Removed ChangePasswordSection, use authenticated flag
- `src/client/components/UserMenu.tsx` - Updated logout call from mutation to direct function
- `e2e/seed.ts` - API key creation instead of user insertion
- `tests/middleware/auth.test.ts` - Three-way auth tests with mocked getAuth and verifyAccessToken
- `tests/services/auth.service.test.ts` - API key CRUD tests only (removed user/session tests)
- `tests/routes/auth.test.ts` - GET /me with mocked OIDC, API key CRUD routes
## Decisions Made
- Login page renders a "Sign In" button that triggers `window.location.href = "/login"` for full-page navigation to server OIDC redirect
- useLogout returns a plain `{ logout }` object instead of useMutation since it performs a redirect, not an API call
- Removed ChangePasswordSection from settings entirely since passwords are managed in Logto
- Settings page API keys section gated on `auth?.authenticated` instead of `auth?.user`
- E2E seed uses a static deterministic API key string for reproducible test runs
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 3 - Blocking] Updated UserMenu.tsx for new useLogout API**
- **Found during:** Task 1 (Rewrite auth hooks)
- **Issue:** UserMenu called `logout.mutate()` but new useLogout returns `{ logout }` function, not a mutation
- **Fix:** Changed `logout.mutate()` to `logout()` in UserMenu onClick handler
- **Files modified:** src/client/components/UserMenu.tsx
- **Verification:** No remaining `logout.mutate` references in codebase
- **Committed in:** 79b27b6 (Task 1 commit)
**2. [Rule 3 - Blocking] Removed ChangePasswordSection from settings page**
- **Found during:** Task 1 (Rewrite auth hooks)
- **Issue:** Settings page imported and used `useChangePassword` which was removed from hooks; page would not compile
- **Fix:** Removed entire ChangePasswordSection component and its import from settings.tsx
- **Files modified:** src/client/routes/settings.tsx
- **Verification:** No references to useChangePassword remain in client code
- **Committed in:** 79b27b6 (Task 1 commit)
---
**Total deviations:** 2 auto-fixed (2 blocking issues)
**Impact on plan:** Both fixes were necessary to keep the client compiling after hook removals. No scope creep.
## Deferred Items
- `tests/routes/oauth.test.ts` still references `createUser` from old auth service (pre-existing, not caused by this plan)
## Issues Encountered
None
## User Setup Required
None - no external service configuration required for this plan (infrastructure was set up in Plan 01).
## Next Phase Readiness
- Client auth UI complete and aligned with OIDC backend from Plan 02
- E2E seed ready for API-key-based test authentication
- All auth-related unit/integration tests updated for new architecture
- Phase 15 external authentication integration is complete across all three plans
---
*Phase: 15-external-authentication*
*Completed: 2026-04-04*