An immutable, hash-chained audit ledger you can embed in any project.
chainblocks is a small, ownable, embeddable piece of cryptographic plumbing. Any project that needs to say "this happened, in this order, and nothing has been edited since" can import it like SQLite, append typed entries to it, and verify the chain in linear time.
The storage layer is pluggable β write to a file, to your application's database, to S3, or to whatever your project already uses for state. The integrity guarantee is in the hash chain, not in the storage.
- AI agent and digital twin builders who need defensible audit trails β "the system learned this fact at this time from this source; here is the unbroken chain back to the observation"
- Government and defense teams who need tamper-evident logs that can be authorized (FedRAMP, IL4/5, STIG) without depending on a vendor blockchain
- Regulated industries (finance, healthcare, supply chain) where audit-trail integrity is a compliance requirement, not a nice-to-have
- Anyone building agentic systems where the question "did the agent really do that?" is going to be asked β in court, in a postmortem, or in a contract dispute
If you have one trusted writer and a need to prove "nothing has been edited since," chainblocks is for you.
If you have many mutually-suspicious writers that need to agree without coordination, you want a blockchain, and chainblocks is not the right tool. We are explicitly the simpler thing.
| chainblocks | A blockchain | Database audit log | Plain syslog | |
|---|---|---|---|---|
| Tamper-evident | β via hash chain | β via consensus | β admin can edit | β root can edit |
| Multi-writer | β single writer per ledger | β many writers | β many writers | β many writers |
| Throughput | β thousands/sec on a laptop | β tens/sec at best | β thousands/sec | β thousands/sec |
| Storage substrate | β pluggable (file, S3, SQL, β¦) | β on-chain only | ||
| Operational complexity | β a library | β a network | β already running | |
| Cross-language verifier | β
from MODEL.md |
β usually | β none | β none |
| Audit-trail guarantee | β verifiable by anyone with the head hash | β verifiable on-chain | β "trust our DB" | β "trust our host" |
| Trust requirement | one honest writer at write-time | distributed consensus | DB administrator | system administrator |
| Adoption-blocker-class | minimal | regulatory, operational, performance | "this is our audit log of our audit log" | nothing is signed |
chainblocks is the smallest piece of cryptographic plumbing that gets you a defensible audit trail. No consensus, no mining, no token, no SaaS, no telemetry.
npm install @chainblocks/coreimport { openLedger, FileStore } from '@chainblocks/core';
// Open or create a ledger
const ledger = await openLedger({
store: new FileStore({ path: './audit.ledger' }),
name: 'app-audit',
writer: 'app',
});
// Append a typed entry
await ledger.append({
kind: 'app.event.recorded',
payload: { eventId: 'e-a8c4', actor: 'alice', action: 'login' },
});
// Read entries (with optional filters)
for await (const entry of ledger.read({ kind: 'app.event.*' })) {
console.log(entry.seq, entry.ts, entry.payload);
}
// Verify the chain
const result = await ledger.verify();
// { ok: true, head: { seq, hash, ts } }
// or
// { ok: false, tamperedAt: 1342, reason: 'hash_mismatch' }
await ledger.close();And the standalone verifier β your assessor's tool:
$ npx chainblocks-verify ./audit.ledger
β Ledger: app-audit
β Writer: app
β Entries: 4,237
β Head: seq=4236 hash=sha256:8f3a91c2β¦
β Chain valid (verified in 47ms)When the chain is broken, the CLI reports the exact failing seq and the reason:
$ npx chainblocks-verify ./tampered.ledger
β Chain broken at seq=1342
reason: hash_mismatch
expected: sha256:8f3a91c2β¦
actual: sha256:def01bc4β¦- πͺͺ FT-CB-01 Open/close lifecycle β create, open, close, reopen ledgers; concurrent-open protection via
O_EXCLlockfile - π FT-CB-02 Block append β atomic append with server-side
seqandts; concurrent calls serialized internally - π FT-CB-03 Sequential read β async-iterate the chain in seq order; safe to read while appending
- π FT-CB-04 Filtered read β read by seq range and/or kind pattern (with trailing wildcard)
- π― FT-CB-05 Head query β O(1) access to the current head
- π’ FT-CB-06 Random access by seq β fetch any block by its sequence number
- β
FT-CB-07 Full-chain verification β walk-and-verify with precise tamper reporting (
hash_mismatch,prev_mismatch,out_of_order,torn_write,missing_block,malformed_block) - β© FT-CB-08 Incremental verification β verify from a trust anchor forward for huge ledgers
- π FT-CB-09 Store port β pluggable storage interface; bring your own backend (Postgres, SQLite, S3, in-memory, β¦)
- πΎ FT-CB-10 FileStore β production default; JSONL on disk with
fsyncafter every append andO_EXCLlockfile - π§ͺ FT-CB-11 MemoryStore β for tests and ephemeral ledgers; satisfies the Store contract
- π₯οΈ FT-CB-12 Verifier CLI β
chainblocks-verify <path>standalone tool, no chainblocks knowledge required of the operator - π FT-CB-13 Append events β EventEmitter
'append'hook for live dashboards or replication tail-ers - β FT-CB-14 Typed error taxonomy β every failure mode is a typed error class with structured context
- π FT-CB-15 RFC 8785 canonicalization β cross-implementation-deterministic hashing; write a verifier in any language and get byte-identical results
- ποΈ FT-CB-16 Project-wide quality bar β CI gates on tests, typecheck, JSDoc coverage, example runs; performance budgets enforced by benchmarks
See docs/FEATURES.md for the full feature inventory mapped to requirements and use cases.
The chainblocks repository is documented at multiple levels of depth.
Narrative (start here):
STORY.mdβ why this exists, who it's for, the design doctrine (seven commitments, six explicit non-goals)- This
README.mdβ the quick pitch
Reference (for integrators):
docs/API.mdβ every exported symbol with signature, parameters, returns, throws, and a runnable exampledocs/USE-CASES.mdβ nine canonical use cases (UC-1 through UC-9) that drove the designdocs/FEATURES.mdβ the feature inventory mapped to requirements and use casesREQUIREMENTS.mdβ 65 numbered requirements (REQ-CB-*) the implementation satisfiesMODEL.mdβ the portable data-model specification (Block format, canonicalization rule, verification algorithm in pseudocode) β sufficient to implement chainblocks in any language
Governance:
SECURITY.mdβ supported versions, vulnerability reporting, threat model summary, cryptographic choicesdocs/SECURITY-MODEL.mdβ deeper threat model: what chainblocks protects against, what it does NOT protect against, trust boundaries, scenarios where chainblocks failsCONTRIBUTING.mdβ how to file issues, run tests, propose changesCODE_OF_CONDUCT.mdβ Contributor Covenant 2.1CHANGELOG.mdβ release-by-release log
Examples:
examples/basic/β minimum runnable exampleexamples/custom-store/β implementing your ownStoreexamples/verify-cli/β thechainblocks-verifyCLI in action, including tamper detection
Stated plainly so no one is surprised. From STORY.md's explicit non-goals:
- β Not a blockchain β no consensus, no mining, no token, no network
- β Not a distributed database β single writer per ledger by design
- β Not an ACID database β queries are linear scans; project the log into a database if you need indexed queries
- β Not a secrets store β payloads are stored as supplied; encrypt before append if needed
- β Not tamper-proof β anyone with substrate write access can overwrite, but the chain will detect it. Tamper-EVIDENT, not tamper-PROOF
- β Not a SaaS β chainblocks is a library; there is no chainblocks.io
- β No telemetry, no network I/O, no phone-home β the ledger is the customer's data, in the customer's substrate, under the customer's keys
π§ Pre-1.0 β APIs may change before v1.0.0.
v0.1 is the initial release: the core library, the file/memory store implementations, the verifier CLI, the test pyramid, and the documentation bundle above. v0.2 will add optional plugins for public-blockchain anchoring and Ed25519 per-entry signatures. v1.0.0 follows once external adoption confirms the v0.x API surface.
Semver applies from day one.
Apache License 2.0 β see LICENSE.
Apache 2.0 was chosen over MIT for the explicit patent grant. chainblocks is targeted at enterprise and government adopters where patent posture matters; the patent grant plus the contributor patent retaliation clause makes adoption decisions cleaner.
ποΈ