Skip to content
Docs for briefcase-ai v3.3.0see what’s new.

Audit Bundles

Audit Bundles

An ExaminerBundle packages a routing decision, the bitemporal evidence that informed it, and the policy version that was in effect — sealed with a content hash so anyone can verify, independently, that nothing was altered.

compliance For: governance & audit

How it works

  1. Gather the material. A routing decision, the bitemporal evidence store it cited, and the PolicyRegistry it routed against.

  2. Build the bundle. ExaminerBundle.build seals the decision, the referenced evidence, and the policy as-of the decision into a content-hashed artifact.

  3. Verify integrity. verify() recomputes the hash and raises BundleIntegrityError if a byte changed.

  4. Transport and re-verify. to_json / from_json move it anywhere; the recipient re-runs verify() to trust it independently.

flowchart LR
    A["AgentRouter.route<br/>AgentRoutingDecision"] --> D["ExaminerBundle.build"]
    B["InMemoryBitemporalStore<br/>evidence_refs"] --> D
    C["PolicyRegistry<br/>policy as-of decision"] --> D
    D --> E["content_hash<br/>(SHA-256)"]
    E --> F["to_json / from_json"]
    F --> G["verify()<br/>raises on tampering"]

Install

Terminal window
pip install briefcase-ai[compliance]
from briefcase.compliance import ExaminerBundle, BundleIntegrityError

Build a Bundle End to End

This ties together an AgentRouter decision, an InMemoryBitemporalStore of evidence, and a PolicyRegistry, then seals and verifies the result.

from datetime import datetime, timezone
from briefcase.bitemporal import BitemporalRecord, InMemoryBitemporalStore
from briefcase.routing.policy import (
PolicyRegistry,
PolicyVersion,
PolicyRule,
AgentRouter,
)
from briefcase.compliance import ExaminerBundle, BundleIntegrityError
# 1. Evidence: a bitemporal store of the facts that inform routing.
evidence = InMemoryBitemporalStore()
tier_record = BitemporalRecord.new(
key="ticket:tier",
valid_time=datetime(2026, 5, 1, tzinfo=timezone.utc),
value="gold",
source="crm",
)
evidence.append(tier_record)
# 2. Policy: a versioned routing policy in a bitemporal-backed registry.
registry = PolicyRegistry()
policy = PolicyVersion(
policy_id="support_triage",
version="2026.05.01",
rules=[
PolicyRule(
rule_id="gold-to-specialist",
condition={"tier": "gold"},
choice="specialist_queue",
rationale="gold-tier tickets route to specialist agents",
),
],
default_choice="general_queue",
)
registry.publish(policy, valid_from=datetime(2026, 5, 1, tzinfo=timezone.utc))
# 3. Decision: route a request, citing the evidence that informed it.
router = AgentRouter(
registry,
use_case="support_triage",
policy_id="support_triage",
)
decision = router.route(
{"tier": "gold"},
evidence_refs=[tier_record.record_id],
)
print(decision.selected) # specialist_queue
# 4. Bundle: seal decision + evidence + policy with a SHA-256 content hash.
bundle = ExaminerBundle.build(decision, evidence, registry)
bundle.verify() # passes — internally consistent
print(bundle.content_hash[:20]) # sha256:...

build looks up the policy as-of the decision (decision.decided_at by default, overridable with as_of_transaction_time=) and pulls exactly the evidence records named in decision.evidence_refs. If a referenced record is missing from the store, build raises BundleIntegrityError. Evidence is sorted deterministically so the hash is stable.

Transport and Verify

Serialize to JSON, send it anywhere, re-import, and re-check the hash. This is what makes a bundle tamper-evident in transit: the recipient re-verifies on their own machine, and any byte changed since the build breaks the content hash, so silent edits cannot pass.

payload = bundle.to_json(indent=2)
restored = ExaminerBundle.from_json(payload)
restored.verify() # ok — hash recomputed from contents matches

Detect Tampering

The hash covers the decision, policy, evidence, and the as-of timestamp. Change any of them and verify() raises.

restored.evidence[0]["value"] = "platinum"
try:
restored.verify()
except BundleIntegrityError as exc:
print("tamper detected:", exc)

Key Classes

SymbolWhy it matters
ExaminerBundle.build(decision, evidence_store, policy_registry, *, as_of_transaction_time=None, metadata=None)Seals the decision, its evidence, and the as-of policy into one artifact.
ExaminerBundle.verify()Recomputes the hash; raises BundleIntegrityError on any change.
ExaminerBundle.to_json() / from_json()Move the bundle between systems without losing the integrity check.
ExaminerBundle.content_hashSHA-256 digest — the tamper-evidence anchor.
BundleIntegrityErrorRaised by build (missing evidence) and verify (hash mismatch).

Bundles are built from AgentRoutingDecision records (see Versioned Routing Policy) and BitemporalRecord evidence (see Bitemporal Storage).

Where this fits