fix: prevent setup restart bypass
This commit is contained in:
@@ -57,6 +57,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 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.
|
||||
- Fixed bearer handling so `/health` is checked without credentials and the token is sent only to the documented authenticated `/v1/models` compatibility route.
|
||||
@@ -64,6 +65,9 @@ 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'` — 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).
|
||||
- `git diff --check` — passed for the setup restart-bypass fix.
|
||||
- First-run Setup Wizard source verification: the source-current offline Android `:app:testDebugUnitTest :app:assembleDebug` run passed on 2026-07-24 with 43 tasks (4 executed, 39 up-to-date) and 104 tests (0 failures); a final identical rerun was blocked before project execution by the sandbox TCP restriction. `git diff --check` passed. No device, release, or real gateway credential test is claimed.
|
||||
- `/root/.openclaw/workspace/scripts/hermes-mobile-preflight.sh` — passed; Android `:app:assembleDebug` BUILD SUCCESSFUL (37 tasks, 14 executed).
|
||||
- `GRADLE_USER_HOME=/root/hermes-mobile/.gradle-user ./gradlew --offline --no-daemon -Dorg.gradle.jvmargs= -Dorg.gradle.daemon=false -Pkotlin.compiler.execution.strategy=in-process :app:testDebugUnitTest :app:assembleDebug` — passed (43 tasks, 5 executed), including `BetaPackageMetadataTest` for application ID `cloud.molberg.hermesmobile`, `versionName` `0.1.0-beta.1`, and `versionCode` `10001`.
|
||||
|
||||
+3
-2
@@ -53,11 +53,12 @@ Complete the Android/client contract pivot before implementing backend behavior.
|
||||
|
||||
_Move finished items here with date, commit, and verification. Keep this section factual; do not claim unverified work._
|
||||
|
||||
- [x] **P0 — First-run Setup Wizard** — 2026-07-24, commit `1b4abfa` (`feat: add first-run setup wizard`).
|
||||
- [x] **P0 — First-run Setup Wizard** — 2026-07-24, commits `1b4abfa` (`feat: add first-run setup wizard`) and pending follow-up (`fix: prevent setup restart bypass`).
|
||||
- Added a Compose first-run flow covering welcome/privacy guidance, required Remote HTTPS and optional Local HTTPS routes, None/Bearer/username-password authentication, local-first connection testing, and completion only after a successful test.
|
||||
- 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.
|
||||
- Verification on 2026-07-24: the source-current offline `:app:testDebugUnitTest :app:assembleDebug` run passed (43 tasks, 4 executed; 104 tests, 0 failures), and `git diff --check` passed. A final identical Gradle rerun was blocked before project execution by the sandbox TCP restriction (`java.net.SocketException: Operation not permitted`). No device, release, or real gateway credential test is claimed.
|
||||
- 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.
|
||||
- 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.
|
||||
- [x] **R2a — Establish beta source packaging and install documentation** — 2026-07-24, commit `98b183e` (`build: establish Android beta packaging`).
|
||||
- Set Android package metadata to semantic `versionName` `0.1.0-beta.1` with monotonic `versionCode` `10001`, enabled generated metadata coverage, and named the debug APK `hermes-mobile-v0.1.0-beta.1-debug.apk`.
|
||||
- Added a direct-gateway-only build, metadata inspection, clean-install, launch, configuration, evidence, and known-limitations guide; changed the npm Android build command to run the native Gradle project without Capacitor synchronization.
|
||||
|
||||
+5
-1
@@ -262,7 +262,11 @@ object SetupWizardReducer {
|
||||
hasLegacyConfiguration &&
|
||||
existing
|
||||
return SetupGateResolution(
|
||||
entry = entry,
|
||||
entry = if (setupVersion >= CURRENT_SETUP_VERSION || migrateExistingUser) {
|
||||
entry
|
||||
} else {
|
||||
SetupEntry.Mandatory(firstRun())
|
||||
},
|
||||
migrateExistingUser = migrateExistingUser
|
||||
)
|
||||
}
|
||||
|
||||
+16
-8
@@ -214,7 +214,22 @@ class SetupWizardReducerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun currentOrNonLegacyExistingConfigDoesNotRequestMigration() {
|
||||
fun failedFirstRunSavedProfileCannotSkipMandatorySetupAfterRestart() {
|
||||
val resolution = SetupWizardReducer.resolveEntry(
|
||||
config = ConnectionConfig(
|
||||
remoteUrl = REMOTE,
|
||||
authMode = ConnectionAuthMode.None
|
||||
),
|
||||
setupVersion = 0,
|
||||
hasLegacyConfiguration = false
|
||||
)
|
||||
|
||||
assertTrue(resolution.entry is SetupEntry.Mandatory)
|
||||
assertFalse(resolution.migrateExistingUser)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun completedExistingConfigSkipsWithoutRequestingMigration() {
|
||||
val config = ConnectionConfig(
|
||||
remoteUrl = REMOTE,
|
||||
authMode = ConnectionAuthMode.None
|
||||
@@ -225,16 +240,9 @@ class SetupWizardReducerTest {
|
||||
setupVersion = SetupWizardReducer.CURRENT_SETUP_VERSION,
|
||||
hasLegacyConfiguration = true
|
||||
)
|
||||
val nonLegacy = SetupWizardReducer.resolveEntry(
|
||||
config = config,
|
||||
setupVersion = 0,
|
||||
hasLegacyConfiguration = false
|
||||
)
|
||||
|
||||
assertTrue(current.entry is SetupEntry.ExistingConfiguration)
|
||||
assertFalse(current.migrateExistingUser)
|
||||
assertTrue(nonLegacy.entry is SetupEntry.ExistingConfiguration)
|
||||
assertFalse(nonLegacy.migrateExistingUser)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+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 valid profiles skip mandatory setup; legacy/current valid profiles receive a one-time setup-version migration without forcing re-entry.
|
||||
- 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.
|
||||
- Compose semantics, minimum touch targets, adaptive layout behavior, and phone/tablet/light/dark previews cover the wizard source contract.
|
||||
- Source verification passed with 104 unit tests and debug assembly. No real device, release, or real gateway credential walkthrough has been performed; those remain part of R1/R2 evidence.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user