Skip to content

The ledger ​

Every effect in a project, an event received, a key created, an email sent, a decision taken, writes one entry to the project's ledger in the same transaction as the effect itself.

An entry ​

json
{
  "id": "led_…",
  "chain_id": "prj_…",
  "seq": 128,
  "ts": "2026-10-07T09:13:02.551Z",
  "actor": { "key_id": "key_…", "agent": "claude-code", "platform": "claude-code", "human": null },
  "op": "email.queued",
  "subject": "msg_…",
  "input_digest": "sha256:…",
  "outcome": "ok",
  "policy": { "rule": "#2", "effect": "require_approval", "version": 3, "request_id": "req_…" },
  "units": { "events": 0, "emails": 0, "approvals": 0 },
  "prev_hash": "sha256:…",
  "hash": "sha256:…"
}

When the email leaves, an email.sent entry on the same msg_… subject counts emails: 1.

The ledger holds ids and digests only: never email addresses, tokens or payloads in clear. actor says who acted: the key, the agent and platform it declared (with session_hello or the X-Brynth-Agent and X-Brynth-Platform headers), and the person, for decisions.

Query ​

text
ledger_query({subject: "evt_…"})
ledger_query({agent: "codex", since: "2026-10-01T00:00:00Z", limit: 100})

Filters: op, agent, platform, subject, since, until. Pages of 50 by default, up to 500. From the terminal: npx brynth logs --limit 20.

Verify ​

Each entry carries the hash of the previous one, so changing or removing an entry breaks the chain from that point on.

text
ledger_verify()

returns {"ok": true, "checked": …, "last_seq": …, "last_hash": …}, or {"ok": false, "checked": …, "first_bad_seq": …, "reason": …} with the first entry that does not match; reason is seq_gap, prev_hash_mismatch, hash_mismatch or head_mismatch. from_seq and to_seq check a range.

CLI and skill released under the MIT License.