Skip to content

PolicyWitness 0.3.3

Choose a tag to compare

@Protonk Protonk released this 24 Oct 03:05
· 245 commits to main since this release

PolicyWitness 0.3.3 retires the unified-log observer: runs no longer scan the system log for sandbox denials or associate denial records with attempts. Builds now run only natively on Apple Silicon and start their helpers on a pinned Python 3.14, which each build's provenance record names.

Compatibility: This release changes the controller envelope to 8 (previously 7). Request schema 5 and runner response schema 23 are unchanged, so existing specimens need no update. The envelope no longer contains data.sandbox_log_capture, and data.runner_sandbox_diagnostics no longer contains correlation_status or permission_failures_without_record. policy-witness run refuses --no-log-capture and --log-timeout-ms as unknown arguments; remove them from scripts. The app no longer contains Contents/MacOS/sandbox-log-observer. Historical evidence retains its original format; current readers do not translate older envelopes. The runner host, worker and validator have no functional changes, so external BYOXPC runners installed from 0.3.2 accept the same requests and return the same responses; reinstall from the new bundle to refresh their recorded provenance. The minimum remains macOS 26, on Apple Silicon.

Changes since 0.3.2:

  • Unified-log observer retired. A run no longer includes the bounded log show scan that 0.3.2 performed by default after the runner client exited, or the candidate associations between denial records and submitted attempts. Attempt outcomes and comparison fields never depended on that evidence and are unchanged; data.runner_sandbox_diagnostics continues to report worker disposition from native execution observations. Sandbox-denial logs are incomplete and do not, by themselves, establish why an operation failed. The observer and its former integration are archived, unmaintained, at Protonk/Observer for independent adaptation.
  • Native Apple Silicon builds only. build.sh refuses before its other checks and the checkout lock unless hw.optional.arm64 reads 1 and sysctl.proc_translated reads 0, so a build started under Rosetta stops with native_builder_required; an unreadable value refuses too. When the build is started through make, make's own launch and SDK check precede that refusal.
  • A pinned interpreter and a witnessed build environment. Build, test and release helpers start on Homebrew's python@3.14 at /opt/homebrew/opt/python@3.14/bin/python3.14 instead of the /usr/bin/python3 shim, which adds or replaces SDKROOT, CPATH, LIBRARY_PATH and MANPATH for everything it starts. The resolver checks the keg, probes the version and refuses with direct_python_unavailable, python_version_mismatch or python_environment_set before any helper runs. The build's front end witnesses the caller's SDKROOT, CPATH, LIBRARY_PATH, MANPATH and LC_CTYPE, and later stages refuse a missing or changed value rather than repairing it. A nonempty SDKROOT must resolve through xcrun to an SDK with a numeric version before the build starts any other developer-tool shim; the Makefile checks the same request while it is parsed. Building from source now needs brew install python@3.14 alongside Meson and Ninja.
  • Provenance names the interpreter. The embedded provenance record moves to schema 3 and requires toolchain.python: the pinned path, its resolved real path, the version the keg names and the version an isolated probe reported. The provenance reader, release verification, publication and release cleanup accept only current records.
  • A build dependency list. The new docs/DEPENDENCIES.md lists what a build and the tests need, the check that enforces each requirement and the toolchain known to work. The Meson and Ninja refusals point to it.

For contributors, Python starts in the test harness use the pinned interpreter, apart from deliberate shim controls, with -B -S and -P for inline and stdin starts, and a drift check enforces that form across tests/. Each run records the interpreter it resolved, every case report declares its own, and the dispatcher records interpreter_mismatch when they differ. The log-capture fixtures and unread fixture generations are removed.