Skip to content

Find actions with no receipt.

A receipt checker can inspect only files it receives. Compare those files with a separate action log to find what is missing.

This runnable example sends four actions and creates three receipts. The receipt files and the test harness’s action log are generated together for the walkthrough. Every check below runs locally.

What this check cannot tell you

The browser recomputes receipt digests, executable bounds, and a local RFC 6962 inclusion proof against a pinned fixture root. It does not verify signature identity, actor time, underlying execution, or independent witness operation.

The walkthrough

1 · Tamper with one receipt

The record below is the run’s fs.write receipt. A log line would carry the path and a timestamp; the receipt also carries the acting principal, declared bounds, and where a challenge goes. Change the path and verify again.

action
fs.write · /workspace/report.md
principal
did:web:example#agent
bounds
scope unstated · rollback P7D
recourse
challenge window P7D · local://recourse-unset
integrity
not yet checked
authority proof
not evaluated
bounds
declared
grounding
not yet checked
recourse
declared · forum unset

STRICT-V1 · REFUSE ON INTEGRITY FAILURE · ESCALATE BELOW COUNTERPARTY-SIGNED GROUNDING

reliance · policy strict-v1not yet computed

2 · Verify the whole run

Unlocked after the first tamper.

3 · Reconcile against the harness log

Unlocked after the run verifies.

Checking a receipt and finding a missing receipt are different jobs

The first checks ask whether a supplied receipt has changed. The final comparison asks whether every action in a separate action log has a matching receipt. Every supplied receipt can pass while the log still contains an unmatched action. In production, that separate record may come from a gateway, receiver, audit system, or test harness.

Limits of the action-log comparison

Bulla can find actions in the supplied action log that have no matching receipt. It cannot find actions missing from that log.

Technical evidence

Coverage is computed relative to the supplied denominator; a compromised or incomplete independent log narrows what reconciliation can find. The browser recomputes digests and the set difference over unsigned fixture receipts and does not verify signer identity or the denominator's independence.

An ActionReceipt carries the transaction fields another party needs to inspect: the action, declared authority and limits, supplied evidence, and challenge path. The counterparty can keep the file after access to the provider’s system ends.

The same checks work in the other direction. When the acting agent belongs to a vendor, these are the records to require from it, and the coverage report is how selective delivery gets caught. The asks are at Require receipts.

Provider logs, traces, and metrics remain useful. An exported provider event can supply evidence for a receipt. The ActionReceipt gives the counterparty a standard file for one transaction, while the receiver log gives it an independent list to compare against. Bulla does not assume that either log is complete.

Run it on your agent

The fixture behind this page is examples/agent-fleet-blind-spot in the Bulla repository. The wrapped path is three lines:

python
from bulla import wrap_action, event_coverage

with wrap_action("payments.charge", {"event_id": "run-7:3", "amount_minor": 12500}) as act:
    ...                                       # the consequential action

report = event_coverage(harness_log, receipts, anchor="agent-harness-log")
report["unreceipted_delta"]                   # actions that left no receipt

The Python API is documented at Wrap your agent’s actions. For the incident-shaped case, a gateway bypass caught by the same reconciliation, see the evaluation-incident replay.