Skip to content

feat(sandbox-mgmt): experimental shields and config commands#1976

Merged
ericksoa merged 11 commits into
mainfrom
feat/sandbox-management-commands-v2
Apr 17, 2026
Merged

feat(sandbox-mgmt): experimental shields and config commands#1976
ericksoa merged 11 commits into
mainfrom
feat/sandbox-management-commands-v2

Conversation

@ericksoa

@ericksoa ericksoa commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Experimental sandbox management commands for shields and config operations. This feature is not formally documented or advertised — it is gated behind the same experimental-feature conventions used elsewhere in the codebase.

  • shields down/up/status — time-bounded policy relaxation with automatic restore
  • config get/set/rotate-token — host-initiated config inspection and mutation
  • E2E test exercising the full lifecycle against a live sandbox

Shields

  • Per-sandbox state namespacing (shields-<name>.json)
  • Auto-restore timer via detached fork() with explicit IPC disconnect
  • Rollback on timer fork failure (sandbox never left unguarded)
  • Timer verifies policy restore succeeded; reverts state on failure
  • Append-only audit trail with credential redaction

Config

  • config get: read-only with credential stripping and gateway section removal
  • config set: SSRF validation, gateway write blocking, kubectl exec for Landlock bypass
  • config rotate-token: env var, stdin, or interactive prompt
  • All openshell sandbox exec calls use --name flag (not positional)

Security hardening (CodeRabbit review)

  • Endpoint URL redaction in plugin /nemoclaw config slash command
  • Audit reason/error fields pass through redact() before writing
  • shields down rejects missing flag values and unknown flags
  • parseCurrentPolicy() strips metadata header from policy snapshots

Test plan

  • E2E: test/e2e/test-shields-config.sh — full 12-phase lifecycle (37/37 pass on CI)
  • Unit: duration parsing, state management, audit format, config set validation, URL redaction
  • Plugin branch coverage 86.28% (above 86% ratchet)

Supersedes #1849.

Summary by CodeRabbit

  • New Features

    • Added NemoClaw shields: shields down|up|status with timeout, reason, policy snapshot, audit logging, auto-restore, and CLI + slash command/status outputs.
    • Added sandbox config commands: config get|set|rotate-token with redacted displays, validation, and optional in-sandbox apply.
    • Improved endpoint display sanitization and duration parsing/limits.
  • Tests

    • Expanded unit, integration, and E2E coverage for shields, config, duration parsing, token rotation, and audit logging.
  • Chores

    • CI failure notification job updated; agent sandbox filesystem policies adjusted.

Add shields down/up/status and config get/set/rotate-token for sandbox
management. These commands are experimental — interfaces may change and
no documentation is published. The feature is exercised by a new E2E
test (test/e2e/test-shields-config.sh) but is not formally supported.

Shields:
- Time-bounded policy relaxation with automatic restore timer
- State namespaced per sandbox (shields-<name>.json)
- Rollback on timer fork failure (never leaves sandbox unguarded)
- Timer checks policy restore result; reverts state on failure
- Audit trail (shields-audit.jsonl) with credential redaction

Config:
- config get: read-only inspection with credential stripping
- config set: host-initiated mutation with SSRF validation
- config rotate-token: credential rotation via env, stdin, or prompt
- All commands use --name flag for openshell sandbox exec

Security:
- Endpoint URL redaction in config-show (plugin slash command)
- Audit reason/error fields redacted via runner.ts patterns
- shields down flag validation (reject missing values, unknown flags)

Testing:
- E2E: full shields lifecycle, config CRUD, timer auto-restore
- Unit: duration parsing, state management, audit format, URL redaction
- Plugin branch coverage 86.28% (above 86% ratchet)

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@coderabbitai

coderabbitai Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds host-side shields and sandbox-config features: persisted shields state fields with backfill, detached auto-restore timer, JSONL audit logging, policy snapshot/restore and config permission toggles, duration and sandbox-config utilities, CLI wiring for shields/config, policy/policy-permissive adjustments, and many unit/e2e tests.

Changes

Cohort / File(s) Summary
CI / Workflow
\.github/workflows/nightly-e2e.yaml
notify-on-failure job now also depends on shields-config-e2e and includes its failure in the issue-creation condition.
Agent policies
agents/hermes/policy-permissive.yaml, nemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml
Added /sandbox to Hermes read-write allowlist and explanatory comments; OpenClaw sandbox disabled include_workdir and moved /sandbox and /sandbox/.openclaw to read-only while preserving other read-write paths.
State model & tests
nemoclaw/src/blueprint/state.ts, nemoclaw/src/blueprint/state.test.ts
Extended NemoClawState with shields fields, initialized defaults in blankState(), and changed loadState() to merge persisted partial state; tests added/updated to assert backfill behavior.
Slash commands & routing
nemoclaw/src/commands/config-show.ts, nemoclaw/src/commands/config-show.test.ts, nemoclaw/src/commands/shields-status.ts, nemoclaw/src/commands/shields-status.test.ts, nemoclaw/src/commands/slash.ts, nemoclaw/src/commands/slash.test.ts
Added slashConfigShow and slashShieldsStatus, wired config/shields subcommands into slash routing; tests cover redaction, display formatting, and routing.
Onboard endpoint sanitization
nemoclaw/src/onboard/config.ts, nemoclaw/src/onboard/config.test.ts
describeOnboardEndpoint now parses and redacts credentials and sensitive query params from endpoint URLs, with a parse-fallback; tests added.
Duration util & tests
src/lib/duration.ts, test/duration.test.ts
New parseDuration plus MAX_SECONDS (1800) and DEFAULT_SECONDS (300); enforces format and bounds; tests added.
Sandbox config management
src/lib/sandbox-config.ts, test/config-set.test.ts, test/config-rotate-token.test.ts
New host-side sandbox-config module: resolveAgentConfig, configGet, configSet, configRotateToken, dotpath helpers, URL validation, stdin reader; heavy logic for reading/updating agent config via sandbox exec and tests added.
Shields core, timer & tests
src/lib/shields.ts, src/lib/shields-timer.ts, test/shields.test.ts
New shields workflows (shieldsDown, shieldsUp, shieldsStatus, isShieldsDown), policy snapshot/restore, config unlock/lock via kubectl exec, detached auto-restore timer script, state persistence; comprehensive tests added.
Shields audit & tests
src/lib/shields-audit.ts, test/shields-audit.test.ts
New JSONL audit module with ShieldsAuditEntry, appendAuditEntry, AUDIT_DIR/AUDIT_FILE; writes redacted JSONL with 0600 perms; tests validate JSONL output and redaction.
CLI integration
src/nemoclaw.ts
Wired CLI subcommands: `nemoclaw shields <down
E2E script
test/e2e/test-shields-config.sh
New comprehensive e2e script exercising shields lifecycle, config get/set/rotate-token, SSRF/private-IP rejection, audit verification, auto-restore, and cleanup against a live sandbox.
Test additions / expansions
test/*.test.ts, test/*.sh
Numerous new and expanded unit/integration tests covering exports, URL validation, dotpath helpers, duration parsing, audit logging, shields behaviors, and CLI routing.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as Host CLI
    participant State as Local State File
    participant Policy as Policy Engine
    participant Timer as Auto-Restore Timer
    participant Audit as Audit Log

    CLI->>State: read state (merge blankState() with persisted)
    State-->>CLI: current shields state
    CLI->>Policy: capture current policy (snapshot)
    Policy-->>CLI: policy YAML
    CLI->>State: persist snapshot path & shieldsDown metadata
    State-->>CLI: persisted
    CLI->>Policy: apply relaxed policy (permissive or provided)
    Policy-->>CLI: applied
    CLI->>Timer: fork detached timer with restoreAt
    Timer-->>CLI: started (PID marker)
    CLI->>Audit: append shields_down entry
    Audit-->>CLI: appended

    Note over Timer: waits until restoreAt
    Timer->>State: read snapshot path & state
    State-->>Timer: state data
    Timer->>Policy: verify snapshot exists
    Policy-->>Timer: snapshot OK
    Timer->>Policy: restore policy from snapshot
    Policy-->>Timer: restored
    Timer->>State: clear shieldsDown fields
    State-->>Timer: persisted
    Timer->>Audit: append shields_auto_restore entry
    Audit-->>Timer: appended
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I nibbled code in moonlit hops,
I snapshot policies, danced with clocks,
Timers hum and audits sing,
Shields dip down, then up they spring,
A rabbit guards the sandbox locks 🐇

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely describes the main change: adding experimental shields and config sandbox management commands.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sandbox-management-commands-v2

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Comment @coderabbitai help to get the list of available commands and usage tips.

@ericksoa ericksoa self-assigned this Apr 16, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
nemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Stale comment: include_workdir: true no longer matches actual value.

Line 9 states "Filesystem: include_workdir: true makes the sandbox home directory writable" but the actual value on line 21 is now false. This comment should be updated to reflect the current behavior.

📝 Suggested fix
-# Filesystem: include_workdir: true makes the sandbox home directory writable.
+# Filesystem: include_workdir must be false (see openclaw-sandbox.yaml for rationale).
+# Config mutability is handled by shields down/up via kubectl exec (bypasses Landlock).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml` at line 9,
Update the stale inline comment describing Filesystem behavior so it matches the
current setting of include_workdir (which is false); locate the comment that
reads "Filesystem: include_workdir: true makes the sandbox home directory
writable" and change it to state that include_workdir: false makes the sandbox
home directory read-only (or otherwise describe the current behavior), ensuring
the comment and the include_workdir setting in openclaw-sandbox-permissive.yaml
are consistent.
nemoclaw/src/commands/slash.test.ts (1)

64-81: ⚠️ Potential issue | 🟡 Minor

Test fixture blankState() is missing lastRebuildAt and lastRebuildBackupPath fields.

The NemoClawState interface (per context snippet from nemoclaw/src/blueprint/state.ts) includes lastRebuildAt and lastRebuildBackupPath, but this test fixture omits them. This could cause type mismatches or incomplete state mocking.

💡 Proposed fix
 function blankState(): NemoClawState {
   return {
     lastRunId: null,
     lastAction: null,
     blueprintVersion: null,
     sandboxName: null,
     migrationSnapshot: null,
     hostBackupPath: null,
     createdAt: null,
     updatedAt: new Date().toISOString(),
+    lastRebuildAt: null,
+    lastRebuildBackupPath: null,
     shieldsDown: false,
     shieldsDownAt: null,
     shieldsDownTimeout: null,
     shieldsDownReason: null,
     shieldsDownPolicy: null,
     shieldsPolicySnapshotPath: null,
   };
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nemoclaw/src/commands/slash.test.ts` around lines 64 - 81, The test fixture
blankState() returns an incomplete NemoClawState; add the missing fields
lastRebuildAt and lastRebuildBackupPath to the returned object so the shape
matches the NemoClawState interface: include lastRebuildAt: null (or ISO string
when appropriate) and lastRebuildBackupPath: null (or an empty string if your
code expects a string) alongside the other properties in the blankState()
function to prevent type mismatches in tests.
🧹 Nitpick comments (3)
agents/hermes/policy-permissive.yaml (1)

14-17: Soften the “must match exactly” claim to avoid policy drift confusion.

Line 14 says this section must match policy-additions.yaml exactly, but this file also includes an extra write path at Line 33 (/sandbox/.nemoclaw). That wording can mislead future edits.

Proposed wording tweak
-  # Filesystem section MUST match the default Hermes policy (policy-additions.yaml)
-  # exactly — OpenShell rejects include_workdir changes and read_only path
+  # Filesystem section should mirror the default Hermes policy
+  # (policy-additions.yaml), except explicitly documented NemoClaw state paths.
+  # OpenShell rejects include_workdir changes and read_only path
   # removals on live sandboxes. Config file mutability is handled separately
   # by shields down/up via kubectl exec (bypasses Landlock).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@agents/hermes/policy-permissive.yaml` around lines 14 - 17, Update the
comment that currently reads "Filesystem section MUST match the default Hermes
policy (policy-additions.yaml) exactly" to a softer phrasing that conveys intent
without implying absolute exactness—e.g., "Filesystem section should generally
match the default Hermes policy (policy-additions.yaml); avoid changing
include_workdir or removing read_only paths on live sandboxes." Ensure the new
text also calls out the known exception (/sandbox/.nemoclaw write path) so
future editors aren't misled, and retain the warning about using kubectl exec
for config mutability and Landlock-related restrictions.
src/lib/sandbox-config.ts (1)

504-512: Consider: readStdin has no timeout.

If stdin never closes (e.g., piped from a process that hangs), this promise will never resolve. For interactive CLI usage this is acceptable, but if --from-stdin is used in automated pipelines, a timeout might be valuable.

This is a minor robustness consideration for future hardening, not blocking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/sandbox-config.ts` around lines 504 - 512, readStdin currently can
hang indefinitely; update the readStdin function to accept an optional
timeoutMillis (or use a sensible default) and implement a Promise.race between
the stdin-reading promise and a timeout promise; when the timeout fires, reject
with a descriptive error, and ensure you remove stdin listeners and clear any
timers on both success and timeout to avoid leaks (refer to the readStdin
function name and its "data"/"end"/"error" listeners when making these changes).
test/e2e/test-shields-config.sh (1)

466-481: Auto-restore test has a potential race condition.

The test waits 15 seconds for a 10-second timeout, which should be sufficient. However, if the timer process is delayed (e.g., slow CI runner, policy set --wait taking longer), the test may flap. The fallback at line 479 (nemoclaw shields up || true) is good for cleanup, but consider increasing the sleep margin or adding a retry loop.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/e2e/test-shields-config.sh` around lines 466 - 481, The auto-restore
check using STATUS_AFTER_TIMER and the command `nemoclaw "${SANDBOX_NAME}"
shields status` can flake because it sleeps a fixed 15s for a 10s timer; modify
the test to avoid the race by replacing the single sleep+check with a short
retry loop: after the initial sleep, poll `nemoclaw "${SANDBOX_NAME}" shields
status` up to a configurable timeout (e.g., 30s total) with small intervals and
break when output contains "Shields: UP"; keep the existing cleanup fallback
using `nemoclaw "${SANDBOX_NAME}" shields up || true` and ensure any failure
still calls `fail "Auto-restore timer did not restore shields within Xs"` with
the total wait reflected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nemoclaw/src/commands/config-show.ts`:
- Around line 32-35: The current rendering of credentialEnv in the config-show
command can echo unsafe or empty values; update the logic in the config-show
handler (where redactedCredential and lastFour are computed) to only render
`$NAME` when config.credentialEnv matches a strict env-var name regexp (e.g.
/^[A-Z0-9_]+$/); if it does not match or is empty, set redactedCredential to a
generic label like "(configured via env var)" or "(not configured)" and adjust
lastFour accordingly so raw tokens or malformed strings from loadOnboardConfig()
are never printed.

In `@nemoclaw/src/commands/shields-status.test.ts`:
- Around line 16-33: The blankState() test fixture returns an incomplete
NemoClawState missing the lastRebuildAt and lastRebuildBackupPath fields; update
blankState() to include these two properties (initialize them similarly to other
timestamp/backup fields—e.g., null) so the fixture matches the full
NemoClawState shape used in tests like slash.test.ts and avoids type/coverage
gaps when using lastRebuildAt or lastRebuildBackupPath in tests.

In `@src/lib/shields-timer.ts`:
- Around line 114-125: The catch block that calls
appendAudit("shields_up_failed", ...) currently lets execution fall into finally
which unconditionally calls process.exit(0), masking failures; modify
shields-timer.ts so the process exits with a non-zero status when an exception
occurs—e.g. set a local flag or call process.exit(1) from the catch (or set
process.exitCode = 1) and ensure the finally block uses that code or only
performs cleanup via cleanupMarker() without forcing exit(0); update the catch
handling around appendAudit(...) and the finally that calls cleanupMarker() /
process.exit(...) so errors produce a non-zero exit (use the function/variable
names appendAudit, cleanupMarker, and process.exit/process.exitCode to locate
changes).

In `@test/config-set.test.ts`:
- Around line 88-90: The test description string "accepts public http URLs" in
the it(...) block does not match the URL passed to validateUrlValue (currently
"https://example.com"); update the test so the description and input agree:
either change the description to "accepts public https URLs" or modify the URL
to "http://example.com" to match "http" — adjust the it(...) description or the
validateUrlValue argument accordingly.

---

Outside diff comments:
In `@nemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml`:
- Line 9: Update the stale inline comment describing Filesystem behavior so it
matches the current setting of include_workdir (which is false); locate the
comment that reads "Filesystem: include_workdir: true makes the sandbox home
directory writable" and change it to state that include_workdir: false makes the
sandbox home directory read-only (or otherwise describe the current behavior),
ensuring the comment and the include_workdir setting in
openclaw-sandbox-permissive.yaml are consistent.

In `@nemoclaw/src/commands/slash.test.ts`:
- Around line 64-81: The test fixture blankState() returns an incomplete
NemoClawState; add the missing fields lastRebuildAt and lastRebuildBackupPath to
the returned object so the shape matches the NemoClawState interface: include
lastRebuildAt: null (or ISO string when appropriate) and lastRebuildBackupPath:
null (or an empty string if your code expects a string) alongside the other
properties in the blankState() function to prevent type mismatches in tests.

---

Nitpick comments:
In `@agents/hermes/policy-permissive.yaml`:
- Around line 14-17: Update the comment that currently reads "Filesystem section
MUST match the default Hermes policy (policy-additions.yaml) exactly" to a
softer phrasing that conveys intent without implying absolute exactness—e.g.,
"Filesystem section should generally match the default Hermes policy
(policy-additions.yaml); avoid changing include_workdir or removing read_only
paths on live sandboxes." Ensure the new text also calls out the known exception
(/sandbox/.nemoclaw write path) so future editors aren't misled, and retain the
warning about using kubectl exec for config mutability and Landlock-related
restrictions.

In `@src/lib/sandbox-config.ts`:
- Around line 504-512: readStdin currently can hang indefinitely; update the
readStdin function to accept an optional timeoutMillis (or use a sensible
default) and implement a Promise.race between the stdin-reading promise and a
timeout promise; when the timeout fires, reject with a descriptive error, and
ensure you remove stdin listeners and clear any timers on both success and
timeout to avoid leaks (refer to the readStdin function name and its
"data"/"end"/"error" listeners when making these changes).

In `@test/e2e/test-shields-config.sh`:
- Around line 466-481: The auto-restore check using STATUS_AFTER_TIMER and the
command `nemoclaw "${SANDBOX_NAME}" shields status` can flake because it sleeps
a fixed 15s for a 10s timer; modify the test to avoid the race by replacing the
single sleep+check with a short retry loop: after the initial sleep, poll
`nemoclaw "${SANDBOX_NAME}" shields status` up to a configurable timeout (e.g.,
30s total) with small intervals and break when output contains "Shields: UP";
keep the existing cleanup fallback using `nemoclaw "${SANDBOX_NAME}" shields up
|| true` and ensure any failure still calls `fail "Auto-restore timer did not
restore shields within Xs"` with the total wait reflected.
🪄 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: ff620ec6-3c66-4952-920e-6950e758f7dd

📥 Commits

Reviewing files that changed from the base of the PR and between c02d29e and d92c9f3.

📒 Files selected for processing (25)
  • .github/workflows/nightly-e2e.yaml
  • agents/hermes/policy-permissive.yaml
  • nemoclaw-blueprint/policies/openclaw-sandbox-permissive.yaml
  • nemoclaw/src/blueprint/state.test.ts
  • nemoclaw/src/blueprint/state.ts
  • nemoclaw/src/commands/config-show.test.ts
  • nemoclaw/src/commands/config-show.ts
  • nemoclaw/src/commands/shields-status.test.ts
  • nemoclaw/src/commands/shields-status.ts
  • nemoclaw/src/commands/slash.test.ts
  • nemoclaw/src/commands/slash.ts
  • nemoclaw/src/onboard/config.test.ts
  • nemoclaw/src/onboard/config.ts
  • src/lib/duration.ts
  • src/lib/sandbox-config.ts
  • src/lib/shields-audit.ts
  • src/lib/shields-timer.ts
  • src/lib/shields.ts
  • src/nemoclaw.ts
  • test/config-rotate-token.test.ts
  • test/config-set.test.ts
  • test/duration.test.ts
  • test/e2e/test-shields-config.sh
  • test/shields-audit.test.ts
  • test/shields.test.ts

Comment thread nemoclaw/src/commands/config-show.ts Outdated
Comment thread nemoclaw/src/commands/shields-status.test.ts
Comment thread src/lib/shields-timer.ts
Comment thread src/nemoclaw.ts
Comment thread test/config-set.test.ts
…e, stale-registry gate

- Validate credentialEnv matches safe env-var pattern before echoing in
  config-show (prevents leaking malformed persisted data)
- Exit with status 1 in shields-timer catch block instead of falling
  through to finally { process.exit(0) }
- Add "shields" and "config" to the stale-registry recovery gate so
  they work when the local registry is out of date
- Fix test description/URL mismatch in config-set test
- Add missing lastRebuildAt/lastRebuildBackupPath to blankState() test
  fixtures in shields-status.test.ts and slash.test.ts
- Fix stale comments in permissive policy YAML files

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@wscurran wscurran added priority: high experimental Has architectural implications, requires consensus from all maintainers before landing labels Apr 16, 2026
ericksoa and others added 3 commits April 16, 2026 14:03
…ds-config)

Both branches added new E2E jobs to the notify-on-failure needs list —
keep both token-rotation-e2e (main) and shields-config-e2e (this branch).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@brandonpelfrey brandonpelfrey self-requested a review April 16, 2026 22:33
@ericksoa ericksoa merged commit 2368927 into main Apr 17, 2026
12 checks passed
miyoungc added a commit that referenced this pull request Apr 17, 2026
Refresh user-facing docs against the 34 commits merged between v0.0.17
and v0.0.18. Highlights:

- Replace the Ollama 0.0.0.0 binding guidance with the new authenticated
  reverse proxy on 127.0.0.1:11435 (#1922).
- Document the compatible-endpoint provider defaulting to
  /v1/chat/completions and the NEMOCLAW_PREFERRED_API=openai-responses
  opt-in (#1984).
- Add the new nemoclaw upgrade-sandboxes command with --check, --auto,
  and --yes flags (#1943).
- Note the cross-sandbox messaging overlap warning and 409 detection in
  nemoclaw <name> status (#1953).
- Document the messaging-token rotation auto-rebuild flow (#1967).
- Cover new troubleshooting entries for the Ollama auth proxy, IPv6
  localhost resolution, orphan SSH port-forward cleanup on re-onboard,
  and rotated messaging credentials (#1978, #1950).
- Note tar failure exit code for nemoclaw debug --output (#1770) and the
  orphaned openshell process cleanup in nemoclaw uninstall (#1940).

Also:

- Extend docs/.docs-skip to exclude the experimental sandbox-mgmt
  shields and config commands (#1976).
- Fix a sphinx-autobuild infinite rebuild loop in docs/conf.py by
  writing docs/project.json only when its contents change.
- Bump the docs version switcher preferred entry to 0.0.18.
- Regenerate nemoclaw-user-* agent skills from docs/.

Signed-off-by: Miyoung Choi <miyoungc@nvidia.com>
Made-with: Cursor
miyoungc added a commit that referenced this pull request Apr 17, 2026
## Summary

Refresh user-facing documentation against the 34 commits merged between
v0.0.17 and v0.0.18, bump the docs version switcher to v0.0.18, and fix
a
`sphinx-autobuild` infinite-rebuild loop triggered by `docs/conf.py`.

## Changes

- **Ollama authenticated reverse proxy** (#1922): Replace the
`0.0.0.0:11434` guidance in `docs/inference/use-local-inference.md` with
the new token-gated proxy on `127.0.0.1:11435`, including persisted
token,
health-check exemption, and sandbox provider wiring. Replace the
matching
  troubleshooting entry in `docs/reference/troubleshooting.md`.
- **Compatible-endpoint default API path** (#1984): Document that the
compatible-endpoint provider now defaults to `/v1/chat/completions` and
  update `NEMOCLAW_PREFERRED_API` to describe `openai-responses` as the
  opt-in instead of `openai-completions`. Updates in
  `use-local-inference.md`, `switch-inference-providers.md`, and
  `troubleshooting.md`.
- **`nemoclaw upgrade-sandboxes` command** (#1943): Add a new reference
entry in `docs/reference/commands.md` covering `--check`, `--auto`, and
  `--yes` flags.
- **Messaging token rotation auto-rebuild** (#1967, #1953): Note the
  automatic rebuild behavior and cross-sandbox overlap warning in
  `docs/deployment/set-up-telegram-bridge.md`, `commands.md`, and
  `troubleshooting.md`.
- **Other troubleshooting additions**:
  - `localhost` → `127.0.0.1` IPv6 note (#1978)
  - Orphan SSH port-forward cleanup on re-onboard (#1950)
  - Orphan `openshell` process cleanup in `nemoclaw uninstall` (#1940)
  - Non-zero exit on tar failure in `nemoclaw debug --output` (#1770)
- **Skip list**: Extend `docs/.docs-skip` to exclude the experimental
  sandbox-mgmt shields and config commands feature (#1976), which was
  explicitly merged as not-yet-documented.
- **Build stability**: `docs/conf.py` now writes `docs/project.json`
only
when contents change, so `make docs-live` / `sphinx-autobuild` no longer
detects its own generated file as a source change and enters an infinite
  rebuild loop.
- **Version switcher**: Bump `docs/versions1.json` and
`docs/project.json`
preferred entry to v0.0.18 so this refresh renders under the new
version.
- **Agent skills**: Regenerate `nemoclaw-user-*` skills from `docs/`
with
  `scripts/docs-to-skills.py`.

## 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)

## Verification

- [x] `npx prek run --all-files` passes (ran via pre-commit hook on
staged files)
- [ ] `npm test` passes
- [ ] 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
- [x] `make docs` builds without warnings (doc changes only)
- [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

- [x] AI-assisted — tool: Cursor

---

Signed-off-by: Miyoung Choi <miyoungc@nvidia.com>

Made with [Cursor](https://cursor.com)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added `nemoclaw upgrade-sandboxes` command to rebuild sandboxes when
base-image digests change.
* Introduced authenticated reverse proxy for local Ollama inference with
token-based access control.
* Automatic sandbox backup, recreation, and restore when messaging
credentials are updated.
* Cross-sandbox messaging token overlap detection with status warnings.

* **Improvements**
* Compatible-endpoint provider now defaults to `/v1/chat/completions`
API path.
* Enhanced troubleshooting documentation with new diagnostics sections.

* **Documentation**
  * Updated onboarding and configuration guides.
  * Expanded version documentation to 0.0.18.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Miyoung Choi <miyoungc@nvidia.com>
@wscurran wscurran added the VDR Linked to VDR finding label May 11, 2026
@wscurran wscurran added feature PR adds or expands user-visible functionality and removed priority: high labels Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

experimental Has architectural implications, requires consensus from all maintainers before landing feature PR adds or expands user-visible functionality VDR Linked to VDR finding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants