The ProofGate Spec: intents, approvals, receipts, audit.
This spec defines the artifacts required to implement deterministic consequence rails: Intent Envelopes, a Policy Gate, Signed Approvals, Signed Receipts, and Append-only Audit.
Intent Envelope
Structured action request. No prompt-as-plan.
- Action type + payload
- Canonicalization
- Hashing
Approval Token
Signed, expiring, intent-hash bound.
- Ed25519 signature
- TTL + nonce
- One-time use
Receipts + Audit
Proof of what happened, forever.
- Decision + execution receipts
- Signed artifacts
- Append-only JSONL
Intent Envelope
An IntentEnvelope is the only admissible input to the policy gate. Free-form text cannot be executed. Implementations must validate the envelope and action payload schema before any side effect.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://proofgate.org/spec/intent-envelope.schema.json",
"title": "IntentEnvelope",
"type": "object",
"required": ["intentId", "action", "actor", "payload"],
"properties": {
"intentId": { "type": "string", "minLength": 8 },
"action": { "type": "string" },
"actor": {
"type": "object",
"required": ["actorId", "actorType"],
"properties": {
"actorId": { "type": "string", "minLength": 2 },
"actorType": { "type": "string", "enum": ["human", "model", "service"] }
},
"additionalProperties": false
},
"payload": { "type": "object" },
"requestedScopes": {
"type": "array",
"items": { "type": "string" },
"default": []
},
"meta": {
"type": "object",
"additionalProperties": true,
"default": {}
}
},
"additionalProperties": false
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://proofgate.org/spec/actions/email.send.schema.json",
"title": "email.send payload",
"type": "object",
"required": ["to", "subject", "body"],
"properties": {
"to": { "type": "array", "minItems": 1, "items": { "type": "string", "format": "email" } },
"cc": { "type": "array", "items": { "type": "string", "format": "email" }, "default": [] },
"bcc": { "type": "array", "items": { "type": "string", "format": "email" }, "default": [] },
"subject": { "type": "string", "minLength": 1, "maxLength": 200 },
"body": { "type": "string", "minLength": 1, "maxLength": 20000 },
"links": { "type": "array", "items": { "type": "string", "format": "uri" }, "default": [] }
},
"additionalProperties": false
}- intentId: caller-provided trace ID (string, min length 8).
- action: action type string (e.g., email.send).
- actor: actorId + actorType (human/model/service).
- payload: action-specific object (validated by action schema).
- requestedScopes/meta: optional and non-authoritative (for auditing).
Canonicalization & Hashing
ProofGate uses canonical JSON to compute hashes used in receipts and approval tokens. In v0.1, the canonical form is defined as “stableStringify”: recursively sort object keys lexicographically, preserve array order, UTF-8 encode, and reject cycles.
// Canonical JSON (v0.1) - recursively sort object keys lexicographically - preserve array order - UTF-8 encode JSON string - reject cycles canonical_json = stableStringify(value) sha256_hex = SHA256(canonical_json_utf8).hex() // NOTE: In v0.2+, ProofGate will specify RFC 8785 (JCS) as the canonicalization standard.
intentHash = sha256_hex(canonical_intent_json)executionHash = sha256_hex(canonical_execution_result_json)receiptId = sha256_hex(canonical_receipt_payload_json)Approval Token
When the gate returns REQUIRE_APPROVAL, the system issues an approval token. The token must: (1) be signed, (2) expire, (3) bind to the exact intent hash, and (4) be invalidated after use.
// token (base64url(JSON))
// decoded JSON object:
{
"payloadB64": "<base64(canonical_payload_json)>",
"sigB64": "<base64(signature_bytes)>",
"pubB64": "<base64(public_key_der_spki)>"
}
// canonical payload JSON:
{
"v": 1,
"intentHash": "<sha256_hex(canonical_intent_json)>",
"exp": 1730000000000,
"nonce": "<random_hex>"
}
// signature:
Ed25519.sign( canonical_payload_json_utf8, privateKey )
- payload includes: v, intentHash, exp (unix ms), nonce.
- payload is canonicalized and signed with Ed25519.
- token embeds public key (v1) or references a known key (v2).
- token must be one-time use; server deletes pending entry after execution.
- approval-time execution must re-check the gate (TOCTOU safety).
Receipts
ProofGate requires receipts for every gate decision and every execution. Receipts contain hashes of canonical intent and execution results and are signed with Ed25519. This enables deterministic incident forensics.
// Decision receipt (canonical payload is hashed + optionally signed)
{
"receiptId": "<sha256_hex(canonical_receipt_payload_json)>",
"issuedAt": "2026-02-06T01:05:09.189Z",
"intentId": "intent_...",
"action": "email.send",
"decision": "DENY | REQUIRE_APPROVAL | EXECUTE",
"reason": "string",
"trace": { "requestedScopes": ["..."] },
"hashes": { "intentHash": "<sha256_hex(canonical_intent_json)>" },
"signature": {
"alg": "Ed25519",
"publicKeyB64": "<base64(der_spki)>",
"signatureB64": "<base64(sig_bytes)>"
}
}
// Execution receipt
{
"receiptId": "<sha256_hex(canonical_exec_receipt_payload_json)>",
"issuedAt": "2026-02-06T01:05:09.467Z",
"intentId": "intent_...",
"action": "email.send",
"execution": { "status": "SIMULATED | SENT | FAILED", "message": "string" },
"hashes": {
"intentHash": "<sha256_hex(canonical_intent_json)>",
"executionHash": "<sha256_hex(canonical_execution_result_json)>"
},
"signature": { "alg": "Ed25519", "publicKeyB64": "...", "signatureB64": "..." }
}- signature is computed over canonical receipt payload JSON (excluding signature field).
- signature algorithm: Ed25519 (v0.1).
- public key provided as DER SPKI base64 (v0.1).
- receiptId is the sha256 of canonical payload JSON (deterministic).
Audit Log
The audit log is the durable truth trail: an append-only sequence of events. Each event includes the request body and the result produced by the gate/executor (including receipts). Logs may be partitioned by day.
// Append-only JSONL (one event per line)
{"type":"DECIDE","at":"2026-02-06T01:05:09.214Z","ip":"127.0.0.1","body":{...},"result":{...}}
{"type":"APPROVE","at":"2026-02-06T01:05:21.545Z","ip":"127.0.0.1","body":{...},"result":{...}}
// Requirements:
- append-only (no rewrites)
- line-delimited JSON (JSONL)
- includes request body and result
- may be partitioned by day (proofgate-YYYY-MM-DD.jsonl)
- append-only (no in-place edits)
- line-delimited JSON (JSONL)
- includes request body and result
- can be partitioned by day
- must be sufficient to reconstruct decision→approval→execution chain
Policy Gate
The policy gate is deterministic and external to the model. It evaluates an intent against explicit policy state and returns one of three outcomes. Any system that allows tool execution without this step is not compliant.
- DENY: intent is rejected; system returns reason; may emit denial receipt.
- REQUIRE_APPROVAL: intent is admissible only with signed approval token.
- EXECUTE: intent is allowed; router may perform side effects; execution receipt required.
EXECUTE, execution must be refused and a denial receipt emitted.proofgate) expose:POST /v1/decide → decision + signed decision receiptPOST /v1/approve → verify approval token → re-check gate → executePOST /v1/execute → decide → execute or return approval tokennpm i proofgate → TypeScript SDK for production integrations