Back to blog

Signed receipts for AI coding agents

Jul 20, 2026

AI coding agents now open their own pull requests and merge them. The git author string on a commit is mutable, so a name in a commit header proves nothing about who wrote the change or under whose authority. When an auditor asks which agent wrote which change, git history alone cannot answer.

The code-authorship receipt is our answer. It is a signed, hash-chained, anchored record that a specific code change existed, was authored by the holder of a signing key, and held a fixed position in the per-agent chain at time T. The authoritative form ships under receipt type authoritative, minted by POST /code-authorship.

The server re-derives the diff

The receipt does not trust a digest the producer hands over. Asqav re-fetches the commit from the GitHub API, re-derives the changed-files diff itself, and signs the SHA-256 it computed over the canonical form of that diff. The signed subject digest is the server value only. A client-supplied change_digest is advisory: it is compared against the server digest and the agreement is recorded as digest_match, but the client value is never signed. A producer that posts a fake digest still receives a receipt whose subject is the value the server computed from GitHub, with the mismatch flagged in the predicate.

Because the server signs a digest it re-derives from a public commit, the receipt is reproducible. Any third party who re-fetches the same commit_sha from GitHub repeats the same projection and recomputes the same digest, then checks it against the signed subject. The producer cannot move the signed subject, because the producer never controls the bytes that feed it. That is what makes the receipt unbypassable.

What the receipt proves, and what it does not

A code-authorship receipt proves a bounded set of facts and refuses to claim anything beyond them.

The change existed, and the server verified it. The subject.digest.sha256 is the SHA-256 the server re-derived from the GitHub compare response and signed. It is a digest the producer cannot forge, because the producer never supplies it.

The change was key-authored. The signature is an ML-DSA-65 signature from a key held outside the agent's environment. Whoever holds that key produced, or authorized, the change. The public key is served for offline verification at /.well-known/jwks.json.

The change held a fixed position in the chain. Each receipt links to the one before it. Reorder, delete, or insert a backdated receipt and the chain breaks at the exact spot.

The capture layer is server-derived too. The receipt stamps capture_layer: github_sha_pull, and any capture_topology a client supplies is dropped before signing, so a caller cannot spoof how the change was captured. In-process capture is observation-only across Asqav: a self-reported in-process receipt cannot drive an allow or deny decision, and the conformance gate fails closed on the attempt.

What the receipt does not prove is just as important. Asqav does not verify the code is correct or safe, and it does not verify which model produced the change. The author field is advisory, carried in the predicate for correlation and never read as Asqav-verified attribution. The receipt is a record, not a code review.

A code-authorship receipt on the wire

The receipt is an in-toto Statement v1 wrapped in a DSSE envelope. The subject names the commit and carries the server-re-derived digest. The predicate carries the producer assertions and the capture layer.

{
  "_type": "https://in-toto.io/Statement/v1",
  "subject": [
    {
      "name": "github.com/acme/payments-service@9f3c1d8b4a6e2f0c5d7b9a1e3c4f6d8b0a2e4c6f",
      "digest": { "sha256": "c4d9f1a7e0b3..." }
    }
  ],
  "predicateType": "https://asqav.com/attestation/code-authorship/v1",
  "predicate": {
    "repo": "acme/payments-service",
    "commit_sha": "9f3c1d8b4a6e2f0c5d7b9a1e3c4f6d8b0a2e4c6f",
    "base_sha": "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b",
    "capture_layer": "github_sha_pull",
    "asset_class": "code",
    "change_class": "write",
    "advisory_client_digest": "sha256:c4d9f1a7e0b3...",
    "digest_match": true,
    "author": "agt_release_bot",
    "verified_at": "2026-07-28T14:11:02.000000Z"
  }
}

The signed bytes are the DSSE Pre-Authentication Encoding of the payload type and the canonical statement, so a verifier recomputes that encoding from the decoded payload and checks the ML-DSA-65 signature offline, with no callback to any Asqav server.

Where it plugs in

The receipt rides the same supply-chain attestation tooling teams already run. It maps onto an in-toto Statement v1, with the subject array naming the produced digest and the predicate carrying the producer assertions and the chain position. Wrapped that way, it rides the same transparency-log rails as a Sigstore Rekor entry or a GitHub Artifact Attestations submission.

What it maps to in an audit

A code-authorship receipt is evidence, not a compliance guarantee. It maps to change-management and record-keeping obligations without claiming to satisfy them on its own.

SOC 2 change management asks for evidence that changes are authorized and tracked. A signed, chained, anchored receipt proves which change was authored at time T, in a form an auditor can verify offline. FINRA and SEC records rules require records that are tamper-evident and independently verifiable. EU AI Act Article 12 requires automatic recording of events over an AI system's lifetime, and a code change authored by an agent in the software development lifecycle is one such event.

In every case Asqav supplies the evidence layer. The receipt proves the change happened and held its place in the chain. Whether the change was correct, the model attribution accurate, or the approval sufficient stays the deploying organization's judgment.

Sign one

Call POST /code-authorship with repo and commit_sha. The server resolves the diff base as the merge-base of the associated pull request, or the git empty tree for a parentless initial commit. A commit that has parents but no pull request is refused with 422 (base_sha_required) rather than guessing a first parent. It then re-fetches the changed files from GitHub and signs the re-derived digest. Private repositories need a configured GitHub token, and without one a private-repo re-fetch fails closed rather than signing a fallback. The Asqav GitHub Action mints one receipt per merged PR when wired into the CI path.

Read more on the code-authorship receipts page.

Stay ahead of AI compliance

Get practical insights on AI agent security and compliance obligations. No spam, unsubscribe anytime.