Skip to content

Improve multi-gateway credential handling#948

Merged
shanselman merged 3 commits into
openclaw:mainfrom
bkudiess:bkudiess-multi-gateway-credentials
Jul 10, 2026
Merged

Improve multi-gateway credential handling#948
shanselman merged 3 commits into
openclaw:mainfrom
bkudiess:bkudiess-multi-gateway-credentials

Conversation

@bkudiess

@bkudiess bkudiess commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Make active gateway switching validated, persisted, observable, and rollback-safe.
  • Add detailed credential resolution states for missing/unreadable/corrupt/fallback/bootstrap outcomes and project them into connection diagnostics/UI.
  • Harden stale old-gateway event handling by using generation + gateway-id checks with captured identity context.
  • Protect shared-token and setup-code mutation paths against credential loss and persistence failures.
  • Gate browser-proxy shared-token guidance on actual active gateway shared-token availability.

Validation

  • ./build.ps1 — passed
  • dotnet test .\tests\OpenClaw.Shared.Tests\OpenClaw.Shared.Tests.csproj --no-restore — passed: 2724 passed / 31 skipped
  • dotnet test .\tests\OpenClaw.Tray.Tests\OpenClaw.Tray.Tests.csproj --no-restore — passed: 1616 passed
  • dotnet test .\tests\OpenClaw.Connection.Tests\OpenClaw.Connection.Tests.csproj --no-restore — passed: 422 passed

Notes: prior full validation attempts hit transient queued-chat / exec-approval timing failures; each failing test passed in isolation and the full suites passed on rerun.

Real behavior proof

  • Computer-use verified isolated setup launch: OpenClaw Setup window, Welcome to OpenClaw, security notice, and Continue button visible.
  • Computer-use verified normal profile companion: Connected, ws://localhost:18789/ • paired via device token • v2026.6.10, saved gateway row Local (OpenClawGateway) with paired via device token, Shared token, and Node active · 8 capabilities.
  • Local MCP proof via normal profile:
    • winnode --list-tools --verbose succeeded against http://127.0.0.1:8765/ with bearer auth from token file.
    • winnode --command system.which --params '{"bins":["git","node"]}' --verbose returned paths for both git and node.
  • Gateway-mediated proof requested by maintainer:
    • openclaw nodes list --json from the OpenClawGateway WSL distro showed paired Windows Node (PERSEID) with commands including system.which.
    • openclaw nodes invoke --node 'Windows Node (PERSEID)' --command system.which --params '{"bins":["git","node"]}' --json --invoke-timeout 30000 succeeded through the gateway and returned resolved git and node executable paths.
  • Existing-profile smoke:
    • Normal profile gateways.json had ActiveId=adceebb2401a4428, one saved gateway, active URL ws://localhost:18789, friendly name Local (OpenClawGateway), shared token present, bootstrap token absent.
    • The active per-gateway identity directory and device-key-ed25519.json existed under %APPDATA%\OpenClawTray\gateways\adceebb2401a4428\.

Corrupt/unreadable device-token fallback decision

  • This PR intentionally keeps corrupt/unreadable identity fallback as a visible same-gateway recovery path rather than silently downgrading durable credentials.
  • Safety constraints:
    • A readable stored device token still always wins over shared/bootstrap credentials.
    • Fallback is only to credentials already stored on the same active GatewayRecord; credential reads never fall back to another gateway identity directory.
    • The snapshot/diagnostics preserve GatewayCredentialResolutionStatus.FallbackUsed with PrimaryStatus=Unreadable or Corrupt, so UI/diagnostics can make repair or re-pairing visible.
  • Test coverage includes corrupt JSON, valid wrong-shape JSON ([] / null), and unreadable-token fallback cases.

Review notes

  • Completed five rubber-duck rounds, then multiple dual-model review passes.
  • Fixed follow-up findings around stale event races, shared-token TOCTOU, registry save rollback/temp cleanup, non-object identity JSON handling, Command Center browser-proxy warning coverage, explicit unreadable/corrupt fallback coverage/rationale, and final suggested cleanup items.
  • Latest cleanup: registry temp files are deleted on write or move failure; duplicate bootstrap-clear logic now delegates; dead V2 reset assignment and redundant missing-credential wording were removed.

Not verified / blocked

  • Isolated MCP proof was blocked because port 8765 was already in use by the normal profile MCP server; normal profile local MCP and gateway-mediated invoke proof were collected instead.

@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed July 9, 2026, 7:29 PM ET / 23:29 UTC.

Summary
This PR makes active gateway switching persisted and observable, adds detailed credential-resolution/fallback state, hardens stale gateway event handling, protects credential mutation persistence paths, updates Command Center/browser-proxy warnings, and adds docs/tests.

Reproducibility: not applicable. as a PR review: there is no open line-level bug finding to reproduce, but the PR body and tests exercise the changed active-gateway and credential-resolution paths.

Review metrics: 3 noteworthy metrics.

  • Changed surface: 30 files changed, +1501/-224. The diff spans connection credentials, registry persistence, WinUI projection, docs, and tests, so maintainer review should focus on auth and upgrade behavior.
  • Reported local validation: build passed; Shared 2724 passed / 31 skipped; Tray 1616 passed; Connection 422 passed. The PR body reports the repository-required validation plus the focused connection suite for the touched subsystem.
  • CI status: Build/Test and CodeQL gate succeeded on 6916aa6. Green current-head checks reduce ordinary validation risk but do not settle the auth-provider merge-risk decision.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

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

Rank-up moves:

  • [P2] Maintainer should explicitly accept or reject the same-gateway corrupt/unreadable fallback policy before merge.

Risk before merge

  • [P1] Merging this PR changes active gateway persistence, per-gateway identity resolution, and diagnostics for existing profiles, so a regression would show up as wrong-gateway connection, failed pairing, or token-source confusion during upgrade.
  • [P2] The corrupt/unreadable identity fallback remains an intentional same-gateway recovery path that can use shared/bootstrap credentials; even though it is now visible and covered, that policy sits next to the durable-device-token downgrade guardrail.

Maintainer options:

  1. Accept the visible fallback policy (recommended)
    Maintainers can merge once they are comfortable that same-gateway fallback plus diagnostics is the desired recovery behavior for existing profiles.
  2. Require fail-closed identity handling
    Ask for a narrow patch and tests that keep missing identity fallback but block corrupt or unreadable paired identity until explicit repair or re-pair.
  3. Pause for an upgrade matrix smoke
    Hold the PR for manual proof covering two saved gateways, restart persistence, corrupt identity fallback visibility, and gateway-mediated node invocation on the same upgraded profile.

Next step before merge

  • [P2] No narrow automation repair remains; maintainer review is needed for the compatibility/auth-provider policy choice and final merge acceptance.

Maintainer decision needed

  • Question: Should this PR land with visible same-gateway corrupt/unreadable identity fallback to shared/bootstrap credentials, or should unreadable/corrupt paired identity fail closed until repair/re-pair?
  • Rationale: The code and tests constrain fallback to the active gateway record, but choosing recovery fallback versus fail-closed behavior is an auth and upgrade policy decision rather than a purely mechanical bug fix.
  • Likely owner: shanselman — He owns the prior maintainer review ask and recent connection-architecture history around the credential precedence guardrail.
  • Options:
    • Accept constrained fallback (recommended): Merge after maintainer review with the current visible same-gateway fallback, tests, diagnostics, and proof as the intended recovery behavior.
    • Fail closed on corrupt identity: Require a follow-up patch so corrupt or unreadable stored device identity blocks connection until the user repairs or re-pairs, while missing identity can still use shared/bootstrap credentials.
    • Ask for broader upgrade proof: Pause merge until a two-gateway existing-profile smoke demonstrates switch, restart, corrupt identity, and fallback/repair behavior on the same profile.

Security
Cleared: No concrete security or supply-chain issue was found; the security-sensitive credential fallback is constrained to the active gateway record and made visible for diagnostics.

Review details

Best possible solution:

Land the constrained, tested credential-handling changes only after a maintainer accepts the same-gateway fallback and upgrade-risk posture; keep GatewayConnectionManager/GatewayRegistry as the ownership boundary.

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

Not applicable as a PR review: there is no open line-level bug finding to reproduce, but the PR body and tests exercise the changed active-gateway and credential-resolution paths.

Is this the best way to solve the issue?

Yes for the implementation shape: it stays within the existing GatewayConnectionManager/GatewayRegistry/CredentialResolver ownership boundary and adds focused regression coverage, while the fallback policy still needs maintainer acceptance.

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P2: This is a normal-priority connection/auth improvement with meaningful but bounded blast radius and no reproduced urgent regression in the review.
  • merge-risk: 🚨 compatibility: The PR changes persisted active-gateway behavior and existing-profile credential mutation paths, so upgrades could affect saved gateway selection or connection recovery.
  • merge-risk: 🚨 auth-provider: The PR changes credential-resolution status, fallback reporting, and shared/bootstrap fallback behavior for gateway authentication.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes current-head UI, local MCP, gateway-mediated node invocation, and existing-profile smoke proof, including the maintainer-requested gateway path.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes current-head UI, local MCP, gateway-mediated node invocation, and existing-profile smoke proof, including the maintainer-requested gateway path.
Evidence reviewed

What I checked:

Likely related people:

  • shanselman: Auth/credential precedence docs and current CredentialResolver/GatewayRegistry code trace to Scott Hanselman’s recent connection-architecture work, and he requested the gateway-mediated proof and fallback clarification on this PR. (role: current PR reviewer and feature-history contributor; confidence: high; commits: 4166e0fd63f8, b3a2b4ee75e2; files: docs/CONNECTION_ARCHITECTURE.md, src/OpenClaw.Connection/CredentialResolver.cs, src/OpenClaw.Connection/GatewayRegistry.cs)
  • bkudiess: Barbara Kudiess authored the recently merged connection snapshot truth work that touched GatewayConnectionManager, ConnectionPagePlan, and CommandCenterStateBuilder, so she is already connected to the affected current-main surface beyond this PR. (role: recent area contributor; confidence: high; commits: 74604aebafef; files: src/OpenClaw.Connection/GatewayConnectionManager.cs, src/OpenClaw.Tray.WinUI/Pages/ConnectionPagePlan.cs, src/OpenClaw.Tray.WinUI/Services/CommandCenterStateBuilder.cs)
  • christineyan4: Christine Yan’s recent atomic device-key token-clearing work is adjacent to this PR’s per-gateway identity and credential-loss handling. (role: adjacent identity-persistence contributor; confidence: medium; commits: 7463a343833f, 5e336be86caa; files: src/OpenClaw.Shared/DeviceIdentity.cs, src/OpenClaw.Shared/DeviceIdentityStore.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.
Review history (4 earlier review cycles)
  • reviewed 2026-07-09T01:01:52.827Z sha 6811204 :: found issues before merge. :: [P2] Resolve the timeout merge conflict
  • reviewed 2026-07-09T01:09:38.571Z sha 37f1252 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-09T20:12:54.059Z sha e28da8d :: needs maintainer review before merge. :: none
  • reviewed 2026-07-09T20:18:51.099Z sha e28da8d :: needs maintainer review before merge. :: none

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. 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 priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. labels Jul 9, 2026
@bkudiess bkudiess force-pushed the bkudiess-multi-gateway-credentials branch from 6811204 to 37f1252 Compare July 9, 2026 01:03
@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. and removed 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. labels Jul 9, 2026
@shanselman

Copy link
Copy Markdown
Contributor

Thanks for the very thorough work here. The direction looks valuable: keeping GatewayConnectionManager/GatewayRegistry as the ownership boundary, making active-gateway changes rollback-safe, surfacing credential-resolution state, and guarding stale old-gateway events are all the right instincts for this area.

Before I’d be comfortable merging this, I’d like one focused proof/clarification pass because this PR touches auth/credential precedence and existing-profile upgrade behavior:

  1. Please add or paste one gateway-mediated proof path, not only local winnode MCP. Ideally something like openclaw nodes invoke ... against the current profile, or an equivalent real gateway path that proves the active gateway + node credential path still works after this change.
  2. Please explicitly address the unreadable/corrupt device-token fallback behavior. The current resolver appears to fall back to shared/bootstrap when the stored device token is unreadable/corrupt. That may be acceptable as a pragmatic recovery path, but it sits right next to our guardrail: durable device tokens must not be silently downgraded to shared/bootstrap. If the fallback is intentional, please call out why it is safe and make sure tests cover the exact unreadable/corrupt case; if not intentional, prefer fail-closed for unreadable/corrupt stored device tokens unless the user explicitly chooses repair/re-pair.
  3. If possible, add a quick existing-profile smoke: two gateway records, switch active gateway, restart/reload, confirm ActiveId persists and the expected per-gateway identity directory/token is used.

This is not a broad rejection; it’s a confidence request for a high-blast-radius connection/auth PR. The tests and local proof already look strong. With the gateway-mediated proof plus an explicit decision on the fallback behavior, this should be much easier to take confidently.

Copilot and others added 2 commits July 9, 2026 13:08
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@bkudiess

bkudiess commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks — I addressed the confidence items you called out.

  1. Gateway-mediated proof: I added a real gateway path proof to the PR body. From the OpenClawGateway WSL distro, openclaw nodes list --json showed the paired Windows Node (PERSEID) with system.which, and openclaw nodes invoke --node 'Windows Node (PERSEID)' --command system.which --params '{"bins":["git","node"]}' --json --invoke-timeout 30000 succeeded through the gateway and returned resolved git and node paths.

  2. Corrupt/unreadable fallback behavior: I kept fallback intentionally, but made the rationale explicit in docs and the PR body. The behavior is constrained to same-gateway recovery:

    • a readable device token still always wins;
    • fallback only uses credentials on the same active GatewayRecord;
    • we never read another gateway's identity directory;
    • snapshot/diagnostics surface FallbackUsed with PrimaryStatus=Unreadable or Corrupt, so this is visible repair state rather than silent downgrade.

    I also added coverage for corrupt JSON, valid wrong-shape JSON ([] / null), and unreadable-token fallback.

  3. Existing-profile smoke: I added the current normal-profile smoke to the PR body: active id, one saved gateway, active URL/name, shared token present, bootstrap absent, and the active per-gateway identity directory + device-key-ed25519.json present.

I also reran validation after the follow-ups:

  • ./build.ps1
  • Shared: 2724 passed / 31 skipped
  • Tray: 1616 passed
  • Connection: 422 passed

@shanselman shanselman 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.

Reviewed with >90% confidence after follow-ups. Maintainer accepts the explicit same-gateway unreadable/corrupt identity fallback policy: readable device tokens always win, fallback never crosses gateway records, and FallbackUsed/PrimaryStatus remains visible in diagnostics. Gateway-mediated invoke and existing-profile proof are present. I also merged this PR locally with current main and validated build plus Shared (2724/31 skipped), Tray (1662), and Connection (422) tests.

@shanselman shanselman merged commit 5a18150 into openclaw:main Jul 10, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants