# ADR-0028 Phase B Roadmap **Document ID:** PHASE_B_ROADMAP **Date:** 2026-05-05 evening **Status:** In Progress **Author:** AI Agent (vibe/batch4-task-b-phase-b-roadmap) --- ## Status as of 2026-05-05 evening - [x] ADR-0028 Phase A complete (PRs #59-#63, #65) - [x] Phase B.1 OIDC config (PR #64) - [x] Phase B prep : pkg/auth skeleton (PR #69) + mkcert doc (PR #68) - [x] Phase B.3 OIDC client implementation : ✅ (PR #74) - [x] Phase B.4 OIDC HTTP handlers + tests : ✅ (PR #75 + PR #76 follow-up tests) ## Status as of 2026-05-05 evening (after autonomous Mistral session) Phase B is essentially complete except B.5. The OIDC client (B.3, PR #74), HTTP handlers and tests (B.4, PR #75 + PR #76) have been delivered and merged. --- ## Remaining work Phase B delivers OpenID Connect Authorization Code flow with PKCE. Work is organized into **3 shippable phases**, each deliverable as an independent PR. At the time of this update, only Phase B.5 (BDD scenarios) remains to be completed. ### Phase B.3 — OIDC client implementation - **Goal:** Implement the core OIDC client methods in `pkg/auth/oidc.go` - **Tasks:** - `Discover()`: HTTP GET to `/.well-known/openid-configuration`, parse + cache discovery document - `RefreshJWKS()`: HTTP GET to JWKS URI, parse RSA public keys, cache with TTL - `ExchangeCode()`: POST to token endpoint with code + PKCE verifier, return TokenResponse - `ValidateIDToken()`: Verify signature against JWKS, validate standard claims (iss, aud, exp, iat) - **LOE:** ~200 lines of Go + unit tests - **Dependencies:** None (uses standard library `crypto/rsa`, `encoding/jwt`) - **Deliverable:** 1 PR ### Phase B.4 — OIDC HTTP handlers - **Goal:** Add OIDC flow endpoints and wire them into the server - **Tasks:** - Create `pkg/user/api/oidc_handler.go` - `GET /api/v1/auth/oidc/start`: - Generate state (CSRF protection) + PKCE verifier + challenge - Store state + verifier (cookie or short-lived in-memory store) - Redirect to provider's authorization endpoint - `GET /api/v1/auth/oidc/callback`: - Validate state parameter matches stored state - Exchange code for tokens (calls B.3 client) - Validate id_token (calls B.3 client) - Issue internal JWT (reuse existing JWT manager from ADR-0021) - Return JWT in Set-Cookie + JSON body - Wire routes in `pkg/server/server.go` - **LOE:** ~150 lines of Go + unit tests + integration tests - **Dependencies:** B.3 (client methods must be implemented) - **Prerequisite:** Run `make cert` (mkcert, from PR #68) before starting dev - **Deliverable:** 1 PR ### Phase B.5 — BDD coverage - **Goal:** End-to-end OIDC testing - **Tasks:** - Create `features/auth/oidc.feature` with scenarios: - Happy path: start → provider auth → callback → JWT issued - Error: state mismatch - Error: invalid code - Error: expired id_token - Use mock OIDC provider (local in-process) OR deterministic test against Authelia/Keycloak in docker-compose - Follow ADR-0030 parallel BDD strategy for email assertions - **LOE:** ~150 lines of Gherkin + step definitions - **Dependencies:** B.3 + B.4 (endpoints must be operational) - **Deliverable:** 1 PR --- ## Dependencies and order ``` B.3 (OIDC client) ↓ B.4 (HTTP handlers) —— requires B.3 ↓ B.5 (BDD coverage) —— requires B.3 + B.4 ``` **Note:** mkcert (PR #68) is ready. When starting B.4 development, run `make cert` once to generate local HTTPS certificates. --- ## Out of scope for Phase B (deferred) | Item | Target Phase | Rationale | |------|--------------|-----------| | Decommission password auth | Phase C | Separate ADR after B is in production | | Multi-provider (Authelia + Google) | Phase B.6 (if needed) | Single provider sufficient for MVP | | JWKS rotation mid-flight retry | B.3 enhancement | Handle in initial implementation | | Token refresh flow | Future | Not required for auth code flow MVP | --- ## Risk register | Risk | Mitigation | Owner | |------|------------|-------| | JWKS rotation handling | Implement refresh + retry logic; key rotation must not break mid-flight validation | B.3 implementer | | PKCE storage | Use signed cookie or short-lived in-memory store; document trade-offs in implementation PR | B.4 implementer | | Testing without real provider | Use mock OIDC server for CI; local dev uses Authelia in docker-compose | B.5 implementer | | State CSRF protection | Use cryptographically random state; store server-side with short TTL | B.4 implementer | --- ## Cross-references - [ADR-0028: Passwordless authentication: magic link → OpenID Connect](../adr/0028-passwordless-auth-migration.md) - [ADR-0029: Email infrastructure (Mailpit)](../adr/0029-email-infrastructure-mailpit.md) - [ADR-0030: BDD email parallel strategy](../adr/0030-bdd-email-parallel-strategy.md) - [PR #59: Email infrastructure](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/59) - [PR #60: BDD Mailpit helper](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/60) - [PR #61: magic_link_tokens table](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/61) - [PR #62: Magic link handlers](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/62) - [PR #63: Magic link BDD](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/63) - [PR #64: OIDC config skeleton](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/64) - [PR #65: Magic link cleanup loop](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/65) - [PR #68: mkcert documentation](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/68) - [PR #69: pkg/auth skeleton](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/69) - [PR #74: Phase B.3 OIDC client implementation](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/74) - [PR #75: Phase B.4 OIDC HTTP handlers](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/75) - [PR #76: Phase B.4 follow-up tests](https://gitea.arcodange.lab/arcodange/dance-lessons-coach/pulls/76) --- ## Appendix: File inventory Existing (merged): - `pkg/auth/oidc.go` — skeleton with TODO methods (PR #69) - `pkg/auth/oidc_test.go` — placeholder tests (PR #69) - `documentation/MKCERT.md` — mkcert setup guide (PR #68) - `Makefile` — includes `make cert` target (PR #68) To be created: - `pkg/auth/oidc.go` — complete implementation (B.3) - `pkg/user/api/oidc_handler.go` — HTTP handlers (B.4) - `pkg/server/server.go` — route wiring (B.4) - `features/auth/oidc.feature` — BDD scenarios (B.5) - `pkg/auth/oidc_test.go` — expanded unit tests (B.3) - `pkg/user/api/oidc_handler_test.go` — handler tests (B.4)