The Ledger

The record, read as evidence.

Which agent, model, and version made each change. Which person reviewed it. Signed, chained, anchored outside the repository, and verified offline by whoever asks.

Our own record right now: Chained and anchored through 2026-09-18.
7
Sessions · 1 with identity
147
Commits · 0 reviewed
2
Days chained · 2 anchored
147
Unreviewed · shown, never hidden

1

What the Ledger is

A bookkeeper's word, and a promise with three parts.

A ledger is the permanent, append only book of every transaction: what, when, who, how much. Entries are never edited; a mistake gets a correcting entry. A log is something you write for yourself and can lose. A ledger is something another party can audit later and trust.

The Ledger is not a second product. It is the same record the Board reads, kept in your own git, with three things the Board does not need: identity per session, a human review record per agent authored commit, and tamper evidence.

  1. Signed

    Every entry is signed by the identity that made it.

  2. Chained

    Entries are chained, so removing or altering one is detectable.

  3. Anchored

    The chain is anchored outside the repository, so the audited party cannot rewrite its own history. Without this it is a log with extra steps, and an assessor will say so.

2

What it records

Two records the Board never needed: who ran each session, and who reviewed each commit.

Per session

When a coding session starts, the hook in the agent runtime writes who directed it (the person, matched from git and the team file) and what ran it: runtime, version, model, model version, the tools it was granted, and its permission mode. Every field comes from the runtime, never typed by a person. If the runtime cannot say, the field is null and the board shows "not reported".

From our own record: Aatir, 18 Sept 2026Live
{
  "startedAt": "2026-09-18T18:24:25.497Z",
  "endedAt": null,
  "agent": {
    "runtime": "claude-code",
    "runtimeVersion": "2.1.277",
    "model": "claude-fable-5-1",
    "modelVersion": null,
    "tools": null,
    "permissions": "default",
    "policyHash": null
  }
}

Per commit

Each commit is attached to the session that made it, so direction is known. The Ledger adds a review record: a signed statement that a named human reviewed the commit, distinct from authoring it. It is captured where review already happens, an approved pull request, or written from the terminal with one command for teams that ship straight to main. The reviewer is never the session's director unless the team turns self review on, off by default and shown as a caveat when on.

The shape of a review record. Our own board shows every agent authored commit as Unreviewed until one is written, and says so rather than hiding it.Example
{
  "commit": "3f1c9a2e",
  "reviews": [
    {
      "reviewer": "maya",
      "reviewedAt": "2026-09-19T16:10:00.000Z",
      "source": "pull_request",
      "pullRequest": 42
    }
  ]
}
Every agent authored commit shows one of three states:Reviewed by a named personSelf reviewed, a caveatUnreviewed, never hidden

3

Tamper evidence

Three mechanisms, all on by default once the Ledger is enabled.

Signed commits

Every tracker commit is signed, with Sigstore by default so no key management is needed, or GPG where a team already has keys. The validator checks every tracker commit and fails the build on an unsigned one from the day signing was required.

The nightly chain

The close writes one entry per day holding the hash of every record file it wrote and the hash of the previous day's entry. One line per day, and the validator walks the whole chain.

External anchoring

The close publishes the day's chain hash to a transparency log outside the repository: Sigstore Rekor, OpenTimestamps as a second anchor, or your own endpoint. The receipt is stored beside the entry. Without one the Ledger says "not anchored" in every view and export.

Our latest chain entry, 18 Sept 2026: 1 file, anchored with rekor and opentimestampsLive
{
  "day": "2026-09-18",
  "hash": "e8c90d286937e151125c531c6b0cd6c6ccc98e6279710c8612b6d4bdff6419a2",
  "previous": null,
  "anchors": [
    {
      "kind": "rekor",
      "at": "2026-09-18T18:01:47.879Z"
    },
    {
      "kind": "opentimestamps",
      "at": "2026-09-18T18:01:49.597Z"
    }
  ]
}

4

Verify

One command replays the chain, checks every signature and every anchor, offline, and prints a verdict. An assessor runs it, not us.

$ npx @truestate/cli verify --offlineverify 2026-09-18 to 2026-09-18, 1 day, offline, zone America/New_Yorkok   2026-09-18  chain ok, 1 file intact  |  signed 4/14, 10 unsigned (not required then)  |  anchored: rekor #2886802074 (receipt present, not re fetched offline); opentimestamps proof from a.pool.opentimestamps.org (172 bytes; the Bitcoin attestation is not checked here)verdict: VERIFIED: 1 days chained, signed as required, and anchored outside the repository

Our own transcript, committed with the record on the first anchored day.

5

The control map

We say evidence for, never compliant with.

Each line names the control, what the record provides, what our own record shows right now, and the ordinary case in which the evidence is insufficient.

Control (NIST SP 800-53 rev 5)The Ledger providesOur record, nowInsufficient when
AU-10 Non repudiationsigned commits bound to a person or an agent identity, reviewer identity bound separatelysigning required; run truestate verify for the count per daysigning not enforced; agents share a credential
AU-9 Protection of audit informationchained daily hashes anchored outside the repository2 of 3 closed days chained, 2 anchored outside the repositoryno external anchor; the anchor is run by the same people
AU-3 Content of audit recordsactor, time, event, outcome, model, version, session, reviewer per commit1 of 7 sessions carry the runtime and modelfields not reported by the runtime
AU-2, AU-6, AU-12 Event logging, review, generationa defined event set and a queryable record101 entries across 3 closed days, every one queryablethe organisation never defines events or reviews the record
CM-3 Configuration change controla review decision distinct from the change, per agent authored commit0 of 147 commits reviewed by a named person, 0 self reviewed, 147 unreviewedself review; no impact analysis
CM-5 Access restrictions for changebranch protection and the review rule recordedthe review rule is recorded; branch protection is read from the repository host in a later itemone identity can author and merge
SA-10 Developer configuration managementthe signed record of authorised changes across the buildsigning required; run truestate verify for the count per dayno CM plan; the repository itself unprotected
SA-11 Developer testingtest results tied to commits when captured from CI, never from the agent's own reporttest results from CI are a later item; nothing self reported countstests are self reported
SR-4 Provenancewhich runtime, model, and version produced each change, at a point in time1 of 7 sessions carry the runtime and modelfields null
IA-9 Service identification and authenticationa distinct identity per agent session1 of 7 sessions carry the runtime and modelagents share a generic credential
AC-6 Least privilegethe tool permissions granted per session, recorded1 of 7 sessions record the permission moderecorded but not enforced (see Policy)

Control map version 2026-09-18. The map is a file in the repository so it can be revised when NIST publishes the agent overlays, and the evidence export always ships the current version.

Where the same controls sit in other frameworks

The families above are referenced, not redefined, by the frameworks a federal or defence buyer will name. The mapping is by control family; the buyer's assessor decides sufficiency.

Row aboveCMMC 2.0 (Level 2 practices, from NIST SP 800-171 rev 2)FedRAMP (Moderate and High baselines)
AU-103.3.2 Ensure actions can be traced to individual usersAU-10 in the High baseline; not selected in Moderate
AU-93.3.8 Protect audit information and tools from unauthorized access, modification, deletion; 3.3.9 Limit management of audit logging to privileged usersAU-9, with AU-9(2) off system backup in High
AU-33.3.1 Create and retain audit records with the content needed to monitor and investigateAU-3, AU-3(1) additional content
AU-2, AU-6, AU-123.3.1, 3.3.3 Review and update logged events, 3.3.5 Correlate audit reviewAU-2, AU-6, AU-12
CM-33.4.3 Track, review, approve or disapprove, and log changesCM-3, CM-3(2) test and validate in Moderate and High
CM-53.4.5 Define, document, approve, and enforce physical and logical access restrictions for changeCM-5, CM-5(1) automated access enforcement in High
SA-10not a Level 2 practice; relevant to Level 3 through 800-172SA-10
SA-11not a Level 2 practiceSA-11
SR-4not a Level 2 practice; supply chain under 800-172SR-4 in the High baseline
IA-93.5.1 Identify system users, processes acting on behalf of users, and devicesIA-9 was withdrawn into IA-3 and IA-8 in rev 5 baselines; cite the session identity under those
AC-63.1.5 Employ the principle of least privilegeAC-6 and its enhancements

What the map does not claim

  • No row means a control is satisfied. The third column names the ordinary case in which it is not.
  • Tests are evidence only when they come from CI, never from what an agent wrote in a commit message or a session.
  • A chain without an external anchor is labelled "not anchored" in every view and export; AU-9 is not met by it.
  • Policy (25-the-record.md section 8) records the rules a session ran under; it is not a control plane and the map does not present it as one.

6

Evidence export

One command writes an evidence package for a period. Names become roles and hours stay out unless the exporter asks for them.

$ npx @truestate/cli export --ledger --from 2026-09-01 --to 2026-09-30truestate-export-2026-09-01-2026-09-30/

ledger.json

Sessions, agents, commits, reviewers, days, the chain, and the verdict, machine readable.

verify.txt

The verification transcript, one line per day.

control-map.md

The map at the version the export was made.

ledger.pdf

The same, for a reader.

The export never includes note screenshots, Ask threads, or emails.

7

Where it fits

Runtime observability watches agents in production. Nobody watches the agents that write the software.

The Ledger records what agents did while the software was being built, inside your boundary, and it will export sessions and commits as OpenTelemetry spans so both sit in one dashboard. In the category a reader searches for, this is the build time record for AgentOps and agentic engineering; on this site it is the Ledger.

Coming next The OpenTelemetry export.

8

Deploying it

The record lives in your git either way. The question is only what reads it and what leaves.

Hosted

The hosted board reads your repository through a GitHub App your organization installs once, with three permissions: contents read and write, issues read and write, metadata read. Accounts and an audit log live in our database; the record never does.

What leaves the boundary

One hash per day, sent to a public transparency log, and the receipt that comes back. Nothing else. An enterprise can point that anchor at its own log instead.

Self hosted and air gapped Coming next

The same app pointed at your own git host, with your own anchor, as a template.

The full boundary in plain words is on the security page.

9

Talk to us

Tell us the project and the assessment it faces. A person replies, with an evidence package for a period of your own record if you want to see one first.

A person reads it and replies within two business days. No calendar, no sequence.

Or write to hello@truestate.space. Pricing for the Ledger and Enterprise tiers is on the home page.