Skip to content

fix(android): harden offline cache lifecycle#100454

Merged
steipete merged 6 commits into
mainfrom
codex/android-offline-cache-lifecycle
Jul 6, 2026
Merged

fix(android): harden offline cache lifecycle#100454
steipete merged 6 commits into
mainfrom
codex/android-offline-cache-lifecycle

Conversation

@steipete

@steipete steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Follow-up to #100227: the Android offline cache shipped before its pairing-reset and WebSocket lifecycle hardening. A pairing or explicit credential change could race old connection callbacks, preserve endpoint-keyed cache across identities, or delete credentials before SQLite cache cleanup was verified.

Advances #100194.

Why This Change Was Made

This makes auth reset and cache ownership one bounded lifecycle. Gateway connection starts are counted without holding the auth monitor across session calls; reset drains starts, retires and joins old sockets/callback work, advances the cache generation, then verifies cache deletion before clearing credentials. Explicit credentials on the same endpoint now replace cached identity state instead of preserving it.

Room cleanup uses the app's single production database handle and clears both transcripts and durable queued commands before verifying the database, journal, WAL, SHM, and master-journal files. Gateway terminal ownership drains accepted connect responses and acknowledges peer closes before teardown. Fresh installs with no database directory remain a successful no-op. The Android Room license notice is included in the app inventory.

User Impact

  • Pairing a new Gateway cannot inherit the previous identity's cached sessions, transcript, or queued commands.
  • Retired sockets cannot restore old auth or write stale cache state after reset.
  • Failed cache cleanup leaves the old credentials recoverable and reports a retryable failure instead of creating a half-reset identity.
  • First-run pairing remains unblocked when the cache database has never been opened.

Evidence

  • Blacksmith Testbox tbx_01kwtaq7dakscv93rrmz0jbrb9 (run 28759024321): focused Play-debug cache, auth-reset, reconnect, terminal-callback, config-resolution, queued-command purge, and license-notice suites passed after the final rebase.
  • Earlier Testbox race proof covered lock inversion, device-token retry, and failure-path draining of accepted connect responses.
  • Native app i18n inventory check and git diff --check passed.
  • Fresh Codex autoreview on exact head 606cf3c440606edc1af8a0eca0c91dbfcc1242d7: clean with no accepted or actionable findings, confidence 0.82.
  • GitHub Actions run 28761404072: all exact-head jobs passed, including Android unit/build lanes and QA smoke.

@openclaw-barnacle openclaw-barnacle Bot added app: android App: android size: XL maintainer Maintainer-authored PR labels Jul 5, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b279fc9ef2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread CHANGELOG.md Outdated

### Fixes

- **Android offline chat cache:** serialize Gateway teardown and cache writes during pairing changes, purge SQLite companion files before credential reset, and prevent old sockets or explicit new credentials from restoring another identity's cached conversations.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the normal-fix changelog entry

Root AGENTS.md says CHANGELOG.md is release-only and that normal fixes/direct commits should put release-note context in the PR body or commit message because release generation owns this file. This Android fix entry bypasses that flow, so it should be removed from the commit and left for the release changelog generator.

Useful? React with 👍 / 👎.

@clawsweeper

clawsweeper Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge. Reviewed July 5, 2026, 9:19 PM ET / 01:19 UTC.

Summary
This PR hardens the Android offline chat cache and gateway auth-reset lifecycle by changing credential replacement, Room cache cleanup, Gateway socket teardown, queued command purge, and Android tests/license inventory.

PR surface: Other +1210. Total +1210 across 17 files.

Reproducibility: yes. Source inspection shows beginConnect can pass the reset flag sample before reset starts and remain outside the in-flight counter until it later calls connectWithAuth.

Review metrics: 1 noteworthy metric.

  • Auth reset contract changes: 1 reset path changed to Boolean fail-closed; 1 saved-auth replacement action added. Credential replacement and cache cleanup are upgrade-sensitive because existing pairing state can be discarded or preserved depending on this decision.

Stored data model
Persistent data-model change detected: persistent cache schema: apps/android/app/src/main/java/ai/openclaw/app/chat/ChatController.kt, persistent cache schema: apps/android/app/src/test/java/ai/openclaw/app/chat/ChatControllerTranscriptCacheTest.kt, persistent cache schema: apps/android/app/src/test/java/ai/openclaw/app/chat/RoomChatTranscriptCacheTest.kt. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🦪 silver shellfish
Result: blocked by patch quality or review findings.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Claim or generation-check the full Android beginConnect path across auth reset.
  • [P2] Add a regression test where connect enters before reset starts and would otherwise reconnect after reset completes.
  • Rerun the focused Android auth-reset and Gateway reconnect tests on the repaired head.

Risk before merge

  • [P1] Merging the current head can still let a stale Android connect attempt cross a pairing or sign-out reset boundary and repopulate device auth or cache state after reset completes.
  • [P1] The affected path clears credentials and cached transcripts, so the remaining lifecycle gap is both session-state and security-boundary sensitive even with useful surrounding tests.

Maintainer options:

  1. Fix the connect/reset race before merge (recommended)
    Move the reset claim or generation guard so a connect attempt that entered before reset began cannot start sessions after reset finishes.
  2. Pause for lifecycle owner review
    If maintainers do not want the current claim helper to cover beginConnect, pause until the Android gateway/auth lifecycle owner chooses the permanent reset boundary.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Update Android NodeRuntime so beginConnect/connectAfterTlsCheck is claimed by the auth-reset lifecycle before reset can drain it; add a regression test where a connect enters before reset flips the flag and would otherwise reach connectWithAuth after reset completes.

Next step before merge

  • [P2] A narrow automated repair is plausible because the blocker is localized to Android NodeRuntime connect/reset lifecycle handling and has clear regression coverage targets.

Security
Needs attention: The remaining Android auth-reset race can cross a credential/cache identity boundary, so the security pass is not cleared.

Review findings

  • [P1] Claim the full connect start before reset can drain it — apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt:2080-2082
Review details

Best possible solution:

Claim or generation-check the whole beginConnect/TLS path before stale auth can reach connectWithAuth, with a regression test for a connect that entered just before reset starts.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection shows beginConnect can pass the reset flag sample before reset starts and remain outside the in-flight counter until it later calls connectWithAuth.

Is this the best way to solve the issue?

No. NodeRuntime is the right layer for this hardening, but the current patch claims only connectWithAuth and leaves the earlier beginConnect/TLS path outside the reset drain.

Full review comments:

  • [P1] Claim the full connect start before reset can drain it — apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt:2080-2082
    This still samples gatewayAuthResetInProgress before the rest of beginConnect. A reconnect can pass this sample just before reset starts, remain uncounted by gatewayConnectOperationsInFlight, and later reach connectWithAuth with pre-reset auth after credentials and cache have been purged.
    Confidence: 0.88

Overall correctness: patch is incorrect
Overall confidence: 0.88

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against eda9b9fb1858.

Label changes

Label justifications:

  • P2: This is a normal-priority Android cache/auth hardening PR for a recently landed feature, with limited blast radius but meaningful session and credential impact.
  • merge-risk: 🚨 session-state: The remaining connect/reset race can let stale session or cache work run after a pairing or sign-out reset.
  • merge-risk: 🚨 security-boundary: The affected reset path clears credentials and cached transcripts, so stale post-reset auth writes can cross an identity boundary.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦞 diamond lobster and patch quality is 🦪 silver shellfish.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (linked_artifact): The PR body and live checks provide linked Android Testbox/GitHub Actions proof, including a passing Real behavior proof check; that proof does not clear the source-level race finding.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body and live checks provide linked Android Testbox/GitHub Actions proof, including a passing Real behavior proof check; that proof does not clear the source-level race finding.
Evidence reviewed

PR surface:

Other +1210. Total +1210 across 17 files.

View PR surface stats
Area Files Added Removed Net
Source 0 0 0 0
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 17 1495 285 +1210
Total 17 1495 285 +1210

Security concerns:

  • [medium] Stale connect can cross auth reset — apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt:2080
    A connect that passes the reset flag sample before reset starts is not counted in the reset drain and can later reconnect with old auth after credentials and cache have been purged.
    Confidence: 0.86

Acceptance criteria:

  • [P1] cd apps/android && ./gradlew :app:testPlayDebugUnitTest --tests 'ai.openclaw.app.GatewayBootstrapAuthTest'.
  • [P1] cd apps/android && ./gradlew :app:testPlayDebugUnitTest --tests 'ai.openclaw.app.gateway.GatewaySessionReconnectTest'.
  • [P1] gh pr checks 100454 --repo openclaw/openclaw --watch=false.

What I checked:

Likely related people:

  • steipete: Peter authored and merged the Android offline cache PR and authored this follow-up plus recent adjacent Android reliability work. (role: feature owner and recent area contributor; confidence: high; commits: 09f9a85145c0, aaf5ab910cbe, 606cf3c44060; files: apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt, apps/android/app/src/main/java/ai/openclaw/app/chat/ChatTranscriptCache.kt, apps/android/app/src/main/java/ai/openclaw/app/gateway/GatewaySession.kt)
  • Vincent Koc: Current-main blame for the resetGatewaySetupAuth implementation in NodeRuntime points to commit 170150a. (role: adjacent Android runtime contributor; confidence: medium; commits: 170150a306e3; files: apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt)
  • Ayaan Zaidi: Ayaan authored earlier Android setup-auth and new-setup-code reset changes that shaped this credential replacement path. (role: adjacent auth-reset contributor; confidence: medium; commits: 6090afa0e5f0, fa150f882834; files: apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt, apps/android/app/src/main/java/ai/openclaw/app/MainViewModel.kt)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (5 earlier review cycles)
  • reviewed 2026-07-05T21:28:19.453Z sha fdd3630 :: needs changes before merge. :: [P2] Remove the release-owned changelog entry
  • reviewed 2026-07-06T00:04:31.485Z sha 99fa987 :: needs changes before merge. :: [P2] Remove the release-owned changelog entry
  • reviewed 2026-07-06T00:11:21.658Z sha 99fa987 :: needs changes before merge. :: [P2] Remove the release-owned changelog entry
  • reviewed 2026-07-06T00:40:29.318Z sha bc9064b :: needs changes before merge. :: [P1] Claim connect starts before reset can drain them
  • reviewed 2026-07-06T01:12:33.021Z sha 606cf3c :: needs changes before merge. :: [P1] Claim the full connect start before reset can drain it

@blacksmith-sh

This comment has been minimized.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 5, 2026
@steipete
steipete force-pushed the codex/android-offline-cache-lifecycle branch from 5e18c93 to fdd3630 Compare July 5, 2026 21:19
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 5, 2026
@steipete steipete self-assigned this Jul 5, 2026
@steipete
steipete force-pushed the codex/android-offline-cache-lifecycle branch from fdd3630 to 99fa987 Compare July 5, 2026 23:48
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: ios App: ios app: web-ui App: web-ui gateway Gateway runtime scripts Repository scripts agents Agent runtime and tooling labels Jul 6, 2026
@steipete
steipete force-pushed the codex/android-offline-cache-lifecycle branch from 6e7b65a to b755d3a Compare July 6, 2026 00:18
@openclaw-barnacle openclaw-barnacle Bot removed docs Improvements or additions to documentation app: ios App: ios app: web-ui App: web-ui labels Jul 6, 2026
@openclaw-barnacle openclaw-barnacle Bot removed channel: slack Channel integration: slack channel: telegram Channel integration: telegram agents Agent runtime and tooling labels Jul 6, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 6, 2026
@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime scripts Repository scripts labels Jul 6, 2026
@steipete
steipete force-pushed the codex/android-offline-cache-lifecycle branch from 7e04b52 to 606cf3c Compare July 6, 2026 01:06
@openclaw-barnacle openclaw-barnacle Bot removed gateway Gateway runtime scripts Repository scripts labels Jul 6, 2026
@steipete
steipete merged commit d6f0747 into main Jul 6, 2026
83 of 85 checks passed
@steipete
steipete deleted the codex/android-offline-cache-lifecycle branch July 6, 2026 01:21
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 6, 2026
* fix(android): harden offline cache lifecycle

* docs(changelog): harden Android offline cache lifecycle

* fix(android): drain terminal gateway work safely

* test(android): cover queued command purge

* chore(android): refresh native i18n inventory

* docs(changelog): avoid duplicate offline cache entry
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
* fix(android): harden offline cache lifecycle

* docs(changelog): harden Android offline cache lifecycle

* fix(android): drain terminal gateway work safely

* test(android): cover queued command purge

* chore(android): refresh native i18n inventory

* docs(changelog): avoid duplicate offline cache entry
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: android App: android maintainer Maintainer-authored PR merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: XL status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant