A human signs the boundary once. The agent then writes whatever it writes, and in CI, outside the agent's reach, Notari measures the diff against that signed boundary and issues a Change Passport: a receipt anyone can re-verify later without trusting Notari's runtime. There is no model anywhere in the verdict, so the verdict cannot be prompt-injected, and every box below corresponds to a command, a file, or a module that exists in the repository today.
notari 0.4.1 · alpha · sources: src/notari/{contract,verify,policy,secrets,passport,audit}.py · docs/SECURITY-MODEL.md
.notari/contract.json plus a detached .sig: the approved task,
the allowed paths, the base commit, and a contract id. --scope is required, so
the boundary is a conscious choice; --scope '**' is the explicit "anything the
perimeter permits" opt-out, and an unrestricted contract is flagged on the passport.
--repo binds the approval to one repository so a signed contract cannot be replayed
elsewhere, and --expires-in gives it a human-set deadline rather than a heuristic.
notari guard. The approver's private key never has to leave that machine.
pull_request_target runs the trusted
workflow from the base branch, not from the pull request..notari/exceptions.json is ignored
entirely under --strict.git diff --name-status -z --find-renames, keeping both ends of a rename
and including binary and mode-only changes.secrets.py..gitattributes that can control diff visibility.verification.run event into the audit log.block-on-review, so it fails the build unless you opt out.verify writes passport.json for tooling and passport.md for
the pull request. The markdown footer cites the verification.run audit MAC, so the
document traces back to the tamper-evident chain instead of asking you to trust it.
CLAUDE.md or AGENTS.md as a short rule, so the next session starts
already knowing it. The gate catches; the loop stops the catch from repeating.
bash examples/bypass_probes.sh, and read
docs/SECURITY-MODEL.md before trusting any one-line claim here.