refactor(cli): group core credentials and security helpers#3193
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR rewires imports into new core/, cli/, and security/ modules; moves credential APIs to credentials/store and updates callers and shims; adds sandbox connect timeout and inference-route swap; reconciles policyPresets on snapshot restore; centralizes sandbox-name validation; and updates many tests and harnesses. ChangesModule Reorganization and Functional Enhancements
Sequence DiagramsequenceDiagram
participant User
participant ConnectCmd
participant Registry
participant Openshell
participant Sandbox
User->>ConnectCmd: run connect
ConnectCmd->>Registry: read sandbox persisted provider/model
ConnectCmd->>Openshell: query live inference route
Openshell-->>ConnectCmd: live route
alt routes differ
ConnectCmd->>Openshell: run "inference set" to swap route
Openshell-->>ConnectCmd: success/failure (warn if fail)
end
ConnectCmd->>Sandbox: readiness poll (deadline from NEMOCLAW_CONNECT_TIMEOUT)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
… refactor/lib-feature-clusters
…nto refactor/lib-core-security # Conflicts: # src/lib/onboard-session.ts # src/lib/onboard.ts # src/lib/state/registry.ts
…urity # Conflicts: # src/lib/agent/defs.ts # src/lib/agent/onboard.ts # src/lib/agent/runtime.ts # src/lib/commands/debug.ts # src/lib/dashboard/contract.ts # src/lib/diagnostics/debug.ts # src/lib/shields/audit.ts # test/onboard.test.ts # test/secret-redaction.test.ts
prekshivyas
left a comment
There was a problem hiding this comment.
Mechanical move-only refactor implementing step 3 of the #3189 migration sequence (after #3191's cluster moves). Net-zero line count (228+/228-) is the signature of a pure rename — 26 git-detected renames at 95-100% similarity, the other 91 files are 1+/1- import-path updates in callers.
Files moved into the four homes documented by the placement map:
src/lib/cli/:branding.ts,command-display-metadata.test.ts,command-registry.{ts,test.ts},duration-flags.{ts,test.ts},oclif-command-metadata.test.ts,terminal-style.{ts,test.ts}src/lib/core/:errno.ts+ test,json-types.ts,ports.ts+ test,shell-quote.ts,url-utils.ts+ test,version.ts+ test,wait.tssrc/lib/credentials/:credentials.ts→credentials/store.tssrc/lib/security/:credential-filter.{ts,test.ts},credential-hash.ts,redact.ts,secret-patterns.ts
Spot-checked src/nemoclaw.ts (the entry point, 4+/4-): pure import path updates — ./lib/ports → ./lib/core/ports, ./lib/branding → ./lib/cli/branding, ./lib/errno → ./lib/core/errno, ./lib/command-registry → ./lib/cli/command-registry. No logic changes.
Tooling correctly updated alongside the moves:
bin/lib/credentials.jsre-export shim retargeted atdist/lib/credentials/store.bin/lib/ports.jsshim retargeted atdist/lib/core/ports.scripts/check-legacy-migrated-paths.tsREMOVED_SHIM_MOVES entry forbin/lib/version.jsupdated tosrc/lib/core/version.ts.scripts/ts-migration-assist.tsSPECIAL_REWRITES entry for credentials updated to./credentials/store.scripts/dev-tier-selector.jsrequire path updated todist/lib/credentials/store.js.scripts/generate-openclaw-config.pydocstring reference updated tosrc/lib/core/url-utils.ts.
Renames are 1:1, no legacy-shim files left at the old flat paths. Tests moved alongside their source.
CI: pr.yaml rollup checks pass (commit-lint, dco, layer-boundary, check-hash, changes, get-pr-info, block edits to migrated legacy paths and removed shims). 1 prior pr-self-hosted run success on pull-request/3193. CodeRabbit / checks / macos-e2e / wsl-e2e / build-sandbox-images and current self-hosted run still in progress at approval time.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/lib/actions/sandbox/connect.ts (1)
199-202:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAdd a timeout to the inference-route reset.
runOpenshell(..., { ignoreError: true })is unbounded here. If OpenShell hangs duringinference set,connectcan block indefinitely before the new readiness timeout logic even starts. Reuse the probe timeout here, or clamp it to the remaining connect deadline.Proposed fix
const swapResult = runOpenshell( ["inference", "set", "--provider", sb.provider, "--model", sb.model, "--no-verify"], - { ignoreError: true }, + { + ignoreError: true, + timeout: OPENSHELL_PROBE_TIMEOUT_MS, + }, );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/lib/actions/sandbox/connect.ts` around lines 199 - 202, The runOpenshell call used to perform the "inference set" (the swapResult assignment) is currently unbounded; update the call to pass a timeout so it cannot hang indefinitely by reusing the existing probe timeout (or clamp to the remaining connect deadline) — e.g., compute the effective timeout from the probe timeout or remaining connect deadline and add it to the runOpenshell options object (alongside ignoreError: true) so the inference set (using sb.provider and sb.model) will fail fast if Openshell hangs.src/lib/actions/sandbox/snapshot.ts (1)
381-404:⚠️ Potential issue | 🟠 Major | ⚡ Quick winReturn a non-zero status when preset reconciliation is incomplete.
This block only warns on failed
removePreset/applyPresetcalls, sosnapshot restorestill exits successfully even when the target’s effective presets no longer match the snapshot. Since preset state is now part of restore, partial reconciliation should surface as a failed restore result.Proposed fix
if (failed.length > 0) { - console.warn(` Warning: could not reconcile preset(s): ${failed.join("; ")}`); + console.error(` Failed to reconcile preset(s): ${failed.join("; ")}`); + process.exitCode = 1; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/lib/actions/sandbox/snapshot.ts` around lines 381 - 404, The code only logs a warning when some presets fail to remove/apply (the failed array populated from policies.removePreset and policies.applyPreset on targetSandbox), so a snapshot restore still exits success; change the behavior so incomplete reconciliation yields a non-zero result by throwing an Error (or otherwise returning a failing result) when failed.length > 0 instead of only console.warn — include a clear message with failed.join("; ") so the CLI's snapshot restore handler receives the failure and terminates with a non-zero status.
🧹 Nitpick comments (2)
src/lib/shields/audit.ts (1)
14-14: Run the shields lifecycle E2E for this refactor touchpoint.Since this file participates in shields audit flow, run the selective shields config E2E once before merge to validate end-to-end behavior after path moves.
As per coding guidelines:
src/lib/shields/**E2E recommendation includesshields-config-e2eviagh workflow run nightly-e2e.yaml --ref <branch> -f jobs=shields-config-e2e.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/lib/shields/audit.ts` at line 14, This file touches the shields audit flow (the imported symbol redactFull in audit.ts) so before merging run the selective shields E2E to validate end-to-end behavior after the refactor: ensure the import of redactFull is still correct and the audit flow exercises this module, then execute the shields-config-e2e job with the GitHub workflow (gh workflow run nightly-e2e.yaml --ref <branch> -f jobs=shields-config-e2e) and verify the audit scenarios pass; if failures occur, revert or fix the import/path and rerun until the shields audit E2E succeeds.test/runner.test.ts (1)
718-727: ⚡ Quick winAssert that the fallback path also exits successfully.
Right now this case passes if the script prints the fallback messages and then exits non-zero. Adding a status check, like the
gh-absenttest above, makes the regression guard verify the full success path instead of just its logs.Proposed fix
try { const result = spawnSync("bash", ["-c", stub], { encoding: "utf-8", timeout: 5000, }); const out = (result.stdout || "") + (result.stderr || ""); + expect(result.status, out).toBe(0); expect(out).toContain("falling back to curl"); expect(out).toContain("CURL_FALLBACK"); expect(fs.readFileSync(checksumLog, "utf-8")).toContain("SHASUM -a 256 -c -"); } finally {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/runner.test.ts` around lines 718 - 727, Add an assertion that the spawned stub completed successfully by checking the spawnSync result status (the result variable returned by spawnSync in this test) is 0, similar to the gh-absent test; place the expect(result.status).toBe(0) (or equivalent status check) right after you capture result and before reading checksumLog to ensure the fallback path not only logs messages but also exits successfully.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/lib/core/version.ts`:
- Around line 30-31: The default root directory computation in version.ts is off
by one: update the fallback for opts.rootDir used in computing root (variable
root in the module) so it points three levels up from __dirname (to account for
compiled path dist/lib/core/version.js) instead of two; change the join call
constructing root (the value assigned to root when opts.rootDir is undefined) to
ascend one additional ".." so lookups for .version/package.json resolve the
project root rather than the dist folder.
---
Outside diff comments:
In `@src/lib/actions/sandbox/connect.ts`:
- Around line 199-202: The runOpenshell call used to perform the "inference set"
(the swapResult assignment) is currently unbounded; update the call to pass a
timeout so it cannot hang indefinitely by reusing the existing probe timeout (or
clamp to the remaining connect deadline) — e.g., compute the effective timeout
from the probe timeout or remaining connect deadline and add it to the
runOpenshell options object (alongside ignoreError: true) so the inference set
(using sb.provider and sb.model) will fail fast if Openshell hangs.
In `@src/lib/actions/sandbox/snapshot.ts`:
- Around line 381-404: The code only logs a warning when some presets fail to
remove/apply (the failed array populated from policies.removePreset and
policies.applyPreset on targetSandbox), so a snapshot restore still exits
success; change the behavior so incomplete reconciliation yields a non-zero
result by throwing an Error (or otherwise returning a failing result) when
failed.length > 0 instead of only console.warn — include a clear message with
failed.join("; ") so the CLI's snapshot restore handler receives the failure and
terminates with a non-zero status.
---
Nitpick comments:
In `@src/lib/shields/audit.ts`:
- Line 14: This file touches the shields audit flow (the imported symbol
redactFull in audit.ts) so before merging run the selective shields E2E to
validate end-to-end behavior after the refactor: ensure the import of redactFull
is still correct and the audit flow exercises this module, then execute the
shields-config-e2e job with the GitHub workflow (gh workflow run
nightly-e2e.yaml --ref <branch> -f jobs=shields-config-e2e) and verify the audit
scenarios pass; if failures occur, revert or fix the import/path and rerun until
the shields audit E2E succeeds.
In `@test/runner.test.ts`:
- Around line 718-727: Add an assertion that the spawned stub completed
successfully by checking the spawnSync result status (the result variable
returned by spawnSync in this test) is 0, similar to the gh-absent test; place
the expect(result.status).toBe(0) (or equivalent status check) right after you
capture result and before reading checksumLog to ensure the fallback path not
only logs messages but also exits successfully.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: fab6b09e-5fa7-41ea-811c-2ded0492c510
📒 Files selected for processing (117)
bin/lib/credentials.jsbin/lib/ports.jsscripts/check-legacy-migrated-paths.tsscripts/dev-tier-selector.jsscripts/generate-openclaw-config.pyscripts/ts-migration-assist.tssrc/lib/actions/deploy.tssrc/lib/actions/maintenance.tssrc/lib/actions/root-help.tssrc/lib/actions/sandbox/connect.tssrc/lib/actions/sandbox/destroy.tssrc/lib/actions/sandbox/doctor.tssrc/lib/actions/sandbox/gateway-state.tssrc/lib/actions/sandbox/policy-channel.tssrc/lib/actions/sandbox/process-recovery.tssrc/lib/actions/sandbox/rebuild.tssrc/lib/actions/sandbox/skill-install.tssrc/lib/actions/sandbox/snapshot.tssrc/lib/actions/sandbox/status.tssrc/lib/actions/upgrade-sandboxes.tssrc/lib/agent/defs.tssrc/lib/agent/onboard.tssrc/lib/agent/runtime.tssrc/lib/build-context.tssrc/lib/cli/branding.tssrc/lib/cli/command-display-metadata.test.tssrc/lib/cli/command-registry.test.tssrc/lib/cli/command-registry.tssrc/lib/cli/duration-flags.test.tssrc/lib/cli/duration-flags.tssrc/lib/cli/oclif-command-metadata.test.tssrc/lib/cli/oclif-dispatch.tssrc/lib/cli/oclif-runner.tssrc/lib/cli/public-oclif-help.tssrc/lib/cli/terminal-style.test.tssrc/lib/cli/terminal-style.tssrc/lib/commands/credentials.test.tssrc/lib/commands/credentials/common.tssrc/lib/commands/credentials/list.tssrc/lib/commands/credentials/reset.tssrc/lib/commands/debug.tssrc/lib/commands/deprecated/start.tssrc/lib/commands/deprecated/stop.tssrc/lib/commands/sandbox/config/get.tssrc/lib/commands/sandbox/connect.tssrc/lib/commands/sandbox/logs.tssrc/lib/commands/sandbox/shields/down.tssrc/lib/commands/simple-global-oclif-adapters.test.tssrc/lib/commands/uninstall.tssrc/lib/core/errno.test.tssrc/lib/core/errno.tssrc/lib/core/json-types.tssrc/lib/core/ports.test.tssrc/lib/core/ports.tssrc/lib/core/shell-quote.tssrc/lib/core/url-utils.test.tssrc/lib/core/url-utils.tssrc/lib/core/version.test.tssrc/lib/core/version.tssrc/lib/core/wait.tssrc/lib/coverage-hotspots.test.tssrc/lib/credentials/store.tssrc/lib/dashboard/contract.tssrc/lib/deploy.tssrc/lib/diagnostics/debug.tssrc/lib/host-artifact-cleanup.tssrc/lib/http-probe.tssrc/lib/inventory-commands.tssrc/lib/local-inference.tssrc/lib/model-prompts.tssrc/lib/nim.tssrc/lib/onboard-command.tssrc/lib/onboard-inference-probes.tssrc/lib/onboard-ollama-proxy.tssrc/lib/onboard-providers.tssrc/lib/onboard-session.tssrc/lib/onboard-vllm.tssrc/lib/onboard-windows-ollama.tssrc/lib/onboard.tssrc/lib/policies.tssrc/lib/preflight.tssrc/lib/provider-models.tssrc/lib/runner.tssrc/lib/sandbox-channels.tssrc/lib/sandbox-config.tssrc/lib/security/credential-filter.test.tssrc/lib/security/credential-filter.tssrc/lib/security/credential-hash.tssrc/lib/security/redact.tssrc/lib/security/secret-patterns.tssrc/lib/services.tssrc/lib/share-command-deps.tssrc/lib/shields/audit.tssrc/lib/state/config-io.tssrc/lib/state/registry.tssrc/lib/state/sandbox.tssrc/lib/usage-notice.tssrc/lib/validation-recovery.tssrc/nemoclaw.tstest/canonical-credential-resolution.test.tstest/credentials.test.tstest/e2e/test-credential-migration.shtest/gateway-start-wait.test.tstest/host-artifact-cleanup.test.tstest/image-cleanup.test.tstest/ollama-tools-capability.test.tstest/onboard-preset-diff.test.tstest/onboard-prompt-default-case.test.tstest/onboard-selection.test.tstest/onboard.test.tstest/policies.test.tstest/policy-tiers-onboard.test.tstest/presets-checkbox.test.tstest/runner.test.tstest/secret-redaction.test.tstest/shellquote-sandbox.test.tstest/wait.test.ts
## Summary - Bump the docs release metadata to `0.0.37`. - Document release-prep updates for messaging policy presets, sandbox runtime utilities, and the GPU CDI troubleshooting path. - Refresh generated `nemoclaw-user-*` skills from the updated docs. ## Source summary - #3159 -> `docs/reference/troubleshooting.md`: Documents the GPU CDI preflight warning and remediation for `nvidia.com/gpu=all` gateway start failures. - #2415 -> `docs/reference/network-policies.md`, `docs/manage-sandboxes/messaging-channels.md`, `docs/network-policy/customize-network-policy.md`: Clarifies that Telegram, Discord, and Slack egress comes from opt-in messaging presets, not the baseline policy. - #3091 -> `docs/deployment/sandbox-hardening.md`, `docs/network-policy/customize-network-policy.md`: Documents the retained sandbox utilities `vi`, `jq`, and `dos2unix` while keeping host-side policy files as the durable source of truth. ## Test plan - `python3 scripts/docs-to-skills.py docs/ .agents/skills/ --prefix nemoclaw-user` - `make docs` - `npm run build:cli` - `npm run typecheck:cli` - Commit and pre-push hooks: markdownlint, docs-to-skills verification, gitleaks, commitlint, CLI typecheck ## Skipped - #3193 and #3191 matched `docs/.docs-skip` entries for experimental shields/config paths. - #3200 and #3183 were test-only fixes. - #3189 and #3163 were internal documentation/refactor changes with no public docs impact. Made with [Cursor](https://cursor.com) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Clarified which utilities remain in the sandbox runtime for lightweight inspection and cleanup * Noted that messaging endpoints (Discord, Slack, Telegram) are not in the baseline policy and that channel presets are applied during onboarding * Added GPU passthrough troubleshooting for gateway startup * Updated release/version bump and release-prep workflow guidance, including Discord preset description updates <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
Moves cross-cutting helpers into the core, CLI, credentials, and security homes documented by the placement map. This keeps the flat
src/libnamespace focused on legacy modules that still need dedicated follow-up work.Changes
src/lib/cli/**.src/lib/core/**.src/lib/credentials/store.ts.src/lib/security/**.Type of Change
Verification
npx prek run --all-filespassesnpm testpassesmake docsbuilds without warnings (doc changes only)Signed-off-by: Carlos Villela cvillela@nvidia.com
Summary by CodeRabbit
New Features
Improvements
Refactor
Tests