Evidence bundle
The evidence bundle is the signed delivery receipt produced at the end of a DevContract engagement. It records what contract was in force, what decisions were made against it, whether the definition of done was met, and what violations were found. It is SHA-256 signed against the contract hash.
What it contains
An evidence bundle is a single JSON document with five sections:
| Section | What it records |
|---|---|
| Header | Contract ID, client, contractor, contract hash, engagement start/end timestamps. |
| Contract queries | Every material decision the AI made during execution, with the clause consulted, the verdict (allow / deny / gate), and the action taken. |
| Clause results | Pass/fail result for each clause category. Any clause with violations is marked fail. |
| Violations | Structured ContractViolation objects for any clause breached. See Violations. |
| Verdict + signature | Overall verdict (contract_fulfilled, contract_breached, or pending_human_gate) and SHA-256 signature. |
The contract hash
Every DevContract has a deterministic hash: SHA-256(canonical JSON of the contract). This hash is stored in the evidence bundle header. If the contract changes between engagements, the hashes differ — creating an auditable record of which exact contract terms were in force during which session.
In Python:
from contract_schema import load_contract
contract = load_contract(".tickety/devcontract.json")
print(contract.contract_hash())
# → e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
The signature
The evidence bundle's signature field is a SHA-256 hash of the entire bundle payload (including the contract hash in the header). This means:
- Any post-delivery modification to the evidence bundle invalidates the signature.
- The signature ties the evidence to the specific contract in force — you cannot reuse the same evidence bundle against a different contract.
- Auditors can verify the signature by recomputing it from the payload.
The current implementation uses SHA-256 over the canonical JSON. Production deployments should use asymmetric signing with a key managed in SSM Parameter Store — the contract hash acts as a message identifier, not as the signing key.
Example bundle
{
"contract_id": "ticketyboo.dev-2026-04-01",
"contractor": "claude-code",
"client": "fenderfonic",
"contract_hash": "a7f3c2d1e9b4580f...",
"engagement_start": "2026-04-01T08:00:00Z",
"engagement_end": "2026-04-01T09:15:00Z",
"contract_queries": [
{
"timestamp": "2026-04-01T08:12:34Z",
"query": "Can I use Secrets Manager for the API key?",
"clause": "cost.forbidden_resources",
"verdict": "deny",
"action_taken": "Used SSM Parameter Store SecureString instead"
},
{
"timestamp": "2026-04-01T08:45:00Z",
"query": "Should I add a print() for debugging?",
"clause": "quality.forbidden_patterns",
"verdict": "deny",
"action_taken": "Used logger.debug() with module_logger_only standard"
}
],
"clause_results": [
{"clause": "stack", "status": "pass", "violations": []},
{"clause": "cost", "status": "pass", "violations": []},
{"clause": "security", "status": "pass", "violations": []},
{"clause": "quality", "status": "pass", "violations": []},
{"clause": "compliance", "status": "pass", "violations": []},
{"clause": "definition_of_done", "status": "pass", "violations": []}
],
"violations": [],
"overall_verdict": "contract_fulfilled",
"signature": "9b2d3e4f1c7a8b5d..."
}
Overall verdict values
| Value | Meaning |
|---|---|
contract_fulfilled | All definition_of_done criteria met. No unresolved violations. |
contract_breached | One or more critical or major violations were not remediated. |
pending_human_gate | A gate clause (e.g. dpo_review_gate, pen_test_gate) requires human approval before the verdict can be finalised. |
Who receives the bundle
The evidence bundle is the artifact for:
- The client — proof that the AI worked under the agreed terms
- Auditors — a structured record of governance decisions during the engagement
- Regulators — for regulated industries, the bundle is the compliance record for the AI-assisted work product
- The PR review process — when
audit.pr_comment_requiredistrue, a summary of the bundle is posted as a PR comment