From b2642df2ca1f9a9129aa7ea68a6e0b6133811653 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Fri, 24 Jul 2026 20:30:13 +0000 Subject: [PATCH] fix: migrate pre-wizard gateway profiles --- CHANGELOG.md | 2 ++ PROJECT_PLAN.md | 2 ++ .../onboarding/SetupWizardModels.kt | 9 ++++++--- .../onboarding/SetupWizardReducerTest.kt | 17 +++++++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be5895a..e27083e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ All notable Hermes Mobile source changes are recorded here. Entries are added du - Ignored `.gradle-user/` and `.dev/` alongside existing generated build artifacts. ### Fixed +- Fixed the setup gate so valid pre-wizard bearer profiles already stored under the current connection keys receive the one-time completion migration; untested no-auth first-run profiles remain gated. - Fixed first-run setup so a profile saved by a failed/offline compatibility test cannot bypass mandatory setup after process restart; only completed or migrated valid profiles skip the wizard. - Fixed durable stream completion so a stale request ID cannot publish a terminal state or clear a newer reservation. - Fixed stream failure handling so HTTP, I/O, and malformed-SSE failures are reported and reduced only against the original lease, while upstream `error` events remain session failures rather than route failures. @@ -66,6 +67,7 @@ All notable Hermes Mobile source changes are recorded here. Entries are added du - Fixed companion/mobile lint issues from missing Node globals and an unused React settings value. ### Verification +- `./gradlew --offline --no-daemon -Dorg.gradle.jvmargs= -Dorg.gradle.daemon=false -Pkotlin.compiler.execution.strategy=in-process :app:testDebugUnitTest --tests 'cloud.molberg.hermesmobile.onboarding.SetupWizardReducerTest' :app:assembleDebug` — passed (43 tasks, 9 executed), including the new current-key migration regression. - Task 5 re-verification on 2026-07-24: `/root/.openclaw/workspace/scripts/hermes-mobile-preflight.sh` passed; `./gradlew --offline --no-daemon -Dorg.gradle.jvmargs= -Dorg.gradle.daemon=false -Pkotlin.compiler.execution.strategy=in-process :app:testDebugUnitTest :app:assembleDebug` passed (43 tasks up-to-date); direct JUnit execution passed all 105 source-current compiled tests; the source-current debug APK reports package `cloud.molberg.hermesmobile`, version `0.1.0-beta.1` (`10001`), and SHA-256 `45f9a4bff72db21fd6e57d30db0eef8fefb429657a40357695e330cdc4906401`; `git diff --check` passed. No device/install, release, or real credential verification is claimed. - `./gradlew --offline --no-daemon -Dorg.gradle.jvmargs= -Dorg.gradle.daemon=false -Pkotlin.compiler.execution.strategy=in-process :app:testDebugUnitTest --tests 'cloud.molberg.hermesmobile.onboarding.SetupWizardReducerTest'` — passed (28 tests), after the new regression first failed as expected. - `./gradlew --offline --no-daemon -Dorg.gradle.jvmargs= -Dorg.gradle.daemon=false -Pkotlin.compiler.execution.strategy=in-process :app:testDebugUnitTest :app:assembleDebug` — passed (43 tasks, 4 executed). diff --git a/PROJECT_PLAN.md b/PROJECT_PLAN.md index 543b66f..54c6d3d 100644 --- a/PROJECT_PLAN.md +++ b/PROJECT_PLAN.md @@ -58,6 +58,8 @@ _Move finished items here with date, commit, and verification. Keep this section - Added direct password login through `/auth/password-login`, allowlisted session-cookie extraction, encrypted cookie/password storage, credential redaction, replacement/retention rules, and cookie-authenticated gateway probes without persisting raw credentials in UI state or connection forms. - Added Settings entry for editing the same profile, skip behavior for existing valid configurations, one-time legacy/current-profile setup-version migration, and accessible adaptive Compose semantics plus phone/tablet/light/dark previews. - Fixed a restart bypass: a profile saved by a failed first-run connection test remains in mandatory setup until setup completion is durably recorded; valid migrated and completed profiles still skip setup. + - Repaired current-key existing-user migration: a valid pre-wizard bearer profile stored under the then-current connection keys now receives the one-time completion migration, while untested no-auth profiles remain mandatory. + - Verification for the migration repair: source-current offline focused `SetupWizardReducerTest` plus `:app:assembleDebug` passed (43 tasks, 9 executed); `git diff --check` passed. - Verification on 2026-07-24: source-current offline `:app:testDebugUnitTest :app:assembleDebug` passed (43 tasks, 4 executed; all unit tests passed), including the focused restart-regression test; `git diff --check` passed. No device, release, or real gateway credential test is claimed. - Task 5 re-verification on 2026-07-24: `/root/.openclaw/workspace/scripts/hermes-mobile-preflight.sh` passed; the documented offline Gradle `:app:testDebugUnitTest :app:assembleDebug` command passed (43 tasks up-to-date); direct JUnit execution of the source-current compiled classes passed all 105 tests; and `git diff --check` passed. The source-current debug APK reports package `cloud.molberg.hermesmobile`, version `0.1.0-beta.1` (`10001`), and SHA-256 `45f9a4bff72db21fd6e57d30db0eef8fefb429657a40357695e330cdc4906401`. No device, release, APK installation, or real credential verification is claimed. - [x] **R2a — Establish beta source packaging and install documentation** — 2026-07-24, commit `3b883bd` (`build: establish Android beta packaging`). diff --git a/apps/mobile/android/app/src/main/java/cloud/molberg/hermesmobile/onboarding/SetupWizardModels.kt b/apps/mobile/android/app/src/main/java/cloud/molberg/hermesmobile/onboarding/SetupWizardModels.kt index 8676b2a..b170536 100644 --- a/apps/mobile/android/app/src/main/java/cloud/molberg/hermesmobile/onboarding/SetupWizardModels.kt +++ b/apps/mobile/android/app/src/main/java/cloud/molberg/hermesmobile/onboarding/SetupWizardModels.kt @@ -257,10 +257,10 @@ object SetupWizardReducer { hasLegacyConfiguration: Boolean ): SetupGateResolution { val entry = entry(config) - val existing = entry is SetupEntry.ExistingConfiguration + val existing = entry as? SetupEntry.ExistingConfiguration val migrateExistingUser = setupVersion < CURRENT_SETUP_VERSION && - hasLegacyConfiguration && - existing + existing != null && + (hasLegacyConfiguration || existing.configuration.isPreWizardCurrentConfiguration()) return SetupGateResolution( entry = if (setupVersion >= CURRENT_SETUP_VERSION || migrateExistingUser) { entry @@ -513,6 +513,9 @@ private fun StoredGatewayConfiguration.isValid(): Boolean { } } +private fun StoredGatewayConfiguration.isPreWizardCurrentConfiguration(): Boolean = + authChoice == SetupAuthChoice.Bearer && hasBearerCredential + private fun ConnectionConfig.toStoredGatewayConfiguration(): StoredGatewayConfiguration = StoredGatewayConfiguration( localUrl = localUrl, diff --git a/apps/mobile/android/app/src/test/java/cloud/molberg/hermesmobile/onboarding/SetupWizardReducerTest.kt b/apps/mobile/android/app/src/test/java/cloud/molberg/hermesmobile/onboarding/SetupWizardReducerTest.kt index 4af2b96..006bf2b 100644 --- a/apps/mobile/android/app/src/test/java/cloud/molberg/hermesmobile/onboarding/SetupWizardReducerTest.kt +++ b/apps/mobile/android/app/src/test/java/cloud/molberg/hermesmobile/onboarding/SetupWizardReducerTest.kt @@ -198,6 +198,23 @@ class SetupWizardReducerTest { assertTrue(editState.canExit) } + @Test + fun validPreWizardCurrentKeyConfigSkipsSetupAndRequestsVersionMigration() { + val resolution = SetupWizardReducer.resolveEntry( + config = ConnectionConfig( + localUrl = LOCAL, + remoteUrl = REMOTE, + authMode = ConnectionAuthMode.BearerToken, + hasBearerToken = true + ), + setupVersion = 0, + hasLegacyConfiguration = false + ) + + assertTrue(resolution.entry is SetupEntry.ExistingConfiguration) + assertTrue(resolution.migrateExistingUser) + } + @Test fun migrationNeverTurnsInvalidLegacyConfigIntoCompletedSetup() { val resolution = SetupWizardReducer.resolveEntry(