8.9 KiB
8.9 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, decisions, metrics
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | decisions | metrics | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01-project-infrastructure-module-wiring | 04 | client-bootstrap |
|
|
|
|
|
|
|
|
Phase 1 Plan 4: Koin + Kermit Bootstrap Wiring — Summary
Wired the Koin DI container and Kermit structured logger across all four composeApp platform entry points (Android Application subclass, iOS SwiftUI App.init, JVM desktop main, Wasm browser main) with a single initKoin() helper in commonMain and an empty appModule placeholder that Phase 2+ extends.
What was built
Task 1 — commonMain DI + logging + iOS bridge (commit cc5002d)
Created four files:
composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/di/Koin.kt— exportsfun initKoin(config: KoinAppDeclaration? = null): KoinApplication = startKoin { config?.invoke(this); modules(appModule) }. The optionalconfiglambda is how Android passesandroidContext(...)and how Phase 2+ tests can inject overrides without touching the helper itself.composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/di/AppModule.kt— declaresval appModule = module { }(empty per D-14). Phase 2 addsauthModule, Phase 4 addssyncModule, etc.composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/logging/Logging.kt—fun configureLogging() { Logger.setTag("recipe") }. Kermit's per-platform writers (OSLog/LogCat/println) install themselves by default; setting the tag is the only required call.composeApp/src/iosMain/kotlin/dev/ulfrx/recipe/di/KoinIos.kt—fun doInitKoin() { configureLogging(); initKoin() }. The top-levelfunin fileKoinIos.ktbecomes the Swift-accessible symbolKoinIosKt.doInitKoin()automatically (Kotlin/Native generates<FileName>Ktfor top-level decls).
Task 2 — Android MainApplication + manifest (commit 8cd608a)
composeApp/src/androidMain/kotlin/dev/ulfrx/recipe/MainApplication.kt—class MainApplication : Application()whoseonCreate()callssuper.onCreate(), thenconfigureLogging(), theninitKoin { androidContext(this@MainApplication) }. Qualifiedthis@MainApplicationis required because theinitKoin { }lambda receiver isKoinApplication, not theApplication.composeApp/src/androidMain/AndroidManifest.xml— addedandroid:name=".MainApplication"as the first attribute on<application>. All other attributes and the<activity>/<intent-filter>subtree preserved verbatim.
Task 3 — JVM + Wasm + Swift entry points (commit fd3e7e1)
composeApp/src/jvmMain/kotlin/dev/ulfrx/recipe/main.kt— convertedfun main() = application { ... }(single-expression) into a body block:configureLogging()→initKoin()→application { Window(title = "recipe") { App() } }. Window title and exit handler preserved.composeApp/src/webMain/kotlin/dev/ulfrx/recipe/main.kt— same init order beforeComposeViewport { App() }.@OptIn(ExperimentalComposeUiApi::class)retained. Defensive against PITFALL #8 (Wasm composition running before DI is ready) — Phase 1 has no ViewModels so the symptom would not surface yet, but the shape is correct from day 1.iosApp/iosApp/iOSApp.swift— addedimport ComposeApp(matches framework basename set byrecipe.kotlin.multiplatform) andinit() { KoinIosKt.doInitKoin() }. TheWindowGroup { ContentView() }body is unchanged.MainViewController.ktandContentView.swiftwere intentionally NOT modified — Koin is bootstrapped exclusively fromiOSApp.init()(PITFALL #4 mitigation).
Init order invariant (every platform)
configureLogging() → installs Kermit tag "recipe"
initKoin() → starts Koin with empty appModule
[platform composition entry — application { } / ComposeViewport { } / ComposeUIViewController { } / setContent { }]
Deviations from Plan
None — plan executed exactly as written. All 3 tasks completed; all artifacts produced; all <acceptance_criteria> satisfied.
Confirmations (per <output> section of PLAN)
- Kermit tag =
"recipe"(D-15) — set inconfigureLogging(). appModulecontent: empty (D-14) —val appModule = module { }.App.ktNOT modified (anti-pattern guard).MainViewController.ktNOT modified (PITFALL #4 guard — Koin started outside).ContentView.swiftNOT modified (already wrapsMainViewControllerKt.MainViewController()).
Threat Mitigations Verified
| Threat ID | Mitigation in delivered code |
|---|---|
| T-01-04-01 (Koin double-init iOS) | KoinIosKt.doInitKoin() is the only init call site on iOS; MainViewController.kt does not call startKoin. |
| T-01-04-02 (Wasm init order) | webMain main() orders configureLogging() → initKoin() → ComposeViewport { }. |
| T-01-04-03 (App.kt calling startKoin) | App.kt unchanged; verified no startKoin reference outside Koin.kt. |
Verification gates
- All three task
<automated>grep blocks passed. - No build files modified →
tools/verify-no-version-literals.shandtools/verify-shared-pure.shremain at exit 0. - Compile gates (
./gradlew build,:composeApp:jvmTest) deferred to Plan 07 per the verification block in 01-04-PLAN.md.
Commits
cc5002d— feat(01-04): add Koin + Kermit bootstrap commonMain + iOS bridge8cd608a— feat(01-04): add Android MainApplication + manifest registrationfd3e7e1— feat(01-04): wire JVM + Wasm main + Swift iOSApp to bootstrap Koin + Kermit
Self-Check: PASSED
Files verified to exist on disk:
- FOUND: composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/di/Koin.kt
- FOUND: composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/di/AppModule.kt
- FOUND: composeApp/src/commonMain/kotlin/dev/ulfrx/recipe/logging/Logging.kt
- FOUND: composeApp/src/iosMain/kotlin/dev/ulfrx/recipe/di/KoinIos.kt
- FOUND: composeApp/src/androidMain/kotlin/dev/ulfrx/recipe/MainApplication.kt
- FOUND: composeApp/src/androidMain/AndroidManifest.xml (modified, contains
android:name=".MainApplication") - FOUND: composeApp/src/jvmMain/kotlin/dev/ulfrx/recipe/main.kt (modified)
- FOUND: composeApp/src/webMain/kotlin/dev/ulfrx/recipe/main.kt (modified)
- FOUND: iosApp/iosApp/iOSApp.swift (modified)
Commits verified in git log: