Files
yvgude--lean-ctx/docs/reference/16-signed-savings-ledger.md
T
wehub-resource-sync 26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

149 lines
6.3 KiB
Markdown

# Journey 16 — Proof & Audit (Signed Savings Ledger)
> You've been saving tokens for weeks; now a lead, client, or finance team wants
> proof. This journey covers the local savings ledger and how to turn it into a
> portable, Ed25519-signed receipt that anyone can verify **offline** — integrity
> and origin — without ever seeing your code, paths, or prompts.
Source files referenced here:
- `rust/src/cli/dispatch/analytics.rs``cmd_savings`, `cmd_savings_sign`, `cmd_savings_verify_batch`
- `rust/src/core/savings_ledger/store.rs` — append-only SHA-256 hash chain (`verify`)
- `rust/src/core/savings_ledger/signed_batch.rs``SignedSavingsBatchV1`, `BatchTotals`, `BatchVerifyResult`
- `rust/src/core/savings_ledger/mod.rs``summary()`, `verify()`, `all_events()`
- `rust/src/core/agent_identity.rs` — persistent per-machine Ed25519 keypair
---
## 0. The principle
> The ledger fills itself as lean-ctx compresses your reads, searches and shell
> output. Nothing leaves your machine unless you explicitly `sign` and share an
> artifact — and even then, only **aggregate numbers** travel, never code, file
> paths, prompts, or per-event timestamps.
---
## 1. The ledger — an append-only hash chain
Every compression event is appended to `~/.lean-ctx/savings/`. Each entry commits the
SHA-256 hash of the previous one (`store.rs`), forming a tamper-evident chain: editing,
reordering, inserting, or deleting any past event breaks `verify()`. The **chain head**
(latest `entry_hash`) is a fingerprint of the entire history.
```bash
lean-ctx savings verify # core::savings_ledger::verify()
```
---
## 2. The `savings` command surface
`cmd_savings` (`analytics.rs`) dispatches on the first argument; default is `summary`.
| Command | Code path | Leaves machine? |
|---------|-----------|-----------------|
| `savings summary` | `format_savings_summary()``savings_ledger::summary()` | No |
| `savings verify` | `savings_ledger::verify()` | No |
| `savings export` | `savings_ledger::all_events()` → pretty JSON | No |
| `savings sign [--out FILE]` | `cmd_savings_sign``SignedSavingsBatchV1::build_all` + `sign` | Only the file you share |
| `savings verify-batch <file>` | `cmd_savings_verify_batch``signed_batch::load_artifact` + `verify` | No (any machine) |
| `savings roi [--json]` | `cmd_savings_roi``savings_ledger::roi_report``RoiReport::from_signed_batch` | No (read-only aggregate) |
### ROI / metering surface (EPIC 12.20)
`savings roi` derives a [`RoiReport`](../../rust/src/core/savings_ledger/roi.rs)
**strictly from the signed batch**`BatchTotals` + the committed
`last_entry_hash` + the Ed25519 signature. It adds derived metering metrics
(net tokens, USD, averages per event, top models/tools) plus provenance
(`chain_valid`, `signed`, signer public key). This is the minimal,
privacy-preserving aggregate the **Cloud plane** meters on: it carries no raw
events, paths, prompts, or code — only numbers and hashes — and is read-only
with respect to the local ledger.
---
## 3. `savings sign` — build + sign the artifact
`cmd_savings_sign` calls `SignedSavingsBatchV1::build_all(agent_id)`, which reads the
ledger (`all_events`, `summary`, `verify`), copies the aggregate totals into `BatchTotals`,
records the first/last `entry_hash`, and signs the canonical bytes with the machine's
Ed25519 key from `agent_identity::get_or_create_keypair`.
```bash
lean-ctx savings sign --out ./sprint-savings.json
```
```text
Signed savings batch written to ./sprint-savings.json
Net saved: 12.8M tokens (~$32.41) over 1,240 event(s)
Chain head: 9f2c4b…e1a7
Chain: intact (SHA-256)
Signer key: 7b1e90…c4d2
Verify anywhere (no ledger needed): lean-ctx savings verify-batch ./sprint-savings.json
```
Default path (no `--out`): `<data_dir>/savings/signed-batch-v1_<utc-stamp>.json`
(`signed_batch::default_artifact_path`). An empty ledger exits non-zero with a hint.
### Artifact shape (`SignedSavingsBatchV1`, schema v1)
`kind = "lean-ctx.savings-batch"`. The two signature fields are excluded from the signed
payload (`canonical_bytes` clears them), so the file is self-verifying.
| Field | Meaning |
|-------|---------|
| `totals` | `BatchTotals`: net tokens, $ saved, event count, top `by_model` / `by_tool` rows (capped at 8) |
| `first_entry_hash` / `last_entry_hash` | chain endpoints — bind totals to a concrete history |
| `chain_valid` | whether the SHA-256 chain verified intact at signing time |
| `created_at`, `lean_ctx_version`, `agent_id`, `period` | provenance (`period = "all"`) |
| `signer_public_key`, `signature` | Ed25519 hex — make the artifact self-verifying |
**Never serialized:** raw events, file paths, code, prompts, per-event timestamps. The
payload is a dedicated struct, so a private field cannot leak by construction.
---
## 4. `savings verify-batch` — offline verification
`cmd_savings_verify_batch` loads the file (`load_artifact`, which rejects foreign JSON by
`kind`) and calls `SignedSavingsBatchV1::verify()`. Verification recomputes the canonical
bytes and checks the embedded Ed25519 signature against the embedded public key — no
network, no ledger, no source access required.
```bash
lean-ctx savings verify-batch ./sprint-savings.json
```
```text
Signed savings batch: VALID
Signed by: 7b1e90…c4d2
Agent: local
Created: 2026-06-02T18:45:00Z
lean-ctx: 3.7.0
Net saved: 12.8M tokens (~$32.41) over 1,240 event(s)
Chain head: 9f2c4b…e1a7
```
Any post-signing edit (totals, public key, chain head) fails:
```text
Signed savings batch: INVALID — signature does not match payload (tampered or wrong key)
```
A valid result proves two things at once:
- **Integrity** — not a byte altered since signing (the signature covers the whole payload).
- **Origin** — produced by the holder of that keypair. Pair the public key with your name
once and every future artifact from that key is attributable to you.
---
## 5. When to use it
- Justify the tool to a lead or finance with a signed dollar figure.
- Bill or report savings to a client; they verify the attestation themselves.
- Procurement / compliance evidence trails (tamper-evident, version-stamped).
- A personal, verifiable record snapshotted each quarter.
On-site deep dive: `/docs/concepts/savings-ledger` · journey page: `/docs/journeys/signed-savings-ledger`.