- add 02-06 execution summary and self-check - update GSD state progress for completed plan
9.1 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 02-authentication-foundation | 06 | auth |
|
|
|
|
|
|
|
|
|
34m | 2026-04-28 |
Phase 02 Plan 06: Common Auth Runtime Summary
AuthSession state machine, token-safe Ktor bearer client, /api/v1/me client, and Koin singleton wiring for persisted OIDC sessions.
Performance
- Duration: 34 min
- Started: 2026-04-28T14:22:01Z
- Completed: 2026-04-28T14:56:05Z
- Tasks: 3
- Files modified: 7
Accomplishments
- Added common AuthSession behavior for Loading -> restored Authenticated/Unauthenticated, login, logout, proactive refresh, and Ktor reactive refresh support.
- Added AuthState with Phase 3-ready
householdId: HouseholdId? = null, with tests asserting Phase 2 authenticated sessions keep it null. - Added MeClient for
GET /api/v1/me, mapping server MeResponse to User so authenticated state is built from the server, not token claims. - Added AuthHttpClient with Ktor bearer
loadTokens,refreshTokens,sendWithoutRequest, ContentNegotiation JSON, and token-redacting logging. - Wired authModule into appModule as Koin singletons without changing Koin startup ownership.
Task Commits
- Task 1: Write AuthSession state-machine tests -
06e5eaf(test) - Task 2: Implement AuthState, AuthSession, MeClient, and bearer HTTP client -
0a24be9(feat) - Task 3: Wire authModule into Koin -
938f324(feat)
Files Created/Modified
composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/auth/AuthState.kt- Loading/Unauthenticated/Authenticated auth model with nullable household id.composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/auth/AuthSession.kt- StateFlow auth owner with restore/login/logout/token refresh behavior and testable gateway seams.composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/auth/AuthHttpClient.kt- Ktor client factory with bearer auth refresh and token redaction.composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/auth/MeClient.kt-/api/v1/meclient mapped to shared User.composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/auth/AuthModule.kt- Koin singleton definitions for auth runtime collaborators.composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/di/AppModule.kt- Includes authModule from the app bootstrap module.composeApp/src/commonTest/kotlin/dev/ulfrx/recipe/auth/AuthSessionTest.kt- State-machine tests for restore, login, invalid_grant/AuthError, logout, and cancellation.
Decisions Made
- Kept platform OidcClient and SecureAuthStateStore expect/actual contracts unchanged; AuthSession uses gateway interfaces internally so common tests can fake dependencies.
- Used explicit token passing only for AuthSession's
/mecall. Broader authenticated API access goes through AuthHttpClient and its bearer plugin. - No auth UI ViewModels were registered because they do not exist yet in this plan's input set.
Deviations from Plan
Auto-fixed Issues
1. [Rule 3 - Blocking] Added testable gateway seams for AuthSession dependencies
- Found during: Task 1/2 (state-machine tests and implementation)
- Issue: The plan required fakes for OidcClient and SecureAuthStateStore, but the existing common contracts are concrete expect classes. Changing expect/actual signatures would have touched platform files outside this plan's write scope.
- Fix: Added small common interfaces (
OidcClientGateway,AuthStateStore,MeGateway) and made AuthSession's production constructor delegate concrete platform classes through adapters. - Files modified:
AuthSession.kt,MeClient.kt,AuthSessionTest.kt - Verification:
./gradlew :composeApp:jvmTest --tests "*AuthSessionTest*"and full plan gate passed. - Committed in:
0a24be9
2. [Rule 3 - Blocking] Added explicit Koin generic types
- Found during: Task 3 verification
- Issue: Koin's
single { ... }calls could not infer expect-class singleton types under the KMP compile targets. - Fix: Changed definitions to
single<SecureAuthStateStore>,single<OidcClient>,single<MeClient>, andsingle<AuthSession>, with typedget<...>()calls. - Files modified:
AuthModule.kt - Verification:
./gradlew :composeApp:jvmTest :composeApp:compileDebugKotlinAndroid :composeApp:compileKotlinIosSimulatorArm64 - Committed in:
938f324
Total deviations: 2 auto-fixed (2 x Rule 3). Impact on plan: No scope expansion beyond common auth runtime and DI wiring. Both fixes were required to satisfy the planned tests and cross-target compile gate while respecting the write scope.
Issues Encountered
- The RED test commit was amended before GREEN to make JUnit test methods return void while still failing on missing production auth runtime. This preserved the TDD red gate without adding a separate formatting-only commit.
- Pre-existing untracked
.claude/andAGENTS.mdremain untouched.
Known Stubs
None.
Threat Flags
None beyond the plan's threat model. The new network client, bearer refresh, secure-store access, and AuthSession UI state surfaces were all covered by T-02-06-01 through T-02-06-05.
User Setup Required
None for this plan. Real OIDC login still requires the Authentik provider setup documented in docs/authentik-setup.md.
Verification
./gradlew :composeApp:jvmTest --tests "*AuthSessionTest*"- PASS./gradlew :composeApp:jvmTest :composeApp:compileDebugKotlinAndroid :composeApp:compileKotlinIosSimulatorArm64- PASS- Task acceptance greps for
invalid_grant|AuthError,householdId,StateFlow<AuthState>,refreshTokens,sendWithoutRequest, noAuthorization.*$,val authModule, and appModuleauthModule- PASS - Token/logging scan - PASS; no bearer token values or AuthState JSON are logged.
Next Phase Readiness
Plan 02-07 can run integration verification against the common AuthSession + platform AppAuth actuals. Phase 3 can extend /api/v1/me with household data and fill AuthState.Authenticated.householdId without changing the sealed auth state shape.
Self-Check: PASSED
- Created/modified files exist: all seven plan-owned source/test files plus this summary were found.
- Commits exist:
06e5eaf,0a24be9, and938f324were found in git history. - Acceptance criteria: all task grep checks passed.
- Plan-level verification:
./gradlew :composeApp:jvmTest :composeApp:compileDebugKotlinAndroid :composeApp:compileKotlinIosSimulatorArm64passed.
Phase: 02-authentication-foundation Completed: 2026-04-28