warrant 0.6.0 — signatures name the protocol, and reasons are readable
Breaking. The signed message is no longer the bare WarrantID. SPEC v0.4 signs "warrant-sig-v1:" || WarrantID_raw — 47 bytes, still pure RFC 8032 Ed25519. A pre-0.6.0 signature MUST NOT verify, and nothing accepts both; warrant resign --key <keyfile> migrates a store you hold the key for, and no WarrantID changes because the envelope is not hashed. If you do not hold the key, the verifier says so by name instead of reporting a generic bad signature.
Why now: a key that signed any other protocol's raw SHA-256 digest signed a Warrant too. The cost of fixing that was at its global minimum with no external users and rises monotonically from here — so this release takes it rather than inheriting it.
Writing a re-runnable reason no longer means writing combinators
A check that any verifier re-executes offline was the point of this format, and authoring one meant hand-building SKI terms. WPL compiles a readable policy to exactly such a term:
fact days_until_travel: int = -12
fact fare_basis: string = "bereavement"
check fare_basis == "bereavement" && days_until_travel >= 0
It borrows CEL's syntax so a Kubernetes or Envoy reader parses it on sight, and claims no CEL conformance — deliberately, because no CEL implementation is available offline and stdlib-only, and an unverified compatibility claim is a provenance defect in a repository about provenance. docs/authoring-checks.md takes an engineer who has never heard of a combinator from nothing to a working policy.
The compiler is not new trusted code. The verifier still re-runs the term; the compiler only produces it. Every compile round-trips its output through the Σ-GLYPH oracle against a plain-Python interpreter of the same source and refuses to emit on disagreement — and, after an external audit found --headroom emitting checks the verifier rejects (a negative value produced a wrong verdict, not an error), it now re-executes the serialized blob under its pinned ATP before writing. The artifact is validated, not the intention.
The Air Canada demo is unchanged where it counts: same check blob, same term, same atp_spent=17.
The normative surface moved into the spec
warrant.verify-report@v0 — the contract CI branches on — lived only in the README. It is in SPEC now, with the JCS escaping battery extracted from a Python script into machine-readable vectors, trust-config.json specified, JSON Schemas published for body/envelope/report/manifest, a draft application/warrant+json registration, and a registry policy for runtime and report tags. Plus THREAT-MODEL.md, consolidating what was scattered across five files, and a CHANGELOG.
A P0 fixed on the way: verify --settlement --trust-config reported 1 warnings in text and "warnings":0, "findings":[] in --json for the same store — Python's quiet path swallowed the unbound-signature finding that Go emitted in both. Two implementations disagreeing on a verification outcome is the severity this project reserves for exactly that.
Also
- MCP server (
integrations/mcp-server/): any MCP client files decision records with two lines of configuration. - Model actors are delegated, bounded actors under a root of authority held by a human — never the maintainer of record, never where non-repudiation rests. The retirement insight is kept, relocated under that framing. Custody is stated in counts rather than implied.
- Every GitHub Action pinned to a full commit SHA; the jobs that mint an OIDC token no longer take a mutable ref.
Verify this release
pipx install warrant-verify
curl -LO https://github.com/s0fractal/warrant/releases/latest/download/air-canada-pack.zip
unzip air-canada-pack.zip
warrant --store air-canada-pack/.warrants verify
warrant --store air-canada-pack/.warrants check b423b6a82c3451bfbd75563b39e6391093a64db57941d9247a61a6c620bd997fThe last line re-executes the reason on your machine and prints pass result=65cd957f… atp_spent=17. You are not trusting a log; you are recomputing the argument.
What this release does not claim
tools/check.py is 33/33 with zero unrun, and the cross-repo seam against Σ-GLYPH is green. But no independent gate reviewed this work: every reviewer was either this model family or an external model run by the same operator. Two such audits did find real defects — a non-recursive file walk in the sibling's proof guard, and both P1s named above — and they are credited where they were fixed. That is defect-hunting, not a gate, and the difference is kept in the record rather than rounded away.