feat(policy): add Personal onboarding tier - #8431
Conversation
📝 WalkthroughWalkthroughThe PR adds a ChangesPersonal policy tier
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Operator
participant Onboarding
participant PolicySelection
participant SandboxPolicy
participant NetworkPolicy
Operator->>Onboarding: choose personal tier
Onboarding->>PolicySelection: resolve tier and presets
PolicySelection->>SandboxPolicy: retain applicable maintained presets
SandboxPolicy->>NetworkPolicy: merge personal-open-internet
NetworkPolicy-->>Onboarding: validate hostless ports and allowed IP ranges
Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
Code Coverage OverviewLanguages: TypeScript TypeScript / code-coverage/pluginThe overall coverage in commit de69e0d in the TypeScript / code-coverage/cliThe overall coverage in commit de69e0d in the Show a code coverage summary of the most impacted files.
Updated |
|
🌿 Preview your docs: https://nvidia-preview-pr-8431.docs.buildwithfern.com/nemoclaw |
PR Review Advisor — No blocking findings reportedAdvisor assessment: No blocking advisor findings reported Model lanes
Second-opinion terminology and E2E selections are advisory. They do not change the primary assessment or E2E / PR Gate. 3 semantic terminology decisionsTerminology decisions are advisory. They affect the assessment only when a separate finding identifies concrete semantic impact.
E2E guidanceAdvisory only. E2E / PR Gate selects and runs jobs independently. Recommended E2E: 1 optional E2E recommendation
2 warnings · 0 suggestionsWarningsWarnings do not block.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/onboard/command.ts`:
- Around line 263-268: Update the portable profile environment-default logic
around NEMOCLAW_POLICY_TIER so an explicitly provided restrictive tier remains
restricted instead of being replaced by personal; apply personal only when the
tier is not explicitly set, while preserving the profile’s portable validation.
🪄 Autofix
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: 186d7f74-111e-4f49-8fb3-8e48649fd381
📒 Files selected for processing (16)
docs/reference/commands.mdxdocs/reference/network-policies.mdxdocs/security/best-practices.mdxnemoclaw-blueprint/policies/tiers.yamlscripts/install.shsrc/lib/onboard/command.test.tssrc/lib/onboard/command.tssrc/lib/onboard/policy-selection-prompts.tssrc/lib/onboard/policy-selection.tssrc/lib/onboard/sandbox-create-plan.test.tssrc/lib/onboard/sandbox-create-plan.tssrc/lib/onboard/station-express-resume.test.tssrc/lib/onboard/station-express-resume.tssrc/lib/policy/tiers.tstest/policy-tiers-onboard.test.tstest/policy-tiers.test.ts
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/lib/onboard/command.test.ts (1)
509-520: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert restoration of the new portable variables after manifest errors.
The portable case checks only the four legacy environment variables.
runOnboardCommandapplies the portable environment beforeapplyAgentsManifestEnvparses--agents. AddNEMOCLAW_POLICY_MODE,NEMOCLAW_POLICY_TIER, andNEMOCLAW_TOOL_DISCLOSUREtotestCase.keys; otherwise a regression that leaks one of these values after the YAML parse error can pass this test.Suggested test update
keys: [ "NEMOCLAW_EXPERIMENTAL_PROFILE", "NEMOCLAW_PROVIDER", "NEMOCLAW_MODEL", "NEMOCLAW_OLLAMA_NO_AUTOSTART", + "NEMOCLAW_POLICY_MODE", + "NEMOCLAW_POLICY_TIER", + "NEMOCLAW_TOOL_DISCLOSURE", ],As per path instructions, review tests for behavioral confidence at the public boundary.
🤖 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/onboard/command.test.ts` around lines 509 - 520, Extend the portable profile test case’s testCase.keys list to include NEMOCLAW_POLICY_MODE, NEMOCLAW_POLICY_TIER, and NEMOCLAW_TOOL_DISCLOSURE, so restoration is verified for all portable environment variables after the manifest YAML parse error. Keep the existing legacy variable assertions unchanged.Source: Path instructions
🤖 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.
Nitpick comments:
In `@src/lib/onboard/command.test.ts`:
- Around line 509-520: Extend the portable profile test case’s testCase.keys
list to include NEMOCLAW_POLICY_MODE, NEMOCLAW_POLICY_TIER, and
NEMOCLAW_TOOL_DISCLOSURE, so restoration is verified for all portable
environment variables after the manifest YAML parse error. Keep the existing
legacy variable assertions unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 7b153933-3529-469c-ac21-323c5cfdbf84
📒 Files selected for processing (3)
docs/reference/commands.mdxsrc/lib/onboard/command.test.tssrc/lib/onboard/command.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/lib/onboard/command.ts
- docs/reference/commands.mdx
b522445 to
f3bf8f1
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@nemoclaw-blueprint/policies/tiers.yaml`:
- Around line 53-57: Add connection-boundary negative-path tests for the
personal-open-internet preset, covering loopback, link-local, unspecified,
IPv4-mapped, and normalized IPv4/IPv6 destinations on ports 80 and 443. Keep
existing CIDR, composition, and unrelated policy coverage unchanged, and assert
these disallowed targets remain blocked.
🪄 Autofix
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: 2e7da59b-51ef-4691-a55e-406cc4d5854d
📒 Files selected for processing (25)
docs/reference/commands.mdxdocs/reference/network-policies.mdxdocs/security/best-practices.mdxnemoclaw-blueprint/policies/presets/personal-open-internet.yamlnemoclaw-blueprint/policies/tiers.yamlschemas/network-policy.schema.jsonscripts/install.shsrc/lib/inference/serving/resolver.test.tssrc/lib/inference/serving/resolver.tssrc/lib/onboard/command.test.tssrc/lib/onboard/command.tssrc/lib/onboard/policy-selection-prompts.tssrc/lib/onboard/policy-selection.tssrc/lib/onboard/sandbox-create-plan.test.tssrc/lib/onboard/sandbox-create-plan.tssrc/lib/onboard/station-express-resume.test.tssrc/lib/onboard/station-express-resume.tssrc/lib/policy/preset-allowed-ips.test.tssrc/lib/policy/preset-scope-render.test.tssrc/lib/policy/preset-scope-render.tssrc/lib/policy/tiers.tstest/personal-open-internet-policy.test.tstest/policy-tiers-onboard.test.tstest/policy-tiers.test.tstest/validate-config-schemas.test.ts
🚧 Files skipped from review as they are similar to previous changes (23)
- src/lib/onboard/policy-selection-prompts.ts
- test/validate-config-schemas.test.ts
- src/lib/policy/preset-allowed-ips.test.ts
- src/lib/onboard/command.test.ts
- src/lib/inference/serving/resolver.ts
- src/lib/policy/preset-scope-render.test.ts
- src/lib/inference/serving/resolver.test.ts
- src/lib/onboard/sandbox-create-plan.test.ts
- nemoclaw-blueprint/policies/presets/personal-open-internet.yaml
- src/lib/onboard/policy-selection.ts
- scripts/install.sh
- test/policy-tiers-onboard.test.ts
- src/lib/policy/tiers.ts
- schemas/network-policy.schema.json
- docs/reference/commands.mdx
- test/personal-open-internet-policy.test.ts
- src/lib/policy/preset-scope-render.ts
- src/lib/onboard/command.ts
- test/policy-tiers.test.ts
- docs/security/best-practices.mdx
- src/lib/onboard/sandbox-create-plan.ts
- src/lib/onboard/station-express-resume.ts
- docs/reference/network-policies.mdx
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@test/personal-open-internet-policy.test.ts`:
- Around line 36-38: In the CIDR validation test, remove the if statement
guarding invalid values and replace it with direct assertions that validate
family and prefix parsing, preserving the clear “invalid policy CIDR” failure
message for malformed CIDRs.
🪄 Autofix
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: 298f5e76-7f29-4632-b11d-41d74327305e
📒 Files selected for processing (25)
docs/reference/commands.mdxdocs/reference/network-policies.mdxdocs/security/best-practices.mdxnemoclaw-blueprint/policies/presets/personal-open-internet.yamlnemoclaw-blueprint/policies/tiers.yamlschemas/network-policy.schema.jsonscripts/install.shsrc/lib/inference/serving/resolver.test.tssrc/lib/inference/serving/resolver.tssrc/lib/onboard/command.test.tssrc/lib/onboard/command.tssrc/lib/onboard/policy-selection-prompts.tssrc/lib/onboard/policy-selection.tssrc/lib/onboard/sandbox-create-plan.test.tssrc/lib/onboard/sandbox-create-plan.tssrc/lib/onboard/station-express-resume.test.tssrc/lib/onboard/station-express-resume.tssrc/lib/policy/preset-allowed-ips.test.tssrc/lib/policy/preset-scope-render.test.tssrc/lib/policy/preset-scope-render.tssrc/lib/policy/tiers.tstest/personal-open-internet-policy.test.tstest/policy-tiers-onboard.test.tstest/policy-tiers.test.tstest/validate-config-schemas.test.ts
🚧 Files skipped from review as they are similar to previous changes (22)
- src/lib/policy/preset-allowed-ips.test.ts
- src/lib/policy/preset-scope-render.test.ts
- src/lib/onboard/command.ts
- scripts/install.sh
- src/lib/inference/serving/resolver.test.ts
- src/lib/onboard/sandbox-create-plan.ts
- test/policy-tiers.test.ts
- src/lib/onboard/station-express-resume.ts
- src/lib/onboard/sandbox-create-plan.test.ts
- src/lib/policy/tiers.ts
- src/lib/onboard/policy-selection-prompts.ts
- test/validate-config-schemas.test.ts
- src/lib/policy/preset-scope-render.ts
- docs/reference/commands.mdx
- nemoclaw-blueprint/policies/presets/personal-open-internet.yaml
- test/policy-tiers-onboard.test.ts
- nemoclaw-blueprint/policies/tiers.yaml
- src/lib/onboard/policy-selection.ts
- src/lib/onboard/command.test.ts
- schemas/network-policy.schema.json
- docs/security/best-practices.mdx
- docs/reference/network-policies.mdx
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@test/onboard-policy-suggestions.test.ts`:
- Line 528: Remove the { name: "brave" } entry from the expected Hermes filtered
result in the relevant test case, while preserving the remaining policy preset
expectations.
🪄 Autofix
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: ff112d21-edb2-4bbe-a535-9679a18f447d
📒 Files selected for processing (3)
src/lib/onboard/openclaw-otel-policy-presets.tstest/onboard-policy-suggestions.test.tstest/policy-tiers-onboard.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- test/policy-tiers-onboard.test.ts
<!-- markdownlint-disable MD041 --> ## Summary Adds the canonical dated changelog entry required before cutting `v0.0.104`. The entry reconciles user-facing changes merged from `v0.0.103` through `8d2b86aaf44968b4f7bc3b714222a73bd28e0403` while excluding hidden and experimental product surfaces. ## Changes - Added `docs/changelog/2026-08-06.mdx` with the exact `## v0.0.104` heading and release themes for local inference, private endpoints, network policy, state authority, lifecycle recovery, uninstall, Hermes, MCP diagnostics, credential safety, and installation guidance. - Source summary links: - [#8399](#8399) -> `docs/changelog/2026-08-06.mdx`: fixed DGX Spark local serving profiles. - [#8418](#8418) -> `docs/changelog/2026-08-06.mdx`: durable llama.cpp lifecycle management. - [#8422](#8422) -> `docs/changelog/2026-08-06.mdx`: recoverable llama.cpp receipt publication. - [#8402](#8402) -> `docs/changelog/2026-08-06.mdx`: remediable DGX Spark storage admission. - [#8391](#8391) -> `docs/changelog/2026-08-06.mdx`: host-local serving recipe contracts. - [#8401](#8401) -> `docs/changelog/2026-08-06.mdx`: serving profile lifecycle provenance. - [#8322](#8322) -> `docs/changelog/2026-08-06.mdx`: guarded llama.cpp route compatibility. - [#8272](#8272) -> `docs/changelog/2026-08-06.mdx`: explicitly trusted private endpoints with stable policy pins and CA trust. - [#8431](#8431) -> `docs/changelog/2026-08-06.mdx`: Personal onboarding policy tier and its trust boundary. - [#8143](#8143) -> `docs/changelog/2026-08-06.mdx`: manifest-derived state authority. - [#7859](#7859) -> `docs/changelog/2026-08-06.mdx`: side-effect-free lifecycle lock timeouts. - [#8262](#8262) -> `docs/changelog/2026-08-06.mdx`: managed gateway lease waiting. - [#8339](#8339) -> `docs/changelog/2026-08-06.mdx`: continued journaled rebuild recreation. - [#8373](#8373) -> `docs/changelog/2026-08-06.mdx`: restore readiness after compatibility decisions. - [#8443](#8443) -> `docs/changelog/2026-08-06.mdx`: fail-closed malformed registry handling. - [#8419](#8419) -> `docs/changelog/2026-08-06.mdx`: bounded recovery for a gateway that never served. - [#8486](#8486) -> `docs/changelog/2026-08-06.mdx`: target-scoped registry recovery. - [#8259](#8259) -> `docs/changelog/2026-08-06.mdx`: scoped uninstall ordering and retry safety. - [#8457](#8457) -> `docs/changelog/2026-08-06.mdx`: desktop metadata exclusion during uninstall. - [#8026](#8026) -> `docs/changelog/2026-08-06.mdx`: typed Hermes configuration policy. - [#8242](#8242) -> `docs/changelog/2026-08-06.mdx`: Hermes WhatsApp session diagnostics. - [#8344](#8344) -> `docs/changelog/2026-08-06.mdx`: patched Hermes image and dependency checks. - [#8491](#8491) -> `docs/changelog/2026-08-06.mdx`: bounded MCP discovery timeout. - [#8490](#8490) -> `docs/changelog/2026-08-06.mdx`: MCP shadow diagnostics. - [#7619](#7619) -> `docs/changelog/2026-08-06.mdx`: web-search credential isolation. - [#8476](#8476) -> `docs/changelog/2026-08-06.mdx`: stable preflight advisory identifiers. - [#8452](#8452) -> `docs/changelog/2026-08-06.mdx`: user-local CLI resolution. - [#8481](#8481) -> `docs/changelog/2026-08-06.mdx`: remote network-policy terminal guidance. - Product-scope exclusions: [#8429](#8429) remains experimental; [#8261](#8261) remains feature-gated; and portable-profile changes [#8408](#8408), [#8415](#8415), [#8446](#8446), [#8458](#8458), [#8462](#8462), and [#8506](#8506) are not promoted as supported product surfaces. ## 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 and validates dated changelog structure and published links. - [ ] 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-08-06.mdx`; release-range scope, writing rules, documentation style, skip terms, exact names, threat-boundary wording, and published routes reviewed; changelog tests and docs build passed. - Agent: Codex Desktop <!-- docs-review-head-sha: 02b51ae --> <!-- docs-review-agents-blob-sha: c69aad4 --> ## DGX Station Hardware Evidence - [ ] Tested on DGX Station - Tested commit: Not applicable; no DGX Station host preparation script changed. - Station profile/scenario: Not applicable. - Result: Not applicable. - Supporting evidence: Not applicable. ## 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 validate:pr` passed after refreshing `origin/main` when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: `npx vitest run test/changelog-docs.test.ts` passed 6/6. - [ ] 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 a single changelog entry. - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [x] `npm run 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) The new dated changelog file includes the required parser-safe SPDX header and intentionally has no frontmatter, matching the changelog contract and existing entries. --- Signed-off-by: Charan Jagwani <cjagwani@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added release notes for v0.0.104. * Documented fixes for local model runtimes, private endpoints, network policies, state recovery, uninstall behavior, safety updates, MCP diagnostics, credential isolation, and installation guidance. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary
Add a selectable Personal policy tier for trusted single-user environments and make the hidden portable experimental profile select it by default. Personal now uses the broadest practical network policy exposed by OpenShell v0.0.85 for Docker and Podman: every sandbox binary can open TCP connections on destination ports 80 and 443 to hosts whose resolved addresses are in the preset's broad public and private ranges, while OpenShell's unspecified, loopback, and link-local blocks remain active.
Changes
personal-open-internet, a hostlessallowed_ipsL4 preset covering broad IPv4, global IPv6, and unique-local IPv6 ranges on ports 80 and 443 for/**binaries.portsarrays without hiding their address scope.--tool-disclosureoverride.mainreadiness-resolver changes so the refreshed branch typechecks and its remediable-storage fixture uses the active preset requirements.OpenShell v0.0.85 rejects a bare all-host wildcard, exposes no Docker/Podman flag for disabling network enforcement, and matches ports exactly rather than supporting an all-port wildcard. The supported hostless
allowed_ipspath is therefore used here instead of claiming that policy enforcement is disabled.Type of Change
Quality Gates
Documentation Writer Review
docs-updateddocs/reference/commands.mdx,docs/reference/network-policies.mdx,docs/security/best-practices.mdxDGX Station Hardware Evidence
scripts/prepare-dgx-station-host.shis unchanged.Verification
Signed-off-by:line and every commit appears asVerifiedin GitHub — PR feat(policy): add Personal onboarding tier #8431 now contains four SSH-signed commits plus one GitHub-signed conflict-resolution merge, and GitHub reports all five asVerified.pre-commit,commit-msg, andpre-pushhooks passed, ornpm run validate:prpassed after refreshingorigin/mainwhen hooks were skipped or unavailablemainrefresh;src/lib/onboard/command.test.tspassed 36/36;src/lib/inference/serving/resolver.test.tspassed 34/34; the one policy-adapter subprocess that hit its 15-second suite timeout passed when rerun alone; all 50 configs pass schema validation; the Personal boundary suite passes 5/5 with both ports and normalized hard-range cases.npm testfor broad runtime/test-harness changes;npm run checkfor repo-wide validation/coverage changes — command/result: PR CI pending. An earliernpm run test:changedrun passed 984/993 tests; affected failures passed in isolation except the unrelated local Homebrew trust prerequisite inrebuild-resume-snapshot.test.ts.npm run docsbuilds without warnings (doc changes only) — 0 errors and 2 existing unprinted Fern warnings.Runtime proof: the standalone preset and the fully composed Personal tier were exercised through an isolated official OpenShell v0.0.85 gateway using
openshell/sandbox-from:1783990254. HTTPS toexample.comandapi.github.comand HTTP toexample.comsucceeded; forced access to169.254.169.254was denied. All 30 Personal preset names composed successfully under the exact v0.0.85 policy parser and supervisor.Signed-off-by: Aaron Erickson aerickson@nvidia.com
Summary by CodeRabbit
New Features
Documentation
Bug Fixes