mirror of
https://github.com/Twigpine/zero.git
synced 2026-11-11 18:00:54 -10:00
* feat(zerocommands): add typed sandbox policy, risk, violation, and decision snapshots The merged permission and verification event contracts (#82) added typed snapshots for config, providers, models, and sessions, and PR #89 added the typed snapshot for the persistent sandbox grant store, but the live sandbox policy, the live risk classification, the live violation, and the live decision were still exposed as the raw backend structs. The TUI render path, the headless 'zero sandbox policy --json' and 'zero sandbox decide' commands, the audit log, and PR/CI automation all need typed snapshots so they do not hand-roll map[string]any payloads and so they do not have to re-implement the runtime default-mode translation themselves. This commit adds five typed snapshot constructors and a bundled plan snapshot to internal/zerocommands. SandboxPolicySnapshot - mode, network, enforceWorkspace, denyDestructiveShell, and allowPolicyOnlyRunner are copied verbatim from the underlying sandbox.Policy. - effectiveMode is the resolved policy mode. An empty Mode in the input falls back to ModeEnforce, which is the runtime default. Consumers can read EffectiveMode to render the 'what is actually in effect' line without re-implementing the default. - effectiveMode is JSON-omitted when empty so the snapshot shape stays stable for downstream consumers. SandboxRiskSnapshot - level, categories, reason. - categories is copied and sorted alphabetically so the JSON output is deterministic. - reason is trimmed. SandboxViolationSnapshot - code, toolName, action, path, reason, recoverable. - The pointer-returning helper returns nil for a nil input so callers can chain it through SandboxDecisionSnapshot without nil checks at the call site. SandboxBackendSnapshot - name, available, platform, fallback, commandWrapping, nativeIsolation, executable, message. - executable and message are trimmed. SandboxPlanSnapshot - bundles policy, backend, restrictions, and workspaceRoot into one payload so 'zero sandbox policy --json' can return one typed result describing the full sandbox posture. - each entry of restrictions is trimmed, whitespace-only entries are dropped, and the result is sorted alphabetically. - workspaceRoot is trimmed and JSON-omitted when empty. SandboxDecisionSnapshot - action, reason, risk, grantMatched, grant, violation. - The optional grant pointer is converted with SandboxGrantSnapshotFromGrant (from PR #89) so the JSON shape matches the persistent-grant snapshot exactly. - The optional violation pointer is converted with SandboxViolationSnapshotFromViolation so the snapshot always carries the same shape regardless of the decision outcome. - When grant or violation is nil, the field is JSON-omitted. Tests - TestSandboxPolicySnapshotFromPolicyFillsEffectiveMode: verifies EffectiveMode is enforced for an empty Mode, set to ModeDisabled for an explicit disabled mode, and preserved for an explicit enforced mode. - TestSandboxRiskSnapshotFromRiskSortsCategoriesAndTrimsReason: verifies alphabetical sort, trimmed reason, and that a nil Categories input produces a nil output (no spurious empty slice). - TestSandboxViolationSnapshotFromViolationHandlesNilAndTrims: verifies the nil-input contract and the trim behaviour for every string field. - TestSandboxBackendSnapshotFromBackendCopiesAllFields: verifies the boolean and string fields round-trip and the trim behaviour for the executable and message. - TestSandboxPlanSnapshotFromPlanSortsRestrictionsAndTrimsRoot: verifies alphabetical sort, per-entry trim, and workspaceRoot trim. - TestSandboxDecisionSnapshotFromDecisionAllowBranchHasNoViolation: verifies the allow path has no grant and no violation. - TestSandboxDecisionSnapshotFromDecisionPersistentDenyCarriesGrantAndViolation: verifies the deny path carries both the resolved grant and the violation, and that the grant snapshot matches the persistent-grant snapshot shape from PR #89. - TestSandboxDecisionSnapshotJSONShapeIsStable: verifies the stable keys and the nil-pointer omission. - TestSandboxPolicySnapshotJSONOmitsEmptyEffectiveMode: verifies the omitempty tag. Verification - go build ./... - go vet ./... - go test -count=1 -p 1 ./internal/zerocommands/... \ ./internal/sandbox/... ./internal/redaction/... DRI: Gnanam (runtime core owner per WORK_SPLIT_PRD.md §4). Closes the typed-snapshot gap for the live sandbox surface that the TUI render path, the 'zero sandbox' headless commands, the audit log, and PR/CI automation consume. * fix(npmwrapper): make copyWrapperFixture create package.json with type:module This ensures the isolated wrapper .js fixture is always treated as ESM (matching real package installs). Previously, without it, Node treated the .js as CJS on some platforms/runners (especially Windows), causing SyntaxError before the missing-native console.error path. This was causing TestNodeWrapperReportsMissingNativeBinary to get empty output + timeout on windows-latest smoke jobs (e.g. in PR 92). The test now reliably hits the error path and captures the expected message on all platforms. Also improves robustness of the npm wrapper smoke test added in #88. --------- Co-authored-by: Gnanam <gnanam@local> Co-authored-by: KRATOS <[email protected]>