feat(policy): support custom preset files via --from-file / --from-dir (closes #2039)#2077
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds CLI support to apply user-authored preset YAMLs via Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI as "nemoclaw CLI"
participant FS as Filesystem
participant Policies as policies.ts
participant OpenShell as openshell
User->>CLI: run "nemoclaw <sandbox> policy-add --from-file /path/preset.yaml [--dry-run] [--yes]"
CLI->>FS: read /path/preset.yaml
FS-->>CLI: file contents
CLI->>Policies: loadPresetFromFile(filePath)
Policies-->>CLI: { presetName, content } or error
alt load success
CLI->>CLI: show endpoint preview & warning
alt dry-run
CLI-->>User: preview only (no apply)
else apply
CLI->>Policies: applyPresetContent(sandbox, presetName, content, options)
Policies->>OpenShell: "openshell policy set --wait" (merge network_policies)
OpenShell-->>Policies: success / failure
Policies-->>CLI: result
CLI-->>User: success / error
end
else load failure
CLI-->>User: error & exit non-zero
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
9e08ba8 to
6ce9ecb
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
test/policies.test.ts (1)
1120-1164: Make prompt response configurable to cover external decline paths.
runPolicyAddExternalhardcodes prompt return value to"y", so the interactive decline behavior for external presets is untestable. Consider parameterizing it and adding a"no"case to prevent regressions around confirmation safety.Possible refactor
- function runPolicyAddExternal(extraArgs = [], envOverrides = {}) { + function runPolicyAddExternal(extraArgs = [], envOverrides = {}, promptAnswer = "y") { ... -credentials.prompt = async (message) => { +credentials.prompt = async (message) => { calls.push({ type: "prompt", message }); - return "y"; + return ${JSON.stringify("PROMPT_SENTINEL")}; }; ... - fs.writeFileSync(scriptPath, script); + fs.writeFileSync(scriptPath, script.replace("PROMPT_SENTINEL", promptAnswer));+ it("does not apply when external preset confirmation is declined with 'no'", () => { + const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-from-file-no-")); + const file = path.join(tmp, "custom-rule.yaml"); + fs.writeFileSync(file, "preset:\n name: custom-rule\nnetwork_policies: {}\n"); + const result = runPolicyAddExternal(["--from-file", file], {}, "no"); + expect(result.status).toBe(0); + const calls = JSON.parse(result.stdout.split("__CALLS__")[1].trim()); + expect(calls.some((c) => c.type === "apply")).toBeFalsy(); + });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/policies.test.ts` around lines 1120 - 1164, runPolicyAddExternal currently hardcodes the interactive prompt response by setting policies.prompt = async (...) => "y", which prevents testing the decline path; change runPolicyAddExternal to accept a promptResponse parameter (default "y"), pass that into the generated script and set policies.prompt = async (message) => { calls.push({ type: "prompt", message }); return promptResponse; }, update any callers in tests to invoke runPolicyAddExternal(..., ..., "no") to cover the decline path and assert behavior based on the calls array and process output; keep existing extraArgs and envOverrides parameters intact so other tests remain unaffected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/nemoclaw.ts`:
- Around line 1539-1542: The confirmation logic incorrectly treats only the
exact string "n" as a decline, so inputs like "no" are accepted; update both
confirmation branches (the block using askPrompt and the similar block around
the code handling the alternative at lines ~1572-1577) to normalize the response
with trim() and toLowerCase() and treat any response starting with "n" (e.g.,
response.toLowerCase().trim().startsWith("n")) as a decline; reference the
askPrompt call and the local yes variable to locate and replace the current
exact-equality checks.
---
Nitpick comments:
In `@test/policies.test.ts`:
- Around line 1120-1164: runPolicyAddExternal currently hardcodes the
interactive prompt response by setting policies.prompt = async (...) => "y",
which prevents testing the decline path; change runPolicyAddExternal to accept a
promptResponse parameter (default "y"), pass that into the generated script and
set policies.prompt = async (message) => { calls.push({ type: "prompt", message
}); return promptResponse; }, update any callers in tests to invoke
runPolicyAddExternal(..., ..., "no") to cover the decline path and assert
behavior based on the calls array and process output; keep existing extraArgs
and envOverrides parameters intact so other tests remain unaffected.
🪄 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: Pro Plus
Run ID: 4f840bb0-6819-4a75-892e-de82dbe3ff7e
📒 Files selected for processing (5)
.agents/skills/nemoclaw-user-manage-policy/SKILL.mddocs/network-policy/customize-network-policy.mdsrc/lib/policies.tssrc/nemoclaw.tstest/policies.test.ts
✅ Files skipped from review due to trivial changes (2)
- docs/network-policy/customize-network-policy.md
- .agents/skills/nemoclaw-user-manage-policy/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (1)
- src/lib/policies.ts
6ce9ecb to
14ca974
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/lib/policies.ts`:
- Around line 519-536: In loadPresetFromFile, fs.readFileSync is called outside
the try-catch which allows a TOCTOU read error to escape; fix by declaring let
content; (and keeping parsed declared) then move the call to
fs.readFileSync(abs, "utf-8") inside the try block before calling
YAML.parse(content), catch any error and call console.error with a descriptive
message (including err.message) and return null so all read/parse failures
follow the same graceful null-return pattern.
🪄 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: Pro Plus
Run ID: cc1781f7-bdb1-42ab-8f84-88dfa7b2d333
📒 Files selected for processing (5)
.agents/skills/nemoclaw-user-manage-policy/SKILL.mddocs/network-policy/customize-network-policy.mdsrc/lib/policies.tssrc/nemoclaw.tstest/policies.test.ts
✅ Files skipped from review due to trivial changes (1)
- docs/network-policy/customize-network-policy.md
14ca974 to
5ba18f5
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/nemoclaw.ts (1)
1534-1536:⚠️ Potential issue | 🟠 Major
--dry-runnever reaches the diff/merge path.Both dry-run branches return before
policies.applyPreset(...)/policies.applyPresetContent(...)runs, so the command only prints endpoint summaries and never shows the merged policy diff promised by this feature. That leaves operators unable to validate the actual policy change before applying a custom preset.Also applies to: 1567-1569
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/nemoclaw.ts` around lines 1534 - 1536, The dryRun branch returns early and thus never invokes policies.applyPreset or policies.applyPresetContent, so the tool only prints endpoint summaries and never computes/shows the merged policy diff — remove the early return and instead call the same applyPreset/applyPresetContent logic in dry-run mode but avoid persisting changes; specifically, when dryRun is true, call policies.applyPreset(...) or policies.applyPresetContent(...), capture the merged/updated policy result and render the diff/merge output (same code used for the real path), but skip any persistence/commit step; apply this change to both occurrences referencing dryRun around policies.applyPreset and policies.applyPresetContent so dry-run shows the merged diff without applying it.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/nemoclaw.ts`:
- Around line 2394-2396: The help text currently claims `--yes /
NEMOCLAW_NON_INTERACTIVE=1 skip prompts`, which is inaccurate; update the string
in the CLI help template that contains `${D}--yes / -y or
NEMOCLAW_NON_INTERACTIVE=1 skip prompts${R}` so it clarifies that `--yes` (or
the env var) only skips the final confirmation prompt and does not bypass the
preset-selection flow — note that preset selection remains interactive unless
`--from-file` or `--from-dir` is supplied; make the wording concise like “skip
confirmation prompt; preset selection remains interactive unless --from-file or
--from-dir is used.”
In `@test/policies.test.ts`:
- Around line 276-286: The tests calling policies.buildPolicySetCommand assume
NEMOCLAW_OPENSHELL_BIN is unset and delete it in finally, making them
non-hermetic; modify the test(s) to capture the current value of
process.env.NEMOCLAW_OPENSHELL_BIN at the start (e.g., const prior =
process.env.NEMOCLAW_OPENSHELL_BIN), then set or delete the env var for the test
case as needed, and in the finally block restore it
(process.env.NEMOCLAW_OPENSHELL_BIN = prior === undefined ? undefined : prior)
so the original environment is preserved; apply the same pattern to the other
argv test(s) that manipulate NEMOCLAW_OPENSHELL_BIN and reference
policies.buildPolicySetCommand to locate the affected tests.
---
Outside diff comments:
In `@src/nemoclaw.ts`:
- Around line 1534-1536: The dryRun branch returns early and thus never invokes
policies.applyPreset or policies.applyPresetContent, so the tool only prints
endpoint summaries and never computes/shows the merged policy diff — remove the
early return and instead call the same applyPreset/applyPresetContent logic in
dry-run mode but avoid persisting changes; specifically, when dryRun is true,
call policies.applyPreset(...) or policies.applyPresetContent(...), capture the
merged/updated policy result and render the diff/merge output (same code used
for the real path), but skip any persistence/commit step; apply this change to
both occurrences referencing dryRun around policies.applyPreset and
policies.applyPresetContent so dry-run shows the merged diff without applying
it.
🪄 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: Pro Plus
Run ID: fa3bcdb8-b5ae-4425-89d6-31dc821775e3
📒 Files selected for processing (5)
.agents/skills/nemoclaw-user-manage-policy/SKILL.mddocs/network-policy/customize-network-policy.mdsrc/lib/policies.tssrc/nemoclaw.tstest/policies.test.ts
✅ Files skipped from review due to trivial changes (2)
- docs/network-policy/customize-network-policy.md
- .agents/skills/nemoclaw-user-manage-policy/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (1)
- src/lib/policies.ts
5ba18f5 to
1d66a89
Compare
|
Thanks for the review, @coderabbitai. Responses: ✅ Fixed: Help text wording for ❌ Declining: ❌ Declining: test env-var hermeticity ( |
|
Tip For best results, initiate chat on the files or code changes.
✏️ Learnings added
🧠 Learnings used |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/nemoclaw.ts`:
- Around line 1501-1505: The current files list creation accepts directory
entries by name ending with .yml/.yaml which lets directories like
"archived.yaml/" slip through and later cause applyExternalPreset() to fail
isFile(); change the filter to only include regular files: enumerate the
directory with fs.readdirSync(absDir, { withFileTypes: true }) (or stat each
entry) and keep entries where dirent.isFile() is true and
/\.ya?ml$/i.test(dirent.name), then map to path.join(absDir, name) and sort;
update the variable named files accordingly so applyExternalPreset() only
receives real files.
- Around line 1555-1580: applyExternalPreset can throw because
policies.loadPresetFromFile and policies.applyPresetContent may throw; wrap the
load and apply calls in a try/catch so any sync/async exceptions are caught, log
a concise error (including the thrown error message) and return false instead of
letting the CLI crash. Specifically, surround the call to
policies.loadPresetFromFile(filePath) and the call to
policies.applyPresetContent(sandboxName, loaded.presetName, loaded.content)
(awaiting it if it returns a promise) with a single try/catch that handles
errors, logs them, and returns false.
🪄 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: Pro Plus
Run ID: 3f4278bd-e469-49c5-b63b-ace810872981
📒 Files selected for processing (5)
.agents/skills/nemoclaw-user-manage-policy/SKILL.mddocs/network-policy/customize-network-policy.mdsrc/lib/policies.tssrc/nemoclaw.tstest/policies.test.ts
✅ Files skipped from review due to trivial changes (2)
- docs/network-policy/customize-network-policy.md
- .agents/skills/nemoclaw-user-manage-policy/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (1)
- src/lib/policies.ts
|
Thanks for addressing the CodeRabbit feedback! Branch has conflicts with main — could you rebase and we'll get a review queued up. |
Lets users apply user-authored preset YAML to a running sandbox without editing the baseline policy or dropping to openshell policy set. - --from-file <path> applies a single custom preset - --from-dir <path> applies every .yaml preset in a directory; stops at the first failure and does not roll back already-applied presets - --yes / -y and NEMOCLAW_NON_INTERACTIVE=1 skip the confirmation prompt, also covering the original built-in preset path - Custom presets must declare preset.name as an RFC 1123 label that does not collide with a built-in preset; the file must include a network_policies section - Custom hosts are not vetted and a warning is printed before apply; the docs page spells out the risk Closes NVIDIA#2039 Signed-off-by: Kim Yang <[email protected]>
1d66a89 to
8c3dae8
Compare
|
Rebased onto Conflict resolutions:
Force-pushed. CLI |
Wrap fs.readFileSync in loadPresetFromFile in a try block so a TOCTOU
read failure between existsSync and readFileSync follows the same
graceful null-return path as YAML parse errors.
Normalize the policy-remove confirmation prompt to match policy-add
(trim + startsWith("n")) so typing "no" actually declines.
Addresses CodeRabbit feedback on PR NVIDIA#2077.
|
Pushed 5f4ef0f addressing remaining CodeRabbit feedback:
Help-text wording concern is moot — the misleading line was dropped during the rebase. |
|
wsl-e2e failure is a pre-existing flake in Can a maintainer rerun the failed job? I don't have repo admin rights. |
PR Review: feat/2039-policy-add-from-fileFiles Changed: 5 | Lines: +629 / -22 Nice work on this, @KimBioInfoStudio — the 🔴 Blockers (must fix before merge)
🟡 Warnings (should fix)
🔵 Suggestions (nice to have)
Overall this is well-structured and well-tested. The blocker around removal is the main thing to sort out — everything else is polish. 🚀 |
Merge main into feat/2039-policy-add-from-file. Keep both sides of the refactor: main's TypeScript type tightening (PresetInfo, PolicyDocument, SelectionOptions, isPolicyDocument, typed signatures, extracted buildSandboxLogsArgs, command-registry-driven help) plus this branch's custom-preset support (--from-file / --from-dir flags, applyPresetContent, loadPresetFromFile, applyExternalPreset, -y alias, JSDoc comments). Advertise --from-file / --from-dir in command-registry.ts so the new help generator lists them under policy-add. Type the new test helpers (writeTmp, runPolicyAddExternal) and cast JSON.parse call-logs to PolicyCall[] so toContainEqual type-checks.
e683eaa to
29d4aa1
Compare
Address CodeRabbit review on NVIDIA#2077: - --from-dir now enumerates with withFileTypes and rejects entries that are not regular files. Previously a sub-directory named 'archived.yaml' would be passed to applyExternalPreset and abort the entire batch even though no preset file was invalid. - applyExternalPreset wraps both loadPresetFromFile and applyPresetContent in try/catch. loadPresetFromFile still has a TOCTOU window around fs.existsSync, and applyPresetContent throws on invalid sandbox names or failed openshell policy-set; previously either would crash the CLI instead of returning false and letting the caller abort cleanly. - Add regression test: --from-dir skips a sub-directory whose name ends in .yaml so the real preset alongside it still applies.
CodeRabbit review triageAddressed the major findings and responded inline on each thread. Summary: Fixed in this PR
Deferred
|
Address jyaunches's blocker on NVIDIA#2077: custom presets applied via --from-file / --from-dir were written to the registry by name only, so policy-remove <name> failed because loadPreset() only reads PRESETS_DIR. This was a one-way door. Fix: - registry: add SandboxEntry.customPolicies (array of { name, content, sourcePath, appliedAt }), plus getCustomPolicies / addCustomPolicy / removeCustomPolicyByName helpers. Built-in preset names continue to live in SandboxEntry.policies, so old registries keep working. - applyPresetContent: when called with options.custom, persist the full YAML in customPolicies instead of appending to policies. External preset apply path now passes { custom: { sourcePath } }. - removePreset: resolve preset content from built-ins first, then from customPolicies; prune the correct registry bucket on success. - policy-remove: accept custom-preset names as valid targets, add -y alias, show custom presets in the interactive selector, preview endpoints from persisted content. - policy-list: mix built-in and custom presets when listing. - command-registry: advertise -y on both add/remove, mention custom presets on remove. - docs: MyST ::: warning block (was GH > [!WARNING]) and a new 'Remove a Custom Preset' section. - tests: registry unit tests for the new helpers and a policy-remove custom-preset round-trip in policies.test.ts.
|
Thanks @jyaunches — addressing the blocker in 🔴 Blocker (custom presets are applied but cannot be removed) — fixed Rather than require users to keep the original preset file around, I took Option C from the reviewer's three suggestions and persisted the full preset YAML in the sandbox registry when
Round-trip tests added in 🟡
🟡 docs (MyST warning syntax + removal limitation) — fixed
🔵 suggestions (file size guard / tmp-dir cleanup / dotfile filter / symlink check) These are all sensible hardening steps but outside the scope of this blocker fix. I'll file a follow-up issue to track them once this PR is in.
|
## Summary Refreshes user-facing docs for the last 24 hours of merged NemoClaw history and bumps the docs metadata to 0.0.29, the next version after v0.0.28. The updates are limited to behavior supported by merged PR descriptions and diffs. ## Changes - `docs/reference/commands.md`: documented `nemoclaw <name> policy-add --from-file` and `--from-dir`, including custom preset review guidance, from #2077 / commit `7720b175`. - `docs/deployment/deploy-to-remote-gpu.md`: clarified that non-loopback `CHAT_UI_URL` disables OpenClaw device pairing for remote browser-only deployments, from #2449 / commit `f5ee8a4d`. - `docs/inference/inference-options.md`: documented provider-aware credential retry validation and the NVIDIA-only `nvapi-` prefix check, from #2389 / commit `6f7f0c6d`. - `docs/inference/switch-inference-providers.md`: documented `NEMOCLAW_INFERENCE_INPUTS` for text/image-capable model metadata baked into `openclaw.json`, from #2441 / commit `f4391892`. - `docs/reference/troubleshooting.md`: added the Git certificate verification entry for proxy CA propagation through `GIT_SSL_CAINFO`, `GIT_SSL_CAPATH`, `CURL_CA_BUNDLE`, and `REQUESTS_CA_BUNDLE`, from #2345 / commit `fa0dc1ab`. - `docs/versions1.json` and `docs/project.json`: promoted docs version `0.0.29`; `docs/versions1.json` omits unpublished `0.0.26`, `0.0.27`, and `0.0.28` entries. - `.agents/skills/nemoclaw-user-*`: regenerated derived user skill references from the updated docs. - Reviewed with no extra doc changes: #2575 / `d392ec07`, #2565 / `a3231049`, #1965 / `db1ef3ca`, #1990 / `db665834`, #2495 / `7da86fa3`, #2496 / `3192f4f4`, #2490 / `8c209058`, #2487 / `1f615e2f`, #2483 / `5653d33a`, #2482 / `31c782c0`, #2464 / `23bb5703`, #2472 / `a54f9a34`, and #2437 / `6bc860d7`. - Skipped per docs policy: #2420 / `7b76df6b` touched the experimental sandbox config path listed in `docs/.docs-skip`; #2466 / `cc15689c` touched a skipped term and CI-only sandbox image files. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [x] Doc only (includes code sample changes) ## Verification <!-- Check each item you ran and confirmed. Leave unchecked items you skipped. --> - [x] `npx prek run --all-files` passes - [ ] `npm test` passes — failed locally in installer-integration tests and one onboard helper timeout; the doc-scoped hook test projects passed under `prek`. - [ ] Tests added or updated for new or changed behavior - [x] No secrets, API keys, or credentials committed - [x] Docs updated for user-facing behavior changes - [ ] `make docs` builds without warnings (doc changes only) — build succeeded, but local Sphinx emitted the existing version-switcher file read message. - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) ## AI Disclosure <!-- If an AI agent authored or co-authored this PR, check the box and name the tool. Remove this section for fully human-authored PRs. --> - [x] AI-assisted — tool: Codex --- <!-- DCO sign-off required by CI. Run: git config user.name && git config user.email --> Signed-off-by: Miyoung Choi <[email protected]> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Support for custom YAML presets in policy configuration via --from-file and --from-dir. * New build-time inference input option to declare accepted modalities (text or text,image). * **Improvements** * Credential validation now offers interactive recovery: re-enter key, retry, choose another provider, or exit. * Clarified provider-specific API key prefix handling (nvapi- only applies to NVIDIA keys). * **Documentation** * TLS certificate troubleshooting for inspected networks. * Clarified remote dashboard security/device-pairing behavior; command docs updated; docs version bumped. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Miyoung Choi <[email protected]>
closes NVIDIA#2039) (NVIDIA#2077) feat(policy): support custom preset files via --from-file / --from-dir (closes NVIDIA#2039) Adds --from-file, --from-dir, --yes/-y, and NEMOCLAW_NON_INTERACTIVE=1 support to nemoclaw policy-add. Custom preset YAML is persisted in the sandbox registry so policy-remove works by name without the original file. Follow-up hardening: NVIDIA#2521
## Summary Refreshes user-facing docs for the last 24 hours of merged NemoClaw history and bumps the docs metadata to 0.0.29, the next version after v0.0.28. The updates are limited to behavior supported by merged PR descriptions and diffs. ## Changes - `docs/reference/commands.md`: documented `nemoclaw <name> policy-add --from-file` and `--from-dir`, including custom preset review guidance, from NVIDIA#2077 / commit `7720b175`. - `docs/deployment/deploy-to-remote-gpu.md`: clarified that non-loopback `CHAT_UI_URL` disables OpenClaw device pairing for remote browser-only deployments, from NVIDIA#2449 / commit `f5ee8a4d`. - `docs/inference/inference-options.md`: documented provider-aware credential retry validation and the NVIDIA-only `nvapi-` prefix check, from NVIDIA#2389 / commit `6f7f0c6d`. - `docs/inference/switch-inference-providers.md`: documented `NEMOCLAW_INFERENCE_INPUTS` for text/image-capable model metadata baked into `openclaw.json`, from NVIDIA#2441 / commit `f4391892`. - `docs/reference/troubleshooting.md`: added the Git certificate verification entry for proxy CA propagation through `GIT_SSL_CAINFO`, `GIT_SSL_CAPATH`, `CURL_CA_BUNDLE`, and `REQUESTS_CA_BUNDLE`, from NVIDIA#2345 / commit `fa0dc1ab`. - `docs/versions1.json` and `docs/project.json`: promoted docs version `0.0.29`; `docs/versions1.json` omits unpublished `0.0.26`, `0.0.27`, and `0.0.28` entries. - `.agents/skills/nemoclaw-user-*`: regenerated derived user skill references from the updated docs. - Reviewed with no extra doc changes: NVIDIA#2575 / `d392ec07`, NVIDIA#2565 / `a3231049`, NVIDIA#1965 / `db1ef3ca`, NVIDIA#1990 / `db665834`, NVIDIA#2495 / `7da86fa3`, NVIDIA#2496 / `3192f4f4`, NVIDIA#2490 / `8c209058`, NVIDIA#2487 / `1f615e2f`, NVIDIA#2483 / `5653d33a`, NVIDIA#2482 / `31c782c0`, NVIDIA#2464 / `23bb5703`, NVIDIA#2472 / `a54f9a34`, and NVIDIA#2437 / `6bc860d7`. - Skipped per docs policy: NVIDIA#2420 / `7b76df6b` touched the experimental sandbox config path listed in `docs/.docs-skip`; NVIDIA#2466 / `cc15689c` touched a skipped term and CI-only sandbox image files. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [x] Doc only (includes code sample changes) ## Verification <!-- Check each item you ran and confirmed. Leave unchecked items you skipped. --> - [x] `npx prek run --all-files` passes - [ ] `npm test` passes — failed locally in installer-integration tests and one onboard helper timeout; the doc-scoped hook test projects passed under `prek`. - [ ] Tests added or updated for new or changed behavior - [x] No secrets, API keys, or credentials committed - [x] Docs updated for user-facing behavior changes - [ ] `make docs` builds without warnings (doc changes only) — build succeeded, but local Sphinx emitted the existing version-switcher file read message. - [x] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) ## AI Disclosure <!-- If an AI agent authored or co-authored this PR, check the box and name the tool. Remove this section for fully human-authored PRs. --> - [x] AI-assisted — tool: Codex --- <!-- DCO sign-off required by CI. Run: git config user.name && git config user.email --> Signed-off-by: Miyoung Choi <[email protected]> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Support for custom YAML presets in policy configuration via --from-file and --from-dir. * New build-time inference input option to declare accepted modalities (text or text,image). * **Improvements** * Credential validation now offers interactive recovery: re-enter key, retry, choose another provider, or exit. * Clarified provider-specific API key prefix handling (nvapi- only applies to NVIDIA keys). * **Documentation** * TLS certificate troubleshooting for inspected networks. * Clarified remote dashboard security/device-pairing behavior; command docs updated; docs version bumped. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Miyoung Choi <[email protected]>
…ed inputs (#3020) ## Summary Three follow-up hardening items from PR #2077 review against `loadPresetFromFile` in `src/lib/policies.ts`: a 10 MB file-size guard, symlink rejection via `O_NOFOLLOW`, and tmp-dir cleanup in the corresponding test block. The size-and-symlink checks now use an atomic `openSync(O_RDONLY | O_NOFOLLOW) → fstatSync → readFileSync(fd)` pattern (per CodeRabbit review), so there is no TOCTOU window between the stat and the read and the kernel rejects symbolic links at open time. ## Related Issue Closes #2521 ## Changes - Add `MAX_PRESET_FILE_BYTES = 10_000_000` and reject files larger than the limit before reading their contents. - Replace the prior `existsSync` + `statSync` pair with an atomic `openSync(O_RDONLY | O_NOFOLLOW)` followed by `fstatSync` on the descriptor and `readFileSync(fd, "utf-8")`, with a `try/finally` `closeSync` on every early-return path. Symbolic links are rejected via `ELOOP` from `openSync` and surfaced with a clear error pointing the user at `realpath`. - Track and clean up `mkdtempSync` directories created by the `writeTmp` helper inside the `loadPresetFromFile` describe block via `afterEach`. - Add tests covering the new oversize-file (>10 MB) and symlink-rejection paths. ## Type of Change - [x] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Verification - [x] `npx prek run --all-files` passes - [x] `npm test` passes - [x] Tests added or updated for new or changed behavior - [x] No secrets, API keys, or credentials committed - [ ] Docs updated for user-facing behavior changes - [ ] `make docs` builds without warnings (doc changes only) - [ ] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) --- Signed-off-by: Tinson Lai <[email protected]> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Enhanced preset file validation with strict extension checking and a 10MB file size limit. * Improved security by rejecting symbolic links and enforcing stricter file access and permission checks, with clearer error messages for invalid files. * **Tests** * Added tests covering preset file size rejection and symbolic link rejection scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Tinson Lai <[email protected]>
Summary
Lets users apply user-authored preset YAML to a running sandbox without editing the baseline or dropping to
openshell policy set. Adds--from-file,--from-dir,--yes/-y, andNEMOCLAW_NON_INTERACTIVE=1support tonemoclaw <name> policy-add.Related Issue
Closes #2039
Changes
src/nemoclaw.ts: extendsandboxPolicyAddwith--from-file <path>,--from-dir <path>,--yes/-y, andNEMOCLAW_NON_INTERACTIVE=1handling; newapplyExternalPresethelper; updated help text.src/lib/policies.ts: newloadPresetFromFile(validates path, YAML,preset.nameas RFC 1123 label, presence ofnetwork_policies, rejects collisions with built-in preset names); refactorapplyPresetto delegate to a newapplyPresetContentthat works on raw content so the external path can reuse the merge + policy-set logic.test/policies.test.ts: unit tests forloadPresetFromFile(valid/invalid/missing fields/name collision) and integration tests for the--from-file/--from-dirCLI paths (success, dry-run, non-interactive env, mutually exclusive flags, missing path, abort-on-first-failure).docs/network-policy/customize-network-policy.md: new Custom Preset Files section with YAML skeleton,--from-file/--from-dirusage, and a warning that external hosts bypass review..agents/skills/nemoclaw-user-manage-policy/SKILL.md: regenerated from docs viascripts/docs-to-skills.py.Design decisions
preset.namematches a built-in preset — the user must rename it. Keeps the preset registry unambiguous.--from-dirfailure mode: stop at the first failure and leave earlier, successfully-applied presets in place. Rollback would require deleting already-merged entries from the running sandbox policy, which is risky; let the user fix the failing file and re-run.customize-network-policy.md.Type of Change
Verification
npx prek run --all-filespassesnpm testpasses (policies project: 95/95; install-preflight project: 57/57)make docsbuilds without warnings (doc changes only)AI Disclosure
Signed-off-by: Kim Yang [email protected]
Summary by CodeRabbit
New Features
Documentation
Tests