Conversation
Open Dashboard marked the tunnel up as soon as ssh.exe started, then put the shared token in the browser URL. Wait for the same listener ownership check StartOwnedAsync uses, and do not build that URL when the wait fails. - Add EnsureSettingsOwnedForwardReadyAsync for the settings-owned forward - Stop the forward and show the existing tunnel toast when ownership fails - Leave direct dashboard opens unchanged when SSH is off Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs real behavior proof before merge. Reviewed September 24, 2026, 2:16 PM ET / 18:16 UTC. ClawSweeper reviewWhat this changesThe branch makes Open Dashboard wait for an SSH forward owned by the app before opening a token-bearing browser URL, and adds connection and tray contract tests. Merge readiness⛔ Blocked before merge - 6 items remain The dashboard race is present on current main, so this PR remains useful. Review found a concurrent tunnel-state regression, and the claimed token protection still needs proof at the browser handoff. Priority: P1 Review scores
Verification
How this fits togetherThe tray opens a Gateway dashboard using connection settings and a resolved credential. When SSH forwarding is enabled, the connection service starts a local forward; the tray then builds a URL and hands it to the browser. flowchart LR
A[Open Dashboard action] --> B[Connection settings]
B --> C{SSH enabled?}
C -->|Yes| D[Local SSH forward]
D --> E[Listener ownership check]
C -->|No| F[Credential and URL]
E --> F
F --> G[Browser launch]
Before merge
Findings
Agent review detailsSecurityNeeds attention: The startup check improves token safety, but ownership at the final browser launch remains unproven. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Keep the dashboard credential handoff tied to the verified tunnel generation through browser launch, preserve a newer tunnel's state when an older wait fails, and show a redacted Windows run covering both an owned forward and a foreign listener. Do we have a high-confidence way to reproduce the issue? Yes for the current-main defect: Open Dashboard builds its URL immediately after starting SSH, while listener ownership is checked later. The introduced concurrent-state defect is clear from the catch path; no live run was performed in this read-only review. Is this the best way to solve the issue? No, not yet. Waiting for an owned listener addresses startup ordering, but the shared state must remain generation-safe and the final browser handoff needs proof. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 273b0182745a. LabelsLabel changes:
Label justifications:
EvidenceSecurity concerns:
What I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
|
|
Global triage: HOLD_FOR_AUTHOR. Take confidence 10%; recommendation confidence 97%; effort medium; risk high. Two handoff races block this exact head:
Please carry a generation-bound ownership lease through browser launch, prevent replacement during that handoff, and guard failure-state updates by the captured process/generation. Add overlapping-attempt and replacement-before-launch regressions. Run The E2E setup refusals appear shared/baseline; the UI lane timed out and remains unresolved. CI Gate is derivative, so the required current-head proof is not green. |
What Problem This Solves
Fixes: Open Dashboard can put the shared gateway token in the browser URL before the SSH forward owns the local port.
User Impact
User impact: the browser opens only after this app's ssh process owns the forward. If another process already has the port, the token is not sent.
Why This Change Was Made
The dashboard path now rejects an occupied forward port and waits with the same owned-listener check
StartOwnedAsyncuses. A failed wait shows the existing SSH tunnel toast and returns before the URL is built. SSH off still opens the dashboard directly. OtherEnsureStartedcallers are unchanged.Evidence
Terminal output from the connection and tray contract runs on this branch.
The occupied-port case returns false and does not report the forward as owned. The source contract requires
OpenDashboardAsyncto awaitEnsureDashboardSshForwardOwnedAsyncbeforeGatewayDashboardUrlBuilder.Build.Change Type
Scope
winnodeRequired proof pools
windows-winui-interactive: the dashboard open path changed. Not verified / blocked: the tray was not launched and no browser was opened.Validation
dotnet test ./tests/OpenClaw.Connection.Tests/OpenClaw.Connection.Tests.csproj --filter FullyQualifiedName~EnsureSettingsOwnedForwardReadyAsync: Passed 2, Failed 0.dotnet test ./tests/OpenClaw.Tray.Tests/OpenClaw.Tray.Tests.csproj --filter "FullyQualifiedName~Dashboard_SurfacesSshTunnelConfigurationFailure|FullyQualifiedName~Dashboard_AwaitsSettingsOwnedForwardBeforeTokenUrl": Passed 2, Failed 0.dotnet build src/OpenClaw.Tray.WinUI/OpenClaw.Tray.WinUI.csproj -p:Platform=x64ondc29fbb4succeeded. One existing Win2D warning../build.ps1was not run.Real Behavior Proof
dotnet test ./tests/OpenClaw.Connection.Tests/OpenClaw.Connection.Tests.csproj --filter FullyQualifiedName~EnsureSettingsOwnedForwardReadyAsyncSecurity Impact
NoYesNoNoNoYes, explain the risk and mitigation: The shared token is appended to the dashboard URL only after the settings-owned ssh process owns the local forward. A failed wait stops the process and skips the URL.Compatibility and Migration
YesNoNoReview Conversations