SPEC v0.1SIGNED PROOFAUDIT FORMAT

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.

COMPLIANCE SUMMARY

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
SPEC SECTION

Intent Envelope

A structured representation of an action request. The model may generate it; the system validates it.
Link

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.

IntentEnvelope JSON Schema
v0.1
{
  "$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
}
Action Payload: email.send
v0.1
{
  "$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
}
Required fields
  • 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).
SPEC SECTION

Canonicalization & Hashing

Deterministic hashing requires deterministic JSON. v0.1 specifies stable key ordering; v0.2 adopts JCS (RFC 8785).
Link

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.

Canonicalization (v0.1)
v0.1
// 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.
Hash definitions
intentHash = sha256_hex(canonical_intent_json)
executionHash = sha256_hex(canonical_execution_result_json)
receiptId = sha256_hex(canonical_receipt_payload_json)
NOTE: In v0.2, canonical JSON will follow RFC 8785 (JSON Canonicalization Scheme).
SPEC SECTION

Approval Token

Signed, expiring, intent-hash bound. Prevents forgery and replay.
Link

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.

Approval Token Wire Format
v0.1
// 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 )
Requirements
  • 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).
v0.2 recommendation: do not embed public key in token; instead use a known key id (kid) and a published keyset.
SPEC SECTION

Receipts

Signed decision and execution receipts. Proof of causality by default.
Link

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.

Receipt Formats (Decision + Execution)
v0.1
// 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 requirements
  • 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).
SPEC SECTION

Audit Log

Append-only JSONL. Every request/result is recorded. No rewrites.
Link

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.

Audit JSONL Format
v0.1
// 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)
Audit requirements
  • 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
v0.2 recommendation: include a rolling hash chain of audit lines (tamper-evident log).
SPEC SECTION

Policy Gate

Deterministic function: (intent, policy) → { DENY | REQUIRE_APPROVAL | EXECUTE }
Link

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.

Gate outputs
  • 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.
TOCTOU rule
If approval is required, the system MUST re-run the gate at approval/execution time with current policy. If the result is not EXECUTE, execution must be refused and a denial receipt emitted.
This prevents time-of-check/time-of-use drift and race-condition policy bypass.
Reference implementation mapping
The ProofGate reference implementation (proofgate.dev) and official SDK (npm proofgate) expose:
POST /v1/decide → decision + signed decision receipt
POST /v1/approve → verify approval token → re-check gate → execute
POST /v1/execute → decide → execute or return approval token
npm i proofgate → TypeScript SDK for production integrations