Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
018eb05
fix(snapshot): preserve external policy authority
apurvvkumaria Aug 24, 2026
1c2f8a5
merge: update rebuild authority base
apurvvkumaria Aug 24, 2026
b8ea391
merge: refresh rebuild authority base
apurvvkumaria Aug 24, 2026
5da165b
merge: update rebuild authority base
apurvvkumaria Aug 24, 2026
06d32ce
Merge branch 'codex/9833-rebuild-authority' into codex/9833-snapshot-…
cv Aug 24, 2026
31b4c94
Merge branch 'codex/9833-rebuild-authority' into codex/9833-snapshot-…
cv Aug 24, 2026
22badc2
merge: refresh snapshot authority base
apurvvkumaria Aug 24, 2026
9a70fc9
Merge remote-tracking branch 'origin/codex/9833-rebuild-authority' in…
apurvvkumaria Aug 24, 2026
1cb2edd
Merge branch 'codex/9833-rebuild-authority' into codex/9833-snapshot-…
apurvvkumaria Aug 24, 2026
0533af1
Merge branch 'codex/9833-rebuild-authority' into codex/9833-snapshot-…
apurvvkumaria Aug 24, 2026
9de46e9
merge: restack rebuild authority
apurvvkumaria Aug 25, 2026
2b2c0c2
merge: restack rebuild authority
apurvvkumaria Aug 25, 2026
bd7f672
merge: restack rebuild registry ownership
apurvvkumaria Aug 25, 2026
354bf07
fix(snapshot): import registry owner directly
apurvvkumaria Aug 25, 2026
dae5e3f
merge: sync parent into PR #10117
cv Aug 28, 2026
cb50a7b
fix(snapshot): pass CLI name to restore hint
cv Aug 28, 2026
5b505e3
fix(snapshot): repair merged authority fixtures
cv Aug 28, 2026
9ca8f72
Merge branch 'codex/9833-rebuild-authority' into codex/9833-snapshot-…
cv Aug 28, 2026
6cb379b
ci: retrigger PR review advisor
cv Aug 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ci/source-architecture-budget.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"src/lib/runner.ts": 86,
"src/lib/security/redact.ts": 54,
"src/lib/state/onboard-session.ts": 36,
"src/lib/state/registry.ts": 103,
"src/lib/state/registry.ts": 104,
"src/lib/state/state-root.ts": 21,
"src/lib/subprocess-env.ts": 24,
"src/lib/validation.ts": 24
Expand Down
6 changes: 5 additions & 1 deletion src/lib/actions/sandbox/policy-authority/preflight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export function inspectPolicyAuthorityRequirements(
) {
const inspections: SandboxPolicyAuthorityInspection[] = [];
const authorities: RecordedPolicyAuthority[] = [];
let liveInspection: SandboxPolicyAuthorityInspection | null = null;
const preparedRequirement = {
appliedPresets: [],
policyPath: "",
Expand All @@ -82,6 +83,7 @@ export function inspectPolicyAuthorityRequirements(
gatewayName: options.gatewayName,
});
if (observed.authority !== "owner-unknown") {
liveInspection = observed;
authorities.push(observed.authority);
if (observed.authority === "externally-managed") inspections.push(observed);
} else {
Expand All @@ -99,6 +101,8 @@ export function inspectPolicyAuthorityRequirements(
},
deps,
);
liveInspection =
qualified.authority === "externally-managed" ? qualified.inspection : observed;
authorities.push(qualified.authority);
if (qualified.authority === "externally-managed") inspections.push(qualified.inspection);
}
Expand Down Expand Up @@ -127,7 +131,7 @@ export function inspectPolicyAuthorityRequirements(
}
return {
authority,
liveInspection: options.inspectLiveSource ? (inspections[0] ?? null) : null,
liveInspection,
verifyRequirements: () => assertPolicyAuthorityRequirements(options, inspections),
};
}
Expand Down
124 changes: 124 additions & 0 deletions src/lib/actions/sandbox/policy-authority/snapshot.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { afterEach, describe, expect, it, vi } from "vitest";

import { makeMessagingPlan } from "../../../../../test/helpers/messaging-plan-fixtures";
import * as registry from "../../../state/registry";
import type { SandboxEntry } from "../../../state/registry";
import {
qualifySnapshotPolicyAuthority,
resolveSnapshotBuiltinPolicyRequirements,
resolveSnapshotPolicyRequirements,
} from "./snapshot";

describe("snapshot policy authority qualification", () => {
afterEach(() => {
vi.restoreAllMocks();
});

it("retains only agreed legacy authority when a requirement is missing (#9833)", () => {
const sourceEntry = { name: "alpha" };
const updateSandbox = vi.spyOn(registry, "updateSandbox").mockReturnValue(true);
const inspection = {
authority: "externally-managed" as const,
effectivePolicy: { network_policies: {} },
policyIdentity: { hash: "external-policy", activeVersion: 1 },
};

expect(() =>
qualifySnapshotPolicyAuthority(
{
gatewayName: "nemoclaw",
managedMcpPolicies: [],
operation: "clone snapshot 'alpha' into sandbox 'beta'",
requiredPolicies: [{ network_policies: { required_api: {} } }],
sourceEntry,
sourceLive: true,
verifyGlobalCreatePolicy: false,
},
{
inspectSandboxPolicyAuthority: vi.fn(() => inspection),
},
),
).toThrow(/missing entries "required_api"/);

expect(updateSandbox).toHaveBeenCalledWith("alpha", {
policyAuthority: "externally-managed",
});
expect(sourceEntry).toEqual({ name: "alpha", policyAuthority: "externally-managed" });
});

it.each([
["absent", "version: 1\n"],
["empty", "version: 1\nnetwork_policies: {}\n"],
])("rejects a required policy whose network_policies mapping is %s (#9833)", (_case, content) => {
expect(() =>
resolveSnapshotPolicyRequirements({
basePolicyContent: content,
builtinPresetNames: [],
customPolicies: [],
operation: "restore snapshot 'alpha'",
sandboxName: "alpha",
}),
).toThrow(
"Refusing to restore snapshot 'alpha': a required network policy document is invalid.",
);
});

it("derives requirements from durable features without NemoClaw attribution (#9833)", () => {
expect(
resolveSnapshotBuiltinPolicyRequirements({
customPolicies: [],
snapshotPolicyPresets: [],
sourceEntry: {
name: "alpha",
agent: "langchain-deepagents-code",
messaging: {
schemaVersion: 1,
plan: {
...makeMessagingPlan({ channels: ["telegram"] }),
networkPolicy: {
presets: ["telegram"],
entries: [
{
channelId: "telegram",
presetName: "telegram",
policyKeys: ["telegram"],
source: "manifest",
},
],
},
},
},
observabilityEnabled: true,
policyAuthority: "externally-managed",
provider: "ollama-local",
webSearchEnabled: true,
webSearchProvider: "brave",
},
}),
).toEqual(
expect.arrayContaining(["telegram", "brave", "local-inference", "observability-otlp-local"]),
);
});

it("does not require local inference for a proven canonical injected route (#9833)", () => {
const routeOnlyEntry = {
name: "alpha",
endpointSource: "inference-set",
endpointUrl: "https://inference.local/v1",
hostLocalInferenceProvenance: {},
hostLocalInferenceReceipt: "receipt",
provider: "ollama-local",
} as SandboxEntry;

expect(
resolveSnapshotBuiltinPolicyRequirements({
customPolicies: [],
snapshotPolicyPresets: [],
sourceEntry: routeOnlyEntry,
}),
).not.toContain("local-inference");
});
});
Loading
Loading