Skip to content

refactor(hermes): generate configurations from one policy - #8026

Open
jyaunches wants to merge 24 commits into
NVIDIA:mainfrom
jyaunches:codex/hermes-policy-model-8008
Open

refactor(hermes): generate configurations from one policy#8026
jyaunches wants to merge 24 commits into
NVIDIA:mainfrom
jyaunches:codex/hermes-policy-model-8008

Conversation

@jyaunches

@jyaunches jyaunches commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Hermes configuration generation now derives the primary home, isolated dashboard home, and config-less named profiles from one typed managed policy. A versioned, root-owned, read-only manifest carries that policy into Python startup consumers. The security-review follow-up keeps dashboard authentication out of mirrored configuration and preserves the selected model context window during Hermes inference switches.

Related Issue

Closes #8008

Changes

  • Build the primary configuration, environment allowlist, dashboard projection, managed paths, and schema-versioned manifest from one TypeScript policy model.
  • Apply inference-route changes through the same typed routing primitive used by image generation.
  • Make dashboard seeding, named-profile patching, and image probes consume the versioned manifest and fail closed on malformed or unsupported policy data.
  • Inject the gateway API token only into the managed dashboard process environment after descriptor-based, no-follow validation; do not persist it in dashboard config, arguments, or output.
  • Resolve the selected model context window during Hermes inference switches and deliberately omit context_length when the target window cannot be established.
  • Remove duplicated Python defaults and add compatibility, malformed-input, credential-boundary, context-window, and image-layout tests.

Type of Change

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

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • 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: The two Medium findings in the security review were fixed at exact head 12435980e. Local security re-review passed with no blockers: raw credential routes are denied; the gateway token is descriptor-read with no-follow validation, removed from internal launch metadata, and provided only to the dashboard process environment; errors are generic; and the selected model context window is propagated or deliberately omitted when unknown. The remaining CodeQL empty-except thread was addressed by documenting the non-retryable close and O_CLOEXEC boundary.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: docs-updated
  • Evidence: docs/inference/configure-model-limits.mdx, docs/inference/switch-models.mdx, docs/manage-sandboxes/transfer-state-manually.mdx, docs/security/credential-storage.mdx, docs/inference/model-capability-audit.mdx, and .agents/skills/nemoclaw-contributor-update-hermes/references/hermes-contract-map.md. Independent exact-head review at b462e8ad4 found no blockers and confirmed that the final test-only commit changes no production or user-facing contract, so it requires no additional documentation.
  • Agent: Codex Desktop

DGX Station Hardware Evidence

  • Tested on DGX Station
  • Tested commit: Not applicable.
  • Station profile/scenario: Not applicable.
  • Result: Not applicable; this change does not modify scripts/prepare-dgx-station-host.sh.
  • Supporting evidence: Not applicable.

Verification

  • PR description includes a Signed-off-by: line and every published commit appears as Verified in GitHub
  • 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
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: Python-backed managed-policy and dashboard-seeder tests passed 35/35; focused Hermes inference-switch tests passed 19/19; npm run test:changed passed 191/191 before the current-main refresh; post-merge focused Hermes security/context, risk-plan, home-channel, and E2E-support validation passed 8 files and 133 tests with one file and 32 skips; the cross-runtime compatibility hash test hit its five-second timeout only under the concurrent focused run and passed 2/2 in isolation; focused wrapper tests passed 4 with 46 platform skips; the final E2E resilience change passed its focused support suite 17/17 and npm run test:changed; npm run checks:repository, npm run test-size:check, npm run docs, Python syntax, checksum validation, ShellCheck, Hadolint, the test-conditionals scan, and normal hooks passed.
  • 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; the change is scoped to Hermes policy generation and its named runtime consumers, covered by focused suites and normal repository hooks.
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only) — passed with 0 errors and 2 existing warnings
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

The merged risk-plan v12 selects the issue-required Hermes live coverage, including Hermes smoke, inference switching, dashboard remote bind, Bedrock compatibility, shields, channel lifecycle, adapter lifecycle, and security posture targets. No unmapped E2E target remains.


Signed-off-by: Julie Yaunches jyaunches@nvidia.com

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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

Hermes configuration now uses one versioned managed-policy model. The policy is serialized, securely loaded by Python consumers, applied to runtime profiles and dashboard configuration, and used for inference route updates. Docker installation, startup wiring, probes, and tests validate the shared policy.

Changes

Hermes managed policy

Layer / File(s) Summary
Managed policy model and route application
agents/hermes/config/*, src/lib/hermes-managed-route.ts
Adds the typed policy model, configuration generation, policy serialization, platform toolset handling, and centralized Hermes route application.
Manifest validation and policy consumers
agents/hermes/managed_policy.py, agents/hermes/patch-profile-policy-defaults.py, agents/hermes/seed-dashboard-config.py
Validates the versioned manifest and derives profile defaults, source patches, dashboard policy, routing, and dotenv mirroring from it.
Image and startup integration
agents/hermes/Dockerfile, agents/hermes/start.sh, agents/hermes/image-build-probes.py, src/lib/sandbox/config.ts, src/lib/onboard/managed-startup/*
Installs immutable policy artifacts, passes the manifest to dashboard setup, and validates policy-derived runtime values.
Policy, routing, image, and startup validation
test/*, src/lib/actions/*test.ts, src/lib/onboard/*test.ts
Extends coverage for policy serialization, secure loading, route output, dashboard seeding, image layout, permissions, and isolated Python execution.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested labels: integration: hermes, area: architecture, area: security

Suggested reviewers: cv, prekshivyas

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.32% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue #8008 by centralizing typed policy generation, manifest consumption, routing, validation, secret references, and policy-based probes.
Out of Scope Changes check ✅ Passed The changes remain within issue #8008 scope and support policy generation, consumers, validation, startup integration, documentation, and tests.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the centralization of Hermes configuration generation around one managed policy.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>

@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: 4

Caution

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

⚠️ Outside diff range comments (1)
test/hermes-start-config-integrity.test.ts (1)

113-118: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Assert the managed-policy argument in the seeder invocation.

prepare_hermes_dashboard_home passes _HERMES_MANAGED_POLICY in the required first position, but the test does not assert this path. Assert the logged invocation includes the managed-policy path before /config.yaml.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/hermes-start-config-integrity.test.ts` around lines 113 - 118, Update
the assertions for prepare_hermes_dashboard_home to verify that the seeder
invocation includes the _HERMES_MANAGED_POLICY path in the required first
argument position, immediately before /config.yaml, using the existing
managed-policy path value.
🧹 Nitpick comments (6)
src/lib/actions/inference-route-api.ts (1)

4-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use src/lib/hermes-managed-route.ts as the only in-repository import path for these symbols.

Import hermesApiMode directly in src/lib/actions/inference-set.ts and its test. Update the placeholder imports in the three tests, then remove both forwarding exports. Retain compatibility paths only for documented external contracts with bounded retirement criteria.

🤖 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/inference-route-api.ts` around lines 4 - 10, Use
src/lib/hermes-managed-route.ts as the sole in-repository import source for
hermesApiMode and remove the forwarding exports from
src/lib/actions/inference-route-api.ts:4-10 and
src/lib/hermes-proxy-api-key.ts:4. Update inference-set, its test, and the three
affected tests to import the symbols directly from hermes-managed-route.ts,
retaining compatibility paths only where they represent documented external
contracts with bounded retirement criteria.

Sources: Coding guidelines, Path instructions

agents/hermes/managed_policy.py (1)

86-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename the loop variable to avoid shadowing the path parameter.

load_managed_policy takes path: Path. Line 91 rebinds path to a str from managed_paths. No current code reads path after the loop, so behavior is correct today. The shadowing invites a type error in later edits, for example adding the file path to an error message.

♻️ Proposed rename
     config = document["config"]
-    for path in managed_paths:
-        policy_value(config, path)
+    for managed_path in managed_paths:
+        policy_value(config, managed_path)
🤖 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 `@agents/hermes/managed_policy.py` around lines 86 - 96, Rename the loop
variable in load_managed_policy’s managed_paths iteration so it no longer
shadows the method’s path: Path parameter, and update the policy_value call to
use the new variable.
agents/hermes/config/managed-policy.ts (1)

263-273: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the dead tts guard.

REMOTE_PLATFORM_TOOLSETS never contains "tts", so !remotePlatformToolsets.includes("tts") is always true. The check adds a condition that cannot fail.

♻️ Proposed simplification
   const remotePlatformToolsets = [...REMOTE_PLATFORM_TOOLSETS];
   if (
     settings.managedToolGateways.brokerEnabled &&
-    settings.managedToolGateways.presets.includes("nous-audio") &&
-    !remotePlatformToolsets.includes("tts")
+    settings.managedToolGateways.presets.includes("nous-audio")
   ) {
     remotePlatformToolsets.push("tts");
   }
🤖 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 `@agents/hermes/config/managed-policy.ts` around lines 263 - 273, Remove the
redundant remotePlatformToolsets.includes("tts") condition from
buildHermesRemotePlatformToolsets, while preserving the brokerEnabled and
nous-audio preset checks and the existing tts insertion behavior.
agents/hermes/patch-profile-policy-defaults.py (1)

345-353: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Report a manifest load failure as a build error.

load_managed_policy raises ManagedPolicyError. This call site does not catch it, so an invalid or unreadable manifest produces a traceback during the image build. The build still fails closed, but the message does not identify the manifest as the cause. patch_file already converts patch failures into SystemExit with a clear prefix. Apply the same treatment here.

♻️ Proposed change
-    values = profile_default_values(load_managed_policy(args.policy))
+    try:
+        values = profile_default_values(load_managed_policy(args.policy))
+    except ManagedPolicyError as exc:
+        raise SystemExit(f"ERROR: {args.policy}: {exc}") from exc

Add ManagedPolicyError to the managed_policy import list.

🤖 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 `@agents/hermes/patch-profile-policy-defaults.py` around lines 345 - 353,
Update the policy-loading flow around load_managed_policy to catch
ManagedPolicyError and convert it into a SystemExit with a clear
manifest-related error prefix, matching patch_file’s failure handling. Add
ManagedPolicyError to the existing managed_policy imports and keep successful
profile_default_values and patch_file processing unchanged.
agents/hermes/config/hermes-config.ts (1)

5-15: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the redundant forwarding module.

generate.ts already imports both symbols from managed-policy.ts. Replace the two test imports and update the path-based test, documentation, and wrapper references. Then delete agents/hermes/config/hermes-config.ts.

🤖 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 `@agents/hermes/config/hermes-config.ts` around lines 5 - 15, Remove the
redundant hermes-config forwarding module and its exported symbols, then update
all references to import buildHermesManagedPolicy and
finalizeHermesPlatformToolsets directly from managed-policy.ts. Replace the two
test imports and revise path-based tests, documentation, and wrapper references
before deleting hermes-config.ts.

Source: Coding guidelines

agents/hermes/seed-dashboard-config.py (1)

197-222: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add a regression test for the dashboard provider rewrite. Use a gateway fixture with model.provider: "custom" and assert that seeding sets it to _nemoclaw_upstream.provider_key while preserving the endpoint, proxy placeholder, and API mode across both provider paths.

🤖 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 `@agents/hermes/seed-dashboard-config.py` around lines 197 - 222, Add a
regression test covering the dashboard provider rewrite through
_normalized_routing, using a gateway fixture whose model.provider starts as
"custom". Assert that the seeded model.provider becomes
_nemoclaw_upstream.provider_key while endpoint, proxy placeholder, and API mode
remain unchanged for both provider paths.
🤖 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 `@agents/hermes/config/write-config.ts`:
- Around line 32-34: Align generate-config.ts, the Python consumers, and
start.sh on a single managed-policy artifact instead of maintaining separate
runtime and installed copies. Update the policy generation path around
policyPath to write the trusted artifact consumed at runtime, ensure env_lines
contain resolved credentials and gateway values rather than placeholders, and
update all consumers to read that same artifact so the manifest and config.yaml
remain consistent.

In `@agents/hermes/start.sh`:
- Around line 229-232: Remove the fallback assignment in the managed-policy
initialization near _HERMES_MANAGED_POLICY, leaving
/usr/local/share/nemoclaw/hermes-managed-policy.json as the sole policy path.
Preserve the existing missing-file behavior so the policy consumer fails closed
when the immutable artifact is absent, and do not read policy from HERMES_DIR.

In `@test/hermes-profile-policy-defaults.test.ts`:
- Around line 282-285: Replace the source-text checks on image-build-probes.py
in the hermes profile defaults test with a behavioral test that runs the probe
against a fixture managed policy and deliberately mismatched configuration.
Assert the process exit status and relevant stdout/stderr to verify the probe
derives and enforces profile_default_values(policy), following the existing
patchSource subprocess pattern; retain only observable public-boundary
assertions.

In `@test/seed-hermes-dashboard-config.test.ts`:
- Around line 65-90: Replace output assertions that currently derive expected
values through projectManagedPolicy or REVIEWED_POLICY with hand-authored
expected dashboard configuration values, specifically the assertions around
lines 178–182 and 439. Keep REVIEWED_POLICY unchanged for input fixtures, and
remove or stop using projectManagedPolicy for these expected outputs so the
assertions are independent of the seeder projection logic.

---

Outside diff comments:
In `@test/hermes-start-config-integrity.test.ts`:
- Around line 113-118: Update the assertions for prepare_hermes_dashboard_home
to verify that the seeder invocation includes the _HERMES_MANAGED_POLICY path in
the required first argument position, immediately before /config.yaml, using the
existing managed-policy path value.

---

Nitpick comments:
In `@agents/hermes/config/hermes-config.ts`:
- Around line 5-15: Remove the redundant hermes-config forwarding module and its
exported symbols, then update all references to import buildHermesManagedPolicy
and finalizeHermesPlatformToolsets directly from managed-policy.ts. Replace the
two test imports and revise path-based tests, documentation, and wrapper
references before deleting hermes-config.ts.

In `@agents/hermes/config/managed-policy.ts`:
- Around line 263-273: Remove the redundant
remotePlatformToolsets.includes("tts") condition from
buildHermesRemotePlatformToolsets, while preserving the brokerEnabled and
nous-audio preset checks and the existing tts insertion behavior.

In `@agents/hermes/managed_policy.py`:
- Around line 86-96: Rename the loop variable in load_managed_policy’s
managed_paths iteration so it no longer shadows the method’s path: Path
parameter, and update the policy_value call to use the new variable.

In `@agents/hermes/patch-profile-policy-defaults.py`:
- Around line 345-353: Update the policy-loading flow around load_managed_policy
to catch ManagedPolicyError and convert it into a SystemExit with a clear
manifest-related error prefix, matching patch_file’s failure handling. Add
ManagedPolicyError to the existing managed_policy imports and keep successful
profile_default_values and patch_file processing unchanged.

In `@agents/hermes/seed-dashboard-config.py`:
- Around line 197-222: Add a regression test covering the dashboard provider
rewrite through _normalized_routing, using a gateway fixture whose
model.provider starts as "custom". Assert that the seeded model.provider becomes
_nemoclaw_upstream.provider_key while endpoint, proxy placeholder, and API mode
remain unchanged for both provider paths.

In `@src/lib/actions/inference-route-api.ts`:
- Around line 4-10: Use src/lib/hermes-managed-route.ts as the sole
in-repository import source for hermesApiMode and remove the forwarding exports
from src/lib/actions/inference-route-api.ts:4-10 and
src/lib/hermes-proxy-api-key.ts:4. Update inference-set, its test, and the three
affected tests to import the symbols directly from hermes-managed-route.ts,
retaining compatibility paths only where they represent documented external
contracts with bounded retirement criteria.
🪄 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: 8a6ec943-5900-49ff-a96e-d67f92467b1a

📥 Commits

Reviewing files that changed from the base of the PR and between 299050f and f078fe3.

📒 Files selected for processing (28)
  • agents/hermes/Dockerfile
  • agents/hermes/config/generate.ts
  • agents/hermes/config/hermes-config.ts
  • agents/hermes/config/managed-policy.ts
  • agents/hermes/config/write-config.ts
  • agents/hermes/hermes-wrapper.py
  • agents/hermes/image-build-probes.py
  • agents/hermes/managed_policy.py
  • agents/hermes/patch-profile-policy-defaults.py
  • agents/hermes/seed-dashboard-config.py
  • agents/hermes/start.sh
  • src/lib/actions/inference-route-api.ts
  • src/lib/actions/inference-set-hermes-run.test.ts
  • src/lib/actions/inference-set-patch-hermes.test.ts
  • src/lib/actions/inference-set.ts
  • src/lib/hermes-managed-route.ts
  • src/lib/hermes-proxy-api-key.ts
  • src/lib/sandbox/config.ts
  • src/lib/sandbox/hermes-dashboard-reseed.test.ts
  • test/generate-hermes-config.test.ts
  • test/hermes-doctor-config-hash.test.ts
  • test/hermes-final-image-layout.test.ts
  • test/hermes-managed-policy.test.ts
  • test/hermes-profile-policy-defaults.test.ts
  • test/hermes-start-config-integrity.test.ts
  • test/sandbox-provisioning.test.ts
  • test/sandbox-rlimit-hooks.test.ts
  • test/seed-hermes-dashboard-config.test.ts

Comment thread agents/hermes/config/write-config.ts
Comment thread agents/hermes/start.sh Outdated
Comment thread test/hermes-profile-policy-defaults.test.ts Outdated
Comment thread test/seed-hermes-dashboard-config.test.ts Outdated
@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings reported

Advisor assessment: No blocking advisor findings reported
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · medium confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Failed after a partial review · low confidence · 0 blockers · 0 warnings · 0 suggestions

Second-opinion terminology and E2E selections are advisory. They do not change the primary assessment or E2E / PR Gate.

Since last review: 0 prior items resolved · 0 still apply · 0 new items found

2 semantic terminology decisions

Terminology decisions are advisory. They affect the assessment only when a separate finding identifies concrete semantic impact.

  • define — managed policy at .agents/skills/nemoclaw-contributor-update-hermes/references/hermes-contract-map.md:37: Define managed policy at its first explanatory use as the root-owned manifest that carries Hermes managed configuration.
  • established — rewrite sentinel at docs/security/credential-storage.mdx:29: Keep using rewrite sentinel for the exact configured marker and credential placeholder for generic replacement metadata.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: cloud-inference, cloud-onboard, full-e2e, hermes-e2e, hermes-inference-switch, security-posture, bedrock-runtime-compatible-anthropic, channels-stop-start, dashboard-remote-bind, device-auth-health, hermes-shields-config, inference-routing, issue-4462-scope-upgrade-approval, mcp-bridge, mcp-bridge-dev, network-policy, onboard-repair, onboard-resume, openclaw-inference-switch

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Comment thread src/lib/actions/inference-set.ts Fixed
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Comment thread src/lib/sandbox/config.ts Fixed
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
@cv

cv commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Security code review — FAIL

Reviewed commit SHA fac55ec51e1cdfb0b708454a37588c874251c336 against main at base SHA 4cd4d64fe67143b57707f874afa0b9d269dfeff2.

This PR is not approval-ready. Issues #8008 and #8004 establish product scope, but two security and correctness findings remain.

Blocking findings

  1. Medium — credential-bearing values can enter dashboard configuration.
    agents/hermes/seed-dashboard-config.py:197-222 copies complete routing objects without requiring the OpenShell rewrite sentinel for each api_key. A raw provider credential in the gateway YAML can therefore enter the dashboard configuration. Lines 314-349 also copy the generated API_SERVER_KEY bearer token into the dashboard .env after checking only its shape. This conflicts with refactor(hermes): generate every Hermes configuration from one policy model #8008's credential-reference requirement.

    Reject routing credentials that do not equal the rewrite sentinel. Provide dashboard authentication without copying the bearer token into a configuration mirror, or obtain an accepted design decision for that credential-custody exception. Add denial-path tests that do not log credential values.

  2. Medium — Hermes inference switches discard context_length.
    src/lib/actions/inference-set.ts:554-567,1178-1201 calls the Hermes route writer without resolving the target model's context window. src/lib/hermes-managed-route.ts:88-98 replaces the complete model block and omits context_length when the caller provides no value. Each Hermes inference switch can therefore remove a probed or configured context window.

    Resolve the target model's context window before writing the Hermes route. Define the failure behavior when the value is unavailable. Add switch coverage that preserves or recomputes context_length.

Nine-category result

  1. Secrets and credentials: FAIL. The dashboard mirrors can copy raw routing credentials and the real dashboard bearer token.
  2. Input validation: WARNING. The routing shape is checked, but credential values are not constrained to the rewrite sentinel.
  3. Authentication and authorization: PASS. The diff adds no endpoint or authorization bypass.
  4. Dependencies: PASS. The diff adds no dependency.
  5. Error handling and logging: PASS. Parser failures use redacted messages.
  6. Cryptography and data protection: PASS. SHA-256 is used for source integrity, not as a credential-protection primitive.
  7. Configuration security: PASS. The managed policy is installed root-owned and read-only, and consumers use stable no-follow reads.
  8. Security testing: WARNING. Tests do not reject a raw routing credential and do not cover context_length after a Hermes inference switch.
  9. System security: WARNING. The route update weakens the existing context-window contract.
Files reviewed
  • .agents/skills/nemoclaw-contributor-update-hermes/references/hermes-contract-map.md
  • agents/hermes/Dockerfile
  • agents/hermes/config/generate.ts
  • agents/hermes/config/hermes-config.ts
  • agents/hermes/config/managed-policy.ts
  • agents/hermes/config/write-config.ts
  • agents/hermes/hermes-wrapper.py
  • agents/hermes/image-build-probes.py
  • agents/hermes/managed_policy.py
  • agents/hermes/patch-profile-policy-defaults.py
  • agents/hermes/seed-dashboard-config.py
  • agents/hermes/start.sh
  • docs/inference/model-capability-audit.mdx
  • src/lib/actions/inference-route-api.test.ts
  • src/lib/actions/inference-route-api.ts
  • src/lib/actions/inference-set-hermes-run.test.ts
  • src/lib/actions/inference-set-patch-hermes.test.ts
  • src/lib/actions/inference-set.ts
  • src/lib/hermes-managed-route.ts
  • src/lib/hermes-proxy-api-key.ts
  • src/lib/onboard/managed-startup-image-runtime.test.ts
  • src/lib/onboard/managed-startup/image-runtime.ts
  • src/lib/sandbox/config.ts
  • src/lib/sandbox/hermes-dashboard-reseed.test.ts
  • test/generate-hermes-config.test.ts
  • test/hermes-dependency-review.test.ts
  • test/hermes-doctor-config-hash.test.ts
  • test/hermes-final-image-layout.test.ts
  • test/hermes-gateway-wrapper.test.ts
  • test/hermes-managed-policy.test.ts
  • test/hermes-profile-policy-defaults.test.ts
  • test/hermes-start-config-integrity.test.ts
  • test/hermes-upgrade-skill.test.ts
  • test/sandbox-provisioning.test.ts
  • test/sandbox-rlimit-hooks.test.ts
  • test/seed-hermes-dashboard-config.test.ts

Required GitHub checks pass for commit fac55ec51e1cdfb0b708454a37588c874251c336 against recorded base SHA eaa6ec4d55ad852478b0191130c8ca1691f6841f. Current main is 4cd4d64fe67143b57707f874afa0b9d269dfeff2, so checks must run again after a branch refresh. Those checks do not resolve the findings above. No local tests were rerun.

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Keep dashboard authentication out of mirrored configuration.

Carry the selected model context window through Hermes inference switches.

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Comment thread agents/hermes/hermes-wrapper.py Fixed
@cjagwani

cjagwani commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Release-queue follow-up: current head b462e8a is DIRTY against main. The existing security review is bound to older head fac55ec, so it cannot establish the current head's disposition. Please resolve the conflict with a signed/verified commit, then refresh the full required CI/advisor/E2E matrix and an exact-head security review before approval.

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed commit b462e8ad4 and the recorded fixes for issue #8008. The typed managed policy, versioned manifest, no-follow dashboard token read, environment-only credential delivery, generic errors, and context-window propagation address the prior credential and routing findings. No unresolved major review thread remains on this commit.

Approval is blocked by a behavior-changing conflict with current main, failed reviewed-npm audit and required CI/E2E checks, and extensive overlap in Hermes configuration, image, inference, credential, and documentation paths. Current main also removed or relocated the Hermes-specific skill reference changed by this branch. I did not apply an automatic merge because choosing between those contracts can change credential handling and generated configuration. A maintainer reconciliation must preserve the manifest schema, dashboard credential boundary, context-window behavior, current dependency audit, and current documentation ownership, then rerun the security and documentation reviews for the resulting commit.

@wscurran wscurran added area: architecture Architecture, design debt, major refactors, or maintainability area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery area: security Security controls, permissions, secrets, or hardening integration: hermes Hermes integration behavior refactor PR restructures code without intended behavior change labels Aug 4, 2026
@github-actions github-actions Bot added v0.0.103 Release target and removed v0.0.102 labels Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: architecture Architecture, design debt, major refactors, or maintainability area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery area: security Security controls, permissions, secrets, or hardening integration: hermes Hermes integration behavior refactor PR restructures code without intended behavior change v0.0.103 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(hermes): generate every Hermes configuration from one policy model

7 participants