fix(policy): re-apply edited presets in policy-add and document tls: skip passthrough#7352
Conversation
…kip passthrough Naming an already-applied preset in policy-add previously failed on the registry name alone, so edited preset files were silently ignored until policy-remove/policy-add. Compare the preset content against the live gateway policy instead: a match becomes a successful idempotent no-op, drift or a missing live entry re-applies through the normal preview/confirm path, and unverifiable states (unreadable preset or live policy, or a name owned by a custom preset) keep the conservative failure. Document the access: full + tls: skip raw CONNECT passthrough for upstreams that reset the proxy's re-originated TLS handshake, switch the preset recipes to apply by name (a --from-file preset saved into the catalog collides with its own built-in name), and align the policy-add reference with the new contract. Refs #7323 Signed-off-by: Dongni-Yang <dongniy@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
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:
📝 WalkthroughWalkthroughNamed policy presets now compare stored content with live gateway state. Matching presets exit successfully without changes, while drifted or absent policies re-apply through the normal preview and confirmation flow. Documentation and tests cover these behaviors and raw TLS passthrough presets. ChangesPolicy preset drift handling
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant policy-add
participant Gateway
participant PolicyApply
User->>policy-add: policy-add <preset>
policy-add->>Gateway: compare preset with live policy
Gateway-->>policy-add: match, drift, absent, or failure
policy-add->>User: preview and confirmation when needed
User->>policy-add: confirm re-apply
policy-add->>PolicyApply: apply preset and refresh context
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
🌿 Preview your docs: https://nvidia-preview-pr-7352.docs.buildwithfern.com/nemoclaw |
PR Review Advisor — Blocking findings reportedAdvisor assessment: Blockers require maintainer review Model lanes
Nemotron output stays in workflow artifacts and does not change the assessment above. E2E guidanceAdvisory only. E2E / PR Gate selects and runs jobs independently. Recommended E2E: 1 optional E2E recommendation
Blockers
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/lib/policy/index.ts (1)
1544-1550: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider threading
sandboxNamefor a concrete re-apply command instead of the<sandbox>placeholder.
selectFromListdoesn't receivesandboxName, so the guidance falls back to a literal<sandbox>placeholder. The caller (policy-channel.ts) already has the real sandbox name at the call site (policies.selectFromList(allPresets, { applied })), so threading it through would let this message show a copy-pasteable command instead of a template.🤖 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/policy/index.ts` around lines 1544 - 1550, Thread the caller’s real sandbox name through selectFromList and its options from policy-channel.ts, then use that value in the already-applied preset guidance instead of the literal <sandbox> placeholder. Preserve the existing policy-add command structure and behavior.src/lib/actions/sandbox/policy-channel.ts (1)
168-216: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCorrect drift-detection logic; consider extracting it to reduce function complexity.
The custom-ownership guard, content load, and
match/null/drift/absentbranching correctly implement the drift contract validated byclassifyPresetEntries(src/lib/policy/index.ts:568-588) and by the accompanying tests. This block does, however, pushaddSandboxPolicyUnlockedwell past its prior branching complexity (already flagged as high-complexity in the line-range details). Consider extracting lines 172-216 into a small helper (e.g.resolveNamedPresetReapply(sandboxName, preset)) that returns either an early-exit signal or thereapplyState, keeping the outer function focused on orchestration.♻️ Illustrative extraction
+function resolveNamedPresetReapply( + sandboxName: string, + preset: { name: string }, +): { exit: true } | { exit: false; reapplyState: "drift" | "absent" | null } { + const customNames = registry.getCustomPolicies(sandboxName).map((entry) => entry.name); + if (customNames.includes(preset.name)) { + console.error(` Preset '${preset.name}' was applied as a custom preset (--from-file).`); + console.error( + ` Edit and re-apply it with --from-file, or run '${CLI_NAME} ${sandboxName} policy-remove ${preset.name}' first.`, + ); + process.exit(1); + } + const appliedContent = policies.loadPresetForSandbox(sandboxName, preset.name); + if (!appliedContent) { + console.error(` Could not read the content of preset '${preset.name}'.`); + process.exit(1); + } + const appliedState = policies.getPresetContentGatewayState(sandboxName, appliedContent); + if (appliedState === "match") { + console.log( + ` Preset '${preset.name}' is already applied and matches the live policy; nothing to do.`, + ); + return { exit: true }; + } + if (appliedState === null) { + console.error(` Preset '${preset.name}' is already applied.`); + console.error( + " Could not read the live sandbox policy to compare (is the sandbox gateway running?).", + ); + process.exit(1); + } + console.log( + appliedState === "drift" + ? ` Preset '${preset.name}' no longer matches the live policy.` + : ` Preset '${preset.name}' is recorded as applied but missing from the live policy.`, + ); + return { exit: false, reapplyState: appliedState }; +}🤖 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/policy-channel.ts` around lines 168 - 216, Extract the custom-ownership guard and preset state branching from addSandboxPolicyUnlocked into a focused helper such as resolveNamedPresetReapply(sandboxName, preset). Preserve the existing custom-policy errors, content loading, match early return, unreadable-live-policy failure, and drift/absent reapplyState behavior; have the outer function use the helper for orchestration.Source: Coding guidelines
🤖 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 `@docs/network-policy/integration-policy-examples.mdx`:
- Around line 103-104: Update the policy-add reapplication description in the
integration policy examples to state that it re-applies whenever the preset
content differs from the live policy, including live-policy overrides or removed
preset entries, not only when the preset file changes. Preserve the existing
safe no-op and exit-zero behavior when the contents already match.
---
Nitpick comments:
In `@src/lib/actions/sandbox/policy-channel.ts`:
- Around line 168-216: Extract the custom-ownership guard and preset state
branching from addSandboxPolicyUnlocked into a focused helper such as
resolveNamedPresetReapply(sandboxName, preset). Preserve the existing
custom-policy errors, content loading, match early return,
unreadable-live-policy failure, and drift/absent reapplyState behavior; have the
outer function use the helper for orchestration.
In `@src/lib/policy/index.ts`:
- Around line 1544-1550: Thread the caller’s real sandbox name through
selectFromList and its options from policy-channel.ts, then use that value in
the already-applied preset guidance instead of the literal <sandbox>
placeholder. Preserve the existing policy-add command structure and behavior.
🪄 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: bab0d24c-9b30-46dc-b9a6-0d505fdcdda0
📒 Files selected for processing (7)
docs/network-policy/customize-network-policy.mdxdocs/network-policy/integration-policy-examples.mdxdocs/reference/commands.mdxsrc/lib/actions/sandbox/policy-channel-add-drift.test.tssrc/lib/actions/sandbox/policy-channel.tssrc/lib/policy/index.tstest/policies.test.ts
The codebase-growth guardrail caps test/policies.test.ts at 1530 lines; fold the picker-hint pin into the existing already-applied assertion as a single regex instead of adding an import and a second assertion. Refs #7323 Signed-off-by: Dongni-Yang <dongniy@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The growth guardrail rejects new if statements in changed test files; rewrite the captureExit helper assertion-style. Refs #7323 Signed-off-by: Dongni-Yang <dongniy@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Note on the |
test/policy-roundtrip-docs.test.ts slices customize-network-policy.mdx from the URL-Based MCP Server heading to the Export heading and pins exactly one binaries path entry in that slice; place the new raw TLS passthrough recipe above the MCP recipe so the slice stays scoped. Refs #7323 Signed-off-by: Dongni-Yang <dongniy@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CodeRabbit: the previous wording implied re-apply only follows preset file edits; drift also covers live-policy overrides and removed entries. Refs #7323 Signed-off-by: Dongni-Yang <dongniy@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The E2E / PR Gate Coordination failure shares the same pre-existing root cause as the image builds: the selected e2e run's jobs (credential-sanitization, network-policy, onboard-repair) all fail while building/onboarding the sandbox image on the Dockerfile.base OpenClaw layer — the mcporter@0.7.3 advisory breakage described above. Re-dispatching e2e will not help until that remediation (#7355 / #7332) lands; the e2e failures contain no assertion against this PR's changed behavior. |
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
apurvvkumaria
left a comment
There was a problem hiding this comment.
Reviewed at exact head 5f26a39 after the append-only refresh from current main. The named preset drift path correctly reapplies the shipped single-key presets, including the required tls: skip field edit; focused drift and policy integration suites pass 100/100, and the merge was conflict-free with a Verified DCO commit. The hypothetical multi-key removed-key ownership case requires registry history and is safe fix-forward rather than a blocker for #7323.
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
<!-- markdownlint-disable MD041 --> ## Summary This PR adds the canonical dated release entry for NemoClaw v0.0.94 before the tag is cut. The entry reconciles all 26 commits since v0.0.93 and links each user-visible change to its owning documentation. ## Changes - Add `docs/changelog/2026-07-24.mdx` with the exact `## v0.0.94` heading, parser-safe SPDX comment, release summary, and detailed bullets. - Record sandbox restore and update behavior, onboarding and inference changes, network policy behavior, security evidence, Hermes build performance, DGX Station guidance, and E2E validation changes. - Preserve `docs/` as the source of truth without changing the AI-agent documentation routing skill. - Use [E2E run 30075443016](https://github.com/NVIDIA/NemoClaw/actions/runs/30075443016) for release QA evidence at exact tested SHA `04e6dfa883071dda9df429c66e73168e1a995cba`. ### Source summary - [#7461](#7461) -> `docs/changelog/2026-07-24.mdx`: Record the ownership-preserving Hermes image layer reduction and hosted timing comparison. - [#7460](#7460) -> `docs/changelog/2026-07-24.mdx`: Record removal of candidate Hermes swap setup from E2E validation. - [#7458](#7458) -> `docs/security/fern-5.80.1-dependency-review.md`, `docs/changelog/2026-07-24.mdx`: Record the reviewed Fern CLI update. - [#7457](#7457) -> `docs/changelog/2026-07-24.mdx`: Record periodic runner-pressure telemetry. - [#7455](#7455) -> `docs/changelog/2026-07-24.mdx`: Record non-blocking absent Fern previews. - [#7450](#7450) -> `docs/changelog/2026-07-24.mdx`: Record stable cancellation handling for live-test child processes. - [#7449](#7449) -> `docs/changelog/2026-07-24.mdx`: Record parallel plugin EXDEV coverage. - [#7448](#7448) -> `docs/changelog/2026-07-24.mdx`: Record isolated long-running E2E lanes. - [#7444](#7444) -> `docs/changelog/2026-07-24.mdx`: Record exact-head Hermes swap validation. - [#7437](#7437) -> `docs/manage-sandboxes/backup-restore.mdx`, `docs/changelog/2026-07-24.mdx`: Record gateway pairing and authenticated verification after cross-sandbox restore. - [#7436](#7436) -> `docs/manage-sandboxes/backup-restore.mdx`, `docs/reference/commands.mdx`, `docs/changelog/2026-07-24.mdx`: Record selected stale-state cleanup and Hermes virtual-environment access repair. - [#7385](#7385) -> `docs/network-policy/customize-network-policy.mdx`, `docs/changelog/2026-07-24.mdx`: Record the read-only agent-variant route check. - [#7371](#7371) -> `docs/changelog/2026-07-24.mdx`: Record host-artifact verification for session exports. - [#7359](#7359) -> `docs/changelog/2026-07-24.mdx`: Record platform validation for managed vLLM model overrides. - [#7356](#7356) -> `docs/changelog/2026-07-24.mdx`: Record token-shaped value redaction for `sandbox doctor --json`. - [#7354](#7354) -> `docs/security/advisory-early-warning.md`, `docs/changelog/2026-07-24.mdx`: Record advisory correlation and retained audit provenance. - [#7352](#7352) -> `docs/network-policy/customize-network-policy.mdx`, `docs/network-policy/integration-policy-examples.mdx`, `docs/reference/commands.mdx`, `docs/changelog/2026-07-24.mdx`: Record preset reapplication and bounded `tls: skip` guidance. - [#7345](#7345) -> `docs/security/openclaw-2026.6.10-dependency-review.md`, `docs/security/openclaw-2026.7.1-dependency-review.md`, `docs/changelog/2026-07-24.mdx`: Record reviewed npm audit exception enforcement. - [#7340](#7340) -> `docs/network-policy/customize-network-policy.mdx`, `docs/changelog/2026-07-24.mdx`: Record the repaired CLI-reference route. - [#7334](#7334) -> `docs/get-started/dgx-station-preparation.mdx`, `docs/changelog/2026-07-24.mdx`: Record the qualified OTA metadata fallback and narrowed override wording. - [#7322](#7322) -> `docs/changelog/2026-07-24.mdx`: Reconcile the gateway source tag added to plugin registration banners. - [#7284](#7284) -> `docs/manage-sandboxes/update-sandboxes.mdx`, `docs/changelog/2026-07-24.mdx`: Record read-only `upgrade-sandboxes --check` behavior and recorded-gateway selection. - [#7277](#7277) -> `docs/changelog/2026-07-24.mdx`: Reconcile deterministic gateway TCP refusal coverage. - [#7234](#7234) -> `docs/reference/troubleshooting.mdx`, `docs/changelog/2026-07-24.mdx`: Record preserved DGX Spark managed vLLM Express intent on resume. - [#7185](#7185) -> `docs/reference/troubleshooting.mdx`, `docs/changelog/2026-07-24.mdx`: Record IPv4 fallback DNS selection and exact resolver probing. - [#6820](#6820) -> `docs/reference/commands.mdx`, `docs/changelog/2026-07-24.mdx`: Record the versioned, redacted `--events=jsonl` onboarding stream. ## Type of Change - [ ] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [x] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates - [ ] Tests added or updated for changed behavior - [x] Existing tests cover changed behavior — justification: `npx vitest run test/changelog-docs.test.ts` passed 6/6 tests. - [ ] Tests not applicable — justification: - [x] Docs updated for user-facing behavior changes - [ ] Docs not applicable — justification: - [ ] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [ ] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Documentation Writer Review - [x] Documentation writer subagent reviewed the completed changes - Result: `docs-updated` - Evidence: `docs/changelog/2026-07-24.mdx`; the writing rules, documentation style, exact release range, skip terms, published routes, and product scope were reviewed; the changelog test passed 6/6; `npm run docs` passed with route checking OK, zero errors, and two existing warnings. - Agent: Codex Desktop <!-- docs-review-head-sha: 65368f9 --> <!-- docs-review-agents-blob-sha: 9c9b36d --> ## DGX Station Hardware Evidence - [ ] Tested on DGX Station - Tested commit: Not applicable - Station profile/scenario: Not applicable - Result: Not applicable - Supporting evidence: Not applicable. This PR does not change `scripts/prepare-dgx-station-host.sh`. ## Verification - [x] PR description includes a `Signed-off-by:` line and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run check:diff` passed when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — `npx vitest run test/changelog-docs.test.ts` passed 6/6 tests. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: Not applicable to the dated changelog entry. - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only). The build passed with zero errors and two existing Fern warnings. - [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). Native dated changelog entries use the required parser-safe MDX SPDX comment and no frontmatter. --- Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added the v0.0.94 release changelog. * Documented improvements to sandbox snapshot and restore behavior. * Added updates for gateway selection, policy comparisons, onboarding event output, and DGX recovery workflows. * Documented enhanced diagnostics redaction, npm audit provenance, image assembly performance, and validation stability improvements. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Summary
NemoClaw-side fix for the two actionable parts of #7323 (Cloudflare-fronted upstreams reset connections because the sandbox egress proxy re-originates TLS even with
access: full).The connection resets themselves originate upstream: the OpenShell egress proxy terminates and re-originates TLS for allowed HTTPS endpoints, and
access: fullonly lifts L7 method/path rules. The supported unblock — declaring the endpoint as a raw L4 CONNECT tunnel withaccess: full+tls: skip— existed but was undocumented (only discoverable in a comment inside the WhatsApp channel preset). The second defect from the report is NemoClaw code and is fixed here:policy-add <preset>refused to pick up edited preset files, forcing a destructivepolicy-remove/policy-addcycle.Changes
policy-add <preset>(src/lib/actions/sandbox/policy-channel.ts): naming an already-applied preset now compares the preset content against the live gateway policy.src/lib/policy/index.ts): already-applied rejection now includes a hint pointing at the named re-apply path.tls: skip" recipe (docs/network-policy/customize-network-policy.mdx): when to use it (CDN/Cloudflare-fronted endpoints resetting re-originated handshakes, protocols like WhatsApp's Noise that tunnel their own crypto), a worked preset example, and a warning that L7 inspection is disabled for that endpoint.my-mcprecipe now apply catalog presets by name — the previously documented flow (save intonemoclaw-blueprint/policies/presets/, thenpolicy-add --from-filethe same file) self-collides with the built-in name-collision guard and cannot work as written. Also documents that the filename must matchpreset.name(a mismatch is a silent no-op today).docs/reference/commands.mdx(policy-add exit-code contract) anddocs/network-policy/integration-policy-examples.mdx(removes the now-obsoletepolicy-remove-first workaround).src/lib/actions/sandbox/policy-channel-add-drift.test.ts(match/drift/absent/dry-run/confirm-declined/non-interactive/custom-guard/unreadable states) plus the updated picker pin.Documentation Writer Review
docs-updatedBehavior notes for reviewers
applyPreseteverywhere else). This means a manual live-policy edit inside a preset-owned key is reverted by a scriptedpolicy-add --yesof that preset; the preview/confirm path and the "no longer matches the live policy" notice make this explicit. Flagging for maintainer sign-off as a deliberate semantics choice.access: full, and the re-originated handshake that Cloudflare rejects) needs an upstream OpenShell change and is out of scope here; a root-cause comment with the workaround is posted on Sandbox egress proxy re-originates TLS even with access: full, causing Cloudflare-fronted upstreams to reset the connection #7323.Testing
tsc -p tsconfig.cli.jsonclean; biome clean;npm run docs:check-agent-variantspasses.Closes #7323
Signed-off-by: Dongni-Yang dongniy@nvidia.com
🤖 Generated with Claude Code
Summary by CodeRabbit
tls: skip, including effective egress scope previews and warnings about disabled L7 inspection.policy-add outlookidempotency), MCP preset application by preset name, andtls: skiplimitations.