BharatCode

Sovereignty

Audit Log

BharatCode keeps an append-only, tamper-evident record of what the agent did on your machine. Every significant event — a model call, a tool run, a file write, a permission decision — is written as one immutable, hash-chained entry. You can export the whole trail for archival and cryptographically verify that no record was added, removed, reordered, or altered after the fact.

Why an audit log

Handing work to an autonomous agent raises a fair question: what exactly did it do? The audit log answers it with evidence rather than trust. It is the “proof” companion to offline mode: offline mode guarantees code did not leave the machine, and the audit log gives you a verifiable account of everything that happened on it. For regulated and sovereignty-first environments, that durable, checkable record is the point.

What gets recorded

Each entry is one event. Events carry a stable type so the trail stays queryable:

  • llm — a completion request sent to a model provider.
  • tool — an agent tool invocation.
  • file_write — a write to a file on disk.
  • permission — a permission decision (ask / allow / deny).

A record also carries an actor (the session, provider, or tool responsible), a short human-readable summary, and optional structured detail stored as canonical JSON. Records are kept in a SQLite database under your data directory — by default ~/.local/share/bharatcode/audit.db (or under $XDG_DATA_HOME when set) — co-located with the main database.

How it stays tamper-evident

Two mechanisms make the log append-only and tamper-evident:

  • A hash chain. Each record's SHA-256 hash is computed over its own fields and the previous record's hash, seeded from a fixed genesis value. Editing, reordering, or deleting any record changes a hash and breaks the link to every record after it.
  • Storage-level triggers. The underlying table installs SQLite triggers that abort any UPDATE or DELETE, so the log is append-only at the database layer too — not merely by convention in application code.

The hash is part of the on-disk contract

The record hash covers, in order, the previous hash, the timestamp, the event type, the actor, the summary, and the canonical JSON detail. That field order is fixed so a hash computed today still verifies tomorrow.

Exporting the trail

bharatcode audit export writes every record to standard output as JSON Lines (one record per line), oldest first — a format that archives cleanly and pipes straight into other tooling. Redirect it to a file to capture the trail:

terminalbash
bharatcode audit export > audit.jsonl

Each line is a self-describing record:

one line of audit.jsonl (illustrative)json
{  "seq": 42,  "timestamp": "2026-06-05T09:14:02.481Z",  "type": "tool",  "actor": "bash",  "summary": "ran go test ./internal/recipe/",  "detail": { "exit_code": 0 },  "prev_hash": "9f2c…",  "hash": "a17b…"}

Because the export carries each record's prev_hash and hash, the exported file is independently checkable — an auditor can re-walk the chain offline without access to your machine.

Verifying integrity

bharatcode audit verify walks the chain from the genesis seed, recomputes every record's hash, and confirms each one links to its predecessor. It reports the number of records verified, and fails at the first inconsistency — a broken prev_hash link or an altered record — which is exactly what tampering or corruption would produce.

terminalbash
bharatcode audit verify

On an intact log you will see a confirmation like:

outputtext
audit log OK: 42 records verified

Point either command at a specific log

Both subcommands accept --path to target an audit database other than the default location — handy for verifying an archived copy: bharatcode audit verify --path ./archived-audit.db.

The sovereignty pair

The audit log and offline mode are designed to be used together. Offline mode is the boundary — a verifiable guarantee that nothing crosses it. The audit log is the ledger — a tamper-evident record of everything the agent did inside it. With both on, you can run an autonomous agent over sensitive code and afterward prove both that the code stayed put and exactly what was done to it.