Skip to content

feat: make mobile setup-code pairing one step#98243

Closed
Solvely-Colin wants to merge 1 commit into
mainfrom
codex/gateway-ios-qr-setup-autopair
Closed

feat: make mobile setup-code pairing one step#98243
Solvely-Colin wants to merge 1 commit into
mainfrom
codex/gateway-ios-qr-setup-autopair

Conversation

@Solvely-Colin

Copy link
Copy Markdown
Contributor

Closes #98242

What Problem This Solves

Resolves a problem where fresh mobile users had to perform QR/setup-code entry plus separate device/node approval steps before iOS or Android could land connected to the Gateway.

Why This Change Was Made

This makes the existing QR/setup-code bootstrap path the one-step mobile onboarding baseline: the setup payload configures the app, the Gateway approves the fresh native mobile device handoff, and the matching fresh node pairing is approved through the same bounded setup-code bootstrap. It also adds an 8-character gateway-local short-code redemption seam for cases where the app already knows which Gateway URL to contact.

The security boundary stays narrow: setup bootstrap keeps the bounded node/operator profile, does not grant operator.admin or operator.pairing, short codes are TTL-bound and single-use, and insecure public Gateway URLs still fail closed outside loopback/private LAN allowances.

User Impact

Users can scan a QR code or paste a setup code and land connected without walking through separate pending approvals for the fresh mobile device and node. Operators still get explicit approval boundaries for later role, scope, capability, or pairing upgrades.

Evidence

Redacted setup-code mobile pairing proof

  • Physical iPhone + Tailscale QR proof: scanned the QR, app connected, Gateway showed device auto-approval and node auto-approval via setup-code bootstrap, and pending device/node counts were 0 afterward.
  • Simulator setup-code proof: clean iPhone 17 simulator install, generated setup code against the running dev Gateway state, pasted setup code, app reached Connected / Gateway Online for 127.0.0.1:19001; redacted GIF generated locally from that run.
  • node scripts/run-vitest.mjs src/pairing/setup-short-code.test.ts src/gateway/server-http.probe.test.ts src/cli/qr-cli.test.ts
  • node scripts/run-vitest.mjs src/gateway/server.auth.control-ui.test.ts --testNamePattern "qr setup code"
  • node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.src.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/test-src.tsbuildinfo
  • swift test --filter GatewaySetupShortCodeRedeemerTests from apps/shared/OpenClawKit
  • node scripts/format-docs.mjs --check docs/cli/qr.md docs/channels/pairing.md docs/gateway/protocol.md
  • node scripts/check-docs-mdx.mjs docs/cli/qr.md docs/channels/pairing.md docs/gateway/protocol.md
  • node scripts/docs-link-audit.mjs docs/cli/qr.md docs/channels/pairing.md docs/gateway/protocol.md
  • git diff --check
  • .agents/skills/autoreview/scripts/autoreview --mode local --prompt-file /tmp/openclaw-qr-setup-pr-prep.md returned autoreview clean: no accepted/actionable findings reported.

Notes:

  • iOS simulator build/run succeeded through XcodeBuildMCP; existing unrelated SwiftLint/Swift warnings remain in GatewaySettingsStore.swift, NodeAppModel.swift, TalkModeManager.swift, ChatViewModel.swift, and RealtimeTalkRelaySession.swift.
  • Broad Crabbox/Testbox check:changed was skipped by request after the local Crabbox binary/toolbox path failed before running the repo check.

@Solvely-Colin
Solvely-Colin requested a review from a team as a code owner June 30, 2026 18:52
Copilot AI review requested due to automatic review settings June 30, 2026 18:52
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: ios App: ios gateway Gateway runtime cli CLI command changes size: XL maintainer Maintainer-authored PR labels Jun 30, 2026
@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Codex review: found issues before merge. Reviewed June 30, 2026, 3:09 PM ET / 19:09 UTC.

Summary
The PR adds one-step mobile QR/setup-code onboarding, setup short-code issuance/redemption, iOS short-code handling, Gateway node auto-approval during setup bootstrap, docs, and focused tests.

PR surface: Source +463, Tests +274, Docs +48, Other +334. Total +1119 across 22 files.

Reproducibility: not applicable. as a bug reproduction: this PR implements a requested feature. Source and CI inspection do reproduce merge blockers, including the setup-short-code lint failure and docs-map failure on the PR head.

Review metrics: 2 noteworthy metrics.

  • Auth/setup surfaces: 1 pre-auth endpoint added, 1 auto-approval path added, 2 CLI JSON fields added. These are public or security-sensitive onboarding surfaces that require upgrade and boundary review beyond green unit tests.
  • Confirmed check blockers: 2 failing checks with concrete PR-caused causes. check-lint fails on the new short-code normalizer and check-docs fails because the generated docs map was not refreshed.

Stored data model
Persistent data-model change detected: serialized state: src/gateway/server-http.probe.test.ts, vector/embedding metadata: docs/gateway/protocol.md. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #98242
Summary: This PR is the open candidate fix for the canonical one-step mobile QR/setup-code onboarding feature request.

Members:

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

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

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

Rank-up moves:

  • [P2] Fix the iOS short-code scheme, lint failure, docs map, stale helper, and Telegram docs.
  • Get explicit maintainer acceptance for the pre-auth short-code endpoint and setup-code node auto-approval boundary.

Risk before merge

  • [P1] Merging changes fresh setup-code mobile onboarding from explicit pending node approval to silent device plus node auto-approval, which is an intentional operator/security expectation change for existing setup-code flows.
  • [P1] The new unauthenticated short-code redeem endpoint returns bootstrap-token setup payload material, so maintainers need to explicitly accept the TTL, one-time-use, rate-limit, and same-Gateway exposure boundary.
  • [P1] The current PR head has confirmed PR-caused lint and docs check failures, plus a local short-code scheme defect that can break the default fresh onboarding path.
  • [P1] The protected maintainer label means this PR should stay open for explicit maintainer handling rather than conservative cleanup closure.

Maintainer options:

  1. Fix blockers before boundary sign-off (recommended)
    Repair the iOS short-code scheme, lint failure, docs map, stale Swift helper, and Telegram docs before maintainers make the final approval-boundary decision.
  2. Accept the bootstrap boundary explicitly
    Maintainers can choose to accept one-step setup-code auto-approval and pre-auth short-code redemption after reviewing the rate-limit, TTL, one-time-use, and scope limits.
  3. Pause for a narrower pairing design
    If silent node approval or pre-auth redemption is too broad, pause this PR and split the accepted iOS UX, short-code, and approval-policy pieces into smaller changes.

Next step before merge

  • [P2] Manual maintainer review is needed because this PR has protected-label handling and security/product approval-boundary decisions in addition to concrete author-fix blockers.

Security
Needs attention: The diff is security-sensitive because it adds pre-auth redemption of bootstrap-token setup payloads and silent bootstrap-driven node approval, with no concrete bypass proven but explicit maintainer sign-off still needed.

Review findings

  • [P2] Use the correct local scheme for short-code redemption — apps/ios/Sources/Onboarding/OnboardingWizardView.swift:750-751
  • [P2] Satisfy oxlint without spreading the code string — src/pairing/setup-short-code.ts:86
  • [P2] Regenerate the docs map for the new docs text — docs/gateway/protocol.md:181
Review details

Best possible solution:

Fix the concrete lint, docs-map, iOS scheme, stale-helper, and Telegram-doc blockers, then merge only if maintainers accept the pre-auth short-code and silent node-approval boundary.

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

Not applicable as a bug reproduction: this PR implements a requested feature. Source and CI inspection do reproduce merge blockers, including the setup-short-code lint failure and docs-map failure on the PR head.

Is this the best way to solve the issue?

No in the current patch state: the implementation uses plausible existing bootstrap seams, but the iOS short-code scheme, CI blockers, stale helper, docs mismatch, and security boundary need resolution before this is the best mergeable solution.

Full review comments:

  • [P2] Use the correct local scheme for short-code redemption — apps/ios/Sources/Onboarding/OnboardingWizardView.swift:750-751
    Fresh onboarding seeds openclaw.local:18789 with TLS enabled in UI state, but the default local Gateway is commonly reached over plain ws:///http://. Building the redemption URL from manualTLS here makes a bare short code try https://openclaw.local:18789/... and fail before it can retrieve the actual setup payload; the Settings helper has the same construction.
    Confidence: 0.9
  • [P2] Satisfy oxlint without spreading the code string — src/pairing/setup-short-code.ts:86
    The PR head's check-lint job fails on this expression with typescript(no-misused-spread). Replace the spread with a lint-accepted character iteration or character-class check so the new short-code file can pass the required lint gate.
    Confidence: 0.98
  • [P2] Regenerate the docs map for the new docs text — docs/gateway/protocol.md:181
    The PR changes public docs but does not refresh docs/docs_map.md; the check-docs job reports docs:map: docs/docs_map.md is out of date. Regenerate the docs map after the pairing/protocol docs changes so the docs gate passes.
    Confidence: 0.92
  • [P2] Remove or reuse the stale setup-code helper — apps/ios/Sources/Design/SettingsProTabActions.swift:251
    applySetupCodeAndConnect() now goes through resolveSetupInputForConnect(), leaving applySetupCode() as an unused older parser path that can diverge from short-code behavior and is already called out by the prior review as dead Swift code. Delete it or route the new path through one canonical helper.
    Confidence: 0.86
  • [P3] Update the Telegram pairing instructions — docs/channels/pairing.md:116-119
    This new pairing page says setup-code mobile bootstrap silently approves the fresh device and node, but docs/channels/telegram.md still says the setup code is node-only and requires /pair pending approval. Update the Telegram page too so the docs do not contradict each other.
    Confidence: 0.88

Overall correctness: patch is incorrect
Overall confidence: 0.9

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add P2: This is a meaningful mobile onboarding feature with security-sensitive but bounded blast radius, not an outage or urgent regression.
  • add merge-risk: 🚨 compatibility: The PR changes the default fresh setup-code flow from pending node approval to silent auto-approval and expands CLI QR JSON output.
  • add merge-risk: 🚨 security-boundary: The diff adds unauthenticated redemption of token-bearing setup payloads and internal bootstrap-driven node approval.

Label justifications:

  • P2: This is a meaningful mobile onboarding feature with security-sensitive but bounded blast radius, not an outage or urgent regression.
  • merge-risk: 🚨 compatibility: The PR changes the default fresh setup-code flow from pending node approval to silent auto-approval and expands CLI QR JSON output.
  • merge-risk: 🚨 security-boundary: The diff adds unauthenticated redemption of token-bearing setup payloads and internal bootstrap-driven node approval.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (recording): The PR body includes a redacted visual proof animation plus physical iPhone/Tailscale and simulator after-fix observations; that is sufficient real behavior proof, though it does not waive the uncovered default short-code scheme defect.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes a redacted visual proof animation plus physical iPhone/Tailscale and simulator after-fix observations; that is sufficient real behavior proof, though it does not waive the uncovered default short-code scheme defect.
  • proof: 🎥 video: Contributor real behavior proof includes video or recording evidence. The PR body includes a redacted visual proof animation plus physical iPhone/Tailscale and simulator after-fix observations; that is sufficient real behavior proof, though it does not waive the uncovered default short-code scheme defect.
Evidence reviewed

PR surface:

Source +463, Tests +274, Docs +48, Other +334. Total +1119 across 22 files.

View PR surface stats
Area Files Added Removed Net
Source 9 465 2 +463
Tests 3 274 0 +274
Docs 3 56 8 +48
Config 0 0 0 0
Generated 0 0 0 0
Other 7 342 8 +334
Total 22 1137 18 +1119

Security concerns:

  • [medium] Review pre-auth setup payload redemption — src/gateway/pairing-setup-short-code-http.ts:35
    The new redeem handler is intentionally unauthenticated and returns a setup payload containing bootstrap-token material, so the TTL, one-time-use, client-IP rate limit, and same-Gateway exposure boundary need maintainer acceptance before merge.
    Confidence: 0.9
  • [medium] Review synthetic node approval scope — src/gateway/server/ws-connection/message-handler.ts:1799
    The auto-approval path approves a fresh pending node using internal pairing/write scopes after setup-code mobile device bootstrap, changing the previous explicit node-approval boundary even though the handed-off operator token remains bounded.
    Confidence: 0.86

Acceptance criteria:

  • [P1] node scripts/run-vitest.mjs src/pairing/setup-short-code.test.ts src/gateway/server-http.probe.test.ts src/cli/qr-cli.test.ts.
  • [P1] node scripts/run-vitest.mjs src/gateway/server.auth.control-ui.test.ts --testNamePattern "qr setup code".
  • [P1] swift test --filter GatewaySetupShortCodeRedeemerTests from apps/shared/OpenClawKit.
  • [P1] node scripts/format-docs.mjs --check docs/cli/qr.md docs/channels/pairing.md docs/gateway/protocol.md docs/channels/telegram.md.
  • [P1] pnpm check-docs or the repository docs-map check after regenerating docs/docs_map.md.

What I checked:

Likely related people:

  • ngutman: Merged prior QR bootstrap operator handoff and talk-secret bootstrap handoff work adjacent to this setup-code/mobile onboarding boundary. (role: bootstrap handoff feature-history contributor; confidence: high; commits: 94d8391c0323, c791e4242bc8; files: src/gateway/server/ws-connection/message-handler.ts, src/shared/device-bootstrap-profile.ts, docs/gateway/protocol.md)
  • pgondhi987: Authored the merged setup-code device-pairing approval work that changed the same bootstrap approval model. (role: device pairing approval contributor; confidence: medium; commits: b17e77a22bf4; files: src/gateway/server/ws-connection/message-handler.ts, src/infra/device-pairing.ts)
  • Solvely-Colin: Authored this PR and also has prior merged mobile setup-code/node approval work, so they are relevant beyond just opening this branch. (role: candidate fix author and prior mobile setup contributor; confidence: medium; commits: 8e77d5e1444f, 5db425956413; files: apps/ios/Sources/Onboarding/OnboardingWizardView.swift, apps/ios/Sources/Design/SettingsProTabActions.swift, src/gateway/server/ws-connection/message-handler.ts)
  • steipete: Git log -S ties the centralized bootstrap profile handling to this author before the current shallow blame collapsed later lines to a grafted merge. (role: bootstrap profile refactor contributor; confidence: medium; commits: 6686f1cb2ce3; files: src/shared/device-bootstrap-profile.ts, src/pairing/setup-code.ts)
  • RomneyDa: Current shallow blame points central setup-code and node-pairing lines to the recent merged PR 97937, though the grafted checkout makes this a weak ownership signal. (role: recent area contributor; confidence: low; commits: fd3f354f4626; files: src/shared/device-bootstrap-profile.ts, src/gateway/node-connect-reconcile.ts, apps/ios/Sources/Onboarding/OnboardingWizardView.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.

@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: 5db4259564

ℹ️ 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 on lines +750 to +751
let scheme = self.manualTLS ? "wss" : "ws"
if let link = GatewayConnectDeepLink.fromGatewayURL("\(scheme)://\(host):\(self.manualPort)") {

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 Redeem local short codes over the correct scheme

For a fresh install, initializeState() seeds the onboarding gateway to openclaw.local:18789 while manualTLS remains at its default true, but Gateway TLS defaults to disabled. In that common default-local setup, an 8-character short code printed by openclaw qr points to a ws:// setup payload, yet this helper redeems it as https://openclaw.local:18789/api/v1/pairing/setup-code/redeem, so redemption fails before the app can retrieve the real payload. The short-code path needs to use/ask for the correct local scheme (and the Settings helper has the same construction) instead of assuming TLS for the default host.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: 🎥 video Contributor real behavior proof includes video or recording evidence. 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: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jun 30, 2026

Copilot AI 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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@Solvely-Colin

Copy link
Copy Markdown
Contributor Author

Split this combined PR into smaller reviewable pieces:

Closing this combined branch so review can happen on the focused PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: ios App: ios cli CLI command changes docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: 🎥 video Contributor real behavior proof includes video or recording evidence. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. 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.

[Feature]: One-step mobile QR/setup-code pairing

2 participants