From 55f0a0da026f8a21922ef1b5ac99edd0a0869e31 Mon Sep 17 00:00:00 2001 From: Gabriel Radureau Date: Tue, 5 May 2026 19:30:58 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20docs:=20ADR-0028=20Phase=20B=20r?= =?UTF-8?q?oadmap=20(B.3=20/=20B.4=20/=20B.5=20outline)=20(#71)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gabriel Radureau Co-committed-by: Gabriel Radureau --- documentation/PHASE_B_ROADMAP.md | 137 +++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 documentation/PHASE_B_ROADMAP.md diff --git a/documentation/PHASE_B_ROADMAP.md b/documentation/PHASE_B_ROADMAP.md new file mode 100644 index 0000000..45f76ef --- /dev/null +++ b/documentation/PHASE_B_ROADMAP.md @@ -0,0 +1,137 @@ +# 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) +- [ ] Phase B.3 not yet started + +--- + +## 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. + +### 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) + +--- + +## 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)