Repository navigation
NockGuard v0.6.0: fail-closed audit, local approver, Wall in the release
NockGuard v0.6.0 refuses tool calls when it cannot write its signed audit record, adds a local approver for held calls, and ships the Wall in the release archives with NockLock events in the same stream.
Upgrade notes: this release has breaking changes. Read the Breaking section before upgrading. Anything that counts audit rows should expect the new dispatch row. nockguard init writes a new starter policy, and existing policy files are not touched.
Install on macOS: brew upgrade nocktechnologies/tap/nockguard (installs nockguard and nockguard-wall). Linux and macOS archives with SHA256SUMS are attached below.
Breaking
- Local
nockguard proxyandmcp-listen(andmcp-http) now refuse tool calls when a required audit write fails, whenever auditing is enabled. The failure latches: every later call is refused until the trail is fixed and reopened with a verified signing key. Pass--audit-best-effortto get the old forwarding back; startup prints a warning.status,doctorand the Wall showaudit failing: calls refusedwhile a failure is outstanding. nockguard proxyandmcp-listennow write adispatchaudit row before they forward an allowedtools/callrequest, when auditing is on and--audit-best-effortis not set. Each such call has one more row than in 0.5.0. Denied calls, other methods andmcp-httpwrite nodispatchrow, andmcp-gatewayalready wrote one. Anything that counts rows or matches decisions should expectdispatch.nockguard initwrites a different starter policy. The agent iscoder(wasmy-agent), it allowsread_fileandread_text_fileand denieswrite_file,defaultstaysmode: deny, andaudit.enabled: trueis on (it was commented out). The oldaskrules and wildcard allows are gone. Runkeygen --agent coderbefore the first proxy run so the audit trail is signed. Existing policy files are not touched, andinitstill refuses to overwrite one without--force.- The Wall now reads the agent's public key with the same resolver as
nockguard verify --agent: theNOCKGUARD_AGENT_<NAME>_ED25519_PUBvariable first, then~/.nockguard/keys/<name>.pub. A Wall that relied on a key being absent will now verify against the file./verifyreports PROTECTED only for a non-empty trail that its signed checkpoint fully covers; empty, unconfigured, unavailable and unanchored trails are shown as such.
Added
- Local approver for
askverdicts, with no network: setNOCKGUARD_APPROVER=localand decide held calls withnockguard approvals list|approve|deny(pruneremoves dead sockets left by crashed proxies). Held calls wait on a0600unix socket in a0700approvals directory, one<pid>-<random>.sockper proxy, removed on exit, and are audited asapproval-granted/approval-deniedwith the approverlocal:<uid>. The listing shows id, agent, tool, reason and age, never arguments. The approver does not start, andaskfails closed, if the directory or socket permissions, ownership or type are wrong. A same-uid agent can still approve its own calls; see the README trust boundary. - Live Wall shows NockLock and NockGuard in one stream.
nockguard-wall --lock-db <events.db>reads a NockLock log read-only (file, network and secret fence events, blocked and passed), labeledLOCK/GUARDand colored by outcome, decision only.--lock-pub-envnames the NockLock public key (defaultNOCKLOCK_AUDIT_ED25519_PUB).--democannot be combined with--lock-db. - Per-session signed-proof badge on the Wall (
GET /sessions): the same verdict asnockguard verify --session(PROTECTED / TAMPERED / UNSIGNED / UNVERIFIABLE / NO_ROWS / UNANCHORED) with both key fingerprints. A missing key is UNVERIFIABLE, never green. A Lock log over 100,000 events is UNVERIFIABLE, too large. An unreadable Lock row shows as UNPARSEABLE and makes its session UNVERIFIABLE; the rest of the batch still shows. nockguard wallsubcommand. It startsnockguard-wallfrom beside the CLI or fromPATHand forwards flags and signals.nockguard-wallnow ships in the Linux and macOS release archives, and a standalonenockguard-wallinstall keeps working.nockguard status --agent <name>anddoctorreport a required audit write failure;statusaccepts--audit <path>for custom trail paths.- A Linux CI check runs the README quickstart end to end (init, keygen, proxy, verify) against a local MCP stub, with a successful read, a blocked write and signed allow and deny rows.
Changed
/exportCSV and JSON gain a trailingsourcecolumn / field (GUARDorLOCK). With--lock-db, each source keeps its own 500-row cap, and theX-NockGuard-Lock-Verificationresponse header isok,unsigned(no Guard key, so nothing is verified) orunavailable(no Lock snapshot, so no Lock rows). The PROOF export remains NockGuard rows only.- The README quickstart uses the
coderagent and a concrete demo path, matchingnockguard init. - Documentation claims now match shipped behavior, and a repository map and the 1.0 contract are added under
docs/.
Fixed
- macOS: the local approver socket path now fits the 104 byte
sun_pathlimit. When~/.nockguard/approvalswould be too long, it falls back to a private per-user directory under/tmp. - macOS 26.5: two nockguard processes starting at once on a fresh machine no longer fail with "opening key lock ... no such file or directory".
Known limits
- With stdio, a response that arrives ahead of an earlier pending call can be released before its deferred decision row is written. The
dispatchrow is durable first. If that later write fails, the latch refuses every later call and status reports the failure. - The failure marker is per trail, not per process or per agent. Every proxy writing the same trail sees it.
- An unsigned trail has no verified reopen, so nothing clears its failure marker short of choosing
--audit-best-effort. Sign the trail to get the repair path.