Commit Graph
5 Commits
Author SHA1 Message Date
Anandan 4cb1f10952 Add sandbox architecture baseline (#240)
* Add sandbox architecture baseline

Record target backend names, enforcement metadata, legacy sandbox entrypoints, and policy JSON baseline coverage for the sandbox rewrite.

Add a focused sandbox smoke script with cross-platform compile checks and an opt-in real backend smoke path.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox -run 'TestTargetBackendForPlatformBaseline|TestLegacySandboxEntrypointsAreExplicitAndExist|TestBackendPlanCarriesPhase0ManagerFields|TestCommandPlanCarriesSandboxMetadata|TestPolicyOnlyDisabledFailClosedForTargetPlatforms|TestSelectBackendChoosesPlatformAdapterWithFallback|TestBackendBuildPlanDocumentsBestEffortIsolation|TestBackendCapabilitiesReflectDisabledPolicy'

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/cli -run 'TestRunSandboxPolicyInspectTextAndJSON|TestRunSandboxPolicyJSONGoldenIncludesManagerBaselineFields|TestRunSandboxPolicyEffectiveTextAndJSON'

Tested: scripts/sandbox-smoke.sh

Tested: git diff --cached --check

* Introduce sandbox manager and permission profile

Add a normalized permission profile and sandbox manager execution request that owns target backend selection, enforcement metadata, and fail-closed validation.

Route command planning and sandbox policy output through the manager boundary while keeping legacy adapters explicit as temporary integration points.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox -run 'TestPermissionProfileFromPolicyBuildsWorkspaceWriteProfile|TestPermissionProfileFromDisabledPolicyDoesNotRequirePlatformSandbox|TestSandboxManagerBuildsExecutionRequestFromProfile|TestSandboxManagerFailsClosedWhenNativeRequiredAndPolicyOnlyDisabled|TestTargetBackendForPlatformBaseline|TestBackendPlanCarriesPhase0ManagerFields|TestCommandPlanCarriesSandboxMetadata|TestPolicyOnlyDisabledFailClosedForTargetPlatforms'

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/cli -run 'TestRunSandboxPolicyInspectTextAndJSON|TestRunSandboxPolicyJSONGoldenIncludesManagerBaselineFields|TestRunSandboxPolicyEffectiveTextAndJSON'

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/tools -run 'TestRegistryRunsBashThroughSandboxEngine|TestBashToolReportsDisabledPolicyOnlyRunner|TestBashToolBuildsWrappedSandboxExecCommand'

Tested: scripts/sandbox-smoke.sh

Tested: git diff --cached --check

* Move sandbox backend selection into manager

Make SandboxManager own platform backend selection and keep SelectBackend as a compatibility shim for existing CLI and TUI wiring.

Add tests proving manager-owned selection and the compatibility wrapper agree.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox -run 'TestSandboxManagerSelectsPlatformBackend|TestSelectBackendDelegatesToSandboxManagerSelection|TestSelectBackendChoosesPlatformAdapterWithFallback|TestLegacySandboxEntrypointsAreExplicitAndExist|TestSandboxManagerBuildsExecutionRequestFromProfile|TestSandboxManagerFailsClosedWhenNativeRequiredAndPolicyOnlyDisabled'

Tested: scripts/sandbox-smoke.sh

Tested: git diff --cached --check

* Route command planning through sandbox manager

Make SandboxManager build command plans from sandbox execution requests, with backend-specific wrapping isolated behind a temporary adapter.

Move Engine.BuildCommandPlan to a single manager boundary and mark buildLegacyCommandPlan as the explicit delete target for later backend work.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox -run 'TestSandboxManagerBuildsCommandPlanThroughTemporaryAdapter|TestSandboxManagerBuildsDegradedPolicyOnlyCommandPlan|TestBuildCommandPlanWrapsBubblewrap|TestBuildCommandPlanWrapsSandboxExec|TestBuildCommandPlanUsesPolicyOnlyFallback|TestBuildCommandPlanCanRejectPolicyOnlyFallback|TestLegacySandboxEntrypointsAreExplicitAndExist|TestSandboxManagerBuildsExecutionRequestFromProfile|TestSandboxManagerFailsClosedWhenNativeRequiredAndPolicyOnlyDisabled'

Tested: scripts/sandbox-smoke.sh

Tested: git diff --cached --check

* Add Linux sandbox helper command boundary

Introduce the zero-linux-sandbox command surface and typed permission-profile argv builder used by the upcoming Linux helper rewrite.

Keep the helper fail-closed until enforcement is wired, and add parser tests plus smoke compilation for the new helper package.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox -run 'TestBuildLinuxSandboxCommandArgsSerializesPermissionProfile|TestParseLinuxSandboxHelperArgs|TestRunLinuxSandboxHelperFailsClosedUntilEnforcementIsWired'

Tested: scripts/sandbox-smoke.sh

Tested: git diff --cached --check

* Fix sandbox policy golden path aliases

Normalize both original and symlink-resolved temp paths before comparing sandbox policy JSON goldens, so macOS /private/var aliases do not fail the smoke job.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/cli -run 'TestRunSandboxPolicyJSONGoldenIncludesManagerBaselineFields|TestRunSandboxPolicyInspectTextAndJSON|TestRunSandboxPolicyEffectiveTextAndJSON'

Tested: scripts/sandbox-smoke.sh

Tested: git diff --cached --check

* Fix Windows sandbox smoke test assumptions

Normalize JSON-escaped Windows paths in the sandbox policy golden test and mark the fake bubblewrap backend as Linux in the command metadata test.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/cli -run 'TestRunSandboxPolicyJSONGoldenIncludesManagerBaselineFields|TestRunSandboxPolicyInspectTextAndJSON|TestRunSandboxPolicyEffectiveTextAndJSON'

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox -run 'TestCommandPlanCarriesSandboxMetadata|TestBackendPlanCarriesPhase0ManagerFields|TestPolicyOnlyDisabledFailClosedForTargetPlatforms'

Tested: scripts/sandbox-smoke.sh

Tested: git diff --cached --check

* Stabilize sandbox policy golden test

Compare the Windows sandbox policy golden as decoded JSON after path tokenization so platform-specific byte formatting does not fail smoke tests while preserving the same field-level regression coverage.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/cli -run TestRunSandboxPolicyJSONGoldenIncludesManagerBaselineFields

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/cli -run 'TestRunSandboxPolicyJSONGoldenIncludesManagerBaselineFields|TestRunSandboxPolicyInspectTextAndJSON|TestRunSandboxPolicyEffectiveTextAndJSON'

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox

Tested: scripts/sandbox-smoke.sh

Tested: git diff --check

* Route Linux sandboxing through helper

Move Linux command planning to invoke zero-linux-sandbox with the permission profile, command cwd, and command argv instead of exposing bubblewrap construction from the runner boundary.

The helper now builds the bubblewrap argv, binds its own executable for the inner stage, applies the seccomp/no-new-privs step before exec, and preserves the original command cwd path.

Package Linux releases with zero-linux-sandbox next to zero so release builds use the helper directly, while local development can fall back to go run for the helper.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/cli ./internal/tools ./cmd/zero-linux-sandbox

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/release ./cmd/zero-release

Tested: scripts/sandbox-smoke.sh

Tested: git diff --check

* Normalize Linux helper cwd test paths

Compare native paths in the helper cwd regression test so Windows smoke does not fail on path separator formatting while preserving the same helper behavior assertion.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox -run TestLinuxHelperPlanPreservesRealExtraRootCwd

Tested: scripts/sandbox-smoke.sh

Tested: git diff --check

* Add Linux Landlock helper enforcement

Implement the zero-linux-sandbox Landlock helper path with fail-closed profile validation, Landlock filesystem rules, and seccomp network-deny enforcement for the fallback backend.

Broaden the Linux real smoke coverage to cover helper write allow/deny, deny-read, temp writes, metadata protection, network deny, and direct Landlock fallback behavior.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox

Tested: scripts/sandbox-smoke.sh

Tested: GOCACHE=/tmp/zero-go-cache go test ./cmd/zero-linux-sandbox ./internal/cli ./internal/tools ./internal/release ./cmd/zero-release

Tested: git diff --check

* Route Seatbelt profiles through permission profiles

Build macOS sandbox-exec profiles from the shared PermissionProfile so read roots, write roots, temp access, deny-read, deny-write, and protected metadata are expressed by the platform profile instead of legacy write-root-only inputs.

Keep the existing sandbox-exec adapter path as a compatibility wrapper while adding target macos-seatbelt capability handling.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox

Tested: scripts/sandbox-smoke.sh

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/cli ./internal/tools

Tested: git diff --check

* Stabilize Seatbelt write carveouts

Emit protected metadata and read-only write-root carveouts as explicit Seatbelt deny rules after the broad write allow. This preserves deny precedence while avoiding fragile allow-rule predicates in real sandbox-exec runs.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox

Tested: scripts/sandbox-smoke.sh

Tested: git diff --check

* Expand macOS Seatbelt runtime allowances

Restore the platform startup allowances needed by sandbox-exec-wrapped commands under restricted filesystem profiles: executable mapping, system metadata reads, pty/device access, preferences, IPC, and standard library/runtime roots.

This keeps project writes constrained to the PermissionProfile roots while preventing macOS shells from aborting before user commands run.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox

Tested: scripts/sandbox-smoke.sh

Tested: git diff --check

* Normalize Seatbelt deny expectations in tests

Build Seatbelt deny-rule expectations from normalized profile paths so the metadata ordering test matches production behavior on Windows and Unix hosts.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox

Tested: scripts/sandbox-smoke.sh

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go test -c ./internal/sandbox -o /tmp/zero-sandbox.test.exe

Tested: git diff --check

* Add Windows sandbox runner command planning

Select the windows-restricted-token backend only when the Windows sandbox command runner is discoverable, and keep the missing-runner path as an explicit policy-only downgrade.

Add the Windows runner argument contract for command cwd, workspace roots, permission profile JSON, child environment JSON, restricted-token level, and payload command parsing.

Update sandbox policy output and tests to describe the missing Windows runner instead of an unimplemented adapter.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/cli

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go test -c ./internal/sandbox -o /tmp/zero-sandbox.test.exe

Tested: scripts/sandbox-smoke.sh

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: git diff --check

* Add Windows sandbox command runner

Add the zero-windows-command-runner executable and wire windows-restricted-token plans to pass sandbox home, command cwd, workspace roots, permission profile JSON, child env JSON, sandbox level, and command argv.

Persist Windows capability SIDs under the resolved sandbox home, select read-only or writable-root capability SIDs from the permission profile, and create a restricted token before launching the payload with CreateProcessAsUserW.

Package the Windows runner next to zero.exe and extend sandbox smoke coverage to cross-build it.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox ./internal/release ./cmd/zero-windows-command-runner ./cmd/zero-release

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go build -o /tmp/zero-windows-command-runner.exe ./cmd/zero-windows-command-runner

Tested: scripts/sandbox-smoke.sh

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: git diff --check

* Plan Windows sandbox ACL operations

Derive a deterministic Windows ACL operation list from the restricted permission profile, including writable root allows, protected metadata deny-write entries, explicit deny-write paths, and deny-read materialization targets.

The plan maps workspace and extra writable roots onto the persisted capability SIDs so the elevated setup helper can apply the same contract without reinterpreting the profile.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go test -c ./internal/sandbox -o /tmp/zero-sandbox.test.exe

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go build -o /tmp/zero-windows-command-runner.exe ./cmd/zero-windows-command-runner

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: scripts/sandbox-smoke.sh

Tested: git diff --check

* Add Windows sandbox setup boundary

Add the zero-windows-sandbox-setup command, setup argument parsing, deterministic ACL plan hashing, and a setup marker contract that can detect profile changes requiring refresh.

Make Windows native backend discovery require both the command runner and setup helper, package the setup helper with Windows releases, and include it in sandbox smoke builds.

The setup command remains fail-closed until the Windows ACL applier is wired, so it cannot create a setup-complete marker without applying enforcement.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox ./internal/release ./cmd/zero-windows-sandbox-setup

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go test -c ./internal/sandbox -o /tmp/zero-sandbox.test.exe

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go build -o /tmp/zero-windows-command-runner.exe ./cmd/zero-windows-command-runner

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go build -o /tmp/zero-windows-sandbox-setup.exe ./cmd/zero-windows-sandbox-setup

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: scripts/sandbox-smoke.sh

Tested: git diff --check

* Apply Windows sandbox ACL setup

Implement the Windows ACL setup path with grouped native DACL updates, deny-read materialization, existing DACL snapshots, and rollback for partial application failures.

Write the setup marker only after ACL setup succeeds, roll back applied ACLs if marker persistence fails, and make the Windows command runner validate the setup marker before creating the restricted token.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox ./cmd/zero-windows-sandbox-setup ./cmd/zero-windows-command-runner

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go test -c ./internal/sandbox -o /tmp/zero-sandbox.test.exe

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go build -o /tmp/zero-windows-command-runner.exe ./cmd/zero-windows-command-runner

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go build -o /tmp/zero-windows-sandbox-setup.exe ./cmd/zero-windows-sandbox-setup

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: scripts/sandbox-smoke.sh

Tested: git diff --check

* Fail closed for Windows network policies

Add Windows network policy validation that allows only explicit network-allow until native Windows network enforcement is implemented.

Make the Windows command runner reject deny, scoped, and unset network modes before launching a restricted-token process so default network-deny cannot silently run open.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox ./cmd/zero-windows-command-runner

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go test -c ./internal/sandbox -o /tmp/zero-sandbox.test.exe

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go build -o /tmp/zero-windows-command-runner.exe ./cmd/zero-windows-command-runner

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: scripts/sandbox-smoke.sh

Tested: git diff --check

* Track Windows network setup state

Add a canonical Windows network-policy hash and persist it in the Windows sandbox setup marker so setup refresh can detect network mode, domain, and proxy-requirement changes.

Bump the setup marker schema and add tests for domain-order normalization plus network-change marker invalidation.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go test -c ./internal/sandbox -o /tmp/zero-sandbox.test.exe

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go build -o /tmp/zero-windows-command-runner.exe ./cmd/zero-windows-command-runner

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go build -o /tmp/zero-windows-sandbox-setup.exe ./cmd/zero-windows-sandbox-setup

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: scripts/sandbox-smoke.sh

Tested: git diff --check

* Add sandbox setup CLI command

Add zero sandbox setup to resolve the active sandbox policy, derive the Windows setup helper next to the command runner, and invoke it with the shared Windows setup argument contract.

Return text or JSON setup results, no-op cleanly for non-Windows native backends, and add tests using an injected helper runner.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/cli ./internal/sandbox

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go test -c ./internal/cli -o /tmp/zero-cli.test.exe

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go test -c ./internal/sandbox -o /tmp/zero-sandbox.test.exe

Tested: GOOS=windows GOARCH=amd64 GOCACHE=/tmp/zero-go-cache go build -o /tmp/zero-windows-sandbox-setup.exe ./cmd/zero-windows-sandbox-setup

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: scripts/sandbox-smoke.sh

Tested: git diff --check

* Stabilize Windows ACL canonical path test

* Add TUI sandbox setup command

* Gate TUI sandbox setup command

* Clarify sandbox doctor setup status

* Add Windows WFP network setup

Adds a Windows network enforcement plan with stable WFP provider, sublayer, and filter specs for deny-mode sandbox identities. The setup helper now installs or removes those filters transactionally before writing the setup marker, and the marker tracks the network enforcement plan so stale filters require refresh.

Scoped Windows network mode remains fail-closed until the proxy exception path is implemented, so it cannot silently become open network.

Diagnostics now report native Windows network enforcement when the restricted-token backend is active.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox -run 'TestValidateWindowsNetworkPolicyAllowsNativeModes|TestValidateWindowsNetworkPolicyFailsClosedForScoped|TestBuildWindowsNetworkPlanForDenyUsesCapabilityIdentity|TestBuildWindowsNetworkPlanFailsClosedForScoped|TestWindowsNetworkPlanHashIsStableAcrossEntryOrder|TestWindowsSandboxSetupMarkerRefreshesWhenNetworkChanges|TestSelectBackendChoosesPlatformAdapterWithFallback'

Tested: GOCACHE=/tmp/zero-go-cache GOOS=windows GOARCH=amd64 go build -o /tmp/zero-windows-sandbox-setup.exe ./cmd/zero-windows-sandbox-setup

Tested: GOCACHE=/tmp/zero-go-cache GOOS=windows GOARCH=amd64 go build -o /tmp/zero-windows-command-runner.exe ./cmd/zero-windows-command-runner

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox ./internal/cli ./internal/doctor

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: GOCACHE=/tmp/zero-go-cache scripts/sandbox-smoke.sh

Tested: git diff --check

* Add Windows sandbox network smoke

Adds a gated Windows real sandbox smoke test that runs the compiled setup helper and command runner, verifies sandboxed writes still work, and proves network=deny blocks a loopback TCP connection from a restricted-token command.

The sandbox smoke script now runs this test on Windows using the helper binaries it builds in its temporary directory.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox -run 'TestValidateWindowsNetworkPolicyAllowsNativeModes|TestBuildWindowsNetworkPlanForDenyUsesCapabilityIdentity'

Tested: GOCACHE=/tmp/zero-go-cache GOOS=windows GOARCH=amd64 go test -c -o /tmp/zero-windows-sandbox.test ./internal/sandbox

Tested: GOCACHE=/tmp/zero-go-cache GOOS=windows GOARCH=amd64 go build -o /tmp/zero-windows-sandbox-setup.exe ./cmd/zero-windows-sandbox-setup

Tested: GOCACHE=/tmp/zero-go-cache GOOS=windows GOARCH=amd64 go build -o /tmp/zero-windows-command-runner.exe ./cmd/zero-windows-command-runner

Tested: GOCACHE=/tmp/zero-go-cache scripts/sandbox-smoke.sh

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: git diff --check

* Remove legacy sandbox runner paths

Drop the old direct bubblewrap adapter, the standalone zero-seccomp wrapper, legacy adapter metadata, and the Phase 0 legacy inventory now that command planning goes through the sandbox manager backends.

Switch platform selection and tests to target backend names: linux-bwrap, macos-seatbelt, windows-restricted-token, and explicit policy-only degradation.

Keep policy as the shared permission/profile and diagnostics surface, but stop exposing legacy adapter fields in CLI policy output and tool metadata.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox ./internal/cli ./internal/tools ./internal/zerocommands ./internal/doctor

Tested: GOCACHE=/tmp/zero-go-cache scripts/sandbox-smoke.sh

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: git diff --check

* Address sandbox baseline review blockers

Restore sandbox.blockUnixSockets as a resolved config and policy field, route it into the Linux helper as --block-unix-sockets, and keep zero-seccomp as a Linux compatibility wrapper packaged with release artifacts.

Add the missing legacy-entrypoint test referenced by the smoke script, extend helper/release/config tests, and make CLI startup tests hermetic by stubbing MCP registration where they assert quiet output.

Document the compatibility path, release helper scope, and the already-resolved #237 prompt-file overlap in the PR body.

Tested: GOCACHE=/tmp/zero-go-cache go test ./internal/sandbox ./internal/cli ./internal/config ./internal/release ./cmd/zero-seccomp -run 'TestLegacySandboxEntrypointsAreExplicitAndExist|TestSandboxManagerBuildsCommandPlanThroughLinuxHelper|TestBuildLinuxSandboxCommandArgsSerializesPermissionProfile|TestParseLinuxSandboxHelperArgs|TestBuildLinuxSandboxBwrapArgsWrapsInnerSeccompStage|TestApplyConfiguredSandboxPolicyDiagnosticsFlags|TestResolveSandboxBlockUnixSocketsFromFile|TestCopyPackageFilesStagesLinuxSandboxHelper'

Tested: GOCACHE=/tmp/zero-go-cache go test ./...

Tested: GOCACHE=/tmp/zero-go-cache scripts/sandbox-smoke.sh

Tested: git diff --cached --check

Tested: local leak scan found no matches
2026-06-18 12:03:10 +05:30
Vasanth T 40cec8d476 Add provider health diagnostics (#151)
* Add provider health diagnostics

* Fix provider health auth review findings

* Fix provider health test handler assertion

* Harden provider health connectivity probes
2026-06-10 13:14:19 +05:30
9c2e14272b CLI: doctor config validation, autonomy ceiling, changes --base, usage report (#142)
* config: add ValidateFile for structured config diagnostics

* doctor: add offsetToLineCol helper for JSON error positions

* doctor: validate config files in config.validation check

* cli: thread config paths into doctor and degrade on bad JSON

* doctor: inline read, single-parse config validation + utf8 col test

- Remove the osReadFile wrapper; call os.ReadFile directly at its one call site
- Add config.ValidateBytes([]byte) so each config file is read and JSON-parsed
  once in configValidationCheck instead of twice (once for position, once via
  ValidateFile); ValidateFile now reads then delegates to its own unmarshal for
  the path-prefixed error message, keeping its public signature unchanged
- Fix the misleading skip comment in configValidationCheck: configFilesCheck
  only checks path-string presence; the skip is a defensive guard for the
  unreachable case where DefaultResolveOptions passed a non-empty path that
  still fails to read
- Add utf8 multibyte case to TestOffsetToLineCol documenting byte-column
  semantics (column counts bytes, not runes)

* sandbox: add Policy.MaxAutonomy ceiling defaulting to high

* sandbox: normalize both operands in autonomyAllowed to fail closed

* sandbox: clamp grant-allow and unsafe escalation to policy autonomy ceiling

* sandbox: add RequiredAutonomyForBatch helper with fail-closed mapping

* config: add sandbox.maxAutonomy field to file and resolved config

* config: merge sandbox.maxAutonomy across layers, env, and overrides

* cli: thread configured autonomy ceiling into sandbox engine construction

* cli: surface max_autonomy in sandbox policy formatters

* zerocommands: carry max autonomy in sandbox policy snapshot

* sandbox: default empty policy ceiling to high + reason const

Evaluate now treats an empty Policy.MaxAutonomy (from a directly-constructed
Policy that bypasses DefaultPolicy) as High instead of letting it normalize to
Low, which would silently clamp every Medium/High decision to Prompt. The
ceiling is a no-op unless explicitly configured.

Also extracts the "above policy ceiling" clamp reason into a package const
referenced at both engine clamp sites and the related tests, and adds a
non-vacuous engine test proving the empty-ceiling trap is closed.

* zerogit: add base-ref three-dot diff to changes inspect

* zerogit: cover base-ref backward-compat and real-git diff

* zerogit: propagate base ref through change snapshot

* cli: parse changes --base ref and reject on commit

* cli: thread base ref into changes inspect output and help

* changes: redact base in cli summary + guard --base= + rename test

- redactChangeSummary now redacts the Base field alongside Root/Branch/Commit/etc.
- --base= equals-form rejects leading-dash values via flagValueLooksLikeOption, closing the option-smuggling gap
- TestParseNameStatusRenameAndCopy asserts rename/copy three-field lines use the new/destination path with correct status, and confirms two-field modify is unaffected

* Add ParseDiffStat helper for git diff --stat summaries

* Add usage report aggregation over persisted session usage events

* Add zero usage report command over persisted session usage

* Wire usage command into CLI dispatch and help

* usage: validate --since format, fix redaction comments, add tests

Fix 1 (BLOCKING): parseUsageArgs now validates --since with time.Parse
against YYYY-MM-DD; returns exitUsage + "invalid --since %q: expected
YYYY-MM-DD" for bare strings like "foo", unpadded "2026-6-1", or
wrong-separator "06/01/2026". Valid dates are stored unchanged for the
existing lexical comparison.

Fix 2: Replace false "pre-redaction stat" claims in diffstat.go and
usage.go with accurate comments: the --stat summary line carries no
secret-bearing tokens so parsing the already-redacted DiffStat is safe.

Fix 3: Add three tests to usage_test.go —
  - TestRunUsageDaysFilter: stubs deps.now, seeds events on two dates,
    asserts --days 3 includes the recent date and excludes the old one.
  - TestRunUsageInvalidSince: table-driven; verifies "foo", "2026-6-1",
    "06/01/2026" each return exitUsage + validation message, while
    "2026-06-01" returns exitSuccess.
  - TestRunUsageEmptyStore: zero usage events → exitSuccess, output
    contains header and "total" row, no panic.

* doctor: surface type-mismatch offsets and drop colliding flat line/col keys

Probe config validation against config.FileConfig instead of a bare any so
a structurally-valid document with a wrong field type (e.g. maxTurns as a
string) surfaces a *json.UnmarshalTypeError carrying the offset, instead of
losing line/col. Remove the flat top-level details["line"]/["col"] keys
that were overwritten by the last malformed file when several were present;
keep only the unambiguous per-path map entry. Tighten the existing malformed
test to assert concrete per-path line/col and add a type-mismatch test that
exercises the previously-dead UnmarshalTypeError branch.

* sandbox: fail closed on invalid configured autonomy ceiling

An invalid non-empty sandbox.maxAutonomy (e.g. "moderate") previously
survived Resolve (only trimmed, never validated), failed to normalize at the
sandbox bridge, and left the policy unchanged at the default High ceiling.
A typo therefore silently disabled the admin's intended ceiling: fail-open on
a security boundary.

Validate at resolve time (fail loud): Resolve now rejects a non-empty
maxAutonomy that does not normalize, returning a clear error. As defense in
depth, applyConfiguredAutonomyCeiling now clamps an unrecognised non-empty
value to the most restrictive ceiling (low) instead of returning the policy
unchanged, so a bad value can never widen the ceiling even via direct use.
Empty/unset stays valid and keeps the default High ceiling.

Add resolver tests for invalid-fails / valid-resolves and bridge tests for
the fail-closed clamp and valid mappings.

* sandbox: fail closed on malformed autonomy and surface policy resolve errors

Treat a genuinely-invalid request autonomy as the highest tier in the engine
so it exceeds a Medium/Low ceiling and clamps to Prompt instead of being
sanitized to Low and auto-allowing on the grant/unsafe path. Surface
resolveConfig failures in the policy command instead of silently falling back
to the permissive DefaultPolicy, which would misreport trust posture.

* usage: bucket and filter by UTC calendar day, reject empty --session

Normalize RFC3339 timestamps to their UTC calendar date before day bucketing
(report) and before the --since/--days cutoff comparison (CLI) so offset
timestamps land on the correct UTC day and the bucket and cutoff agree;
malformed timestamps fall back to the leading-10 slice. Reject empty
--session/--session-id values with a value-required error matching the --since
validation style.

* doctor: fail on unreadable config files and stop fabricating positions

Surface a present-but-unreadable config path (permissions, is-a-directory) as
a failing per-path validation detail instead of silently skipping it; a
genuinely-missing path stays a skip. Return ok=false for a JSON parse error
that carries no offset so it routes through the no-position ValidateBytes path
rather than fabricating a (1,1) line/col. Assert empty stderr on the JSON
doctor failure path.

* config: make sandbox maxAutonomy resolver tests hermetic

Pass an explicit empty Env to the maxAutonomy Resolve tests so host
environment variables cannot leak in through the nil-Env os.Getenv fallback.

* sandbox: preserve raw autonomy for ceiling check so invalid clamps under default ceiling

Defaulting invalid request.Autonomy to High only clamped under a Medium/Low
ceiling; under the default High ceiling autonomyAllowed(High, High) returned true
and still auto-allowed (fail-open). Keep the raw requested value for the ceiling
check so autonomyAllowed's unknown-tier guard fails it closed under ANY ceiling.
Adds default-High-ceiling regression tests for the unsafe and grant-allow paths.

---------

Co-authored-by: KRATOS <[email protected]>
Co-authored-by: Vasanthdev2004 <[email protected]>
2026-06-08 17:15:57 +05:30
Vasanth T 43c256068a feat: make Go runtime the app path (#71)
* feat: make go runtime the app path

* fix: harden update semver parsing
2026-06-05 17:24:58 +05:30
KRATOSandKRATOS 152bb6b62d [codex] add Go observability backend commands (#59)
* feat(go): add observability backend primitives

* feat(go): add session search and doctor backends

* feat(go): expose observability cli commands

* fix(go): address observability review feedback

---------

Co-authored-by: KRATOS <[email protected]>
2026-06-04 21:43:23 +05:30