fix: prevent bearer setup migration bypass
This commit is contained in:
@@ -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 first-run gate so an uncompleted Bearer profile cannot self-migrate after a failed/offline test and bypass setup on restart; only profiles with recorded legacy provenance migrate.
|
||||
- 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.
|
||||
@@ -67,6 +68,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
|
||||
- Focused wizard regression: `./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 Bearer restart regression.
|
||||
- `./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 source-current 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, 1 executed); the generated Gradle XML report records 106 tests with 0 failures/errors, including 29 `SetupWizardReducerTest` cases; a localhost gateway health probe returned HTTP 200, establishing reachability only; the debug APK reports package `cloud.molberg.hermesmobile`, version `0.1.0-beta.1` (`10001`), and SHA-256 `45e4ab4783a74eb766070b0f670a2631a9ebdc044468bbe03087788f8106f150`; and `git diff --check` passed. No ADB device/emulator or `/dev/kvm` was available; no device installation, real authentication, release, or end-to-end gateway verification is claimed.
|
||||
- Later Task 5 current-sandbox rerun on 2026-07-24: the exact guide Gradle command was blocked before project execution because no usable wildcard IP was available; the offline/no-daemon variant was blocked because Gradle could not open its daemon TCP socket (`java.net.SocketException: Operation not permitted`). Direct JUnit execution of the existing source-current compiled `SetupWizardReducerTest` classes passed all 29 tests. The existing XML reports remain 106 tests with 0 failures/errors, and the existing ignored APK remained unchanged; `aapt` and SHA-256 inspection reconfirmed package `cloud.molberg.hermesmobile`, version `0.1.0-beta.1` (`10001`), and SHA-256 `45e4ab4783a74eb766070b0f670a2631a9ebdc044468bbe03087788f8106f150`. ADB 37.0.0 could not start its daemon, and `/dev/kvm` plus `/dev/bus/usb` were absent. This adds fresh focused reducer execution only; no fresh Gradle compilation/test task, APK assembly, device, authentication, release, or end-to-end evidence is claimed.
|
||||
|
||||
+3
-1
@@ -58,7 +58,9 @@ _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.
|
||||
- Repaired the setup gate so only valid profiles with recorded legacy provenance receive the one-time completion migration; untested first-run None and Bearer profiles remain mandatory after restart.
|
||||
- Follow-up regression repair on 2026-07-25: removed bearer-token-only self-migration, which could classify a failed/offline first-run Bearer profile as a historical profile. Added a focused restart regression covering that state.
|
||||
- Verification for the follow-up repair: offline focused `SetupWizardReducerTest` plus `:app:assembleDebug` passed (43 tasks, 9 executed); `git diff --check` passed.
|
||||
- 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 source-current re-verification on 2026-07-24: `/root/.openclaw/workspace/scripts/hermes-mobile-preflight.sh` passed; the documented offline `:app:testDebugUnitTest :app:assembleDebug` command passed (43 tasks, 1 executed); the generated Gradle XML report records 106 tests with 0 failures/errors, including 29 `SetupWizardReducerTest` cases; and `git diff --check` passed. A localhost gateway health probe returned HTTP 200, establishing reachability only. The debug APK reports package `cloud.molberg.hermesmobile`, version `0.1.0-beta.1` (`10001`), SHA-256 `45e4ab4783a74eb766070b0f670a2631a9ebdc044468bbe03087788f8106f150`. No ADB device/emulator or `/dev/kvm` was available; no device installation, real authentication, release, or end-to-end gateway verification is claimed.
|
||||
|
||||
+1
-4
@@ -260,7 +260,7 @@ object SetupWizardReducer {
|
||||
val existing = entry as? SetupEntry.ExistingConfiguration
|
||||
val migrateExistingUser = setupVersion < CURRENT_SETUP_VERSION &&
|
||||
existing != null &&
|
||||
(hasLegacyConfiguration || existing.configuration.isPreWizardCurrentConfiguration())
|
||||
hasLegacyConfiguration
|
||||
return SetupGateResolution(
|
||||
entry = if (setupVersion >= CURRENT_SETUP_VERSION || migrateExistingUser) {
|
||||
entry
|
||||
@@ -513,9 +513,6 @@ private fun StoredGatewayConfiguration.isValid(): Boolean {
|
||||
}
|
||||
}
|
||||
|
||||
private fun StoredGatewayConfiguration.isPreWizardCurrentConfiguration(): Boolean =
|
||||
authChoice == SetupAuthChoice.Bearer && hasBearerCredential
|
||||
|
||||
private fun ConnectionConfig.toStoredGatewayConfiguration(): StoredGatewayConfiguration =
|
||||
StoredGatewayConfiguration(
|
||||
localUrl = localUrl,
|
||||
|
||||
+19
-2
@@ -199,7 +199,7 @@ class SetupWizardReducerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun validPreWizardCurrentKeyConfigSkipsSetupAndRequestsVersionMigration() {
|
||||
fun validPreWizardCurrentKeyConfigWithRecordedProvenanceRequestsMigration() {
|
||||
val resolution = SetupWizardReducer.resolveEntry(
|
||||
config = ConnectionConfig(
|
||||
localUrl = LOCAL,
|
||||
@@ -208,7 +208,7 @@ class SetupWizardReducerTest {
|
||||
hasBearerToken = true
|
||||
),
|
||||
setupVersion = 0,
|
||||
hasLegacyConfiguration = false
|
||||
hasLegacyConfiguration = true
|
||||
)
|
||||
|
||||
assertTrue(resolution.entry is SetupEntry.ExistingConfiguration)
|
||||
@@ -245,6 +245,23 @@ class SetupWizardReducerTest {
|
||||
assertFalse(resolution.migrateExistingUser)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun failedFirstRunSavedBearerProfileCannotSkipMandatorySetupAfterRestart() {
|
||||
val resolution = SetupWizardReducer.resolveEntry(
|
||||
config = ConnectionConfig(
|
||||
localUrl = LOCAL,
|
||||
remoteUrl = REMOTE,
|
||||
authMode = ConnectionAuthMode.BearerToken,
|
||||
hasBearerToken = true
|
||||
),
|
||||
setupVersion = 0,
|
||||
hasLegacyConfiguration = false
|
||||
)
|
||||
|
||||
assertTrue(resolution.entry is SetupEntry.Mandatory)
|
||||
assertFalse(resolution.migrateExistingUser)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun completedExistingConfigSkipsWithoutRequestingMigration() {
|
||||
val config = ConnectionConfig(
|
||||
|
||||
@@ -12,6 +12,8 @@ The `v0.1.0-beta.1` Android package metadata and direct-gateway build/install gu
|
||||
|
||||
A later Task 5 rerun on 2026-07-24 was blocked before project execution: the guide's exact Gradle command could not determine a usable wildcard IP, and the offline/no-daemon variant could not open Gradle's daemon TCP socket (`java.net.SocketException: Operation not permitted`). Both attempts left the existing ignored APK unchanged. The source-current generated XML reports still record 106 tests with 0 failures/errors, including 29 `SetupWizardReducerTest` cases, while fresh `aapt` and SHA-256 inspection reconfirmed the package/version/hash above. ADB 37.0.0 was present at `/opt/android-sdk/platform-tools/adb` but could not create its smart-socket/netlink sockets; `/dev/kvm` and `/dev/bus/usb` were absent. This rerun provides no fresh Gradle test/assembly, device, authentication, release, or end-to-end evidence.
|
||||
|
||||
A follow-up P0 audit identified that a failed/offline first-run Bearer profile could be mistaken for a historical current-key profile and bypass setup after restart. On 2026-07-25, the gate was corrected to require recorded legacy provenance for migration and a focused Bearer restart regression was added. The offline focused `SetupWizardReducerTest` and `:app:assembleDebug` command then passed (43 tasks, 9 executed). This is source-level verification only; no fresh clean-install, device, authentication, release, or end-to-end evidence is claimed.
|
||||
|
||||
The first-run Setup Wizard is also source-complete and unit/build verified, including None/Bearer/password choices and direct password-session cookie handling. No real None/Bearer/password credential flow has been exercised against a live gateway, so R2 must include the chosen authentication mode and observed connection result without recording credentials.
|
||||
|
||||
ADB is installed, but the R1 evidence above confirms that its daemon sockets are prohibited and that no emulator executable, AVD, `/dev/kvm`, USB device bus, or running target is available. Package metadata and the SHA-256 of the existing ignored source-current APK were inspected, but no fresh assembly, clean uninstall/install, launch, or direct-gateway device connection was verified here. No APK was published or uploaded, and no final release criterion is claimed.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
- Welcome/privacy guidance precedes configuration; Remote HTTPS is required and Local HTTPS is optional for the same logical gateway profile.
|
||||
- Authentication choices are None, Bearer token, or username/password. Password login exchanges credentials directly with the configured remote gateway and stores encrypted credentials/session state outside Compose UI models.
|
||||
- Test-and-finish uses the existing local-first route selection, requires a successful compatibility check before completion, and exposes the same profile for later Settings edits.
|
||||
- Existing completed valid profiles skip mandatory setup; legacy/current valid profiles receive a one-time setup-version migration without forcing re-entry. A failed/offline first-run test cannot create a restart bypass.
|
||||
- Existing completed valid profiles skip mandatory setup; valid profiles with recorded legacy provenance receive a one-time setup-version migration without forcing re-entry. A failed/offline first-run None or Bearer test cannot create a restart bypass.
|
||||
- Compose semantics, minimum touch targets, adaptive layout behavior, and phone/tablet/light/dark previews cover the wizard source contract.
|
||||
- Existing source-current Gradle output records 106 unit tests with 0 failures/errors and a debug APK assembled after the latest Android source change. No real device, release, or real gateway credential walkthrough has been performed; those remain part of R1/R2 evidence.
|
||||
- Task 5 source-current re-verification on 2026-07-24 passed the external recovery preflight and documented offline Gradle test/assembly command (43 tasks, 1 executed); the generated Gradle XML report records 106 passing tests with 0 failures/errors, including 29 `SetupWizardReducerTest` cases. A localhost gateway health probe returned HTTP 200, establishing reachability only. The debug APK is package `cloud.molberg.hermesmobile`, version `0.1.0-beta.1` (`10001`), SHA-256 `45e4ab4783a74eb766070b0f670a2631a9ebdc044468bbe03087788f8106f150`; `git diff --check` passed. No ADB device/emulator or `/dev/kvm` was available; no device installation, real authentication, release, or end-to-end gateway verification was performed.
|
||||
|
||||
Reference in New Issue
Block a user