Skip to content

fix: keep iOS LAN QR pairing authenticated after bootstrap#98066

Merged
steipete merged 3 commits into
openclaw:mainfrom
ooiuuii:fix/ios-lan-bootstrap-device-token
Jul 2, 2026
Merged

fix: keep iOS LAN QR pairing authenticated after bootstrap#98066
steipete merged 3 commits into
openclaw:mainfrom
ooiuuii:fix/ios-lan-bootstrap-device-token

Conversation

@ooiuuii

@ooiuuii ooiuuii commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Fixes #98064

What Problem This Solves

Fixes an issue where users scanning /pair qr with the iOS app against a LAN Gateway could see the Control/Gateway card become online while Chat stayed disconnected and the Gateway still reported that a token was required.

In the real repro, the Gateway accepted the setup bootstrap once, then the next iPhone node/chat WebSocket reconnected with no auth and was rejected as token_missing.

Why This Change Was Made

The iOS setup-code parser already allows plaintext ws:// bootstrap URLs when the host is local-network scoped, such as 192.168.x.x, while still rejecting public plaintext hosts. This change aligns bootstrap handoff token persistence with that same local-network boundary: wss:// remains allowed, public ws:// remains non-persistent, and private LAN ws:// now persists the bounded device tokens issued by the Gateway after bootstrap succeeds.

This does not change token validation, expired setup-code handling, or public/non-local plaintext WebSocket policy.

User Impact

Users can scan a fresh /pair qr code from a phone on the same LAN and keep the iOS app connected after the one-time bootstrap token is consumed. Chat should no longer fall back to auth=none immediately after an otherwise successful local pairing.

Evidence

AI-assisted: yes, Codex.

  • Issue/repro: iOS LAN pairing drops bootstrap handoff token before chat reconnect #98064 tracks the real Windows Gateway + iOS LAN pairing failure on OpenClaw 2026.6.11-beta.2, where Control showed the Main gateway online but Chat showed Disconnected / not connected.
  • Before-fix live log evidence, redacted: device pairing auto-approved ... role=node, followed by unauthorized ... client=iPhone node v2026.6.10 role=node scopes=0 auth=none ... reason=token_missing, then closed before connect ... gateway token missing.
  • Source-level boundary check: apps/shared/OpenClawKit/Sources/OpenClawKit/DeepLinks.swift accepts private LAN ws:// setup-code hosts through LoopbackHost.isLocalNetworkHost, while the pre-fix GatewayChannel.shouldPersistBootstrapHandoffTokens() only persisted bootstrap-issued tokens for wss:// or loopback.
  • Regression coverage added: GatewayNodeSessionTests verifies that a bootstrap hello from ws://192.168.x.x:18889 persists the issued node and operator device tokens.
  • After-fix reconnect coverage added: GatewayNodeSessionTests.private lan bootstrap reconnect uses persisted handoff token simulates a fresh LAN bootstrap over ws://192.168.x.x:18889, disconnects after the one-time bootstrap succeeds, reconnects with no bootstrap token, and asserts the next connect request sends the persisted token=lan-node-token while sending no bootstrapToken and no deviceToken. This is the source-level regression for the observed auth=none / token_missing reconnect failure.
  • Existing guard retained: the adjacent untrusted bootstrap test still covers public plaintext ws://example.invalid not persisting bootstrap handoff tokens.
  • Diff sanity passed: git diff --check.
  • Autoreview passed after the reconnect test was added: python .agents\skills\autoreview\scripts\autoreview --mode branch --base upstream/main --thinking low reported autoreview clean: no accepted/actionable findings reported.
  • Local test limitation: the focused Swift tests were added but not executed locally because this Windows environment does not have swift/Xcode installed. CI should run the OpenClawKit Swift/iOS lanes on the PR head.
  • Remaining live-device proof limitation: I do not have a PR/TestFlight iOS app build installed on a real iPhone, so I cannot honestly claim an after-patch real-device QR scan. The real incident evidence and the new reconnect regression cover the same auth transition that caused Chat to reconnect as auth=none after the bootstrap token was consumed.

@ooiuuii

ooiuuii commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 2, 2026, 5:11 PM ET / 21:11 UTC.

Summary
The PR changes OpenClawKit to persist bootstrap-issued node/operator device tokens for private-LAN ws:// Gateway URLs and adds a Swift reconnect regression test.

PR surface: Other +92. Total +92 across 2 files.

Reproducibility: yes. at source level: current main accepts private-LAN ws:// setup codes but only persists bootstrap handoff tokens for wss:// or loopback, matching the linked token_missing logs. I did not run a live iPhone LAN pairing scenario in this read-only pass.

Review metrics: 1 noteworthy metric.

  • Auth persistence boundary: 1 predicate changed. The diff expands where bootstrap-issued device tokens are persisted, so maintainers should notice the plaintext-LAN trust boundary before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #98064
Summary: This PR is the active candidate fix for the focused iOS LAN bootstrap handoff-token issue; broader and adjacent reports provide context but do not replace the linked issue.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🦞 diamond lobster
Result: blocked until real behavior proof from a real setup is added.

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

Rank-up moves:

  • [P1] Add redacted after-fix iPhone LAN QR pairing proof showing Chat remains connected after bootstrap reconnect.
  • Update the PR body with that proof; ClawSweeper should re-review automatically, or a maintainer can comment @clawsweeper re-review.

Proof guidance:

  • [P1] Needs real behavior proof before merge: After-fix evidence is Swift regression coverage, an xcodebuild simulator-test summary, and CI only; no redacted real iPhone/LAN QR scan or live device log shows the changed user flow. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] After-fix proof is still Swift regression coverage, a simulator-test summary, and CI; no redacted real iPhone LAN QR scan or live device log shows Chat staying connected after bootstrap reconnect.
  • [P1] Merging intentionally persists bootstrap-issued device tokens for accepted private-LAN plaintext ws:// setup codes, so maintainers should explicitly accept that auth boundary.

Maintainer options:

  1. Require real iPhone LAN proof (recommended)
    Ask for redacted after-fix /pair qr evidence showing the iOS Chat reconnect remains authenticated on the same LAN before merge.
  2. Accept maintainer proof override
    Maintainers may explicitly accept the simulator regression, CI, and incident logs as enough for this bounded security-boundary change.

Next step before merge

  • [P1] Human merge handling is still needed for the private-LAN auth boundary and real-device proof gap; there is no narrow code repair for automation to queue.

Security
Cleared: No concrete security or supply-chain defect was found; the auth-boundary expansion is surfaced as merge risk for maintainer acceptance.

Review details

Best possible solution:

Land the narrow predicate/test after maintainers accept the private-LAN token-persistence boundary and attach redacted iPhone LAN QR pairing proof or explicitly override the proof gate.

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

Yes at source level: current main accepts private-LAN ws:// setup codes but only persists bootstrap handoff tokens for wss:// or loopback, matching the linked token_missing logs. I did not run a live iPhone LAN pairing scenario in this read-only pass.

Is this the best way to solve the issue?

Yes for the code shape: it reuses the existing local-network setup-code trust predicate and keeps public plaintext hosts non-persistent. Merge readiness still depends on real-device proof or explicit maintainer override for that proof gap.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦞 diamond lobster.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🦪 silver shellfish, so this older rating label is no longer current.

Label justifications:

  • P1: The PR targets a real iOS LAN QR pairing regression that leaves the mobile Chat/operator workflow disconnected immediately after setup.
  • merge-risk: 🚨 security-boundary: The diff expands bootstrap-issued device-token persistence from secure/loopback transports to accepted private-LAN plaintext ws:// setup codes.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦞 diamond lobster.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: After-fix evidence is Swift regression coverage, an xcodebuild simulator-test summary, and CI only; no redacted real iPhone/LAN QR scan or live device log shows the changed user flow. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Other +92. Total +92 across 2 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 2 96 4 +92
Total 2 96 4 +92

What I checked:

Likely related people:

  • ngutman: Authored the merged QR/setup-code bounded device-token handoff work that introduced the token persistence surface this PR extends. (role: bootstrap handoff feature contributor; confidence: high; commits: a9140abea6d4, 20266ff7ddd5; files: apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift, apps/shared/OpenClawKit/Tests/OpenClawKitTests/GatewayNodeSessionTests.swift, src/infra/device-bootstrap.ts)
  • Val Alexander: Authored the iOS LAN pairing repair that introduced the current local-network setup-code acceptance boundary reused by this PR. (role: recent iOS LAN pairing contributor; confidence: medium; commits: 36df0d93b93a; files: apps/shared/OpenClawKit/Sources/OpenClawKit/DeepLinks.swift, apps/shared/OpenClawKit/Sources/OpenClawKit/LoopbackHost.swift, apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift)
  • steipete: Merged the earlier mobile bootstrap handoff PR and authored the latest test consolidation commit on this PR branch. (role: adjacent mobile bootstrap contributor; confidence: high; commits: 20266ff7ddd5, 4c1278d5ad7a; files: apps/shared/OpenClawKit/Sources/OpenClawKit/GatewayChannel.swift, apps/shared/OpenClawKit/Tests/OpenClawKitTests/GatewayNodeSessionTests.swift)
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.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jun 30, 2026
@ooiuuii

ooiuuii commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@steipete

steipete commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Maintainer repair complete and land-ready at 4c1278d5ad7a5fb561c622c6dfe8783e665bd2a1.

  • Kept token handoff persistence at the Gateway session owner and aligned the plaintext trust check with the existing private-LAN setup-code boundary. Public ws:// hosts remain excluded.
  • Consolidated the duplicated coverage into one full bootstrap → bounded node/operator token persistence → disconnect → authenticated reconnect scenario.
  • Before: restoring the current-main persistence predicate makes the simulator reconnect scenario fail after the one-use bootstrap token is consumed.
  • After: xcodebuild test -scheme OpenClawKit-Package -destination 'platform=iOS Simulator,name=iPhone 17 Pro,OS=26.5' -only-testing:OpenClawKitTests/GatewayNodeSessionTests passes all 16 tests.
  • SwiftFormat and git diff --check pass. Fresh Codex autoreview reports no accepted/actionable findings.
  • Exact-head hosted CI is green, including ios-build, macos-swift, and native-i18n.

No remaining proof gaps for this bounded fix.

@steipete
steipete force-pushed the fix/ios-lan-bootstrap-device-token branch from 9090b3d to 4c1278d Compare July 2, 2026 21:06
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jul 2, 2026
@steipete
steipete merged commit 155c2f4 into openclaw:main Jul 2, 2026
51 of 53 checks passed
@steipete

steipete commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 3, 2026
…98066)

* Persist iOS LAN bootstrap handoff tokens

* test: cover iOS LAN bootstrap reconnect auth

* test(ios): consolidate LAN bootstrap reconnect proof

---------

Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P1 High-priority user-facing bug, regression, or broken workflow. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: S status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iOS LAN pairing drops bootstrap handoff token before chat reconnect

2 participants