Skip to content

fix(dashboard): Open Dashboard keeps secrets in the wrong part of the URL - #1505

Open
SebTardif wants to merge 10 commits into
openclaw:mainfrom
SebTardif:fix/f075-dashboard-url-join
Open

SebTardif wants to merge 10 commits into
openclaw:mainfrom
SebTardif:fix/f075-dashboard-url-join

Conversation

@SebTardif

@SebTardif SebTardif commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes dashboard routes and credentials landing in the wrong URL component when a saved Gateway address contains a query or fragment.

User Impact

Dashboard links keep routes on the path, remove userinfo and old token query parameters, preserve supported session selection, and place the selected shared token in the fragment. Unsupported saved schemes fail recoverably.

October 1 disposition: NEEDS_HUMAN_TEST, not merged. The author published the session repair at 17def2bb8987cdc7fda5a5db4db6926ecc98f5be, and the required hosted CI Gate is now passing. Real current-head enabled-auth SPA proof established wrong-token refusal, correct-token hello-ok, successful read-only RPCs, token scrubbing and selector retention in the cleaned browser URL. Current native Open Dashboard click proof remains blocked by the supported isolated-launch limitation. The exact selected-session RPC parameter was not captured; it is not inferred from the URL or source tests.

Why This Change Was Made

One existing builder composes components rather than appending routes after queries/fragments. It keeps the first query session, including empty/bare values, ahead of fragment selection; otherwise the first route-fragment selector precedes the saved URL selector. Fragment password, gateway endpoint overrides and unknown fields stay excluded. Current-main view compatibility is retained. A supplied shared token replaces old fragment auth; the existing fragment token is retained only in the compatibility mode appendSharedGatewayToken=true with a null/empty replacement. Current production callers require a nonempty shared token before enabling export.

Current GatewayDashboardLauncher owns native launch and expected error handling; App is its composition root. The modified MCP and saved-row callers use TryBuild. Shared-token-first interactive resolution, device-first operator/node WebSockets, managed/native endpoint authorization, selected endpoint and existing connection owners are unchanged. No legacy credential writes, parallel clients or new auth protocol.

Evidence

Exact revisions and preserved work:

  • Published author head tested: 17def2bb8987cdc7fda5a5db4db6926ecc98f5be, tree fcac637670f8c2ef3a0d77c34785062e06bf728c.
  • Author changes: e684d78d restores the supported session selector and characterization tests; 55c11847 merges main; 17def2bb retains current-main view/token compatibility.
  • Tested head already contains main f4122a8927e7cd452d166a23c0d5e30299f94368.
  • Latest main refreshed after another landing: 28df9c599b88889f70dee6640885e47cdaeafee8. A read-only, conflict-free merge-tree is a90afd41dd8ed1a5ee2abba9e65704e90628b969. Its delta from the tested author head is only seven Local AI artifact-cache/setup files. Dashboard, credential, endpoint authorizer, Connection/Shared and all five exercised Gateway provisioning/cleanup owners are unchanged. No extra integration commit/checkout, blind full rerun or runtime restart was made. This is source applicability, not a claim that the combined tree was built or exercised.
  • Original author head 95a1bfe924e4e89996d1a72938d17262e2ca2c8d, September 28 unpublished integration 5284dc0439d393f493878b89c5c940a69434ed0c and September 30 unpublished integration f2f9fefc8440dbb0f8c806287d093a319bb0d7c4 are preserved. The original dirty three-file repair and exact patch SHA256 51C2B1978BFC0D5CBA10097BC0C70A7F44E92640E433B812F711A12885B9DFE7 remain unchanged. Its builder/test blobs exactly match the author's e684d78d commit. Its uncommitted documentation addition remains retained, not silently discarded.
  • Exact-head validation used one explicitly authorized detached checkout; it was removed after confirming no unique changes or processes. The original dirty session stays open. No agent source commit/push/reset/stash/rebase/workflow mutation or superseding PR.

Current independent source review: one identical-prompt direct pair, actual runtime metadata claude-opus-5.5 and gpt-6-astra, no nested reviewers, fallback models or duplicate panel. Both found no blocking code defect. Opus alone noted two LOW nonblocking hardening cases: empty-token route fallback (unreachable in current production callers), and unusual saved query passwords also being forwarded to route URLs (root forwarding existed already). Neither led to unrelated parser/auth redesign.

Current issue Opus 5.5 GPT-6 Astra Assessment
Original session loss Resolved Resolved Author builder/tests incorporate the verified repair
Empty-token route compatibility fallback LOW Not flagged No current production caller enters that mode
Saved query-password forwarding to route LOW Not flagged Configured-URL hardening note, not a blocking shared-token regression
Blocking source findings None None Runtime evidence boundaries remain separate

Pinned dependency: the body and author source retain openclaw/openclaw@2d2ddc43d0dcf71f31283d780f9fe9ff4cc04fe4, v2026.7.1. SPA startup consumes/scrubs the fragment token and applies query-first session precedence. Browser connect carries auth in the WebSocket envelope. Chat startup selects chat.startup when advertised, with chat.history as fallback. The proof driver's unconditional chat.history assertion was too narrow and is recorded below, not rewritten into a pass.

Preserved historical author/maintainer evidence (not current-head proof)

At original remote 95a1bfe..., September 28 reported build passed, Shared 4,115 passed/32 skipped, Tray 3,160 passed, focused builder 9 passed, and diff check passed. Initial missing test assets were restored before nonzero-count --no-restore reruns.

Historical isolated MCP-only app discovery exposed app.dashboard.url. Saved address ws://127.0.0.1:43179/ui?x=1&to%6ben=old#old-base, route config?tab=one&token=old-route#old-route, returned http://127.0.0.1:43179/ui/config?tab=one&x=1#token=[REDACTED], shared-token source, usesSharedGatewayToken=true, hasTokenQuery=false. Computer Use selected Open Dashboard; Edge's structured URL was http://127.0.0.1:43179/ui?x=1#token=[REDACTED]. The deterministic target returned 404. This established historical native launch and composition, not authentication.

Seb's September 24 c869ed59 comment also recorded eight builder tests and a dev/disposable-profile protocol launch opening /ui/config?x=1#token=[REDACTED]. The protocol omitted the route query; query composition had separate unit/MCP coverage. No usable screenshot was attached.

September 30 local repair validation: build passed; Shared 4,169/33 skipped, Tray 3,388, Connection 1,419/1 skipped, WinNode 129, focused URL 28, combined owner checks 183. Thirty-two exact production-startup controls verified original chat#session=... loss/reset to main and its local correction. The author handoff preserves the full patch.

Historical red run 36448923464 was on 95a1bfe...: post-wizard state-lifecycle restart contention prevented dashboard assertion execution. Historical main 04a880fe... had a different MXC 3232ms cleanup-deadline failure. These are not current blockers: author run 36890718374 now passes its required Gate and executes the dashboard assertion.

Change Type

  • Bug fix
  • Feature
  • Refactor
  • Docs or instructions
  • Tests or validation
  • Security hardening
  • Chore or infrastructure

Scope

  • Tray or WinUI UX
  • Windows node capability
  • Local MCP or winnode
  • Gateway, connection, or pairing
  • Setup or onboarding
  • Permissions, privacy, or security
  • Tests, CI, or docs

Required proof pools

  • windows-winui-interactive: current native Open Dashboard click/error UX and browser handoff still need visible isolated proof. Historical native evidence is retained, not promoted to the new head.
  • windows-wsl-gateway-e2e: real local ownership/credential handoff and enabled-auth packaged SPA path. One scoped headless scenario collected current auth/read evidence and cleaned its owned resources; it is not a native UI proof.

Validation

All October 1 local results are exact author 17def2bb... / tree fcac637..., not the old dirty repair or generated current-main merge tree. OPENCLAW_REPO_ROOT pointed at the detached validation checkout. Task-only tray data and C: NTFS TEMP/TMP were process-local; both competing local-data/root overrides and real E2E enable flags were unset. No user settings, global environment/ACL/default-distro change or shared process kill.

Fresh Shared, Tray, Connection and WinNode test projects each ran dotnet build .\tests\<Project>\<Project>.csproj --source https://packagefeedproxy.microsoft.io/nuget/v3/index.json --verbosity quiet: passed, zero warnings/errors. Tests ran with nonzero counts. Each command below also used a named TRX logger, task-owned <session-files>\validation-oct1 results directory and --verbosity quiet.

Exact command Result
$env:OPENCLAW_REPO_ROOT=(Get-Location).Path; .\build.ps1 Full build/docs passed after diagnosis
dotnet test .\tests\OpenClaw.Shared.Tests\OpenClaw.Shared.Tests.csproj --no-restore -- xUnit.MaxParallelThreads=1 xUnit.ParallelizeTestCollections=false Full suite: 4,224 passed, 0 failed, 33 skipped, total 4,257. Explicit documented collection serialization, no filter/exclusion/assertion changes; shared-serialized-diagnostic-17def2bb.trx
dotnet test .\tests\OpenClaw.Tray.Tests\OpenClaw.Tray.Tests.csproj --no-restore Full default suite: 3,884 passed, 0 failed/skipped; tray-serialized-closeout-17def2bb.trx
dotnet test .\tests\OpenClaw.Connection.Tests\OpenClaw.Connection.Tests.csproj --no-restore Full rerun: 1,476 passed, 0 failed, 1 skipped, total 1,477; connection-rerun-17def2bb.trx
dotnet test .\tests\OpenClaw.WinNode.Cli.Tests\OpenClaw.WinNode.Cli.Tests.csproj --no-restore 129 passed, 0 failed/skipped
dotnet test .\tests\OpenClaw.Tray.Tests\OpenClaw.Tray.Tests.csproj --no-restore --no-build --filter 'FullyQualifiedName~GatewayDashboardUrlBuilderTests|FullyQualifiedName~SetupDashboardHandoffTests|FullyQualifiedName~GatewayDirectConnectServiceTests|FullyQualifiedName~ActivationRouterTests|FullyQualifiedName~AppRefactorContractTests' 256 passed, 0 failed/skipped. Pipes are literal runner OR selectors
& '<session-files>\reproduce-dashboard-session.ps1' -Repository '<exact-author-validation-checkout>' -ExpectPatched 32 controls passed using the actual production builder plus exact pinned SPA startup/normalization; dummy token ingested/scrubbed, requested selector retained
git diff --check / exact candidate diff check Passed; original dirty patch unchanged
dotnet run --no-build --project '<session-files>\wsl-browser-proof-1505\Proof.csproj' --verbosity quiet One scenario, exit 4, not wholly passed. Real negative/positive auth and read RPC evidence collected; driver's obsolete mandatory chat.history assertion failed. Immediate cleanup bind check also failed; later IPv4/IPv6 checks both free, resources fully removed. No second scenario

Local failures retained and diagnosed, not hidden:

  • Initial Tray run on D: ReFS: NativeRestartAdmissionTests.BoundedFailureRetainsProtectedHandleForExplicitReopen failed its protected-file-ACL assertion. Exact case passed with task-owned C: NTFS temp; the entire required subset was rerun, not just the case.
  • Default-parallel Shared runs had an exec-approvals fixture cleanup sharing violation and process-global McpHttpServerTests.Dispose_DuringInFlightHandler_DoesNotSurfaceObjectDisposedException captures of closed FileStream/SafeFileHandle + StreamReader.ReadToEndAsyncInternal tasks. The MCP test has no nonparallel collection annotation and observes global unobserved exceptions during forced GC. Exact focused cases passed, but were not substituted for a full pass. Producer attribution is not established from the stacks. Two direct owned-process BoundedProcessWait diagnostics produced zero unobserved faults, so no speculative attribution to that owner or another OS session. The one final bounded correction used the repository's existing xUnit runner's documented collection setting, then reran full build/Shared/Tray successfully. Default-parallel instability remains recorded; serialized success is labelled explicitly.
  • Initial Connection run: LocalAiApiCredentialStoreTests.ConcurrentCreationConvergesOnOneCredential hit a sharing IOException reading its task-local DPAPI credential. That owner has no PR delta. Focused case passed and the complete Connection rerun passed; required build/Shared/Tray closeout followed. No Local AI/MCP source repair or assertion weakening.
  • One metadata command needed PowerShell quoting for HEAD^{tree}. Corrected read-only command confirmed the tree; no checkout/ref mutation.

Current hosted CI: 36890718374, exact 17def2bb..., success. Required CI Gate passes; Setup/connect, Revocation, Network, Tray/setup/integration and UI tests pass. Core/CLI is classifier-skipped, not credited as a hosted pass. The dashboard assertion did run: source=record.SharedGatewayToken; tokenQuery=False; length=93, static HTTP 200, assertion passed in 387ms. This is current runtime MCP/URL evidence, not SPA browser authentication by itself. No required Gate was bypassed or waived.

Real Behavior Proof

  • Environment tested: one approved headless task-owned WSL Gateway OpenClawE2E-1505, port 31355, pinned CLI 2026.7.1, token auth enabled with allowlisted dummy token, no providers/models. Real packaged SPA in two fresh ephemeral Playwright Chromium contexts (wrong-token control, then correct-token control), never a user's browser profile.
  • PR head or commit tested: 17def2bb8987cdc7fda5a5db4db6926ecc98f5be, tree fcac637670f8c2ef3a0d77c34785062e06bf728c.
  • Exact steps or command run: one scratch harness invokes production CreateWslInstance, ConfigureWslInstance, pinned InstallCli, InstallGatewayService and StartGateway steps; actual managed provenance + InteractiveGatewayCredentialResolver + InteractiveGatewayEndpointAuthorizer + current builder supply the browser URL. Existing supported Playwright launches the real served SPA. No fake bootstrap, auth-disabled server, ad-hoc proxy or native shell launch.
  • Evidence after fix: copied sanitized facts from the original transcript:
{"phase":"real-spa-negative","facts":{"hello":false,"authRefused":true,"connectIdentityPresent":true,"httpTokenRequests":0,"tokenScrubbed":true,"requestedSessionPreserved":true,"successfulReadOperations":[],"actualNativeOpenDashboardClick":false}}
{"phase":"real-spa-positive","facts":{"hello":true,"authRefused":false,"connectTokenMatches":true,"connectIdentityPresent":true,"httpTokenRequests":0,"tokenScrubbed":true,"requestedSessionPreserved":true,"successfulReadOperations":["sessions.subscribe","sessions.messages.subscribe","agent.identity.get","models.authStatus","config.get","sessions.list","chat.startup","chat.metadata"],"actualNativeOpenDashboardClick":false}}
{"phase":"browser-blocked","facts":{"type":"AssertionError","assertionFailed":true}}
  • Observed result: wrong auth was refused; correct selected shared auth reached real hello-ok with browser device identity and successful read-only sessions.list/config.get/startup RPCs. HTTP credential queries stayed absent; the SPA scrubbed the token and retained the requested selector in its cleaned URL. These auth/read controls count independently of the driver's failed assertion. The pinned SPA actually prefers advertised chat.startup, so requiring chat.history was not the product requirement. The original run remains ASSERTFAILED and exit 4; it is not relabelled a wholly passing scenario. Exact selected-session RPC parameters were not retained, so request-level selected-session routing is still unverified. No reprovisioning or scenario rerun.
  • Screenshot or artifact links verified? (Yes/No/N/A): N/A. No new native screenshot/public binary artifact. Sanitized original transcript, immutable source harness, TRX and pinned source controls are retained in session artifacts; the hosted run link above resolves.
  • Not verified or blocked: current native Open Dashboard click/error-UX proof remains blocked because supported Computer Use launch cannot supply per-launch isolation environment. No wrapper/shell launch, global/server/user environment mutation or user Gateway was used to evade it. Real selected-session RPC parameter routing was not captured. Hosted static HTTP 200 is not an auth substitute. No live SSH/remote/native transport proof is newly claimed.

Resource cleanup: product cleanup ran with ConfirmDestructive=false, requiring its durable marker and live canonical registry BasePath checks. It succeeded; task registration and VHD/install path are absent, local marker/temp directories empty, baseline default unchanged. The immediate port bind check failed; later scoped checks found no listener and both IPv4/IPv6 binds succeeded. No PID or shared WSL relay/broker was killed. The inspected exact task root, task NTFS temp and clean detached validation worktree were then removed. The local-wsl-gateway lease is released; no live fixture is inherited.

Security Impact

  • New permissions or capabilities? (Yes/No): No.
  • Secrets or tokens handling changed? (Yes/No): Yes.
  • New or changed network calls? (Yes/No): No new auth protocol or production call.
  • Command or tool execution surface changed? (Yes/No): No new command; existing dashboard URL composition/error behavior changes.
  • Data access scope changed? (Yes/No): No.
  • If any answer is Yes, explain the risk and mitigation: userinfo and token queries are excluded; only the selected shared token replaces fragment auth. Supported session/view fields are retained without arbitrary password/gateway overrides. Export-disabled mode excludes supplied/existing token fragments. Dummy-only proof, no real credential/storage/config content published. Current endpoint authorization and device/bootstrap exclusion are unchanged.

Compatibility and Migration

  • Backward compatible? (Yes/No): Yes for tested root/path/query/session selectors and current-main custodian/view compatibility. Original session loss is repaired in the published head.
  • Config or environment changes? (Yes/No): No persistent user/global changes. Proof fixture was disposable and removed.
  • Migration needed? (Yes/No): No.
  • If yes, list the exact upgrade steps: N/A.

Review Conversations

  • I replied to or resolved every bot review conversation addressed by this PR.
  • I left unresolved only conversations that still need maintainer judgment.

No submitted reviews or inline threads exist. Current ClawSweeper's missing-proof observation is advisory but the remaining native/current-session-request evidence gaps are genuine. Source repair and old CI blockers are closed; no stale red-CI rationale remains. Current blocker: safely isolated current-head native proof, plus narrowly uncaptured session-RPC parameter evidence. Do not merge until the applicable proof gates are resolved.

- Drop userinfo from the opened dashboard URL
- Stop appending the shared token inside an existing fragment
- Keep the route off the query string

Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
@clawsweeper

clawsweeper Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
@shanselman shanselman added the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Sep 24, 2026
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: c998b504-ca22-49c5-8712-15da55226686
@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. 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. labels Sep 24, 2026
@clawsweeper

clawsweeper Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed October 1, 2026, 3:12 PM ET / 19:12 UTC (Revision 16).

ClawSweeper review

What this changes

The PR composes dashboard routes, queries, and fragments separately, removes misplaced credentials, preserves supported session selection, and handles unsupported saved addresses recoverably.

Merge readiness

⛔ Blocked before merge - 2 items remain

Keep open: current main still lacks the complete repair, and no blocking source defect remains in the published head. Updated authenticated Gateway evidence resolves much of the previous proof gap; the latest maintainer disposition still requires native launch and request-level session evidence.

Priority: P2
Reviewed head: 17def2bb8987cdc7fda5a5db4db6926ecc98f5be

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) The repaired patch has good source and validation support, with substantial real Gateway evidence, but the specific native and session-request proof gate remains open.
Proof confidence 🦐 gold shrimp (3/6) Needs stronger real behavior proof before merge: Current-head production credential resolution, endpoint authorization, and URL composition reached a real enabled-auth WSL Gateway SPA, demonstrating wrong-token refusal, correct-token hello-ok, successful reads, and token scrubbing. These observations retain their value despite the driver's failed assertion. The explicitly required current-head native launcher action and actual chat.startup sessionKey remain uncovered; the reviewer isolation limitation is recorded separately from the positive evidence. No stored-data contract changes. 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.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Needs proof Needs stronger real behavior proof before merge: Current-head production credential resolution, endpoint authorization, and URL composition reached a real enabled-auth WSL Gateway SPA, demonstrating wrong-token refusal, correct-token hello-ok, successful reads, and token scrubbing. These observations retain their value despite the driver's failed assertion. The explicitly required current-head native launcher action and actual chat.startup sessionKey remain uncovered; the reviewer isolation limitation is recorded separately from the positive evidence. No stored-data contract changes. 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 10 items Pinned introduced change: Read the complete merge-base-to-head diff across all four files. The introduced changes affect URL composition, two recoverable-error callers, and regression tests; they do not change credential storage, endpoint authorization, dependencies, or workflows.
Still necessary on current main: Current main still preserves token-bearing saved queries, drops saved queries when a route is supplied, and lacks the PR's route-fragment session handling. Its dashboard builder and launcher have no changes between the pinned base and fetched main.
Latest release remains affected: The v2026.9.4 release builder uses string concatenation for the route and chooses fragment-token separators from the resulting string; it does not implement component composition or query-token filtering.
Findings None None.
Security None None.

How this fits together

Windows Companion turns saved Gateway addresses and selected credentials into dashboard links for native browser actions and MCP callers. The Gateway web app then consumes fragment authentication and selects the requested session.

flowchart LR
  A[Saved Gateway address] --> C[Dashboard URL composition]
  B[Authorized shared credential] --> C
  D[Requested route and session] --> C
  C --> E[Native browser or MCP result]
  E --> F[Gateway web app]
  F --> G[Authentication and session selection]
Loading

Before merge

  • Add real behavior proof - Needs stronger real behavior proof before merge: Current-head production credential resolution, endpoint authorization, and URL composition reached a real enabled-auth WSL Gateway SPA, demonstrating wrong-token refusal, correct-token hello-ok, successful reads, and token scrubbing. These observations retain their value despite the driver's failed assertion. The explicitly required current-head native launcher action and actual chat.startup sessionKey remain uncovered; the reviewer isolation limitation is recorded separately from the positive evidence. No stored-data contract changes. 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.
  • Complete next step (P2) - Complete the latest maintainer-requested current-head isolated native Open Dashboard proof and capture sanitized chat.startup sessionKey metadata. Screenshots or a diagnostic recording can show the native action; redacted logs can show the request. Omit tokens, private endpoints, identity files, and unrelated desktop content. Update the PR body to trigger review, or ask a maintainer for @clawsweeper re-review.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production and test LOC production +202/-26, tests +151/-0 Production growth implements component parsing and recoverable errors, with regression coverage for credential filtering and session precedence.

Technical review

Best possible solution:

Keep one dashboard URL composer behind the existing authorized credential and launch owners, with verified native handoff and intended session routing.

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

Yes, from source: saved token queries remain in current-main dashboard links, and supplying a route discards the saved query. This read-only review did not execute a failing runtime reproduction.

Is this the best way to solve the issue?

Yes. Repairing the existing composer and preserving its callers' authorization owners is a focused solution; the earlier session and rejection defects are now addressed.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 28df9c599b88.

Labels

Label changes:

No label changes.

Label justifications:

  • P2: This is a bounded dashboard URL and credential-placement repair with no demonstrated urgent regression remaining in the patch.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: Current-head production credential resolution, endpoint authorization, and URL composition reached a real enabled-auth WSL Gateway SPA, demonstrating wrong-token refusal, correct-token hello-ok, successful reads, and token scrubbing. These observations retain their value despite the driver's failed assertion. The explicitly required current-head native launcher action and actual chat.startup sessionKey remain uncovered; the reviewer isolation limitation is recorded separately from the positive evidence. No stored-data contract changes. 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

What I checked:

  • Pinned introduced change: Read the complete merge-base-to-head diff across all four files. The introduced changes affect URL composition, two recoverable-error callers, and regression tests; they do not change credential storage, endpoint authorization, dependencies, or workflows. (src/OpenClaw.Tray.WinUI/Helpers/GatewayDashboardUrlBuilder.cs:13, 17def2bb8987)
  • Still necessary on current main: Current main still preserves token-bearing saved queries, drops saved queries when a route is supplied, and lacks the PR's route-fragment session handling. Its dashboard builder and launcher have no changes between the pinned base and fetched main. (src/OpenClaw.Tray.WinUI/Helpers/GatewayDashboardUrlBuilder.cs:20, 28df9c599b88)
  • Latest release remains affected: The v2026.9.4 release builder uses string concatenation for the route and chooses fragment-token separators from the resulting string; it does not implement component composition or query-token filtering. (src/OpenClaw.Tray.WinUI/Helpers/GatewayDashboardUrlBuilder.cs:13, 3c43751b2bac)
  • Earlier findings resolved: The published builder retains first-query session precedence, including empty values, then route-fragment selection before saved-fragment selection. Both changed callers use TryBuild, while the existing native launcher catches expected construction failures. Tests cover the previously reported rejection and session-loss defects. (tests/OpenClaw.Tray.Tests/GatewayDashboardUrlBuilderTests.cs:131, 17def2bb8987)
  • Complete proof snapshot inspected: Retrieved the full PR body and verified SHA256 6b5b17573ca5cf2d3fa328b5d92ce64cbf4e8fd03b9cca95a0023839b215626d and 23,144 UTF-16 units against the supplied snapshot. Current-head copied runtime facts show wrong-token refusal, correct-token hello-ok, successful read RPCs, zero HTTP token queries, token scrubbing, and selector retention. The harness's obsolete mandatory chat.history assertion failed; these positive observations remain independently useful. (17def2bb8987)
  • Specific remaining proof disposition: The October 1 collaborator comment confirms the repair and passing CI, but expressly retains NEEDS_HUMAN_TEST for a current-head isolated native Open Dashboard action and sanitized chat.startup session-key metadata. Native launch is historical; the current browser run did not capture the request parameter. fix(dashboard): Open Dashboard keeps secrets in the wrong part of the URL #1505 (comment). (17def2bb8987)

Likely related people:

  • bkudiess: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • shanselman: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • Ranjesh: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Provide current-head isolated native Open Dashboard evidence and sanitized chat.startup sessionKey metadata; retain the existing authentication observations.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
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.

Workflow

  • 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.

History

Review history (15 earlier review cycles; latest 8 shown)
  • reviewed 2026-09-27T15:58:49.901Z sha fa5b142 :: needs maintainer review before merge. :: none
  • reviewed 2026-09-28T16:14:49.300Z sha 95a1bfe :: needs maintainer review before merge. :: none
  • reviewed 2026-09-28T16:57:12.082Z sha 95a1bfe :: needs changes before merge. :: none
  • reviewed 2026-09-28T19:27:32.220Z sha 95a1bfe :: blocked before merge. :: none
  • reviewed 2026-09-30T19:55:25.930Z sha 95a1bfe :: blocked before merge. :: none
  • reviewed 2026-09-30T20:24:57.171Z sha 95a1bfe :: blocked before merge. :: [P1] Preserve the dashboard session selector
  • reviewed 2026-10-01T16:22:31.807Z sha 17def2b :: needs real behavior proof before merge. :: none
  • reviewed 2026-10-01T18:27:21.686Z sha 17def2b :: needs real behavior proof before merge. :: none

@shanselman shanselman removed the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Sep 24, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Sep 24, 2026
@karkarl

karkarl commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator

Global triage: TAKE_AFTER_CHECKS. Take confidence 85%; recommendation confidence 90%; effort extra-small; risk low.

Reviewed exact head 06f243f3ab26. The builder keeps the token in the fragment, strips injected token query/fragment values including percent-encoded keys, prevents cross-host route injection, and preserves route queries. Focused and full Tray tests pass. The four red checks match the repository-wide issue #1498 failure, not this two-file change. One low-reach edge remains: a scheme-less gateway input can produce a wrong host, although stored gateway URLs are normalized and require ://.

Owner: maintainer. Complete the declared browser-launch windows-winui-interactive proof, optionally reject non-absolute inputs defensively, then take after the #1498 CI-gate disposition. This PR is independent of #1503 and #1504.

A scheme-less value such as localhost:18789 parses as an absolute URI
with scheme localhost, and the dashboard builder then opened the wrong
host. Accept only http, https, ws, and wss.

Test: GatewayDashboardUrlBuilderTests 8 passed.
Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
@SebTardif

Copy link
Copy Markdown
Contributor Author

The scheme-less edge is closed on c869ed59. localhost:18789/ui parsed as a URI whose scheme was localhost, so the builder could open the wrong host. It now accepts only http, https, ws, and wss. GatewayDashboardUrlBuilderTests is 8 passed, including Build_RejectsSchemeLessGatewayInput.

Browser launch on that head: dev-identity Debug tray, disposable profile, dummy shared token, then openclaw-dev://dashboard/config with a route query. Microsoft Edge opened. The live address bar read http://127.0.0.1:43179/ui/config?x=1#token=[REDACTED]. The route is on the path, the saved gateway query x=1 remains, and the old token query and fragment are absent. The shared token is only in the fragment. A screen copy of that window was not usable, so it is not attached.

The protocol delivered the path config and did not include the route query tab=one. That join is covered by the unit test and by the earlier app.dashboard.url call on 06f243f3.

The three red setup E2E jobs on 06f243f3 match #1498. If this head fails the same way, I will not send an empty commit.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. labels Sep 24, 2026
@shanselman shanselman added status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. and removed status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. labels Sep 25, 2026
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. label Sep 25, 2026
@shanselman shanselman added the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Sep 25, 2026
Preserve SebTardif's dashboard commits while integrating the latest setup and migration fixes from main.

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

Copilot-Session: c998b504-ca22-49c5-8712-15da55226686
@clawsweeper clawsweeper Bot removed the merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. label Sep 25, 2026
@shanselman shanselman removed the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Sep 25, 2026
A nonempty unsupported address still passes credential resolution, then the dashboard builder throws. Open Dashboard, the saved-row dashboard action, and the app-capability handler now catch that rejection. The tray opens Connection settings or shows the error. The capability caller returns the error instead of throwing.

./build.ps1 exit 0. Shared tests: 4107 passed, 32 skipped. Tray tests: 3121 passed, 0 failed. GatewayDashboardUrlBuilderTests: 9 passed.

Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
@clawsweeper clawsweeper Bot removed the merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. label Sep 27, 2026
@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 status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Sep 27, 2026
@shanselman shanselman added the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Sep 28, 2026
@shanselman

Copy link
Copy Markdown
Collaborator

@clawsweeper re-review

@shanselman shanselman removed the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Sep 28, 2026
@clawsweeper

clawsweeper Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@shanselman shanselman added status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. and removed status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. labels Sep 28, 2026
@shanselman

Copy link
Copy Markdown
Collaborator

@SebTardif: the current-main review found one bounded compatibility regression in the original patch. Build("ws://localhost:18789", "chat#session=agent%3Amain%3Areview", "test-auth-token", true) drops the supported session selector. The exact pinned v2026.7.1 SPA startup function then selects main; the previous builder and query-form positive control select agent:main:review.

Per maintainer direction, I prepared the small repair below locally only, on unpublished normal integration f2f9fefc8440dbb0f8c806287d093a319bb0d7c4 with current main 04a880fe9488dbbd68ef786c1ebdc03c240c26c6. Your remote head 95a1bfe924e4e89996d1a72938d17262e2ca2c8d and the retained September 28 integration 5284dc0439d393f493878b89c5c940a69434ed0c remain intact. There is no repair commit, push, reset, rebase, workflow edit or superseding PR.

The repair only allowlists the existing fragment session selector. It preserves first-query precedence, including empty/bare values, then first route-fragment selection ahead of the saved URL's selector. Encoded values remain encoded. Old authentication, password, endpoint overrides and unknown fragment content stay removed. Query behavior and credential/authorization owners are unchanged.

Please apply the bounded repair/tests in your author-owned update. The original builder and test file are identical between your remote head and the local integration; the documentation addition targets the current connection architecture. Patch SHA256: 51C2B1978BFC0D5CBA10097BC0C70A7F44E92640E433B812F711A12885B9DFE7. git apply --reverse --check passes against the tested working tree.

Patched local validation: full build passed; Shared 4,169 passed/33 skipped; Tray 3,388 passed; full Connection 1,419 passed/1 skipped; full WinNode CLI 129 passed; focused URL tests 28 passed; combined caller/owner characterization 183 passed. The production builder plus exact pinned SPA startup/normalization passed 32 controls, retaining the requested session and ingesting/scrubbing only the dummy token.

Review: actual runtime models claude-opus-5.5 and gpt-6-astra, identical prompts, one direct reviewer each with no nesting. Astra alone initially flagged MEDIUM session loss; it was independently executed and verified. Both bounded fix reviews found no remaining actionable defect. No security vulnerability was found in the separate initial direct security review.

Not merge-ready: local source-chain proof is not a native Open Dashboard click or successful real Gateway/browser authentication. Supported native launch lacks the isolation environment; no workaround or user Gateway was used. Your required hosted Setup/connect, Revocation and CI Gate remain red. Current-main E2E is green but its different Shared MXC cleanup-deadline failure is not a waiver. The PR body now retains the full template, historical author proof, exact revision provenance and current blockers. A new author head needs fresh required CI and behavior proof.

Applyable working-tree repair, three files (+104/-2)
diff --git a/docs/CONNECTION_ARCHITECTURE.md b/docs/CONNECTION_ARCHITECTURE.md
index 2d94f6aa..6dffaa93 100644
--- a/docs/CONNECTION_ARCHITECTURE.md
+++ b/docs/CONNECTION_ARCHITECTURE.md
@@ -211,6 +211,12 @@ Node credential precedence follows the same invariant with a distinct stored tok
 
 **`InteractiveGatewayCredentialResolver`** resolves credentials for HTTP surfaces (chat URL `?token=` auth). It **prefers SharedGatewayToken** over DeviceToken because HTTP endpoints expect the shared token, not the per-device WebSocket token. Browser proxy diagnostics should treat the missing shared token as a browser-control caveat, not as proof that the operator or node gateway connection is disconnected.
 
+Dashboard links put only the selected shared token in `#token` and preserve the
+SPA's supported `session` selector. The first query selector takes precedence,
+including an empty value; otherwise the first route-fragment selector wins over
+the saved URL's selector. Other fragment parameters, including old authentication
+and endpoint overrides, are discarded.
+
 The legacy web-chat readiness probe bypasses the process proxy only for loopback
 URLs; remote HTTPS gateways retain proxy support. It accepts the original
 200-399 response without following redirects, so a readiness check never
diff --git a/src/OpenClaw.Tray.WinUI/Helpers/GatewayDashboardUrlBuilder.cs b/src/OpenClaw.Tray.WinUI/Helpers/GatewayDashboardUrlBuilder.cs
index d782dfef..5672e458 100644
--- a/src/OpenClaw.Tray.WinUI/Helpers/GatewayDashboardUrlBuilder.cs
+++ b/src/OpenClaw.Tray.WinUI/Helpers/GatewayDashboardUrlBuilder.cs
@@ -18,6 +18,7 @@ public static class GatewayDashboardUrlBuilder
 
         var route = path?.Trim() ?? string.Empty;
         var fragmentStart = route.IndexOf('#');
+        var routeFragment = fragmentStart >= 0 ? route[fragmentStart..] : string.Empty;
         if (fragmentStart >= 0)
             route = route[..fragmentStart];
 
@@ -32,10 +33,17 @@ public static class GatewayDashboardUrlBuilder
         var scheme = ToHttpScheme(uri.Scheme);
         var url = $"{scheme}://{FormatHost(uri)}{FormatPort(scheme, uri.Port)}{JoinPath(uri.AbsolutePath, routePath)}{query}";
 
+        // The SPA prefers the first query session, even when empty, over a fragment session.
+        var session = FindSessionParameter(query) is null
+            ? FindSessionParameter(routeFragment) ?? FindSessionParameter(uri.Fragment)
+            : null;
+        var fragment = new List<string>();
+        if (session is not null)
+            fragment.Add(session);
         if (appendSharedGatewayToken && !string.IsNullOrEmpty(sharedGatewayToken))
-            url += $"#token={Uri.EscapeDataString(sharedGatewayToken)}";
+            fragment.Add($"token={Uri.EscapeDataString(sharedGatewayToken)}");
 
-        return url;
+        return fragment.Count == 0 ? url : $"{url}#{string.Join('&', fragment)}";
     }
 
     public static bool TryBuild(
@@ -66,6 +74,23 @@ public static class GatewayDashboardUrlBuilder
         scheme.Equals("ws", StringComparison.OrdinalIgnoreCase) ||
         scheme.Equals("wss", StringComparison.OrdinalIgnoreCase);
 
+    private static string? FindSessionParameter(string parameters)
+    {
+        if (string.IsNullOrEmpty(parameters))
+            return null;
+
+        var body = parameters[0] is '?' or '#' ? parameters[1..] : parameters;
+        foreach (var part in body.Split('&', StringSplitOptions.RemoveEmptyEntries))
+        {
+            var nameEnd = part.IndexOf('=');
+            var name = nameEnd >= 0 ? part[..nameEnd] : part;
+            if (Uri.UnescapeDataString(name).Equals("session", StringComparison.Ordinal))
+                return nameEnd >= 0 ? $"session{part[nameEnd..]}" : "session=";
+        }
+
+        return null;
+    }
+
     private static string ToHttpScheme(string scheme)
     {
         if (scheme.Equals("wss", StringComparison.OrdinalIgnoreCase) ||
diff --git a/tests/OpenClaw.Tray.Tests/GatewayDashboardUrlBuilderTests.cs b/tests/OpenClaw.Tray.Tests/GatewayDashboardUrlBuilderTests.cs
index d68109eb..25c3d412 100644
--- a/tests/OpenClaw.Tray.Tests/GatewayDashboardUrlBuilderTests.cs
+++ b/tests/OpenClaw.Tray.Tests/GatewayDashboardUrlBuilderTests.cs
@@ -107,4 +107,75 @@ public sealed class GatewayDashboardUrlBuilderTests
 
         Assert.Equal("http://localhost:4317/ui/config?tab=one&x=1", url);
     }
+
+    [Theory]
+    [InlineData("ws://gateway.example", "chat#session=agent%3Amain%3Areview", "http://gateway.example/chat#session=agent%3Amain%3Areview")]
+    [InlineData("ws://gateway.example#session=agent%3Amain%3Areview", null, "http://gateway.example#session=agent%3Amain%3Areview")]
+    [InlineData("ws://gateway.example#session=base", "chat#ses%73ion=route%26one%2Btwo+three", "http://gateway.example/chat#session=route%26one%2Btwo+three")]
+    [InlineData("ws://gateway.example#session=base", "chat#session=first&session=second", "http://gateway.example/chat#session=first")]
+    [InlineData("ws://gateway.example#session=base", "chat#session=&session=second", "http://gateway.example/chat#session=")]
+    [InlineData("ws://gateway.example#session=base", "chat#session", "http://gateway.example/chat#session=")]
+    public void Build_PreservesOnlyTheFirstFragmentSession(
+        string gatewayUrl, string? path, string expected)
+    {
+        Assert.Equal(expected, GatewayDashboardUrlBuilder.Build(
+            gatewayUrl, path, "test-auth-token", appendSharedGatewayToken: false));
+        Assert.Equal(expected + "&token=test-auth-token", GatewayDashboardUrlBuilder.Build(
+            gatewayUrl, path, "test-auth-token", appendSharedGatewayToken: true));
+    }
+
+    [Theory]
+    [InlineData("ws://gateway.example", "chat?session=query#session=fragment", "http://gateway.example/chat?session=query")]
+    [InlineData("ws://gateway.example?session=base-query", "chat#session=fragment", "http://gateway.example/chat?session=base-query")]
+    [InlineData("ws://gateway.example?session=base-query", "chat?session=route-query#session=fragment", "http://gateway.example/chat?session=route-query&session=base-query")]
+    [InlineData("ws://gateway.example", "chat?ses%73ion=encoded%3Aquery#session=fragment", "http://gateway.example/chat?ses%73ion=encoded%3Aquery")]
+    [InlineData("ws://gateway.example", "chat?session=&session=second#session=fragment", "http://gateway.example/chat?session=&session=second")]
+    [InlineData("ws://gateway.example", "chat?session#session=fragment", "http://gateway.example/chat?session")]
+    public void Build_PreservesQuerySessionPrecedenceIncludingEmptySelection(
+        string gatewayUrl, string path, string expected)
+    {
+        Assert.Equal(expected, GatewayDashboardUrlBuilder.Build(
+            gatewayUrl, path, "test-auth-token", appendSharedGatewayToken: false));
+        Assert.Equal(expected + "#token=test-auth-token", GatewayDashboardUrlBuilder.Build(
+            gatewayUrl, path, "test-auth-token", appendSharedGatewayToken: true));
+    }
+
+    [Theory]
+    [InlineData(false)]
+    [InlineData(true)]
+    public void Build_SessionAllowlistDoesNotRestoreFragmentAuthOrEndpointOverrides(bool appendToken)
+    {
+        var url = GatewayDashboardUrlBuilder.Build(
+            "ws://gateway.example?token=old&x=1#gatewayUrl=wss%3A%2F%2Fother.example&password=old&token=old&session=base",
+            "chat?to%6ben=old-route#token=old-route&session=agent%3Amain%3Areview&token=duplicate&gatewayUrl=wss%3A%2F%2Fother.example&password=old-route",
+            "test-auth-token",
+            appendToken);
+
+        Assert.Equal(
+            "http://gateway.example/chat?x=1#session=agent%3Amain%3Areview" +
+            (appendToken ? "&token=test-auth-token" : string.Empty),
+            url);
+    }
+
+    [Theory]
+    [InlineData(null)]
+    [InlineData("")]
+    public void Build_PreservesSessionWithoutAnAvailableSharedToken(string? sharedToken)
+    {
+        Assert.Equal("http://gateway.example/chat#session=agent%3Amain%3Areview",
+            GatewayDashboardUrlBuilder.Build(
+                "ws://gateway.example", "chat#session=agent%3Amain%3Areview",
+                sharedToken, appendSharedGatewayToken: true));
+    }
+
+    [Theory]
+    [InlineData("chat#old")]
+    [InlineData("chat#SESSION=ignored")]
+    [InlineData("chat#token=old&password=old&gatewayUrl=wss%3A%2F%2Fother.example")]
+    public void Build_DoesNotInventMissingSessionSelection(string path)
+    {
+        Assert.Equal("http://gateway.example/chat#token=test-auth-token",
+            GatewayDashboardUrlBuilder.Build(
+                "ws://gateway.example", path, "test-auth-token", appendSharedGatewayToken: true));
+    }
 }

@shanselman shanselman added status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. labels Sep 30, 2026
@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. 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 Sep 30, 2026
A route or saved fragment session such as agent:main:review was dropped when the shared token was written into the hash. Keep the first query session, including an empty value, otherwise the first route-fragment session, ahead of the saved URL. Other fragment parameters stay removed.

Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
Keep the session-selector builder. Open Dashboard uses main's GatewayDashboardLauncher, which calls that builder.

Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
Session selection stays the supported selector. A non-secret view parameter stays in the fragment, and an existing fragment token stays when no replacement token is supplied. Password, gatewayUrl, and other fragment content stay out.

Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
@clawsweeper clawsweeper Bot added status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. proof: sufficient Contributor real behavior proof is sufficient. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Oct 1, 2026
@shanselman shanselman added the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Oct 1, 2026
@shanselman

Copy link
Copy Markdown
Collaborator

@SebTardif: the published session repair at 17def2bb is verified, both current Opus 5.5/Astra reviews found no blocking source defect, and the required CI Gate is passing. The body now records exact-head validation and current enabled-auth real-SPA evidence, preserving the older proof as historical.

The one owned runtime attempt demonstrated wrong-token refusal, correct-token hello-ok, successful read-only sessions.list/config.get and chat.startup RPCs, zero HTTP credential queries, token scrubbing and selector retention in the cleaned browser URL. The driver incorrectly required chat.history; its ASSERTFAILED/exit 4 is preserved, not relabelled a fully passing scenario. No second attempt. All task Gateway/distro/VHD/port/profile resources were cleaned and the default distro was unchanged.

Remaining proof is specific: a current-head native Open Dashboard click from an isolated Companion profile, and metadata showing the actual chat.startup request selects the intended session key. That parameter was not captured in this attempt, so source controls and the browser URL are not promoted to request-routing proof. A developer can use the supported . un-app-local.ps1 -Dev -Isolated on the exact 17def2bb checkout, with an explicitly owned enabled-auth test Gateway and fresh browser context, then capture the native action/resulting cleaned URL plus sanitized hello-ok and chat.startup session-key metadata. Do not share tokens, raw auth frames, identity/config files or unrelated desktop content. The agent cannot supply the required per-launch isolation environment through supported Computer Use and did not use a shell/wrapper/global-environment workaround.

Disposition remains NEEDS_HUMAN_TEST, not a stale source/CI blocker. No merge, agent source push or superseding PR. The retained dirty maintainer repair is still intact.

@shanselman shanselman removed the status: 🚢 actively landing A maintainer or agent is actively driving this item through implementation, validation, or merge. label Oct 1, 2026
@SebTardif

Copy link
Copy Markdown
Contributor Author

Native Open Dashboard click on 17def2bb8987cdc7fda5a5db4db6926ecc98f5be.

Launch was .\run-app-local.ps1 -NoBuild -Dev -Isolated -AllowNonMain from that checkout. The data directory was a new temp tray profile. The gateway was a disposable loopback OpenClaw 2026.9.6 with token auth. It is not the pinned 2026.7.1 SPA, and it is not a user gateway. The pairing request was approved.

The click was the Connection page Dashboard button.

The address bar first showed 127.0.0.1:31356/chat#session=agent%3Amain%3Areview with no token parameter. A second click, with the saved selector changed to agent:dev:proofcheck, first showed 127.0.0.1:31356/chat#session=agent%3Adev%3Aproofcheck, again with no token. Both loads then settled on 127.0.0.1:31356/chat/dev.

chat.startup sessionKey was agent:dev:main for both loads. On this 2026.9.6 dev profile the fragment selector was kept in the cleaned URL, and the startup RPC used the profile default session rather than that fragment value.

This branch has not been deployed

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

Labels

P2 Normal priority bug or improvement with limited blast radius. 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants