SPEC · V0.1 · DRAFT FOR COMMENT

ActionReceipt — Open Specification

Version: 0.1 (draft for public comment) Status: Experimental Editor: HAL — Human Accountability Layer (halayer.com) License: Specification text CC BY 4.0 · schemas and reference code Apache 2.0 — free to implement, no royalties, no permission required Canonical URL: https://actionreceipt.com/spec/v0.1


1. Purpose

An ActionReceipt is a signed, verifiable, tamper-evident record that an AI agent performed a specific action under a scoped mandate granted by a named, accountable human (the principal).

Money has receipts. Code has commits. AI actions have nothing. As agents move from drafting content to taking actions — sending, scheduling, ordering, quoting, committing — every party involved needs an answer to one question: who stands behind this action, and were they entitled to authorize it?

ActionReceipt is the answer format. It is deliberately minimal: one JSON object, one signature, one verification URL.

2. Design principles

  1. A human is always named. Every receipt resolves to an accountable person or legal entity. Anonymous agents do not get receipts.
  2. Privacy by hashing. Receipts carry cryptographic hashes of inputs and outputs, never the content itself. A receipt proves that an email was sent and who authorized it — not what it said.
  3. Mandate-scoped. Every receipt references the mandate under which the action was taken: what was permitted, what limits applied, when it expires.
  4. Tamper-evident. Receipts are signed (JWS) and chained (each receipt references the hash of the previous receipt from the same agent), so history cannot be silently rewritten.
  5. Verifiable by strangers. Any counterparty can verify a receipt in one step, with no account and no relationship to the issuer.
  6. Issuer-neutral. Anyone may issue receipts — HAL, a company's own infrastructure, or an open-source implementation. Trust derives from the issuer's published keys and the named principal, not from a central authority.

3. Receipt structure

A receipt is a JSON object with the following top-level fields:

Field Type Req. Description
spec string Spec identifier and version, e.g. "actionreceipt/0.1"
id string Globally unique receipt ID (ULID recommended)
issued_at string RFC 3339 timestamp of issuance
issuer object Who issued and signed this receipt (see 3.1)
principal object The accountable human or legal entity (see 3.2)
agent object The AI system that performed the action (see 3.3)
mandate object The authority under which the action was taken (see 3.4)
action object What was done (see 3.5)
evidence object Hashes of inputs/outputs (see 3.6)
review object Human review of the action, when the mandate requires it (see 3.7)
chain object Link to the previous receipt (see 3.8)
verify_url string URL where this receipt's current status can be checked
status string Status at issuance: valid | revoked | disputed | settled. Current status MUST be taken from verify_url (see §5)

review is REQUIRED whenever the governing mandate's review_policy is not none; a receipt missing a required review is invalid regardless of signature.

3.1 issuer

{
  "name": "HAL",
  "domain": "halayer.com",
  "keys": "https://halayer.com/.well-known/actionreceipt-jwks.json"
}

keys MUST point to a JWKS (RFC 7517) document containing the issuer's public signing keys. Key discovery via https://{domain}/.well-known/actionreceipt-jwks.json is the default convention.

3.2 principal

{
  "name": "Jane Doe",
  "role": "Managing Director",
  "org": "Example GmbH",
  "identity_assurance": "verified",
  "principal_id": "hal:principal:01J8ZK…"
}

identity_assurance is one of self_asserted | email_verified | verified (issuer performed identity verification). Counterparties decide how much assurance they require.

3.3 agent

{
  "agent_id": "hal:agent:01J8ZQ…",
  "software": "acme-assistant/2.4",
  "model": "claude-sonnet-4-6",
  "operator": "Example GmbH"
}

model and software are informative, not load-bearing: accountability attaches to the principal and mandate, never to the model.

3.4 mandate

{
  "mandate_id": "hal:mandate:01J8ZR…",
  "granted_at": "2026-06-01T09:00:00Z",
  "expires_at": "2026-12-01T09:00:00Z",
  "scope": ["email.send", "calendar.schedule", "quote.issue"],
  "review_policy": "none",
  "constraints": {
    "quote.issue": { "max_value": 5000, "currency": "EUR" },
    "email.send": { "domains_excluded": ["press.*"] }
  },
  "revocable": true
}

Scopes use dot-notation verbs. Constraints are scope-keyed objects; unknown constraint keys MUST be preserved by intermediaries. A receipt whose action falls outside its mandate's scope/constraints is invalid regardless of signature.

review_policy is one of none | flagged | full, and is set by the principal in the mandate: full means every action under this mandate requires human review before release; flagged means actions or sections matching the mandate's flagging rules wait for a named reviewer (allowed once reviewed); none means no review gate. Unreviewed means unreleased: an implementation MUST NOT issue a receipt for an action whose required review has not occurred.

3.5 action

{
  "type": "quote.issue",
  "performed_at": "2026-07-02T14:22:31Z",
  "channel": "email",
  "counterparty": { "name_hash": "sha256:9f2c…", "domain": "customer.example" },
  "summary": "Issued quote Q-2026-0417 for EUR 4,200"
}

summary SHOULD be a single human-readable sentence containing no sensitive content. Counterparty identity MAY be hashed for privacy; the domain is kept clear so recipients can confirm the receipt refers to them.

3.6 evidence

{
  "input_hash": "sha256:aa41…",
  "output_hash": "sha256:b7ce…",
  "hash_alg": "sha256"
}

Hashes allow either party to later prove that a document they hold is the exact one referenced by the receipt, without the receipt ever containing the document.

3.7 review

{
  "reviewed_by": {
    "name": "Dr. Amara Osei",
    "principal_id": "hal:principal:01J8ZT…"
  },
  "reviewed_at": "2026-07-02T09:40:12Z",
  "items": ["dosage", "contraindications"],
  "decision": "approved"
}

Present when the mandate's review_policy required human review. reviewed_by names the accountable reviewer — a person, not a system. items lists what was reviewed (sections, fields, or the literal ["*"] for full review). decision is approved; rejected actions are never released and therefore never produce a receipt. The review is part of the signed payload: it cannot be added, altered, or removed after issuance.

3.8 chain

{
  "seq": 4183,
  "prev_receipt_id": "01J8ZS…",
  "prev_receipt_hash": "sha256:c3d9…"
}

Receipts from one agent form a hash chain with a monotonically increasing seq. A missing or broken link is detectable, which makes selective deletion of inconvenient receipts evident; seq additionally makes truncation of the most recent receipts detectable by any party holding a later receipt.

4. Signing

A receipt is transported as a JWS (RFC 7515), compact serialization, with the JSON receipt as payload.

5. Verification

A verifier (any counterparty) performs five checks:

  1. Signature — fetch the issuer's JWKS from issuer.keys; verify the JWS.
  2. Status — GET verify_url; confirm current status (a signed receipt may since have been revoked or disputed). The status field inside the payload records status at issuance only and MUST NOT be treated as current.
  3. Scope — confirm action.type is within mandate.scope and satisfies mandate.constraints, and that action.performed_at falls inside the mandate's validity window.
  4. Review — if the mandate's review_policy is not none, confirm the receipt carries a review object naming an accountable reviewer.
  5. Principal — confirm the named principal and their identity_assurance meet the verifier's own bar.

A receipt passing checks 1–4 is authentic and authorized. Check 5 is a policy decision left to the verifier.

Issuers MUST keep signing keys published in their JWKS for at least the retention life of the receipts signed with them; rotated keys remain published (for verification) but are no longer used for issuance.

verify_url MUST also serve an HTML representation so a human clicking the link sees a plain-language certificate: who acted, for whom, under what authority, current status.

6. Status lifecycle and settlement

valid → revoked — the issuer or principal withdraws the receipt (e.g. mandate was compromised). valid → disputed — either party contests the action. The receipt chain becomes the evidentiary record. disputed → settled — resolution recorded; a settlement note (free text plus optional signed settlement object) is attached at verify_url.

Settlement semantics beyond this lifecycle are out of scope for v0.1 and will be defined in a companion spec (ActionSettlement).

7. Extensibility and versioning

8. What ActionReceipt is not


Appendix A — Complete example receipt (payload before signing)

{
  "spec": "actionreceipt/0.1",
  "id": "01J9AB3XK7Q2M4N5P6R7S8T9V0",
  "issued_at": "2026-07-02T14:22:32Z",
  "issuer": {
    "name": "HAL",
    "domain": "halayer.com",
    "keys": "https://halayer.com/.well-known/actionreceipt-jwks.json"
  },
  "principal": {
    "name": "Jane Doe",
    "role": "Managing Director",
    "org": "Example GmbH",
    "identity_assurance": "verified",
    "principal_id": "hal:principal:01J8ZK4F2G"
  },
  "agent": {
    "agent_id": "hal:agent:01J8ZQ9H3J",
    "software": "acme-assistant/2.4",
    "model": "claude-sonnet-4-6",
    "operator": "Example GmbH"
  },
  "mandate": {
    "mandate_id": "hal:mandate:01J8ZR5K7L",
    "granted_at": "2026-06-01T09:00:00Z",
    "expires_at": "2026-12-01T09:00:00Z",
    "scope": ["email.send", "calendar.schedule", "quote.issue"],
    "review_policy": "none",
    "constraints": {
      "quote.issue": { "max_value": 5000, "currency": "EUR" }
    },
    "revocable": true
  },
  "action": {
    "type": "quote.issue",
    "performed_at": "2026-07-02T14:22:31Z",
    "channel": "email",
    "counterparty": {
      "name_hash": "sha256:9f2c8a41d6e3b7c5f0a2d9e8b1c4f7a6d3e0b9c8a7f4e1d2c5b8a9f6e3d0c7b4",
      "domain": "customer.example"
    },
    "summary": "Issued quote Q-2026-0417 for EUR 4,200"
  },
  "evidence": {
    "input_hash": "sha256:aa4138c2e9f7d6b5a4c3e2d1f0b9a8c7e6d5f4a3b2c1d0e9f8a7b6c5d4e3f2a1",
    "output_hash": "sha256:b7ce29d4f1a8e6c3b0d7f4a1e8c5b2d9f6a3c0e7b4d1f8a5c2e9b6d3f0a7c4e1",
    "hash_alg": "sha256"
  },
  "chain": {
    "seq": 4183,
    "prev_receipt_id": "01J9AA8WJ6P1L3M4N5Q6R7S8T9",
    "prev_receipt_hash": "sha256:c3d94f2a1b8e7c6d5f4a3b2e1d0c9f8a7b6e5d4c3f2a1b0e9d8c7f6a5b4e3d2"
  },
  "verify_url": "https://executionproof.com/r/01J9AB3XK7Q2M4N5P6R7S8T9V0",
  "status": "valid"
}

Appendix B — Minimal JSON Schema (informative)

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://actionreceipt.com/spec/v0.1/schema.json",
  "type": "object",
  "required": ["spec", "id", "issued_at", "issuer", "principal", "agent", "mandate", "action", "verify_url", "status"],
  "properties": {
    "spec": { "const": "actionreceipt/0.1" },
    "id": { "type": "string", "minLength": 10 },
    "issued_at": { "type": "string", "format": "date-time" },
    "issuer": {
      "type": "object",
      "required": ["name", "domain", "keys"],
      "properties": {
        "name": { "type": "string" },
        "domain": { "type": "string" },
        "keys": { "type": "string", "format": "uri" }
      }
    },
    "principal": {
      "type": "object",
      "required": ["name", "identity_assurance", "principal_id"],
      "properties": {
        "name": { "type": "string" },
        "role": { "type": "string" },
        "org": { "type": "string" },
        "identity_assurance": { "enum": ["self_asserted", "email_verified", "verified"] },
        "principal_id": { "type": "string" }
      }
    },
    "agent": {
      "type": "object",
      "required": ["agent_id"],
      "properties": {
        "agent_id": { "type": "string" },
        "software": { "type": "string" },
        "model": { "type": "string" },
        "operator": { "type": "string" }
      }
    },
    "mandate": {
      "type": "object",
      "required": ["mandate_id", "granted_at", "scope"],
      "properties": {
        "mandate_id": { "type": "string" },
        "granted_at": { "type": "string", "format": "date-time" },
        "expires_at": { "type": "string", "format": "date-time" },
        "scope": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
        "review_policy": { "enum": ["none", "flagged", "full"] },
        "constraints": { "type": "object" },
        "revocable": { "type": "boolean" }
      }
    },
    "action": {
      "type": "object",
      "required": ["type", "performed_at"],
      "properties": {
        "type": { "type": "string" },
        "performed_at": { "type": "string", "format": "date-time" },
        "channel": { "type": "string" },
        "counterparty": { "type": "object" },
        "summary": { "type": "string", "maxLength": 280 }
      }
    },
    "evidence": {
      "type": "object",
      "properties": {
        "input_hash": { "type": "string" },
        "output_hash": { "type": "string" },
        "hash_alg": { "type": "string" }
      }
    },
    "review": {
      "type": "object",
      "required": ["reviewed_by", "reviewed_at", "items", "decision"],
      "properties": {
        "reviewed_by": {
          "type": "object",
          "required": ["name"],
          "properties": {
            "name": { "type": "string" },
            "principal_id": { "type": "string" }
          }
        },
        "reviewed_at": { "type": "string", "format": "date-time" },
        "items": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
        "decision": { "const": "approved" }
      }
    },
    "chain": {
      "type": "object",
      "properties": {
        "seq": { "type": "integer", "minimum": 0 },
        "prev_receipt_id": { "type": "string" },
        "prev_receipt_hash": { "type": "string" }
      }
    },
    "verify_url": { "type": "string", "format": "uri" },
    "status": { "enum": ["valid", "revoked", "disputed", "settled"] }
  },
  "patternProperties": { "^x_": {} },
  "additionalProperties": false
}

Feedback and implementations welcome. This is a v0.1 draft published for public comment; nothing here is final.


Canonical URL: actionreceipt.com/spec/v0.1 · schema.json · GitHub · Edited by HAL, Sentidant AG