Repository navigation
Conversation
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 October 7, 2026, 12:38 PM ET / 16:38 UTC (Revision 18). ClawSweeper reviewWhat this changesThe branch removes leftover gateway credentials during uninstall and prevents unsaved default gateway URLs from acquiring legacy credentials during startup, chat, settings saves, or rollback. Merge readiness⛔ Blocked before merge - 4 items remain The fix remains necessary and the earlier rollback defect is repaired. No new correctness defect was found, but production credential-boundary proof and the required signed-installer lifecycle evidence remain incomplete. Priority: P2 Review scores
Verification
How this fits togetherCompanion loads saved gateway settings and device identities to connect its operator, node, and chat surfaces. Uninstall cleanup and settings rollback determine whether those credentials remain associated with an explicitly selected gateway. flowchart TD
A[Uninstall or settings rollback] --> B[Saved gateway settings]
B --> C[Explicit gateway target?]
D[Gateway registry and device identity] --> C
C -->|Configured| E[Credential resolution]
E --> F[Operator node and chat connections]
C -->|Unconfigured| G[Setup or Connection guidance]
Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Keep credentials bound only to explicit gateway targets, preserve unrelated existing state, and demonstrate both guarantees through the production consumer and signed installer lifecycle. Do we have a high-confidence way to reproduce the issue? Yes, source establishes the existing defect: current main removes the saved URL during uninstall while retaining legacy token fields. This review did not execute a current-main reproduction. Is this the best way to solve the issue? Yes, removing orphaned credentials and preserving explicit-target provenance is a focused repair consistent with the recorded maintainer decision; its remaining limitation is production and upgrade proof. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 5e3fb40bcc89. LabelsLabel changes: No label changes. Label justifications:
EvidenceWhat 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
HistoryReview history (17 earlier review cycles; latest 8 shown)
|
|
Global triage: NEEDS_HUMAN_TEST. Take confidence 55%; recommendation confidence 85%; effort small; risk high. Reviewed exact head |
Uninstall drops gateway tokens even when node settings are preserved. Credential resolution for App and Chat now has a test for that cleared state, and the duplicate guard is gone where SettingsManager already enforces it. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a4fbf4c9-96de-4b6d-98bd-aa82320241a6
Remove legacy gateway fields in the production PowerShell reset independently of preserved node settings. Exercise only its real JSON/logging helpers under Windows PowerShell 5.1 with isolated fixtures, including leftover-token, clean-state, and write-failure cases. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a4fbf4c9-96de-4b6d-98bd-aa82320241a6
Keep three distinct fake token values and the same runtime assertions while avoiding review-bundle secret-scanner false positives. No production behavior or review policy changes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a4fbf4c9-96de-4b6d-98bd-aa82320241a6
|
@shanselman This pull stops loading a saved token when GatewayUrl is missing. The review on
Which one do you want? |
|
Maintainer decision: choose 2, fail closed and reconnect explicitly. A token left behind with no I am taking the original branch through current-main integration and validation. I will also verify the separate retained device-identity path cannot authorize an unintended default-port listener, and determine the strongest installer uninstall/upgrade proof this host can provide. |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9ba54a2d-477b-4b8e-994c-5fb3755d8b01
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9ba54a2d-477b-4b8e-994c-5fb3755d8b01
|
@clawsweeper re-review |
|
🦞👀 I queued a lightweight read-only assist pass. It will post a separate answer comment and will not edit the durable ClawSweeper review comment or trigger close, merge, repair, label, or branch changes. Request: re-review |
|
@clawsweeper re-review Exact-head proof is now in the PR body. The two unrelated failed CI jobs are rerunning. |
|
🦞👀 Re-review progress:
|
|
ClawSweeper assist: The proof update is documented for head Evidence:
Suggested next action: Check the rerun results and request the full current-head review with Source: #1481 (comment) |
|
CI reconciliation update: Core and CLI passed on rerun. Network recovery failed a second time before either test executed, again during shared setup fixture initialization with StateDatabaseCoordinatorContentionError and GATEWAY_RESTART_PREPARATION_REFUSED. This is unrelated to the uninstall/credential diff, but required CI remains red. I am pausing active landing rather than overriding the signed-current-artifact proof and branch-protection gates. |
…r-gateway-tokens Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca> # Conflicts: # src/OpenClaw.Tray.WinUI/Pages/ChatPage.xaml.cs
…meout ConnectNodeOnlyAsync gives the previous node disconnect two seconds. The test waited only three, so a busy runner timed out before the disconnect budget elapsed. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
A failed settings save restored the settings record but left the explicit-target flag set, so the setup default looked like a saved gateway. Direct-connect rollback snapshotted that same fallback and could write it back. Both paths now keep an unsaved profile unsaved, while a gateway the user already saved still restores. The credential resolver returns no endpoint after either rollback, so no credential-bearing request is built for the setup port. A saved gateway still resolves. Validation: build.ps1 succeeded. Shared tests passed 4263, skipped 33. Tray tests passed 4016. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
A loopback listener accepted one TCP chat request for an explicitly saved gateway. The request line was GET /chat with a token query. After a failed save and a failed direct connect from a URL-less profile, this process had no TCP connection to the setup port. build.ps1 succeeded. Shared tests passed 4263, skipped 33. Tray tests passed 4017. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
What Problem This Solves
Uninstall deleted
GatewayUrlbut left legacyTokenandBootstrapToken. The next launch fell back tows://127.0.0.1:18789and could import those secrets into a new record.Why
A token without a persisted gateway URL is uninstall residue, not a safely attributable credential. Binding it to the default local URL could expose it to the next listener on that port.
User Impact
Uninstall removes
TokenandBootstrapTokenwithGatewayUrl. URL-less legacy credentials and root identity are not bound to the default URL. The user reconnects explicitly with a fresh setup code or supplied URL and token. An explicitly saved URL and active registry credentials retain their compatibility paths.Evidence
The original contributor commits remain intact. Current
mainwas merged normally, then the bounded maintainer repair closed two lifecycle bypasses found by rubber-duck review: settings save no longer repersists the in-memory default URL, and operator/node startup backfill no longer binds root identity without an explicitly persisted target. No force push was used.origin/mainat94006b3672a034983e80a78dafe311e24ba80cceconflicted inChatPage.xaml.cs. The merge keeps main's credential parameter flow and still passesGetLegacyCredentialGatewayUrlOrNull()into chat resolution, so a URL-less legacy token is not attached to the default gateway URL. No force push was used.Merge head:
3286b88b66ecc770aed57bdfd8fb35f6da721955. Test-wait head:285346ac3fece4a95547f7fc8d284506c021a7d4. Rollback head:999a05c9048dabe670e958e05c803c23a13e8c2a. Final head:632aae785f9cedfd659be2453693192073388083. The test-wait commit only widens one connection test wait.999a05c9keeps an unsaved gateway target unsaved when a settings save or a direct connect rolls back.632aae78records the socket check for that behavior. The earlier installer and app proof below was captured on29c83ff9ca877b39bb7507dea1a0e7b105f6a5c5, except for the rollback checks, the socket check, and the signed alpha matrix recorded later.ConnectNodeOnlyAsync_StalledRetirementDoesNotBlockManagerDisconnecttimed out once on3286b88bbecause the test waited 3 seconds while the coordinator allows the previous node disconnect 2 seconds. The test now waits 10 seconds. It passed locally in 3 seconds.Required proof pools
windows-clean-installer-upgrade: Partially verified, signed-current-artifact blocked. The exact head built a 146.36 MB x64 Inno candidate on a clean Azure Windows host, installed over the previous release, and installed the current uninstall helper plus migration checker. The current candidate is locally built and unsigned, so it cannot satisfy the exact signed-current-artifact requirement. PublishedOpenClawCompanion-Setup-x64.exefromv2026.9.5-alpha.61andv2026.9.5-alpha.97are AuthenticodeValidand signed byCN=OpenClaw Foundation. They are not a signed build of this head. The Server 2022 host also cannot complete the destructive cleanup path: AppX registration discovery returns unknown and itswsl.exeis a non-functional stub. Both conditions correctly activate existing fail-closed state preservation. No product guard was weakened to make the proof pass.node-mcp-live: isolated current-head app/MCP proof passed locally for the credential boundary.Validation
Native Windows validation at head
632aae785f9cedfd659be2453693192073388083:.\build.ps1dotnet test .\tests\OpenClaw.Shared.Tests\OpenClaw.Shared.Tests.csproj --no-restoredotnet test .\tests\OpenClaw.Tray.Tests\OpenClaw.Tray.Tests.csproj --no-restoreNative Windows validation after the main merge, head
3286b88b66ecc770aed57bdfd8fb35f6da721955:.\build.ps1dotnet test .\tests\OpenClaw.Shared.Tests\OpenClaw.Shared.Tests.csproj --no-restoredotnet test .\tests\OpenClaw.Tray.Tests\OpenClaw.Tray.Tests.csproj --no-restoreConnection and SetupEngine suites were not rerun on this merge head.
Native Windows validation at the previous head
29c83ff9:.\build.ps1dotnet test .\tests\OpenClaw.Shared.Tests\OpenClaw.Shared.Tests.csproj --no-restoredotnet test .\tests\OpenClaw.Tray.Tests\OpenClaw.Tray.Tests.csproj --no-restoredotnet test .\tests\OpenClaw.Connection.Tests\OpenClaw.Connection.Tests.csproj --no-restoredotnet test .\tests\OpenClaw.SetupEngine.Tests\OpenClaw.SetupEngine.Tests.csproj --no-restoreFocused uninstall, settings lifecycle, credential resolver, startup/chat contract, and installer assertions also passed. The production PowerShell reset helper ran under Windows PowerShell 5.1 in isolated directories for both
PreserveNodeSettingsmodes, including atomic-write failure handling and repeat-call stability.Rubber-duck review initially found two blocking lifecycle gaps; both were fixed and re-review found no remaining blockers. Autoreview did not invoke its model because its scanner rejected removed pre-existing synthetic credential literals before review. Canonical dummy fixtures were used for new tests; the scanner limitation is not a code-review finding.
Real behavior proof
Local isolated app and MCP
Current-head isolated runtime proof showed:
GatewayUrl,Token, andBootstrapTokenabsent;This directly verifies that a URL-less retained identity cannot authorize the default-port listener through the app's final credential-selection boundary.
Crabbox clean Windows proof
azurewindows, modenormalcbx_24ba59036876(silver-barnacle,Standard_D16ads_v6)29c83ff9ca877b39bb7507dea1a0e7b105f6a5c5run_c289cae9bc9e(portal=-,logs=-)run_01436fd1a997(portal=-,logs=-)run_89013bd17492(portal=-,logs=-)Observed results:
Uninstall-LocalGateway.ps1token-removal logic andTest-InnoMigration.ps1.2because Server 2022 could not read Store registration. Inno correctly preserved gateway state rather than performing an unsafe destructive cleanup.wsl.exereturned usage text for list, terminate, and unregister. The helper correctly failed closed instead of claiming cleanup.29c83ff9is not a GitHub release asset.OpenClawCompanion-Setup-x64.exeassets do exist.v2026.9.5-alpha.61(128,224,112 bytes) andv2026.9.5-alpha.97(128,706,568 bytes) both returned Authenticode statusValid, subjectCN=OpenClaw Foundation, O=OpenClaw Foundation, L=Mill Valley, S=California, C=US. Those files are not a signed build of head632aae78. Launching the newer exe with/?opened the installer GUI, which was stopped before it installed anything. The upgrade, launch, repair, and uninstall of those two files was run later on this PC. See Signed installer upgrade and uninstall on this PC. That published uninstall left the seeded token keys.These remote limitations are explicit proof blockers, not successful cleanup claims. The changed token-removal function itself is covered by the passing Windows PowerShell 5.1 production-helper tests and the local isolated runtime proof above. That isolated app/MCP run and the Azure installer trace are from
29c83ff9, not from the final head. Rollback rejection before credential I/O is recorded below. A signed installer built from632aae78is still not a release asset.Signed installer upgrade and uninstall on this PC
Two published x64 installers, both Authenticode
Valid, signerCN=OpenClaw Foundation, O=OpenClaw Foundation, L=Mill Valley, S=California, C=US:4F5FA904B4353948E443D8F7DE67C4BBA52EB988A941BFE0520529E9FDF3EA8F2026.9.5-alpha.61+24263d3b06c4f2c3af1c7d9c1c834d43323ea9bc96F90A2819BA269C6939229079C398AF26EB960404989F0F22D5D78CE17A35542026.9.5-alpha.97+7127c16d537cf9d2d92012cc0c16ea6d3c7c73a7They are not a signed build of head
632aae78. The install used/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /CURRENTUSERinto a temporary directory, not the everyday install folder.GatewayUrland withTokenandBootstrapTokenpresent was seeded before the upgrade.unins000.exe /VERYSILENT /SUPPRESSMSGBOXES: exit 0. The installed tray exe and uninstaller were removed.TokenandBootstrapTokenwere still present afterward. That is the published alpha uninstall, not the token removal in this pull.Silent uninstall unregistered
OpenClawGateway. That distro was exported before the run and imported again afterward. It is registered and stopped.Ubuntu-24.04stayed running. Port 18789 stayed in use bywslrelay. The original tray AppData file was restored after the settings check. The bundled Visual C++ redistributable asked for administrator permission and was stopped so the file copy could finish. That skip only suppresses the installer's automatic tray launch.Rollback does not admit the setup gateway
On head
999a05c9, a URL-less profile still exposes the setup URL from theGatewayUrlgetter. That value is not a saved target.UpdateAndSaveassigned that getter back through the setter. That was the path that leftHasPersistedGatewayUrltrue. After the exception,PersistedGatewayUrlandGetLegacyCredentialGatewayUrlOrNull()were null.InteractiveGatewayCredentialResolver.TryResolvereturned false for the root device identity and for the leftover token strings. No chat URL was built, and no request was sent to the setup port.wss://saved.example.invalidkept that URL as the legacy credential target.GatewayDirectConnectService.ConnectAsyncfrom a URL-less profile towss://candidate.examplefailed and rolled back. The registry was empty, the savedGatewayUrlwas blank, and the resolver returned no credential. A previously saved gateway URL still restored.On head
632aae78the same production types also opened sockets:An explicitly saved
ws://127.0.0.1:62214gateway produced one TCP connection to that listener. The request line wasGET /chatand the query included a token. The token value is omitted here. After the failed URL-less save, and after the failed URL-less direct connect, this process had zero TCP connections to port 18789.The direct-connect rollback directory from that test was then loaded by the current-head tray executable,
OpenClaw.Tray.WinUI.exefrom this worktree's Debug win-x64 build. The directory had an empty gateway registry, noGatewayUrl, and noTokenorBootstrapToken. The isolated process opened its setup window, then logged that the profile has no explicitly managed gateway and skipped lifecycle actions. It then logged that the gateway URL was not configured and that client initialization was skipped. That process had zero TCP connections to port 18789. It was stopped after the log line. The saved settings still had noGatewayUrl,Token, orBootstrapToken.A second launch of that same executable kept the failed save and the network consumer in one process. The profile still had no
GatewayUrl. Auto-start was true, so startup reconciliation tried to save. An external writer changed the file first. That process logged, in order:The next line recorded that the gateway URL was not configured and that client initialization was skipped. The failure was 09:23:21.521 and the skip was 09:23:21.525. The process id was 44676. It had zero TCP connections to port 18789. It was stopped after the log was written.
Release signing for
OpenClawCompanion-Setup-x64.exeruns only for a tag or promotion build in therelease-signingenvironment, so this PC still has no signed installer of head632aae78.CI reconciliation
The first current-head CI run passed setup/connect, revocation recovery, tray/setup/integration, UI/accessibility, release publish, MSIX, and proof contracts. Its two failures were unrelated baseline flakes:
PiperVoiceExtractionTests.ExtractTarBz2Async_CancellationIsBoundedAndKillsExtractorobserved the fixture process still running.StateDatabaseCoordinatorContentionErrorandGATEWAY_RESTART_PREPARATION_REFUSEDbefore either network recovery test executed.Only the failed jobs were rerun.