Skip to content

[Repo Assist] fix(connection): operator client always connects as operator, never node role#721

Draft
github-actions[bot] wants to merge 1 commit into
mainfrom
repo-assist/fix-issue-720-operator-qr-pair-role-544f4ed8213368cc
Draft

[Repo Assist] fix(connection): operator client always connects as operator, never node role#721
github-actions[bot] wants to merge 1 commit into
mainfrom
repo-assist/fix-issue-720-operator-qr-pair-role-544f4ed8213368cc

Conversation

@github-actions

@github-actions github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🤖 This PR was created by Repo Assist, an automated AI assistant.

Closes #720

Root Cause

GatewayClientFactory.Create() constructed the operator (chat) client with bootstrapPairAsNode: credential.IsBootstrapToken. For QR-code and setup-code pairing — where the credential is always a bootstrap token — this set bootstrapPairAsNode: true. That flag caused GetConnectRole() to return "node" instead of "operator", putting the tray in a permanent loop:

  1. Bootstrap token → bootstrapPairAsNode = true → role "node"
  2. Gateway returns hello-ok with node token only (no operator handoff token)
  3. On reconnect: still using bootstrap token → role still "node"
  4. chat.send rejected: unauthorized role: node

Fix

Set bootstrapPairAsNode: false unconditionally in GatewayClientFactory.Create(). The operator (chat) client should always connect as "operator" regardless of credential type. The node-platform client has its own separate creation path (NodeConnector) which sets bootstrapPairAsNode as needed.

Changes

src/OpenClaw.Connection/GatewayClientFactory.cs
Change bootstrapPairAsNode: credential.IsBootstrapTokenbootstrapPairAsNode: false.
Added a comment explaining the invariant.

tests/OpenClaw.Connection.Tests/GatewayClientFactoryTests.cs
Updated Create_BootstrapCredential_PairsAsNode (now Create_BootstrapCredential_PairsAsOperator) to assert the corrected behavior.

tests/OpenClaw.Shared.Tests/OpenClawGatewayClientTests.cs
Added OperatorClient_WithBootstrapToken_ConnectsAsOperatorRole regression test.

Trade-offs

  • The bootstrapPairAsNode: true path in OpenClawGatewayClient (node token storage, operator handoff) is preserved for the node-platform client. This PR only changes which value the operator-client factory passes — the OpenClawGatewayClient logic itself is unchanged.
  • The gateway will now receive an operator-role connect request for bootstrap tokens. This is the expected behavior for chat-only clients.

Test Status

  • Shared tests: 2123 passed (+1 new regression test), 8 pre-existing failures unchanged
  • Tray tests: 974 passed, 0 failed
  • Connection tests: 297 passed, 0 failed
  • ⚠️ Build (./build.ps1): GitVersion MSBuild task requires GITHUB_ENV path present on CI runner; not available in agent environment (pre-existing infrastructure limitation)

Generated by 🌈 Repo Assist, see workflow run. Learn more.

Add this agentic workflows to your repo

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@97143ac59cb3a13ef2a77581f929f06719c7402a

…ode role

GatewayClientFactory created the operator (chat) client with
bootstrapPairAsNode: credential.IsBootstrapToken.  For bootstrap tokens
(QR-code and setup-code pairing) this set bootstrapPairAsNode: true, which
caused GetConnectRole() to return "node" — permanently locking the tray app
in node role with no device-token upgrade path.  Every reconnect re-used the
bootstrap token, GetConnectRole() returned "node" again, and chat.send was
rejected with "unauthorized role: node".

Fix: set bootstrapPairAsNode: false unconditionally for the operator client.
The operator (chat) client should always connect as "operator" regardless of
credential type.  The node-platform client has its own creation path
(NodeConnector) which sets bootstrapPairAsNode as needed.

Updated GatewayClientFactoryTests to reflect the corrected behaviour and
added a regression test in OpenClawGatewayClientTests covering the
bootstrap-token operator-role case.

Closes #720

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@clawsweeper

clawsweeper Bot commented Jun 8, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed June 8, 2026, 10:15 AM ET / 14:15 UTC.

Summary
The PR changes the operator GatewayClientFactory to always pass bootstrapPairAsNode: false and updates/adds regression tests for bootstrap-token operator connections.

Reproducibility: yes. from source inspection, not from a live run: current main passes credential.IsBootstrapToken into bootstrapPairAsNode, and GetConnectRole() returns node for fresh bootstrap credentials. The linked issue supplies concrete QR pairing steps.

Review metrics: 3 noteworthy metrics.

  • Auth role call site: 1 constructor argument changed. A single factory argument controls whether fresh bootstrap credentials connect as operator or node.
  • Changed surface: 3 files, +38/-3. The PR is small, but it touches authentication/pairing behavior plus regression tests.
  • Live proof artifacts: 0 provided. Unit tests do not prove the changed bootstrap handshake works against a real gateway.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🐚 platinum hermit
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 live QR/setup-code pairing proof showing operator-role connection, device-token storage, and successful chat.
  • [P1] Provide the required build/CI result for ./build.ps1 or a maintainer-run equivalent.
  • Confirm node-mode pairing still works through NodeConnector after the operator-client change.

Proof guidance:

  • [P1] Needs real behavior proof before merge: Only test results are described; add redacted live pairing/chat evidence such as logs, terminal output, a recording, or diagnostics artifact, then update the PR body for a fresh ClawSweeper review.

Mantis proof suggestion
A real Windows tray pairing/chat smoke would materially improve confidence in this auth-role change. A maintainer can ask Mantis to capture proof by posting a new PR comment that starts with the OpenClaw Mantis account mention, followed by:

visual task: verify fresh Windows tray QR/setup-code pairing connects as operator, sends chat successfully, and node mode still pairs through NodeConnector.

Risk before merge

  • [P1] Live gateway compatibility remains unproven: the PR changes fresh bootstrap credentials from node-role to operator-role connect for the operator client, and only unit/regression tests are cited.
  • [P1] The PR body says ./build.ps1 did not complete in the agent environment, so the repo-required build result is still missing before merge.
  • [P1] The node path appears separate in source, but a real smoke should still confirm node-mode bootstrap pairing continues to obtain and reuse the node token.

Maintainer options:

  1. Require live pairing proof (recommended)
    Ask for a redacted QR/setup-code pairing run against a supported gateway that shows operator-role hello-ok/device-token issuance, successful chat, and unchanged node-mode pairing.
  2. Accept after gateway contract review
    Maintainers can accept the auth-role change once they confirm the gateway contract intentionally permits operator-role bootstrap pairing for the tray operator client.
  3. Pause if operator bootstrap is unsupported
    If supported gateways cannot issue operator device tokens from bootstrap credentials, pause this PR and move the fix to a coordinated client/gateway pairing change.

Next step before merge

  • [P2] This active PR has a plausible narrow fix; the remaining work is maintainer review plus live proof/build validation, not a separate automated repair.

Security
Cleared: No supply-chain, secret-handling, or concrete security regression was found in the diff; the auth-role contract uncertainty is tracked as merge risk.

Review details

Best possible solution:

Land the narrow factory change with regression tests after required build/CI and redacted live QR/setup-code pairing proof show operator chat works and node-mode pairing still works.

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

Yes from source inspection, not from a live run: current main passes credential.IsBootstrapToken into bootstrapPairAsNode, and GetConnectRole() returns node for fresh bootstrap credentials. The linked issue supplies concrete QR pairing steps.

Is this the best way to solve the issue?

Unclear until live gateway proof: the patch is the narrowest client-side fix and preserves the separate NodeConnector path, but maintainers need proof that operator-role bootstrap pairing is accepted and mints the expected device token.

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 37b0ea672037.

Label changes

Label changes:

  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: Only test results are described; add redacted live pairing/chat evidence such as logs, terminal output, a recording, or diagnostics artifact, then update the PR body for a fresh ClawSweeper review.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦪 silver shellfish, so this older rating label is no longer current.
  • remove status: 👀 ready for maintainer look: Current PR status label is status: 📣 needs proof.

Label justifications:

  • P1: The PR targets an auth-role bug that can leave QR-paired tray chat unable to send messages.
  • merge-risk: 🚨 auth-provider: The diff changes the role and scopes requested for bootstrap-token operator connections, so gateway token issuance compatibility must be proven before merge.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: Only test results are described; add redacted live pairing/chat evidence such as logs, terminal output, a recording, or diagnostics artifact, then update the PR body for a fresh ClawSweeper review.
Evidence reviewed

What I checked:

Likely related people:

  • Christine Yan: Git blame points the current factory wiring, role helper, and factory test file to the commit that introduced these paths in this checkout history. (role: introduced current behavior; confidence: medium; commits: 85445c78066b; files: src/OpenClaw.Connection/GatewayClientFactory.cs, src/OpenClaw.Shared/OpenClawGatewayClient.cs, tests/OpenClaw.Connection.Tests/GatewayClientFactoryTests.cs)
  • Scott Hanselman: Recent git history shows a hardening pass touching OpenClawGatewayClient and its tests shortly before this PR. (role: recent adjacent contributor; confidence: medium; commits: d23f8ca50013; files: src/OpenClaw.Shared/OpenClawGatewayClient.cs, tests/OpenClaw.Shared.Tests/OpenClawGatewayClientTests.cs)
  • AlexAlves87: Recent history shows test-isolation work in OpenClawGatewayClientTests, which is part of this PR's regression surface. (role: recent test contributor; confidence: low; commits: 8bcd0f399abd; files: tests/OpenClaw.Shared.Tests/OpenClawGatewayClientTests.cs)
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: 🐚 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. P1 Urgent regression or broken agent/channel workflow affecting real users now. merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. 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 Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automation merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. P1 Urgent regression or broken agent/channel workflow affecting real users now. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. repo-assist 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.

QR-code pairing leaves the tray app permanently stuck in role: "node"

0 participants