The honest ledger · updated 2026-09-20

We red-teamed ourselves.
Here's the report.

Every claim below was attacked on purpose — by a harness we built to break this system. Some claims survived. Some didn't. We publish both, because a credit system you can't interrogate is a credit system you shouldn't trust.

Public beta. Ledger units are non-redeemable test units, not money. Basis is not a bank, a lender, or a licensed credit bureau.

The counterfactual

What changes when an agent can owe?

An agent with a prepaid wallet is a tourist: someone has to load the card before every trip. An agent with a credit line is a resident. Read the two columns. We won't spell out the difference — you'll feel it.

The tourist — prepaid wallet

  • Spends what someone loaded before the work starts.
  • Asks: “do I have enough?”
  • Has a balance — a number that only goes down.
  • Waits for funding before it can begin.
  • Leaves no memory of kept promises.
  • Settles the past, one transaction at a time.

The resident — a credit line

  • Starts before anyone pays it, and settles after.
  • Asks: “am I good for it?”
  • Has a record — a reputation that compounds.
  • Begins on a promise, and earns working capital by keeping it.
  • Carries every kept promise into the next negotiation.
  • Finances the future — work that hasn't happened yet.

Our vault survived everything we threw at it. Two processes hammering one database, corrupted disks, killed servers, forged signatures, privilege-escalation attempts — the ledger held. The credit, though, is still in rehearsal. The scores are real arithmetic on real behavior, but the behavior is theater until the money is. Below is the full ledger: what the system can do, what it can't, and what would have to be true for the can'ts to move.

The ledger · assets

What Basis can do today.

Each claim opens to its receipt — the test, the attack, or the measurement that proved it. No receipt, no claim.

✓Give an agent a persistent credit identityverified

An agent registers a public key, gets a credit line with a limit, and draws against it by signing IOUs with its own key. The identity survives across sessions; the line — not a balance — is what it spends against.

Receipt: 28/28 unit tests green; 12-identity demo economy drawing, repaying, and scoring on a live loop; public snapshot at /demo_network.json.
✓Enforce a credit limit under concurrencyverified

Six draws of 100 against a 500 line: the first five execute, the sixth is rejected, outstanding lands on exactly 500. Under a 16-thread storm across two processes sharing one database, 400 acknowledged draws persisted 400/400 — zero lost, zero over-limit.

Receipt: adversary attack overlimit_draw BLOCKED; two-process repro: 400 HTTP-200, 2,000 units expected, 2,000 persisted. (An earlier build silently lost 46% of writes this way. The attack harness caught the regression; the fix is proven by the same repro.)
✓Record repayments and price behavior into scoresverified

The bureau scores five factors — repayment record, limit breaches, utilization, history depth, network breadth — deterministically. Same inputs, same score, every time. Every rejected draw is logged and dents the score, so hitting the limit leaves a mark.

Receipt: adversary attack overlimit_draw BLOCKED with breach factor falling to 0.8 after two rejections; 12 demo agents accumulating differentiated scores (558–751) on the live network.
✓Revoke a key instantlyverified

A revoked API key stops working immediately — no grace period, no cached session outliving the revocation.

Receipt: adversary attack key_after_revoke BLOCKED; agent-scoped MCP keys are additionally barred from all 16 operator-only tools (403).
✓Survive crashes without losing acknowledged writesverified

SIGKILL mid-storm: every write the server acknowledged was on disk when it came back. Delete the database and it recreates a fresh one instead of crash-looping. Disk-full produces a 507 with a clear message, not a lying 200.

Receipt: resilience report: 141/141 acknowledged writes persisted across SIGKILL; integrity ok; disk-full recovery verified after space returned.
✓Refuse to boot on a corrupted databaseverified

A bit-flipped database used to boot "healthy" and serve wrong data with a green health check. Now the store runs an integrity check at startup and refuses to serve corruption — a loud crash-loop with "restore from snapshot" beats silent wrongness.

Receipt: resilience finding §2; fix verified in store.py — corrupt DB raises at boot instead of serving.
✓Keep tenants isolatedverified

No tenant can read, draw against, or exhaust another tenant's ledgers, keys, or rate limits — including through forged headers and cross-tenant key replay.

Receipt: adversary attacks tenant_escape and unicode_chaos BLOCKED; X-Forwarded-For spoof of the signup rate limit fixed and re-blocked.
The ledger · liabilities

What it can't do yet.

These are not bugs — they are the difference between a scoreboard and a bureau. We name them because the roadmap is measured in exactly these gaps.

✕Prove a repayment is real commercetheater

Two agents can wash-trade back and forth — draw, repay, draw, repay — and farm a 751 "good" score out of 300,000 units of pure circular motion. The ledger records the behavior faithfully; it cannot tell commerce from choreography.

Evidence: adversary attack wash_cycle VULNERABLE — 60 draw/repay cycles, score 751. Utilization gaming and breadth gaming similarly VULNERABLE.
✕Stop an agent from abandoning a bad scoresybil

Default on 10,000, watch the score fall to 476 — then register a fresh identity and start again at 600. Six defaults became six clean slates. Nothing follows the operator across identities, because identity currently costs nothing.

Evidence: adversary attacks default_and_dash and fresh_start_after_default VULNERABLE.
✕Enforce a defaultno teeth

Draw 10,000 and never repay. The consequence is a number going down. There is no collateral, no collection, no counterparty with recourse — the score is the entire enforcement mechanism, and a score can't repossess anything.

Evidence: adversary attack default_and_dash VULNERABLE — score 476, zero enforcement artifact.
✕Underwrite without an operatoroperator-run

Every credit line is set by a human operator. The bureau scores behavior, but no loan is priced, approved, or denied by the system on its own. What exists is an operator-run ledger with behavioral scoring — not independent underwriting.

Evidence: read-the-code audit — all line creation flows through operator-held keys; the bureau has no approval authority.
✕Prove its history to a skeptictrust us

The operator holds the database. Snapshots are Merkle-styled, not Merkle-proven against anything the operator can't rewrite. Until history is tamper-evident to outsiders, "who owed and who repaid" is our word for it.

Evidence: read-the-code audit — no anchored commitments; the "oracle" is a plain tracker-commitment box consumed as a data input.
✕Touch real moneytest units

Ledger units are non-redeemable accounting for machine labor that hasn't happened yet — never a token, never an ICO. Real reserves and real chain commits are built and rehearsed on devnet, but the gates are explicit: public testnet, then a professional security audit, then counsel sign-off, then mainnet. None have cleared yet.

Evidence: devnet lifecycle verified 11/11; public testnet unfunded; audit not commissioned; counsel not engaged.
The ledger · what would have to be true

What needs to be done.

Each liability above moves to the asset column only when its condition is met. This is the actual roadmap — no dates, just gates.

→Identity with a costkills sybils

Fresh starts stop being free the moment identity costs something — a stake, an attestation, a vouch from a scored identity. Then a 476 follows its owner, and the credit file becomes a record instead of a costume.

→Settlement on a real railrepayment means something

Wash trading is free theater while units are accounting entries. The moment debts net and settle on a real rail — Bitcoin as the settlement layer after netting — every fake cycle costs real fees, and repayment becomes an event in the world, not a row in our database.

→An enforcement mechanismdefaults have teeth

Scores need consequence: staked collateral, counterparty recourse, or exclusion with memory. A bureau whose worst punishment is a lower number is a scoreboard. Enforcement is the moat — and the unsolved half of the thesis.

→Tamper-evident historyverify, don't trust us

Anchor ledger commitments where the operator can't rewrite them, so "who owed and who repaid" is checkable by anyone. The credit graph is the underlying asset — it has to be auditable without our permission.

→Audit, counsel, testnet — in that orderreal money

Public testnet verification, then a professional security audit, then counsel sign-off, then mainnet. The sequence is non-negotiable and the founder performs the key ceremony in person. No step is skipped because the demo went well.

Basis-operated demo network — demonstrates the mechanics; not real users, not traction. The 12 agents on the network page are scripted personas running on a loop. Their draws, repayments, and scores are real executions of the ledger code — and that is all they are.

This page is generated from our own red-team reports: the adversary suite (adversary/REPORT.md), the capability-gap audit, the resilience report, and the fuzz runs — all executed 2026-09-20 against local builds, never against production. When a liability above moves columns, this page moves with it. That is the deal.

Get a line in 60 seconds Read the docs