EVE Core/ Docs/ Decision Certificates
Reference

Decision Certificates

Every governance decision EVE CoreGuard makes is a signed, verifiable record — not just a log entry. A Decision Certificate is a cryptographically bound document that proves exactly what was decided, by which policy version, at what time, and why. This page explains what a certificate contains, how it is signed, how to verify it independently, and how long to retain it for regulatory purposes.

What Is a Decision Certificate?

When you call POST /v1/decisions/evaluate, EVE CoreGuard does two things: it evaluates the action against the requested policy pack, and it generates a Decision Certificate that permanently records that evaluation. The certificate is issued regardless of whether the decision is ALLOWED, BLOCKED, or MODIFIED — every governance decision has a certificate.

The certificate's purpose is regulatory proof. If your organization is audited by a financial regulator, a healthcare compliance officer, or a state attorney general, the certificate is the evidence that your AI system applied governance controls before the output reached an end user. The cryptographic signature on every certificate (Ed25519 in production; HMAC-SHA256 in legacy mode) makes it tamper-evident — any post-hoc modification of the decision record invalidates the signature, providing mathematical proof of record integrity.

Decision Certificates differ from conventional audit logs in three critical ways:

  • Signed at issuance — The signature is computed at decision time, not appended retroactively. There is no window in which a valid certificate can be produced for a decision that did not actually occur.
  • Self-describing — Every certificate carries the policy version, the governance disposition, the risk score, and a signed digest of the rule-result set (rule_results_sha256). The signed record binds these values; the full rule-result array and the policy-artifact bytes are provided in the accompanying evidence bundle rather than always inline, so a certificate can be interpreted without a live call to EVE Core but the underlying rule-result and policy artifacts are referenced by digest.
  • Third-party verifiable — Ed25519 verification requires only the certificate, the verification profile below, and EVE's published public key. EVE Core does not need to be online or consulted. Note the distinction: a certificate being verifiable by any third party is not the same as it having been verified by an independent party — the latter requires an external auditor, customer, or transparency witness to actually run the check.

Certificate Signing Process

In production, each Decision Certificate is signed with Ed25519 — an asymmetric signature that any third party (your auditor or a regulator) can independently verify against EVE's published public key (/.well-known/eve-pubkey) with no shared secret. The verifier holds only the public key and cannot forge a certificate. A valid signature establishes tamper-evidence and origin against the supplied or pinned key; it does not, by itself, establish the truth of every upstream input or full runtime integrity, and CoreGuard's verdict is a statement of policy admissibility, not final business approval. Signatures are self-describing (tagged ed25519- / hmac-), so a mixed corpus stays verifiable across a key-rotation boundary. External independent verification by a third party has not yet been performed.

A legacy HMAC-SHA256 mode (documented below) is also supported for internal, tenant-scoped integrity using a symmetric key. HMAC proves integrity only to a party that already holds the same secret — it is not a third-party proof and should not be presented as publicly verifiable evidence. For external audit, use the Ed25519 records and the public key.

EVE Decision Evidence — schema eve.decision.v3, the current authoritative certificate contract. The record carries payload_schema: "eve.decision.v3" and audit_schema: "3". Two canonicalizations apply — one for the record content hash, one for the bound content digests:

Schema:              eve.decision.v3   (payload_schema; audit_schema "3")

Record content hash  eve-jsonc-v1
  Serialization:     json.dumps(signed_payload, sort_keys=True, default=str)   # Python default
  Separators:        ", " and ": "   (a single space after each — NOT compact)
  Unicode:           ensure_ascii=true  (non-ASCII escaped as \uXXXX)
  Excluded fields:   "hash", "signature", and unsigned metadata (see table)
  Evidence hash:     "sha256-" + sha256(canonical_bytes).hexdigest()
  Signed message:    the UTF-8 bytes of the "sha256-<hex>" hash string
  Signature:         Ed25519 (asymmetric, independently verifiable)

Content digests      eve-request-v1 / eve-response-v1   (bind request / model output / rule results)
  Serialization:     json.dumps(obj, sort_keys=True, separators=(",",":"), ensure_ascii=True, default=str)  # COMPACT
  Digest:            "sha256-" + sha256(canonical_bytes).hexdigest()
  Bound into:        request_payload_sha256 / response_payload_sha256 / rule_results_sha256 (signed fields)

The record hash uses eve-jsonc-v1 — a deterministic JSON format that is not RFC 8785 JCS: JCS removes all whitespace; eve-jsonc-v1 keeps the single spaces that Python's default json.dumps emits. The content-digest canonicalization (eve-request-v1 / eve-response-v1) is the compact form (no spaces). Using the wrong form produces a different hash and verification fails.

The Ed25519 signing process follows these steps:

1
Assemble the canonical payload

Take the signed-payload fields (every field except hash and signature) and serialize them with json.dumps(payload, sort_keys=True): keys sorted lexicographically, a single space after each comma and colon (Python's default separators), ensure_ascii=true so non-ASCII is escaped as \uXXXX. This is the eve-jsonc-v1 canonicalization.

2
Compute the evidence hash

Compute sha256 over the canonical UTF-8 bytes and prefix the lowercase hex digest with sha256-. This sha256-<hex> string is the certificate's Evidence Hash.

3
Sign the evidence-hash string

Ed25519 signs the ASCII bytes of the Evidence Hash string (not the raw canonical payload bytes) with the deployment's private key, stored in an HSM-backed key management system and never exposed in any component or API response. The hex-encoded signature is stored in the signature field, tagged ed25519-; key_id records the key version for rotation. A legacy hmac- mode signs the same hash string with a symmetric key for internal tamper-evidence only.

4
Anchor in the decision chain (unsigned metadata)

When persisted, each certificate is anchored in the organization's append-only audit chain, recorded in the chain_previous_hash / chain_entry_hash / chain_tree_head / chain_sequence coordinates. These chain coordinates are unsigned metadata — they are not part of the eve.decision.v3 signed-field contract, so the certificate signature alone does not prove chain inclusion. Chain integrity (detecting deletion or reordering) is a separate verification over the chain state, not part of offline signature verification of a single certificate.

Key rotation: Signing keys can be rotated without invalidating historical certificates. Each certificate records the key_id used to sign it. To verify historical certificates after a key rotation, provide the historical key version to the verification function. Enterprise key management documentation is available on request — contact our team.

Certificate Schema Reference

The eve.decision.v3 decision record is returned in the audit field of every POST /v1/decisions/evaluate response. The Signing status column states, for each field, whether it is part of the signed-field contract (covered by the Ed25519 signature via the record content hash), a signed digest that binds external content, or unsigned metadata. Only the fields marked Signed are covered by the signature.

FieldTypeSigning statusDescription
audit_idstringSigned · requiredUnique decision-record identifier. Example: audit_<12-hex>.
request_idstringSigned · requiredThe caller-supplied request identifier for this evaluation.
decisionstring (enum)Signed · requiredPolicy-admissibility outcome: ALLOWED, BLOCKED, or MODIFIED. Not a business decision.
governance_verdictstring (enum)Signed · requiredNormalized verdict: ALLOW / BLOCK / MODIFY.
response_dispositionstring (enum)SignedDisposition of the model output: RELEASE or WITHHELD.
response_releasedbooleanSignedWhether the model output was released to the caller.
business_decisionstringSignedAlways NOT_MADE — CoreGuard governs policy admissibility; it does not make the underlying business decision.
request_payload_sha256string (sha256-)Signed digest — binds request contentSHA-256 of the exact request (canonicalization eve-request-v1). The signature binds this digest, so a holder of the original request can prove it produced this decision; the raw request is not in the certificate.
request_canonicalizationstringSignedCanonicalization used for the request digest: eve-request-v1.
response_payload_sha256string (sha256-)Signed digest — binds model outputSHA-256 of the exact model output (eve-response-v1). Binds the governed model output by digest, not plaintext.
response_canonicalizationstringSignedCanonicalization used for the response digest: eve-response-v1.
rule_results_sha256string (sha256-)Signed digest — binds rule outcomesSHA-256 over {"decision": …, "violations": [sorted rule IDs]}. The signature binds the decision and the sorted rule IDs that fired — not the human-readable rule descriptions, which are unsigned unless they are part of this digest preimage.
signature_key_idstringSignedKey ID (kid) of the signing key, e.g. ed25519:<b64url16>. Binds key identity into the signature; a verifier derives the same kid/fingerprint from the public key and checks consistency.
charter_hashstringSignedDigest of the governance charter artifact in force for this decision.
policy_versionstring (sha256:)SignedVersion hash of the policy set. (The policy-set name is unsigned metadata carried elsewhere in the response.)
payload_schemastringSignedSchema label: eve.decision.v3.
audit_schemastringSignedNumeric schema version: "3".
violationsintegerSignedCount of rules that fired.
risk_scorenumberSignedComposite risk score.
timestampstring (ISO 8601)Signed · requiredUTC timestamp of the evaluation.
org_idstringSignedTenant identifier scoping the certificate to your audit namespace.
hashstring (sha256-)Unsigned — output; required for verificationThe eve-jsonc-v1 content hash the signature is computed over. Recomputed by a verifier and compared.
signaturestring (tagged hex)Unsigned — output; required for verificationEd25519 signature over the UTF-8 bytes of the hash string. Tagged ed25519- (asymmetric, independently verifiable) or, in legacy mode, hmac- (symmetric, internal tamper-evidence only).
decision_tracearrayUnsigned — informationalHuman-readable evaluation steps. Not covered by the signature.
chain_previous_hashstring (hex)Unsigned metadataHash of the preceding chain entry. Not in the signed-field contract; the signature does not prove chain inclusion.
chain_entry_hash / chain_tree_head / chain_sequencestring / string / integerUnsigned metadataDecision-chain anchoring coordinates recorded at persistence. Verified separately over the chain state, not by single-certificate signature verification.

Full Certificate Example (eve.decision.v3)

A sanitized, independently verifiable sample. Scenario: an autonomous agent requested a capability outside its declared envelope and an action exceeding its blast-radius limit; CoreGuard blocked autonomous execution and queued mandatory human review. Signed fields are covered by the signature; hash/signature/decision_trace and the chain_* coordinates are unsigned.

{ "audit_id": "audit_ef7db5df3f84", "request_id": "req-editorial-review-agent-0001", "timestamp": "2026-07-17T15:13:05.259782Z", "org_id": "org_demo_review", "decision": "BLOCKED", "governance_verdict": "BLOCK", "response_disposition": "WITHHELD", "response_released": false, "business_decision": "NOT_MADE", "violations": 4, "risk_score": 1.0, "payload_schema": "eve.decision.v3", "audit_schema": "3", "charter_hash": "216d2b843cc9f2cfcfcc32376236649fc5db7e3bcb906064c65df95676062276", "policy_version": "sha256:bc0ac6e4c09d47d75062a9e185882782318f337cbebe3a5523dd12f592ec338c", "request_payload_sha256": "sha256-d0137c2046d42220ab5cbf8afde8d636742c81d34b6576af577a09650031b481", "request_canonicalization": "eve-request-v1", "response_payload_sha256": "sha256-5f4a721b66a544d2afa8a6db6da36417560f3ab0cb995e7664909f12ba37922b", "response_canonicalization": "eve-response-v1", "rule_results_sha256": "sha256-c2f43421f7c9595558ee87ebe0dcbd9a989c3cbf17d82123d60d017441ecd35e", "signature_key_id": "ed25519:zb1bX3Y_eHJIsB1q", "hash": "sha256-f5bf0ce35f803eda6b64e8a74691407a53502ed3c09d2a11cd1009ad07359320", "signature": "ed25519-a2f4acebf84f742f4eeadfe4f4deefb5c3bc0386fdfd102c4d5a715a899e507fb56eba304728525f834cec2983754fe6907ab6d9efbae189582cf56120242d0c", "chain_sequence": 408, "chain_previous_hash": "59c0f5dc93bd9c5239f9ed790130a1e927b5800f570c06cbda22fa91a2f091fc", "chain_entry_hash": "bfd0ab868730769aff0ddd9941e8072825ad8d5c3dd7e0a36c454ca9182f1152", "chain_tree_head": "656c64aa95be96e080b68a43848f554d2bf8ace351491301b1d24d8a8a282403" }

Verify this sample offline with the public key ed25519:zb1bX3Y_eHJIsB1q (fingerprint sha256:cdbd5b5f763f787248b01d6a4a0a7e8fde73ad18e2d5b4942d5a2822d8a79fd2). Two self-contained sample verifiers are provided — Python (verify_certificate.py) and Node (node verify_certificate.mjs) — and two additional vendor-reproduced cross-checks exist: the eve-coreguard SDK verifier and the standalone repository verifier (scripts/verify_eve_decision.py).

Offline Verification

Decision Certificates are designed to be verified without a network connection and without calling any EVE CoreGuard API. Verification requires:

  • The full signed evidence record (as received or stored).
  • For Ed25519 records: EVE's published public key from /.well-known/eve-pubkey (no shared secret).

Verification procedure (schema eve.decision.v3):

  1. Record hash. Take the signed-field payload (every Signed field from the schema table — not hash, signature, or unsigned metadata), serialize with eve-jsonc-v1 (json.dumps(payload, sort_keys=True, default=str) — sorted keys, a single space after each comma and colon, ensure_ascii=true; do not strip the whitespace), compute "sha256-" + sha256(canonical_bytes).hexdigest(), and compare to the record's hash.
  2. Signature. Verify the Ed25519 signature over the UTF-8 bytes of that sha256-<hex> hash string, against the published public key. A match establishes tamper-evidence and origin against that key — it does not establish the truth of upstream inputs. (Legacy hmac- records are checked with the shared HMAC key — internal tamper-evidence only, not third-party proof.)
  3. Key identity. Derive the public-key fingerprint (sha256(SPKI DER)) and kid (ed25519: + base64url of that digest, first 16 chars) from the supplied public key, and confirm they match the certificate's signature_key_id, the published fingerprint, and — where both are supplied — that the PEM and JWK describe the same key. To attribute a certificate to EVE, pin EVE's fingerprint out-of-band.
  4. Content binding. When you hold the original inputs, recompute the request, model-output, and rule-results digests with the compact eve-request-v1 / eve-response-v1 canonicalization and confirm they match the signed request_payload_sha256, response_payload_sha256, and rule_results_sha256. This proves those exact inputs produced this decision.

A verifier should report these checks individually (schema recognized, signature valid, hash reproduced, fingerprint derived and matched, kid matched, PEM/JWK matched, each digest matched or not evaluated) rather than a single "fully verified" result, and must fail visibly on any modified signed field, signature, key, fingerprint, or digest preimage.

Chain verification is separate and unsigned: the chain_previous_hash / chain_entry_hash / chain_tree_head / chain_sequence coordinates are not part of the signed-field contract, so a valid certificate signature does not prove chain inclusion. Chain integrity (detecting deletion or reordering) is a distinct check over the append-only chain state, performed by the repository chain verifier — not by offline signature verification of a single certificate.

Compliance Retention Guidance

How long you retain Decision Certificates depends on the regulatory regimes that govern your AI deployment. The following table summarizes minimum retention requirements by regulatory domain.

Regulatory DomainAuthorityMinimum RetentionNotes
Consumer Lending (ECOA / Reg B)CFPB / Fed25 monthsAdverse action records; Reg B § 202.12. Retain from date of action, not from credit application.
Consumer Reporting (FCRA)CFPB / FTC5 yearsFor AI systems using consumer reports. Permissible purpose documentation.
Mortgage (HMDA)CFPB3 yearsLoan application register records under Reg C.
Securities / Trading (FINRA)FINRA / SEC7 yearsBooks and records rules (FINRA Rule 4511, SEC Rule 17a-4). Governance decisions related to trading activity.
Healthcare (HIPAA)HHS OCR6 yearsFrom date of creation or last effective date. BAA terms may require longer retention.
Insurance (State)State DOI5–7 yearsVaries by state. Underwriting records typically 5 years; claims-related AI decisions 7 years in most jurisdictions.
Federal Government (NARA)NARA / OMB7+ yearsPer agency records schedule. AI decision records may qualify as program records requiring permanent retention in some agencies.
General EnterpriseSOX / internal7 yearsSOX Section 802 general records standard for public companies. Internal policy may require longer.

EVE Core recommendation: Retain all Decision Certificates for a minimum of 7 years regardless of regulatory domain. This matches the most stringent common requirement (FINRA / SOX) and eliminates the operational complexity of maintaining domain-specific retention schedules. For highly regulated deployments, retain indefinitely and rely on storage compression — certificate records are compact (typically under 2 KB each) and compressible.

Python Verification Example

The eve-coreguard Python SDK (PyPI, v0.2.0) includes a built-in offline verifier. The example below is a minimal, standalone check of the record hash + Ed25519 signature for an eve.decision.v3 record, using only cryptography plus the standard library. It intentionally verifies only those two properties (signature integrity). It does not by itself check key identity or reproduce the request / model-output / rule-results digests — for the full per-field verification (key-identity checks and content-digest reproduction, with individual PASS/FAIL statuses) use the two self-contained sample verifiers verify_certificate.py and node verify_certificate.mjs, or the standalone repository verifier scripts/verify_eve_decision.py.

import json import hashlib from cryptography.hazmat.primitives.serialization import load_pem_public_key from cryptography.exceptions import InvalidSignature # The eve.decision.v3 signed-field contract (mirror of core/coreguard/audit._V3_FIELD_DEFAULTS). # Only these fields are covered by the signature; hash/signature/decision_trace and the # chain_* coordinates are UNSIGNED and are excluded from the record hash. V3_SIGNED_FIELDS = { "audit_id", "request_id", "decision", "violations", "risk_score", "timestamp", "org_id", "audit_schema", "charter_hash", "policy_version", "payload_schema", "request_payload_sha256", "request_canonicalization", "response_payload_sha256", "response_canonicalization", "response_released", "rule_results_sha256", "signature_key_id", "governance_verdict", "response_disposition", "business_decision", } def eve_jsonc_v1(payload: dict) -> bytes: """eve-jsonc-v1: sorted keys, DEFAULT spaced separators (", " / ": "), ensure_ascii=True. This is NOT RFC 8785 JCS — do not strip the spaces.""" return json.dumps(payload, sort_keys=True, default=str).encode("utf-8") def verify_record_hash_and_signature(record: dict, public_key_pem: bytes) -> dict: """Check the RECORD HASH + Ed25519 SIGNATURE of an eve.decision.v3 record offline. This verifies signature integrity only. It does NOT check key identity or the request/response/rule-results content digests — use verify_certificate.py / verify_certificate.mjs for the full per-field verification. """ # 1. Signed payload = only the v3 signed fields that are present. payload = {k: v for k, v in record.items() if k in V3_SIGNED_FIELDS} # 2. Recompute the content hash over the eve-jsonc-v1 canonical bytes. content_hash = "sha256-" + hashlib.sha256(eve_jsonc_v1(payload)).hexdigest() if content_hash != record.get("hash"): return {"valid": False, "error": "hash mismatch — signed fields do not reproduce the stated hash"} # 3. Verify the Ed25519 signature over the UTF-8 bytes of the hash STRING. sig = record.get("signature", "") if not sig.startswith("ed25519-"): return {"valid": False, "error": "not an Ed25519 record (hmac- records are internal-only)"} pub = load_pem_public_key(public_key_pem) try: pub.verify(bytes.fromhex(sig[len("ed25519-"):]), content_hash.encode("utf-8")) except InvalidSignature: return {"valid": False, "error": "signature mismatch — record may have been modified"} return { "signature_integrity": True, "schema": record.get("payload_schema"), "governance_verdict": record.get("governance_verdict"), "note": "signature integrity only — run verify_certificate.py/.mjs for key identity + content digests", "error": None, } # --- Example usage --- with open("eve-pubkey.pem", "rb") as f: PUBLIC_KEY_PEM = f.read() # from GET /.well-known/eve-pubkey result = verify_record_hash_and_signature(record, PUBLIC_KEY_PEM) print("SIGNATURE OK" if result.get("signature_integrity") else f"INVALID: {result['error']}") # On INVALID: raise an alert — do not trust this record

Using the EVE CoreGuard Python SDK (v0.2.0), the offline verifier eve_coreguard.evidence.verify_decision_record() performs the full eve.decision.v3 check (hash, signature, and the signed content digests). The decision chain is a separate, unsigned mechanism: chain-inclusion integrity is verified over the append-only chain state by the repository chain verifier, not by single-certificate signature verification.

Security note: Never transmit your HMAC verification key over the network or store it in application code. Use an HSM, secrets manager (AWS Secrets Manager, Azure Key Vault, HashiCorp Vault), or encrypted key store. The verification_key_hex parameter in the SDK can be loaded from an environment variable or a secrets manager at runtime.

Part of the EVE AI Core control plane Deterministic AI Governance Control Plane → Policy decisions that return the same result for the same input every time, before execution.