notebooks + README: wire the teaching stack to the newest edge

Audit: are the zero-to-hero notebooks current and macOS-runnable, and
does the README present the new teaching surfaces and CLI well?

Verified by execution: all 14 notebooks run headlessly cell-by-cell,
offline, pure-Python (zero shell magics), degrading gracefully where
Lean/built binaries are absent — before AND after these edits. That is
also the macOS answer: no GNU userland is touched by any cell.

Gaps found and closed:
- README's notebook list stopped at 10; notebook 11 (the customer's
  eye view) now listed.
- No notebook knew the cockpit era existed. Three pointer cells added:
  00 (course map: the three-track teaching stack — notebooks = code
  track, lab manual = role track, guide = reference), 10 (see the
  wallet you built through the cockpit; --demo and --wallet forms),
  11 (the Inspect instrument is this notebook's recomputation, живой).
- README: cockpit command block now shows --demo, --wallet, --port/
  --host variants; curriculum section names the teaching stack and the
  notebooks' offline/runnable contract.

Suite 144 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
mrwulf 2026-07-21 18:15:57 +02:00
parent 37429335e6
commit aff1c32fc5
4 changed files with 799 additions and 735 deletions

View file

@ -97,8 +97,10 @@ PyYAML is optional. Without it, `pacta` can still read the included simple YAML
```bash
python -m pacta --help
pacta wallet cockpit --demo # the human surface: bridge, deck, lab manual
pacta wallet status --wallet DIR # custody posture from the CLI
pacta wallet cockpit --demo # human surface from zero: bridge /deck /manual /guide
pacta wallet cockpit --wallet DIR # same cockpit over a real wallet (default port 8471)
pacta wallet cockpit --wallet DIR --port 9000 # --host/--port to taste; localhost-only by design
pacta wallet status --wallet DIR # custody posture from the CLI
pacta scan --config examples/repos.yaml
pacta doctor --config examples/repos.yaml --repo-name dalek-ed25519-verified
pacta claims --config examples/repos.yaml --repo-name dalek-ed25519-verified --offline-fixture --out claims.yaml
@ -129,9 +131,19 @@ The `notebooks/` directory contains a zero-to-hero teaching sequence for undergr
- `08_capstone_research_program.ipynb`: audit the shipped R4 evidence; design the R5 discharge plan.
- `09_dogfood_verified_crypto.ipynb`: the proven-path verifier in the agent's own loop; hybrid-PQC posture.
- `10_verified_custody_wallet.ipynb`: warden - the quorum custody boundary and signing firewall, ratchet-rule (toy 3-of-3, then the real four proven forks), plus the counterparty recomputing a custody card's inclusion proof.
- `11_the_customers_eye_view.ipynb`: the counterparty's seat - what a customer can and cannot recompute about someone else's wallet from its custody card and the public log.
The course states and keeps a "ratchet rule": every load-bearing idea runs twice - napkin scale, then real scale - and every pair is executable in the notebook.
The notebooks are the **code-level track** of a three-part teaching stack;
the **role-level track** is the [lab manual](docs/warden-lab-manual.md)
(served at `/manual` in the cockpit: sessions, drills, self-tests, a
capstone incident across all six roles), and the in-cockpit **Guide**
(`/guide`) is the plain-language reference both lean on. All fourteen
notebooks execute offline, top to bottom, with pure-Python cells (no
shell magics), degrading gracefully where Lean or built binaries are
absent.
The notebooks are committed without execution output. They can be opened in Jupyter, VS Code, or any notebook reader. They import `pacta` directly from this repository and avoid external notebook-only dependencies.
## Consequence Engine

View file

@ -1,168 +1,188 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# PACTA Curriculum: From Zero to Hero\n",
"\n",
"This curriculum teaches proof-aware cryptographic tooling from first principles to a research-grade professional workflow. It is designed for undergraduate students who know some programming and discrete math, but have not yet worked with formal verification, Lean, certificate transparency, or autonomous-agent risk gates.\n",
"\n",
"The practical anchor is PACTA: Proof-Aware Crypto Tooling Agent. The goal is not to build a trading bot. The goal is to teach an agent, and the engineer supervising it, to ask:\n",
"\n",
"> Does this theorem cover the exact code path that will protect funds?\n",
"\n",
"The course takes that question seriously. Every notebook connects theory to a runnable artifact in this repository.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Learning Objectives\n",
"\n",
"By the end of the sequence, a strong student should be able to:\n",
"\n",
"- Explain why cryptographic implementation proofs have theorem boundaries.\n",
"- Distinguish formal proof evidence from tests, audits, marketing claims, and operational controls.\n",
"- Read a PACTA claim card and understand its guarantees, preconditions, exclusions, trusted base, and risk level.\n",
"- Reproduce a local Lean replay or diagnose why local replay is unavailable.\n",
"- Perform a proof hygiene scan and explain why `sorry`, local axioms, and trivial theorem targets are dangerous.\n",
"- Explain how a third-party proof-checking provider changes the trusted base.\n",
"- Implement and verify RFC 9162-style Merkle inclusion and consistency proofs.\n",
"- Explain why Signed Tree Heads need accountable signatures, why Ed25519 is useful here, and why ML-DSA requires a real backend.\n",
"- Design policy gates that convert verification evidence into consequences.\n",
"- Read R4 four-tier apex evidence, name its residual blockers, and write a research plan toward R5 production assurance.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Prerequisites\n",
"\n",
"Recommended background:\n",
"\n",
"- Python basics: functions, dictionaries, lists, files, subprocesses.\n",
"- Discrete math: modular arithmetic, induction, trees, hashes.\n",
"- Basic cryptography vocabulary: public keys, signatures, hashes, finite fields.\n",
"- Basic command-line usage on macOS or Linux.\n",
"\n",
"Not required at the start:\n",
"\n",
"- Lean.\n",
"- Rust internals.\n",
"- Elliptic curve implementation expertise.\n",
"- Certificate transparency expertise.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"import sys\n",
"\n",
"repo_root = Path.cwd()\n",
"if not (repo_root / \"src\" / \"pacta\").exists():\n",
" repo_root = repo_root.parent\n",
"sys.path.insert(0, str(repo_root / \"src\"))\n",
"\n",
"print(repo_root)\n",
"print((repo_root / \"README.md\").exists())\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Course Map\n",
"\n",
"1. `01_threat_model_and_truth_boundary.ipynb`\n",
" Learn the product problem, the security boundary, and the difference between verified arithmetic and verified wallets.\n",
"\n",
"2. `02_claim_cards_and_risk_model.ipynb`\n",
" Study PACTA claim cards, risk levels R0-R5, and how claim serialization supports machine decisions.\n",
"\n",
"3. `03_lean_replay_and_axiom_audit.ipynb`\n",
" Learn how local Lean replay works, why PACTA avoids transpilation, and what an axiom audit proves.\n",
"\n",
"4. `04_proof_hygiene_and_boundaries.ipynb`\n",
" Learn to scan proof artifacts for `sorry`, local `axiom`, trivial theorem statements, and missing manifest coverage.\n",
"\n",
"5. `05_third_party_attestation_provider.ipynb`\n",
" Learn how a proof-checking service can transform hard local verification into provider trust.\n",
"\n",
"6. `06_merkle_transparency_logs.ipynb`, then the MIRRORED PAIR\n",
" `06a_provider_build_the_log.ipynb` / `06b_agent_verify_inclusion.ipynb`\n",
"\n",
" The trust architecture has exactly two domains - ONE provider\n",
" who builds and signs the authenticated structure (and pays the\n",
" Lean bill), MANY agents who verify inclusion proofs in\n",
" milliseconds. The course mirrors that split structurally: 6a is\n",
" written entirely in the provider's voice, 6b entirely in the\n",
" agent's. If you cannot say which notebook a step belongs to,\n",
" you have not understood the step.\n",
" Build the Merkle accumulator intuition behind inclusion proofs, consistency proofs, and Signed Tree Heads.\n",
"\n",
"7. `07_agent_consequences.ipynb`\n",
" Connect evidence to action: build a lower-layer Rust capsule only when policy gates pass.\n",
"\n",
"8. `08_capstone_research_program.ipynb`\n",
" Design a PhD-level roadmap for closing the gaps from R4 toward R5.\n",
"\n",
"9. `09_dogfood_verified_crypto.ipynb`\n",
"\n",
" Eat your own dogfood: run the agent's own signature checks through the proven code path, and hold the post-quantum line honestly.\n",
"\n",
"## The Ratchet Rule\n",
"\n",
"This course follows the same didactic contract as its companion book (*Verifying Cryptography with Lean 4*): **every load-bearing idea is worked at least twice** - once at napkin scale (trees of three leaves, toy claim cards you can score in your head) and once at real scale (the shipped R4 claim cards, real receipts, the real proven-path verifier), with nothing hidden in between. The napkin run teaches the moves; the real-size run proves the moves are the whole story. If a step ever feels like a leap, back up one cell: the smaller rung is there.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Assessment Model\n",
"\n",
"Each notebook contains:\n",
"\n",
"- A lecture section for concepts.\n",
"- A lab section with runnable code.\n",
"- Checkpoints that force precise answers.\n",
"- Exercises for mastery.\n",
"- Research prompts for advanced students.\n",
"\n",
"The capstone asks students to produce a defensible assurance case, not a slogan.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## References\n",
"\n",
"- RFC 9162, Certificate Transparency Version 2.0: https://datatracker.ietf.org/doc/html/rfc9162\n",
"- RFC 8032, Edwards-Curve Digital Signature Algorithm: https://datatracker.ietf.org/doc/html/rfc8032\n",
"- NIST FIPS 204, Module-Lattice-Based Digital Signature Standard: https://csrc.nist.gov/pubs/fips/204/final\n",
"- PACTA README: `../README.md`\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# PACTA Curriculum: From Zero to Hero\n",
"\n",
"This curriculum teaches proof-aware cryptographic tooling from first principles to a research-grade professional workflow. It is designed for undergraduate students who know some programming and discrete math, but have not yet worked with formal verification, Lean, certificate transparency, or autonomous-agent risk gates.\n",
"\n",
"The practical anchor is PACTA: Proof-Aware Crypto Tooling Agent. The goal is not to build a trading bot. The goal is to teach an agent, and the engineer supervising it, to ask:\n",
"\n",
"> Does this theorem cover the exact code path that will protect funds?\n",
"\n",
"The course takes that question seriously. Every notebook connects theory to a runnable artifact in this repository.\n"
]
},
"nbformat": 4,
"nbformat_minor": 5
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Learning Objectives\n",
"\n",
"By the end of the sequence, a strong student should be able to:\n",
"\n",
"- Explain why cryptographic implementation proofs have theorem boundaries.\n",
"- Distinguish formal proof evidence from tests, audits, marketing claims, and operational controls.\n",
"- Read a PACTA claim card and understand its guarantees, preconditions, exclusions, trusted base, and risk level.\n",
"- Reproduce a local Lean replay or diagnose why local replay is unavailable.\n",
"- Perform a proof hygiene scan and explain why `sorry`, local axioms, and trivial theorem targets are dangerous.\n",
"- Explain how a third-party proof-checking provider changes the trusted base.\n",
"- Implement and verify RFC 9162-style Merkle inclusion and consistency proofs.\n",
"- Explain why Signed Tree Heads need accountable signatures, why Ed25519 is useful here, and why ML-DSA requires a real backend.\n",
"- Design policy gates that convert verification evidence into consequences.\n",
"- Read R4 four-tier apex evidence, name its residual blockers, and write a research plan toward R5 production assurance.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Prerequisites\n",
"\n",
"Recommended background:\n",
"\n",
"- Python basics: functions, dictionaries, lists, files, subprocesses.\n",
"- Discrete math: modular arithmetic, induction, trees, hashes.\n",
"- Basic cryptography vocabulary: public keys, signatures, hashes, finite fields.\n",
"- Basic command-line usage on macOS or Linux.\n",
"\n",
"Not required at the start:\n",
"\n",
"- Lean.\n",
"- Rust internals.\n",
"- Elliptic curve implementation expertise.\n",
"- Certificate transparency expertise.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"import sys\n",
"\n",
"repo_root = Path.cwd()\n",
"if not (repo_root / \"src\" / \"pacta\").exists():\n",
" repo_root = repo_root.parent\n",
"sys.path.insert(0, str(repo_root / \"src\"))\n",
"\n",
"print(repo_root)\n",
"print((repo_root / \"README.md\").exists())\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Course Map\n",
"\n",
"1. `01_threat_model_and_truth_boundary.ipynb`\n",
" Learn the product problem, the security boundary, and the difference between verified arithmetic and verified wallets.\n",
"\n",
"2. `02_claim_cards_and_risk_model.ipynb`\n",
" Study PACTA claim cards, risk levels R0-R5, and how claim serialization supports machine decisions.\n",
"\n",
"3. `03_lean_replay_and_axiom_audit.ipynb`\n",
" Learn how local Lean replay works, why PACTA avoids transpilation, and what an axiom audit proves.\n",
"\n",
"4. `04_proof_hygiene_and_boundaries.ipynb`\n",
" Learn to scan proof artifacts for `sorry`, local `axiom`, trivial theorem statements, and missing manifest coverage.\n",
"\n",
"5. `05_third_party_attestation_provider.ipynb`\n",
" Learn how a proof-checking service can transform hard local verification into provider trust.\n",
"\n",
"6. `06_merkle_transparency_logs.ipynb`, then the MIRRORED PAIR\n",
" `06a_provider_build_the_log.ipynb` / `06b_agent_verify_inclusion.ipynb`\n",
"\n",
" The trust architecture has exactly two domains - ONE provider\n",
" who builds and signs the authenticated structure (and pays the\n",
" Lean bill), MANY agents who verify inclusion proofs in\n",
" milliseconds. The course mirrors that split structurally: 6a is\n",
" written entirely in the provider's voice, 6b entirely in the\n",
" agent's. If you cannot say which notebook a step belongs to,\n",
" you have not understood the step.\n",
" Build the Merkle accumulator intuition behind inclusion proofs, consistency proofs, and Signed Tree Heads.\n",
"\n",
"7. `07_agent_consequences.ipynb`\n",
" Connect evidence to action: build a lower-layer Rust capsule only when policy gates pass.\n",
"\n",
"8. `08_capstone_research_program.ipynb`\n",
" Design a PhD-level roadmap for closing the gaps from R4 toward R5.\n",
"\n",
"9. `09_dogfood_verified_crypto.ipynb`\n",
"\n",
" Eat your own dogfood: run the agent's own signature checks through the proven code path, and hold the post-quantum line honestly.\n",
"\n",
"## The Ratchet Rule\n",
"\n",
"This course follows the same didactic contract as its companion book (*Verifying Cryptography with Lean 4*): **every load-bearing idea is worked at least twice** - once at napkin scale (trees of three leaves, toy claim cards you can score in your head) and once at real scale (the shipped R4 claim cards, real receipts, the real proven-path verifier), with nothing hidden in between. The napkin run teaches the moves; the real-size run proves the moves are the whole story. If a step ever feels like a leap, back up one cell: the smaller rung is there.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Assessment Model\n",
"\n",
"Each notebook contains:\n",
"\n",
"- A lecture section for concepts.\n",
"- A lab section with runnable code.\n",
"- Checkpoints that force precise answers.\n",
"- Exercises for mastery.\n",
"- Research prompts for advanced students.\n",
"\n",
"The capstone asks students to produce a defensible assurance case, not a slogan.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## References\n",
"\n",
"- RFC 9162, Certificate Transparency Version 2.0: https://datatracker.ietf.org/doc/html/rfc9162\n",
"- RFC 8032, Edwards-Curve Digital Signature Algorithm: https://datatracker.ietf.org/doc/html/rfc8032\n",
"- NIST FIPS 204, Module-Lattice-Based Digital Signature Standard: https://csrc.nist.gov/pubs/fips/204/final\n",
"- PACTA README: `../README.md`\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The course's operational twin: the cockpit and the lab manual\n",
"\n",
"These notebooks are the *code-level* track: you build the machinery with your own hands.\n",
"Two sibling surfaces teach the *operational* track on the very same system:\n",
"\n",
"- **The custody cockpit** — `pacta wallet cockpit --demo` serves a read-only bridge of six\n",
" role stations (proposer, quorum bench, operator, cryptographer, architect, newcomer) over\n",
" live evidence, with a tmux-style deck (`/deck`) showing every station in parallel.\n",
"- **The lab manual** (`docs/warden-lab-manual.md`, served at `/manual`) — a study-club course\n",
" that teaches each *role* hands-on: labs with checkpoints, a safe ledger-tamper drill,\n",
" self-tests, and a capstone incident walked through all six chairs.\n",
"\n",
"Recommended weave: notebooks 0009 first (build it), then the lab manual (run it as a crew),\n",
"with notebook 10 and the manual's warden sessions read side by side."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View file

@ -1,345 +1,364 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Lecture 10: The Verified-Custody Wallet (warden)\n",
"\n",
"Everything so far *decided* which cryptographic code to trust.\n",
"This lecture *acts* on the decision: we build a custody boundary\n",
"out of the four proven curve25519-dalek forks and use it to\n",
"guard signatures - inbound and outbound.\n",
"\n",
"The one idea: **inbound acceptance requires a unanimous quorum of\n",
"provably-equivalent verifiers, and every outbound signature must\n",
"pass the same quorum before it is released.**\n",
"\n",
"We keep the course's ratchet rule: every load-bearing idea runs\n",
"twice - napkin scale by hand, then real scale against the live\n",
"system - and both are executable here.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Learning Objectives\n",
"\n",
"- Explain why a *unanimous* quorum of provably-equivalent\n",
" verifiers turns disagreement into evidence of a fault, and why\n",
" majority voting would hide exactly that fault.\n",
"- Classify a quorum divergence as a documented semantic edge\n",
" (note) versus unexplained (tamper -> latch).\n",
"- Describe the outbound signing firewall as verify-after-sign\n",
" with a proven verifier, and state warden's honest asymmetry\n",
" (verify custody-grade, sign trusted base).\n",
"- Recompute a custody card's inclusion proof as a counterparty -\n",
" trust by recomputation, not by assertion.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Why a quorum, when one proof would do?\n",
"\n",
"Each member is *proven* to decide the same predicate,\n",
"`accept(A,m,R,s) \u21d4 decompress(R) = [k](\u2212A) + [s]B`. So on the\n",
"proven domain they cannot disagree about *meaning*. Classic\n",
"N-version programming hopes independent code won't share a bug;\n",
"we do not hope - we know the semantics coincide, so a runtime\n",
"disagreement is not opinion, it is **evidence of a fault**: a\n",
"corrupted build, a memory error, or tampering. The quorum turns\n",
"\"the verifiers differed\" into an alarm with a theorem behind it.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Napkin scale: a 3-of-3 quorum with toy verifiers\n",
"\n",
"Forget real curves for a moment. Model three verifiers as\n",
"functions and watch the boundary logic: unanimity accepts,\n",
"any disagreement fails closed and is classified.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def toy_quorum(verdicts):\n",
" kinds = set(verdicts.values())\n",
" if kinds == {\"accept\"}:\n",
" return \"unanimous-accept\", True\n",
" if kinds == {\"reject\"}:\n",
" return \"unanimous-reject\", False\n",
" return \"divergence -> FAIL CLOSED + incident\", False\n",
"\n",
"print(toy_quorum({\"dalek\": \"accept\", \"anza\": \"accept\", \"risc0\": \"accept\"}))\n",
"print(toy_quorum({\"dalek\": \"reject\", \"anza\": \"reject\", \"risc0\": \"reject\"}))\n",
"print(toy_quorum({\"dalek\": \"accept\", \"anza\": \"reject\", \"risc0\": \"accept\"}))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The third line is the whole point: a lone dissenter does not get\n",
"out-voted. Acceptance needs *everyone*; anything else is a\n",
"refusal plus a recorded incident. Majority voting would hide\n",
"exactly the fault we most want to see.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The divergence taxonomy\n",
"\n",
"The forks are *allowed* to differ on documented degenerate\n",
"inputs (anza rejects `A = 0` and a legacy excluded-small-order-R\n",
"list). We still fail closed; the taxonomy only grades the alarm:\n",
"\n",
"- **semantic-edge** - they differ AND a documented edge flag\n",
" applies (small-order R, non-canonical s, zero key): severity\n",
" *note*.\n",
"- **unexplained** - they differ with no documented reason, or a\n",
" member errored: severity *tamper* -> custody **latches**.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys, pathlib\n",
"for parent in [pathlib.Path.cwd(), *pathlib.Path.cwd().parents]:\n",
" if (parent / \"src\" / \"pacta\").exists():\n",
" sys.path.insert(0, str(parent / \"src\")); ROOT = parent; break\n",
"\n",
"from pacta.quorum import semantic_edge_flags, SMALL_ORDER_ENCODINGS\n",
"\n",
"small_order_R = sorted(SMALL_ORDER_ENCODINGS)[0]\n",
"print(\"edge flags for a small-order R:\",\n",
" semantic_edge_flags(b\"\\x02\" * 32, small_order_R + b\"\\x00\" * 32))\n",
"print(\"edge flags for an ordinary sig:\",\n",
" semantic_edge_flags(b\"\\x02\" * 32, b\"\\x01\" * 64))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A divergence on the first input is a documented edge (note); a\n",
"divergence on the second has no excuse (tamper). Same fail-closed\n",
"verdict, very different alarm.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Real scale: the four proven forks, if built\n",
"\n",
"If you have run `pacta wallet build-quorum`, the next cell drives\n",
"the **real** four-fork quorum: sign a payload with the dogfood\n",
"(attested) signer, then watch all four proven verifiers agree on\n",
"accept, and on reject for a flipped byte. If the binaries are not\n",
"built, we say so and skip - honestly, the way the wallet itself\n",
"fails closed.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pacta.quorum import load_quorum, binary_path\n",
"\n",
"built = [b for b in (\"dalek\", \"anza\", \"risc0\", \"betrusted\") if binary_path(b).exists()]\n",
"if len(built) < 2:\n",
" print(\"quorum not built (need >=2). Run: pacta wallet build-quorum --sources-root <...>\")\n",
"else:\n",
" import tempfile, os\n",
" from pacta.dogfood import locate_verifier, pem_public_key_to_raw, sign_payload_dogfood\n",
" from pacta.signing import generate_ed25519_keypair\n",
" v = locate_verifier()\n",
" if v is None:\n",
" print(\"dogfood signer not built; run pacta dogfood-build\")\n",
" else:\n",
" d = tempfile.mkdtemp()\n",
" key, pub = os.path.join(d, \"k.pem\"), os.path.join(d, \"k.pub\")\n",
" generate_ed25519_keypair(key, pub)\n",
" payload = b\"curriculum lecture 10 payload\"\n",
" sig = sign_payload_dogfood(payload, key, v)\n",
" pk = pem_public_key_to_raw(pub)\n",
" q = load_quorum(min_members=2)\n",
" print(\"members:\", sorted(q.members))\n",
" good = q.verify(payload, sig, pk)\n",
" print(\"valid signature ->\", good.classification, \"accepted =\", good.accepted)\n",
" bad = q.verify(payload, bytes([sig[0] ^ 0xFF]) + sig[1:], pk)\n",
" print(\"one flipped byte ->\", bad.classification, \"accepted =\", bad.accepted)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The signing firewall: verify-after-sign, but proven\n",
"\n",
"Outbound is `intent -> sign -> firewall -> release`. The fresh\n",
"signature faces the same quorum; only unanimity releases it. A\n",
"rejected self-signature is *quarantined, never returned*, and\n",
"custody latches. This is the textbook fault-injection\n",
"countermeasure - verify a signer's output before trusting it -\n",
"with the verifier upgraded to machine-checked code.\n",
"\n",
"Note the honest asymmetry: the *verify* paths are certificate-\n",
"covered (custody-grade), but the *signing* step is trusted base -\n",
"the attested artifact, not a third implementation. The firewall\n",
"is exactly how we fence that weaker edge.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Two voices, one boundary (the domain split, again)\n",
"\n",
"Lecture 06 split provider and agent. warden inherits the split:\n",
"\n",
"- **The operator voice** seals the capsule: it runs the R4 gate,\n",
" pins the attested source commits, and stores the transparency-\n",
" log receipts that authorized each member.\n",
"- **The counterparty (agent) voice** never trusts the operator's\n",
" adjectives. It reads the *custody card* and recomputes the\n",
" inclusion proofs itself - trust by recomputation.\n",
"\n",
"The next cell is the counterparty side: given a card, verify a\n",
"member's inclusion proof with nothing but stdlib hashing.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Counterparty-side check of ONE member's inclusion proof.\n",
"# (Works whenever you have a wallet + its fetched evidence; here\n",
"# we show the primitive the card relies on.)\n",
"from pacta.transparency import verify_inclusion, leaf_bytes_for_attestation\n",
"import json, glob\n",
"\n",
"ev = sorted(glob.glob(str(ROOT / \"examples\" / \"wallet-evidence\" / \"*.attestation.json\")))\n",
"if not ev:\n",
" print(\"no bundled evidence; fetch with `pacta log-fetch` to try live\")\n",
"else:\n",
" att = json.load(open(ev[0]))\n",
" rec = json.load(open(ev[0].replace(\".attestation.\", \".receipt.\")))\n",
" ok = verify_inclusion(\n",
" leaf_bytes_for_attestation(att),\n",
" rec[\"leaf_index\"], rec[\"tree_size\"],\n",
" [bytes.fromhex(h) for h in rec[\"inclusion_proof\"]],\n",
" bytes.fromhex(rec[\"sth\"][\"root_hash\"]),\n",
" )\n",
" print(f\"{att['subject']['component']}: inclusion recomputes ->\", ok)\n",
" print(\"The counterparty believed no adjective; it recomputed a Merkle root.\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Corrupt a member, watch the pin catch it (executable)\n",
"\n",
"The wallet seals each member's SHA-256 into its capsule. The\n",
"next cell stages a COPY of a real member binary in a temp\n",
"directory, \"seals\" its hash the way the capsule does, appends\n",
"one byte (a supply-chain attack in miniature), and re-checks.\n",
"Nothing on your machine is modified.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import hashlib, shutil, tempfile, pathlib\n",
"from pacta.quorum import binary_path\n",
"\n",
"member = binary_path(\"dalek\")\n",
"if not member.exists():\n",
" print(\"quorum not built; run pacta wallet build-quorum first\")\n",
"else:\n",
" stage = pathlib.Path(tempfile.mkdtemp()) / member.name\n",
" shutil.copy2(member, stage)\n",
" sealed = hashlib.sha256(stage.read_bytes()).hexdigest() # capsule pin\n",
" print(\"sealed :\", sealed[:24], \"...\")\n",
" with stage.open(\"ab\") as f:\n",
" f.write(b\"\\x00\") # the attack\n",
" current = hashlib.sha256(stage.read_bytes()).hexdigest()\n",
" print(\"current:\", current[:24], \"...\")\n",
" if current != sealed:\n",
" print(\"PIN CAUGHT IT: wallet.quorum() would refuse to assemble ->\")\n",
" print(\" 'quorum member dalek binary hash changed since the capsule was sealed'\")\n",
" else:\n",
" print(\"impossible: SHA-256 collision\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One appended byte and the wallet refuses to even *assemble* the\n",
"quorum - before any verification runs. Note what this control\n",
"is and is not: it stops binary substitution *between* wallet\n",
"sessions; an attacker with live root outranks it (see\n",
"docs/threat-model.md, attacker #7 - that is what the choir and\n",
"the airgap profiles are for).\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercises\n",
"\n",
"- Change `toy_quorum` to majority voting and write two sentences\n",
" on exactly which attack that lets through.\n",
"- Extend the corrupt-a-member cell: corrupt the capsule JSON\n",
" itself instead of the binary. What catches that, and when?\n",
" (Hint: nothing does until the ledger genesis is compared -\n",
" write down the exact trust statement the capsule hash in the\n",
" genesis entry provides.)\n",
"- The signing path is trusted base. Write the strongest *true*\n",
" sentence you can about warden's outbound safety, and the\n",
" strongest *false* one a marketer would write - and name the\n",
" word that makes the second one false.\n",
"- Design `warden-treasury`: which member re-verifies Solana\n",
" transactions, and what exactly the RPC provider is still\n",
" trusted for after you do.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Lecture 10: The Verified-Custody Wallet (warden)\n",
"\n",
"Everything so far *decided* which cryptographic code to trust.\n",
"This lecture *acts* on the decision: we build a custody boundary\n",
"out of the four proven curve25519-dalek forks and use it to\n",
"guard signatures - inbound and outbound.\n",
"\n",
"The one idea: **inbound acceptance requires a unanimous quorum of\n",
"provably-equivalent verifiers, and every outbound signature must\n",
"pass the same quorum before it is released.**\n",
"\n",
"We keep the course's ratchet rule: every load-bearing idea runs\n",
"twice - napkin scale by hand, then real scale against the live\n",
"system - and both are executable here.\n"
]
},
"nbformat": 4,
"nbformat_minor": 5
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Learning Objectives\n",
"\n",
"- Explain why a *unanimous* quorum of provably-equivalent\n",
" verifiers turns disagreement into evidence of a fault, and why\n",
" majority voting would hide exactly that fault.\n",
"- Classify a quorum divergence as a documented semantic edge\n",
" (note) versus unexplained (tamper -> latch).\n",
"- Describe the outbound signing firewall as verify-after-sign\n",
" with a proven verifier, and state warden's honest asymmetry\n",
" (verify custody-grade, sign trusted base).\n",
"- Recompute a custody card's inclusion proof as a counterparty -\n",
" trust by recomputation, not by assertion.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Why a quorum, when one proof would do?\n",
"\n",
"Each member is *proven* to decide the same predicate,\n",
"`accept(A,m,R,s) ⇔ decompress(R) = [k](A) + [s]B`. So on the\n",
"proven domain they cannot disagree about *meaning*. Classic\n",
"N-version programming hopes independent code won't share a bug;\n",
"we do not hope - we know the semantics coincide, so a runtime\n",
"disagreement is not opinion, it is **evidence of a fault**: a\n",
"corrupted build, a memory error, or tampering. The quorum turns\n",
"\"the verifiers differed\" into an alarm with a theorem behind it.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Napkin scale: a 3-of-3 quorum with toy verifiers\n",
"\n",
"Forget real curves for a moment. Model three verifiers as\n",
"functions and watch the boundary logic: unanimity accepts,\n",
"any disagreement fails closed and is classified.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def toy_quorum(verdicts):\n",
" kinds = set(verdicts.values())\n",
" if kinds == {\"accept\"}:\n",
" return \"unanimous-accept\", True\n",
" if kinds == {\"reject\"}:\n",
" return \"unanimous-reject\", False\n",
" return \"divergence -> FAIL CLOSED + incident\", False\n",
"\n",
"print(toy_quorum({\"dalek\": \"accept\", \"anza\": \"accept\", \"risc0\": \"accept\"}))\n",
"print(toy_quorum({\"dalek\": \"reject\", \"anza\": \"reject\", \"risc0\": \"reject\"}))\n",
"print(toy_quorum({\"dalek\": \"accept\", \"anza\": \"reject\", \"risc0\": \"accept\"}))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The third line is the whole point: a lone dissenter does not get\n",
"out-voted. Acceptance needs *everyone*; anything else is a\n",
"refusal plus a recorded incident. Majority voting would hide\n",
"exactly the fault we most want to see.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The divergence taxonomy\n",
"\n",
"The forks are *allowed* to differ on documented degenerate\n",
"inputs (anza rejects `A = 0` and a legacy excluded-small-order-R\n",
"list). We still fail closed; the taxonomy only grades the alarm:\n",
"\n",
"- **semantic-edge** - they differ AND a documented edge flag\n",
" applies (small-order R, non-canonical s, zero key): severity\n",
" *note*.\n",
"- **unexplained** - they differ with no documented reason, or a\n",
" member errored: severity *tamper* -> custody **latches**.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys, pathlib\n",
"for parent in [pathlib.Path.cwd(), *pathlib.Path.cwd().parents]:\n",
" if (parent / \"src\" / \"pacta\").exists():\n",
" sys.path.insert(0, str(parent / \"src\")); ROOT = parent; break\n",
"\n",
"from pacta.quorum import semantic_edge_flags, SMALL_ORDER_ENCODINGS\n",
"\n",
"small_order_R = sorted(SMALL_ORDER_ENCODINGS)[0]\n",
"print(\"edge flags for a small-order R:\",\n",
" semantic_edge_flags(b\"\\x02\" * 32, small_order_R + b\"\\x00\" * 32))\n",
"print(\"edge flags for an ordinary sig:\",\n",
" semantic_edge_flags(b\"\\x02\" * 32, b\"\\x01\" * 64))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A divergence on the first input is a documented edge (note); a\n",
"divergence on the second has no excuse (tamper). Same fail-closed\n",
"verdict, very different alarm.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Real scale: the four proven forks, if built\n",
"\n",
"If you have run `pacta wallet build-quorum`, the next cell drives\n",
"the **real** four-fork quorum: sign a payload with the dogfood\n",
"(attested) signer, then watch all four proven verifiers agree on\n",
"accept, and on reject for a flipped byte. If the binaries are not\n",
"built, we say so and skip - honestly, the way the wallet itself\n",
"fails closed.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pacta.quorum import load_quorum, binary_path\n",
"\n",
"built = [b for b in (\"dalek\", \"anza\", \"risc0\", \"betrusted\") if binary_path(b).exists()]\n",
"if len(built) < 2:\n",
" print(\"quorum not built (need >=2). Run: pacta wallet build-quorum --sources-root <...>\")\n",
"else:\n",
" import tempfile, os\n",
" from pacta.dogfood import locate_verifier, pem_public_key_to_raw, sign_payload_dogfood\n",
" from pacta.signing import generate_ed25519_keypair\n",
" v = locate_verifier()\n",
" if v is None:\n",
" print(\"dogfood signer not built; run pacta dogfood-build\")\n",
" else:\n",
" d = tempfile.mkdtemp()\n",
" key, pub = os.path.join(d, \"k.pem\"), os.path.join(d, \"k.pub\")\n",
" generate_ed25519_keypair(key, pub)\n",
" payload = b\"curriculum lecture 10 payload\"\n",
" sig = sign_payload_dogfood(payload, key, v)\n",
" pk = pem_public_key_to_raw(pub)\n",
" q = load_quorum(min_members=2)\n",
" print(\"members:\", sorted(q.members))\n",
" good = q.verify(payload, sig, pk)\n",
" print(\"valid signature ->\", good.classification, \"accepted =\", good.accepted)\n",
" bad = q.verify(payload, bytes([sig[0] ^ 0xFF]) + sig[1:], pk)\n",
" print(\"one flipped byte ->\", bad.classification, \"accepted =\", bad.accepted)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The signing firewall: verify-after-sign, but proven\n",
"\n",
"Outbound is `intent -> sign -> firewall -> release`. The fresh\n",
"signature faces the same quorum; only unanimity releases it. A\n",
"rejected self-signature is *quarantined, never returned*, and\n",
"custody latches. This is the textbook fault-injection\n",
"countermeasure - verify a signer's output before trusting it -\n",
"with the verifier upgraded to machine-checked code.\n",
"\n",
"Note the honest asymmetry: the *verify* paths are certificate-\n",
"covered (custody-grade), but the *signing* step is trusted base -\n",
"the attested artifact, not a third implementation. The firewall\n",
"is exactly how we fence that weaker edge.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Two voices, one boundary (the domain split, again)\n",
"\n",
"Lecture 06 split provider and agent. warden inherits the split:\n",
"\n",
"- **The operator voice** seals the capsule: it runs the R4 gate,\n",
" pins the attested source commits, and stores the transparency-\n",
" log receipts that authorized each member.\n",
"- **The counterparty (agent) voice** never trusts the operator's\n",
" adjectives. It reads the *custody card* and recomputes the\n",
" inclusion proofs itself - trust by recomputation.\n",
"\n",
"The next cell is the counterparty side: given a card, verify a\n",
"member's inclusion proof with nothing but stdlib hashing.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Counterparty-side check of ONE member's inclusion proof.\n",
"# (Works whenever you have a wallet + its fetched evidence; here\n",
"# we show the primitive the card relies on.)\n",
"from pacta.transparency import verify_inclusion, leaf_bytes_for_attestation\n",
"import json, glob\n",
"\n",
"ev = sorted(glob.glob(str(ROOT / \"examples\" / \"wallet-evidence\" / \"*.attestation.json\")))\n",
"if not ev:\n",
" print(\"no bundled evidence; fetch with `pacta log-fetch` to try live\")\n",
"else:\n",
" att = json.load(open(ev[0]))\n",
" rec = json.load(open(ev[0].replace(\".attestation.\", \".receipt.\")))\n",
" ok = verify_inclusion(\n",
" leaf_bytes_for_attestation(att),\n",
" rec[\"leaf_index\"], rec[\"tree_size\"],\n",
" [bytes.fromhex(h) for h in rec[\"inclusion_proof\"]],\n",
" bytes.fromhex(rec[\"sth\"][\"root_hash\"]),\n",
" )\n",
" print(f\"{att['subject']['component']}: inclusion recomputes ->\", ok)\n",
" print(\"The counterparty believed no adjective; it recomputed a Merkle root.\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Corrupt a member, watch the pin catch it (executable)\n",
"\n",
"The wallet seals each member's SHA-256 into its capsule. The\n",
"next cell stages a COPY of a real member binary in a temp\n",
"directory, \"seals\" its hash the way the capsule does, appends\n",
"one byte (a supply-chain attack in miniature), and re-checks.\n",
"Nothing on your machine is modified.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import hashlib, shutil, tempfile, pathlib\n",
"from pacta.quorum import binary_path\n",
"\n",
"member = binary_path(\"dalek\")\n",
"if not member.exists():\n",
" print(\"quorum not built; run pacta wallet build-quorum first\")\n",
"else:\n",
" stage = pathlib.Path(tempfile.mkdtemp()) / member.name\n",
" shutil.copy2(member, stage)\n",
" sealed = hashlib.sha256(stage.read_bytes()).hexdigest() # capsule pin\n",
" print(\"sealed :\", sealed[:24], \"...\")\n",
" with stage.open(\"ab\") as f:\n",
" f.write(b\"\\x00\") # the attack\n",
" current = hashlib.sha256(stage.read_bytes()).hexdigest()\n",
" print(\"current:\", current[:24], \"...\")\n",
" if current != sealed:\n",
" print(\"PIN CAUGHT IT: wallet.quorum() would refuse to assemble ->\")\n",
" print(\" 'quorum member dalek binary hash changed since the capsule was sealed'\")\n",
" else:\n",
" print(\"impossible: SHA-256 collision\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One appended byte and the wallet refuses to even *assemble* the\n",
"quorum - before any verification runs. Note what this control\n",
"is and is not: it stops binary substitution *between* wallet\n",
"sessions; an attacker with live root outranks it (see\n",
"docs/threat-model.md, attacker #7 - that is what the choir and\n",
"the airgap profiles are for).\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercises\n",
"\n",
"- Change `toy_quorum` to majority voting and write two sentences\n",
" on exactly which attack that lets through.\n",
"- Extend the corrupt-a-member cell: corrupt the capsule JSON\n",
" itself instead of the binary. What catches that, and when?\n",
" (Hint: nothing does until the ledger genesis is compared -\n",
" write down the exact trust statement the capsule hash in the\n",
" genesis entry provides.)\n",
"- The signing path is trusted base. Write the strongest *true*\n",
" sentence you can about warden's outbound safety, and the\n",
" strongest *false* one a marketer would write - and name the\n",
" word that makes the second one false.\n",
"- Design `warden-treasury`: which member re-verifies Solana\n",
" transactions, and what exactly the RPC provider is still\n",
" trusted for after you do.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The human surface: see this wallet through the cockpit\n",
"\n",
"Everything this notebook built programmatically has a read-only human console:\n",
"\n",
"```\n",
"pacta wallet cockpit --demo # throwaway demo wallet, zero setup\n",
"pacta wallet cockpit --wallet DIR # the wallet you just sealed here\n",
"```\n",
"\n",
"Open `/deck` for all six role stations live in parallel (the quorum bench you built is the\n",
"indigo pane; the ledger you hash-chained is re-verified on every page load), and `/manual`\n",
"for the lab-manual sessions that teach each role — Session 4's tamper drill breaks a *copy*\n",
"of a ledger exactly like this notebook's and watches two independent surfaces catch it."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View file

@ -1,229 +1,242 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Lecture 11: The Customer's-Eye View \u2014 You Hold the Ruler\n",
"\n",
"Every earlier lecture looked at the log from the *operator's*\n",
"side: replaying proofs, signing attestations, building the\n",
"tree. This one flips the telescope. You are now a customer \u2014 an\n",
"agent, a wallet, a developer \u2014 who wants to trust one of the\n",
"four verified Ed25519 forks and has no theorem prover, no Lean,\n",
"no desire to spend hours re-checking anything. What actually\n",
"happens on your side? The answer reframes the whole system, and\n",
"it is the most intuitive on-ramp to it.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Learning Objectives\n",
"\n",
"- Separate the three roles that a verification touches:\n",
" *measurement* (operator), *publication* (the log), and\n",
" *judgment* (you) \u2014 and see that only the last is yours.\n",
"- Understand the \"allowed axioms\" list as a **requirements\n",
" card** you own, can read, and could write yourself.\n",
"- Explain why a self-written card meeting the supply *exactly*\n",
" is engineered, not coincidental.\n",
"- State the three honest outcomes when your card is stricter\n",
" than the supply: relax (itemized), walk away, or grow the\n",
" supply.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The card is a requirements card \u2014 and ideally you write it\n",
"\n",
"The list of axioms a certificate is *allowed* to rest on is not\n",
"handed to you by the operator at verification time. It ships\n",
"inside your own tooling (the ed25519 profile), on your disk,\n",
"versioned by you. A maximally paranoid customer ignores the\n",
"shipped copy and writes the card from first principles:\n",
"\n",
"> *\"I accept Lean's three foundational axioms, because that is\n",
"> what the proof kernel's logic IS. For the signature-tier\n",
"> theorems I accept named placeholders for SHA-512 and the wire\n",
"> format, because RFC 8032 tells me those parts exist and I can\n",
"> see they are declared, not smuggled. Nothing else.\"*\n",
"\n",
"That is a wish-list: the assumptions you are willing to live\n",
"under. Call it your ruler.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys, pathlib\n",
"for parent in [pathlib.Path.cwd(), *pathlib.Path.cwd().parents]:\n",
" if (parent / \"src\" / \"pacta\").exists():\n",
" sys.path.insert(0, str(parent / \"src\")); break\n",
"\n",
"# A customer writes their OWN card, from first principles - no\n",
"# peeking at the operator. Lean's three, plus named oracle slots.\n",
"my_card = {\n",
" \"foundational\": {\"propext\", \"Classical.choice\", \"Quot.sound\"},\n",
" \"apex_oracle_allowed\": {\n",
" \"sha2.Sha512\", \"verifying.sha512_new\",\n",
" \"verifying.sha512_update\", \"verifying.sha512_finalize_bytes\",\n",
" \"ed25519.Signature\", \"ed25519.Signature.to_bytes\",\n",
" \"signature.error.Error\", \"signature.error.Error.new\",\n",
" },\n",
"}\n",
"print(\"my requirements card:\", sum(len(v) for v in my_card.values()), \"named assumptions\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Wish meets supply \u2014 and it is no accident\n",
"\n",
"Now compare your self-written card against what the four forks\n",
"actually declare. They match. That convergence is *engineered*:\n",
"the supply was deliberately shrunk \u2014 every axiom made to justify\n",
"its existence \u2014 so that any reasonable person's independently\n",
"written card lands on the same minimal list. When the wish meets\n",
"the supply exactly, it is because the supplier spent months\n",
"making the supply as small as honesty allows.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pacta.profiles.ed25519 import APEX_BOUNDARIES\n",
"\n",
"# The supply: the apex-tier certificate's documented, allowed\n",
"# axiom cone for the upstream fork - the exact set the strongest\n",
"# theorem is permitted to rest on, nothing more, nothing less.\n",
"supply = set(APEX_BOUNDARIES[\"dalek-wrappers\"])\n",
"wish = my_card[\"foundational\"] | my_card[\"apex_oracle_allowed\"]\n",
"print(\"supply == my wish:\", supply == wish)\n",
"print(\"axioms in supply my card did not anticipate:\", (supply - wish) or \"none\")\n",
"print(\"axioms my card wanted that are absent:\", (wish - supply) or \"none\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The three roles, kept apart\n",
"\n",
"It is tempting to say \"the inclusion proof proves the Lean proof\n",
"is about my card.\" It does not, and the precision matters:\n",
"\n",
"| role | who | what it establishes |\n",
"|---|---|---|\n",
"| measurement | operator's kernel run | \"this theorem rests on exactly these named axioms\" (recorded verbatim in the attestation) |\n",
"| publication | the transparency log | \"this measurement is in the permanent record, shown identically to everyone\" (the inclusion proof + signed head) |\n",
"| judgment | **you** | \"these observed axioms are inside my allowed card\" (re-derived locally, every time) |\n",
"\n",
"Only judgment is yours, and it is the only step that involves an\n",
"opinion. The operator is trusted to *copy down what the kernel\n",
"printed* \u2014 never to interpret it.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## If you are happy \u2014 you are already finished\n",
"\n",
"If your card covers the observed cone, verification is: check\n",
"one signature, walk ~4 hashes to the signed root, compare cones\n",
"to your card. Milliseconds, standard library, no Lean. Done.\n",
"\n",
"## If you are NOT happy \u2014 there is nothing to negotiate\n",
"\n",
"Suppose your card is stricter: *\"I require SHA-512 itself\n",
"proven, not an oracle.\"* The system has no sales pitch for you.\n",
"Its entire answer is an **itemized** statement of the gap:\n",
"*not in supply; SHA-512-proven is the R5 frontier; here is the\n",
"exact list of what you would be accepting if you proceed\n",
"anyway.* Your decision is never \"lower my standards\" in the\n",
"abstract \u2014 it is a named line item: *SHA-512 as oracle: yes/no.*\n",
"Informed compromise, not diffuse trust.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# The honest gap, itemized. A stricter customer wants no hash oracle.\n",
"strict_card = my_card[\"foundational\"] # foundational ONLY, no oracle slots\n",
"gap = supply - strict_card\n",
"print(\"this customer must explicitly accept, or walk away:\")\n",
"for ax in sorted(gap):\n",
" print(\" -\", ax)\n",
"print()\n",
"print(\"verdict for the strict card:\", \"PASSES\" if supply <= strict_card else \"REFUSED (gap above)\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The third option: grow the supply\n",
"\n",
"The gap between anyone's dream card and today's supply is a\n",
"to-do list, not a wall. Prove SHA-512, certify the wire\n",
"parsers, and the new certificates enter the same log \u2014 and\n",
"stricter cards start passing. The log is additive in exactly\n",
"the way requirements are.\n",
"\n",
"**So: you hold the ruler. If your ruler is stricter than our\n",
"supply, your ruler is our roadmap.** That is the quiet\n",
"invitation built into the whole design.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercises\n",
"\n",
"- Write your own requirements card for the *foundational*\n",
" (non-signature) certificates from scratch. Those certificates\n",
" are expected to carry exactly Lean's three standard axioms\n",
" (`propext`, `Classical.choice`, `Quot.sound`) and nothing\n",
" else - did your card guess exactly those three?\n",
"- A vendor's attestation says `status: proven`. Explain in two\n",
" sentences why your tooling ignores that field entirely, and\n",
" what it looks at instead.\n",
"- You require reproducible builds. Is that a card you can write\n",
" today and have pass? Name the tier that gap belongs to, and\n",
" what would have to enter the log to close it.\n",
"- Argue both sides: is \"wish meets supply exactly\" a strength\n",
" (minimal, auditable) or a weakness (the same author wrote the\n",
" card and the supply)? What single action by a customer\n",
" settles the argument in their favor?\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Lecture 11: The Customer's-Eye View — You Hold the Ruler\n",
"\n",
"Every earlier lecture looked at the log from the *operator's*\n",
"side: replaying proofs, signing attestations, building the\n",
"tree. This one flips the telescope. You are now a customer — an\n",
"agent, a wallet, a developer — who wants to trust one of the\n",
"four verified Ed25519 forks and has no theorem prover, no Lean,\n",
"no desire to spend hours re-checking anything. What actually\n",
"happens on your side? The answer reframes the whole system, and\n",
"it is the most intuitive on-ramp to it.\n"
]
},
"nbformat": 4,
"nbformat_minor": 5
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Learning Objectives\n",
"\n",
"- Separate the three roles that a verification touches:\n",
" *measurement* (operator), *publication* (the log), and\n",
" *judgment* (you) — and see that only the last is yours.\n",
"- Understand the \"allowed axioms\" list as a **requirements\n",
" card** you own, can read, and could write yourself.\n",
"- Explain why a self-written card meeting the supply *exactly*\n",
" is engineered, not coincidental.\n",
"- State the three honest outcomes when your card is stricter\n",
" than the supply: relax (itemized), walk away, or grow the\n",
" supply.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The card is a requirements card — and ideally you write it\n",
"\n",
"The list of axioms a certificate is *allowed* to rest on is not\n",
"handed to you by the operator at verification time. It ships\n",
"inside your own tooling (the ed25519 profile), on your disk,\n",
"versioned by you. A maximally paranoid customer ignores the\n",
"shipped copy and writes the card from first principles:\n",
"\n",
"> *\"I accept Lean's three foundational axioms, because that is\n",
"> what the proof kernel's logic IS. For the signature-tier\n",
"> theorems I accept named placeholders for SHA-512 and the wire\n",
"> format, because RFC 8032 tells me those parts exist and I can\n",
"> see they are declared, not smuggled. Nothing else.\"*\n",
"\n",
"That is a wish-list: the assumptions you are willing to live\n",
"under. Call it your ruler.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys, pathlib\n",
"for parent in [pathlib.Path.cwd(), *pathlib.Path.cwd().parents]:\n",
" if (parent / \"src\" / \"pacta\").exists():\n",
" sys.path.insert(0, str(parent / \"src\")); break\n",
"\n",
"# A customer writes their OWN card, from first principles - no\n",
"# peeking at the operator. Lean's three, plus named oracle slots.\n",
"my_card = {\n",
" \"foundational\": {\"propext\", \"Classical.choice\", \"Quot.sound\"},\n",
" \"apex_oracle_allowed\": {\n",
" \"sha2.Sha512\", \"verifying.sha512_new\",\n",
" \"verifying.sha512_update\", \"verifying.sha512_finalize_bytes\",\n",
" \"ed25519.Signature\", \"ed25519.Signature.to_bytes\",\n",
" \"signature.error.Error\", \"signature.error.Error.new\",\n",
" },\n",
"}\n",
"print(\"my requirements card:\", sum(len(v) for v in my_card.values()), \"named assumptions\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Wish meets supply — and it is no accident\n",
"\n",
"Now compare your self-written card against what the four forks\n",
"actually declare. They match. That convergence is *engineered*:\n",
"the supply was deliberately shrunk — every axiom made to justify\n",
"its existence — so that any reasonable person's independently\n",
"written card lands on the same minimal list. When the wish meets\n",
"the supply exactly, it is because the supplier spent months\n",
"making the supply as small as honesty allows.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pacta.profiles.ed25519 import APEX_BOUNDARIES\n",
"\n",
"# The supply: the apex-tier certificate's documented, allowed\n",
"# axiom cone for the upstream fork - the exact set the strongest\n",
"# theorem is permitted to rest on, nothing more, nothing less.\n",
"supply = set(APEX_BOUNDARIES[\"dalek-wrappers\"])\n",
"wish = my_card[\"foundational\"] | my_card[\"apex_oracle_allowed\"]\n",
"print(\"supply == my wish:\", supply == wish)\n",
"print(\"axioms in supply my card did not anticipate:\", (supply - wish) or \"none\")\n",
"print(\"axioms my card wanted that are absent:\", (wish - supply) or \"none\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The three roles, kept apart\n",
"\n",
"It is tempting to say \"the inclusion proof proves the Lean proof\n",
"is about my card.\" It does not, and the precision matters:\n",
"\n",
"| role | who | what it establishes |\n",
"|---|---|---|\n",
"| measurement | operator's kernel run | \"this theorem rests on exactly these named axioms\" (recorded verbatim in the attestation) |\n",
"| publication | the transparency log | \"this measurement is in the permanent record, shown identically to everyone\" (the inclusion proof + signed head) |\n",
"| judgment | **you** | \"these observed axioms are inside my allowed card\" (re-derived locally, every time) |\n",
"\n",
"Only judgment is yours, and it is the only step that involves an\n",
"opinion. The operator is trusted to *copy down what the kernel\n",
"printed* — never to interpret it.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## If you are happy — you are already finished\n",
"\n",
"If your card covers the observed cone, verification is: check\n",
"one signature, walk ~4 hashes to the signed root, compare cones\n",
"to your card. Milliseconds, standard library, no Lean. Done.\n",
"\n",
"## If you are NOT happy — there is nothing to negotiate\n",
"\n",
"Suppose your card is stricter: *\"I require SHA-512 itself\n",
"proven, not an oracle.\"* The system has no sales pitch for you.\n",
"Its entire answer is an **itemized** statement of the gap:\n",
"*not in supply; SHA-512-proven is the R5 frontier; here is the\n",
"exact list of what you would be accepting if you proceed\n",
"anyway.* Your decision is never \"lower my standards\" in the\n",
"abstract — it is a named line item: *SHA-512 as oracle: yes/no.*\n",
"Informed compromise, not diffuse trust.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# The honest gap, itemized. A stricter customer wants no hash oracle.\n",
"strict_card = my_card[\"foundational\"] # foundational ONLY, no oracle slots\n",
"gap = supply - strict_card\n",
"print(\"this customer must explicitly accept, or walk away:\")\n",
"for ax in sorted(gap):\n",
" print(\" -\", ax)\n",
"print()\n",
"print(\"verdict for the strict card:\", \"PASSES\" if supply <= strict_card else \"REFUSED (gap above)\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The third option: grow the supply\n",
"\n",
"The gap between anyone's dream card and today's supply is a\n",
"to-do list, not a wall. Prove SHA-512, certify the wire\n",
"parsers, and the new certificates enter the same log — and\n",
"stricter cards start passing. The log is additive in exactly\n",
"the way requirements are.\n",
"\n",
"**So: you hold the ruler. If your ruler is stricter than our\n",
"supply, your ruler is our roadmap.** That is the quiet\n",
"invitation built into the whole design.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercises\n",
"\n",
"- Write your own requirements card for the *foundational*\n",
" (non-signature) certificates from scratch. Those certificates\n",
" are expected to carry exactly Lean's three standard axioms\n",
" (`propext`, `Classical.choice`, `Quot.sound`) and nothing\n",
" else - did your card guess exactly those three?\n",
"- A vendor's attestation says `status: proven`. Explain in two\n",
" sentences why your tooling ignores that field entirely, and\n",
" what it looks at instead.\n",
"- You require reproducible builds. Is that a card you can write\n",
" today and have pass? Name the tier that gap belongs to, and\n",
" what would have to enter the log to close it.\n",
"- Argue both sides: is \"wish meets supply exactly\" a strength\n",
" (minimal, auditable) or a weakness (the same author wrote the\n",
" card and the supply)? What single action by a customer\n",
" settles the argument in their favor?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Do it in the cockpit: the Inspect instrument\n",
"\n",
"The recomputation this notebook performs by hand is exactly what the cockpit's **Inspect**\n",
"instrument (`/inspect`) runs on paste — same deployed verifier, verbatim diagnostics —\n",
"and what the lab manual's Cryptographer session drills: verify the sample evidence, then\n",
"deliberately corrupt one character and learn the distinct failure surfaces.\n",
"`pacta wallet cockpit --demo`, then Inspect → “Load the sample evidence”."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}