Lab 03 — Tamper-Evident Agent Approval Ledger

Difficulty: 4/5 | Runs locally: yes

Pairs with the Phase 11 WARMUP Chapter 11 (approval gates, audit, human ownership) and the HITCHHIKERS-GUIDE ("Audit"). Builds on Phase 00 evidence integrity.

Why This Lab Exists (Purpose & Goal)

When an AI agent takes a consequential action — a write, a privilege change, a disclosure, an external message — you must be able to prove, afterward, exactly what happened: what the model proposed, what policy decided, who approved it, and what executed. The goal of this lab is to build the tamper-evident ledger that records that chain so it cannot be silently altered — the accountability backbone of any agent that can act.

The Concept, In the Weeds

The ledger is a hash-chained record of the agent action lifecycle:

proposal → policy decision → human approval → capability issuance → execution → result

Each entry's hash incorporates the previous entry's hash (this_hash = H(prev_hash || entry)), so deleting or editing any entry breaks the chain and is detectable — the same tamper-evidence as a blockchain or a Phase 00 evidence manifest. The ledger verifies:

  • actor, tenant, request ID — who did what, for whom;
  • timestamp ordering — no time regression (a reordered or back-dated entry is rejected);
  • chain integrity — the hash links are unbroken.

Two design principles carry the weight. First, human-in-the-loop for consequential actions: writes, privilege changes, disclosure, external communication, and spending require an approval artifact, and the human must see a transaction preview (approving a concrete action, not rubber-stamping). High-risk actions may need two-person approval. The bar: 100% of privileged actions have a policy decision and an approval artifact. Second, the ledger stores hashes/metadata, not secrets or full prompts — you get accountability without creating a new sensitive-data store (Phase 00 minimization).

Why This Matters for Protecting the Company

As agents take real actions, "what did the AI do, and who authorized it?" becomes a question with legal, compliance, and incident-response weight. Without a tamper-evident record, you cannot investigate an agent that misbehaved, prove to an auditor that approvals happened, or defend the company when an agent's action is challenged. An approval ledger gives the company non-repudiable accountability for autonomous actions — the same property that makes financial systems and access logs trustworthy. It is also the control that keeps a human meaningfully in the loop for the actions that matter, rather than letting an over-eager (or hijacked) agent act unchecked because "it's usually right" — which is exactly when the rare wrong action becomes a breach.

Build It

Create the hash-chained ledger for proposal, policy decision, human approval, capability issuance, execution, and result events. Verify actor, tenant, request ID, timestamp ordering, and chain integrity. Store hashes/metadata, not secrets or full prompts.

LAB_MODULE=solution pytest -q

Secure Implementation Patterns

The anti-pattern. A plain append-only log an attacker (or a bug) can edit or reorder, storing full prompts and secrets.

The secure pattern — a hash-chained, tamper-evident ledger (mirrors solution.py):

def _digest(record: dict) -> str:
    body = {k: v for k, v in record.items() if k != "hash"}          # canonical, hash excluded
    return hashlib.sha256(json.dumps(body, sort_keys=True, separators=(",", ":")).encode()).hexdigest()

def append(chain: list[dict], event: dict) -> dict:
    for field in ("request_id", "tenant", "actor", "kind", "timestamp"):
        if event.get(field) in (None, ""):
            raise ValueError(f"missing {field}")                     # who/what/when is mandatory
    if chain and event["timestamp"] < chain[-1]["timestamp"]:
        raise ValueError("time regression")                          # no back-dating
    record = dict(event, previous_hash=chain[-1]["hash"] if chain else "GENESIS")
    record["hash"] = _digest(record)                                 # this_hash = H(prev_hash || record)
    chain.append(record)
    return record

def verify(chain: list[dict]) -> bool:
    previous, last_time = "GENESIS", -1
    for r in chain:
        if r.get("previous_hash") != previous or r.get("hash") != _digest(r):
            return False                                             # any edit/deletion breaks the chain
        if r.get("timestamp", -1) < last_time:
            return False
        previous, last_time = r["hash"], r["timestamp"]
    return True

Because each record's hash incorporates the previous hash, deleting or editing any entry breaks the chain and verify() returns False — the same tamper-evidence as a blockchain or a Phase 00 evidence manifest. The lifecycle recorded is proposal → policy decision → human approval → capability issuance → execution → result.

Production practices to carry forward:

  • Store hashes/metadata, not secrets or full prompts — accountability without creating a new sensitive-data store (data minimization, Phase 00).
  • Require a policy decision and an approval artifact for every privileged action (transaction preview shown to the approver; dual control for the highest risk).
  • Anchor the chain periodically (a published checkpoint / WORM storage) so even an attacker who rewrites the whole chain can't match an external anchor.
  • Make it reconstructable — you must be able to prove, after the fact, exactly what the model proposed, what policy decided, who approved, and what executed.

Validation — What You Should Be Able to Do Now

  • Build a hash-chained, tamper-evident audit of the agent action lifecycle and detect any deletion/edit.
  • Require a policy decision and an approval artifact for every privileged action; use transaction previews and dual control for high-risk actions.
  • Explain why the ledger stores hashes/metadata, not secrets — accountability without a new sensitive store.
  • Identify which actions need a human (writes, privilege changes, disclosure, external comms, spend).

The Broader Perspective

This lab unites two threads that run through the whole curriculum: tamper-evident evidence (Phase 00 hash chains and chain of custody) and human ownership of consequential decisions (Phase 03 risk acceptance, Phase 09 incident command, Phase 12 "which judgments require a qualified human"). The mature position on automation — whether it's a CI pipeline, a remediation script, or an AI agent — is the same: automate the proposal and the low-risk work, but keep consequential decisions human-owned and every action provably recorded. As AI takes on more agency, this accountability infrastructure becomes more important, not less. An action that can't be audited and wasn't approved is an action that should never have been autonomous.

Interview Angle

  • "Which agent actions need a human, and how do you prove they were approved?" — Writes, privilege changes, disclosure, external communication, and spending need a previewed human approval (dual control for high-risk). Prove it with a tamper-evident, hash-chained ledger recording proposal→policy→approval→execution, so 100% of privileged actions have a policy decision and an approval artifact.

Extension (Stretch)

Integrate the ledger into the tool gateway so every gated action is recorded, and verify the chain after an injected tamper attempt.

References

  • Phase 11 WARMUP Chapter 11; Phase 00 WARMUP Chapter 7 (evidence integrity); OWASP Agentic Security; NIST AI RMF.