Repository navigation
Governance Receipts and Audit
Most systems can tell you what they did if you trust them. IGL is built so that you do not have to. Every projection and every governed answer comes with a receipt signed by the service, and every change is written to an audit chain where each entry is hashed together with the one before it. A receipt can be checked by anyone with the public key. A chain can be re-verified from the outside. Neither can be altered after the fact without the alteration being visible.

A governance receipt is the governance object returned with projections, intelligence answers and other governed results, and it can be fetched again later with GET /audit/receipts/{receiptId}. The signed part contains:
| Field | Meaning |
|---|---|
receiptId |
Unique id, also the key for fetching it later |
actor |
The identity, organization and roles the decision was made for: the credential's identity by default, or the actor a request declares for authority and policy evaluations, runs and intelligence operations, which must be well formed identity and role ids |
authorityDecision |
The decision object: its effect (allow, deny, conditional or escalate), reason codes, required approvals and decision id |
policiesEvaluated |
The ids of the policies consulted to reach it |
evidenceIds |
For governed answers, the evidence records the answer relied on |
outputHash |
SHA-256 of the canonical JSON of what was returned (for a projection, the admitted nodes) |
createdAt |
When it was issued |
Around that signed part sit signer (the key id, igl-production or igl-sandbox), alg (Ed25519), publicKey (the signer's public key in SPKI form) and signature.
The signature covers the string IGL-RECEIPT-v0.2: followed by the canonical JSON of the signed part. Canonical means object keys sorted, no whitespace, arrays in order. The public key is published at https://auth.id-me.ai/.well-known/jwks.json for production and https://sandbox.id-me.ai/.well-known/jwks.json for the sandbox, so a verifier checks two things: the signature is valid for the embedded publicKey, and that publicKey is the one in the JWKS. The code is in Quickstart: the API; it is fifteen lines of Node.js with no dependencies.
The conformance suite performs this exact check on every deploy. If a build ever produced receipts the published key could not verify, it would not reach production.
Every write and every governed read appends an event to the tenant's audit chain: identity.created, projection.served, policy.evaluated, key.issued, key.revoked, consent.revoked, outcome.recorded, agent.run_completed, platform.bootstrapped and the rest. Each event stores previousHash and its own eventHash, computed as:
eventHash = sha256(previousHash + canonical({ type, body }))
The table has database triggers that reject updates and deletes, so even an operator with database access cannot quietly rewrite history; they can only append, and an appended fake would have to match a hash it cannot produce.
GET /audit/events searches a tenant's chain by time, actor, resource and event type, and returns the hashes, so a client can re-verify any stretch of the chain itself. The small script docs/examples/verify-audit-chain.mjs does that against a live tenant.
A projection tells an assistant what it may see. POST /audit/interactions records what the assistant then did with it: completed, refused, proceeded_on_truncated, proceeded_on_empty or escalated, with the model name and the receipt id of the projection it used. That entry joins the same chain, so a reviewer can walk from "what did the model receive" to "what did it do" to "what was the outcome" without leaving the audit log. The record_interaction MCP tool is the same operation for assistants.
On your own machine the journal in src/store.js is the chain. It is file backed, hash chained, and refuses to load if any entry was changed. Two features go beyond the platform today:
Merkle inclusion proofs. The journal publishes a root, and inclusionProof(seq) produces a proof that one entry belongs to the journal with that root. An auditor can confirm a single disclosed entry without seeing the rest. docs/examples/verify-journals.mjs shows it.
Runtime attestation. Every trace and head receipt signed by src/sign.js carries runtime, a SHA-256 digest of the runtime's own source manifest, inside the signed envelope. Which build produced a receipt is settled by recomputation, not by trust.
Tenants can register HTTPS endpoints for graphUpdated, outcomeRecorded and approvalRequired. Each delivery carries x-igl-event, x-igl-delivery and x-igl-signature: t=<unix seconds>,v1=<hmac-sha256(secret, t + "." + body)>, where the secret was returned once at registration. Verify the signature and reject old timestamps, as you would for any payment provider's webhooks. Three attempts are made.
Three sentences. Every decision this system made is in a signed receipt whose key is public. Every change is in a chain the database itself refuses to edit. You can check both from your own laptop, and here is the fifteen-line script.
IGL, Identity Governed Logic. Code and contract under Apache 2.0; IGL and the logo are trademarks of SMEPro Technologies LLC. Platform at id-me.ai. Security reports: security@id-me.ai. This wiki describes what runs today; see Roadmap and Contributing for what is planned.
Start
Quickstart: the API
Quickstart: the Runtime
MCP Integration
Understand
Why IGL
Core Concepts
Ricorsa and IGL
Purposes and Projections
Governance Receipts and Audit
Policies, Agents and Workflows
Run
Operator Console
Deployment and Operations
Security Model
Reference
Use Cases
FAQ
Glossary
Roadmap and Contributing
Brand Assets
The founder's essay
Live
id-me.ai
API reference
Sandbox