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
UPDATEorDELETE, 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
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:
bharatcode audit export > audit.jsonlEach line is a self-describing record:
{ "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.
bharatcode audit verifyOn an intact log you will see a confirmation like:
audit log OK: 42 records verifiedPoint either command at a specific log
--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.