From 1acbaa1a760173a28ef6f472528436881a421679 Mon Sep 17 00:00:00 2001 From: mrwulf Date: Mon, 20 Jul 2026 10:58:59 +0200 Subject: [PATCH] cockpit: estate map as a fifth view, with RUNTIME as a first-class dimension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Operator questions answered in code: (1) the estate map now lives IN the cockpit too — /estate serves the interactive map (lanes, typed edges, loops, clickable dossiers) to the same human audience the cockpit serves; ESTATE.md remains the canonical committed version (renders on GitHub, reachable by agents via llms.txt, needs no running process), and a name-level sync test guards drift between the two renderings — the published_assets lesson applied preemptively. (2) 'What is RUNNING?' is now answered everywhere: an operations strip on the map (ALWAYS ON: caddy + the LTL read-only container + Forgejo with its single 03:00 mirror cron, all droplet; ON-DEMAND: append/publish/sign ceremonies, cockpit, MCP, operator machine only; NOT RUNNING: warden — prototype, no deployed instance, no funds watched; everything else: static files or external parties), a per-entity Runtime line in every dossier, and a verified What-is-running table in ESTATE.md (container commands, :ro mounts and read_only:true on the LTL service, and the crontab checked on the droplet 2026-07-20, not recalled). Suite 128 -> 130 (estate route + drift guard). Local-only as before: nothing deployed, live estate untouched. Co-Authored-By: Claude Fable 5 --- ESTATE.md | 20 +- docs/cockpit.md | 1 + src/pacta/estateview.py | 411 ++++++++++++++++++++++++++++++++++++++++ src/pacta/walletui.py | 6 +- tests/test_walletui.py | 35 ++++ 5 files changed, 471 insertions(+), 2 deletions(-) create mode 100644 src/pacta/estateview.py diff --git a/ESTATE.md b/ESTATE.md index 6381223..e088ca5 100644 --- a/ESTATE.md +++ b/ESTATE.md @@ -9,7 +9,7 @@ machinery hub and the only repo that changes freely. State snapshot (2026-07-19): log **13 leaves**, root `3488a2d0…`, key fingerprint `874c8a00…`, paper **v0.9 camera-ready (23 pp)**, five -attested components, pacta suite 118 green. +attested components, pacta suite 130 green. ```mermaid flowchart LR @@ -133,6 +133,24 @@ deployed verifier; see the corpus KNOWN-GAPS ledger). | **Operational log state** | `provider/state/transparency-log-main` — the true accumulator. Appends happen here; the mirror is its projection. | | **Evidence archive (offline)** | review kits and stamped artifacts (`_timestamp_hash8` convention); never in git. | +## What is running (operations, verified 2026-07-20) + +| Entity | Runtime | Where | Starts / stops | +|---|---|---|---| +| caddy (TLS, static blog) | **always on** | droplet container | `docker compose`, restart-unless-stopped | +| LTL web service (ltl.zkdefi.org) | **always on** | droplet container | `pacta_provider serve` with read-only mounts and `read_only: true` — it *cannot* write, sign, or append | +| Forgejo mirror | **always on** | droplet container | plus exactly one cron: 03:00 daily mirror reconcile | +| provider write side (check / append / publish / sign) | **on demand** | operator machine | runs only during an append ceremony, minutes at a time; the signing key is offline otherwise | +| warden (the financial agent) | **not running** | nowhere | implemented prototype: a wallet directory plus CLI/MCP/cockpit processes that exist only while explicitly started; no deployed instance, no funds watched | +| custody cockpit | **on demand** | operator machine, localhost | `pacta wallet cockpit`, stops with Ctrl-C; read-only | +| everything else (repos, paper, book, mirror, SD) | **no process** | — | static files; consumers and reviewers are external and episodic | + +The human-facing interactive rendering of this whole map, runtime +dimension included, is the cockpit's **Estate map** view +(`pacta wallet cockpit` → `/estate`); this file remains the canonical +committed version, and `tests/test_walletui.py` guards name-level drift +between the two. + ## Edge glossary | Edge | Meaning | diff --git a/docs/cockpit.md b/docs/cockpit.md index fdf071c..83d0aab 100644 --- a/docs/cockpit.md +++ b/docs/cockpit.md @@ -34,6 +34,7 @@ separate, explicitly reviewed milestone. | **Posture** (`/`) | custody latch state, ledger head with full hash-chain re-verification, the pinned quorum members (backend, component, tier, source commit, binary hash), spending policy verbatim, incident/refusal counts | `Wallet.posture()` / `Wallet.verify_ledger()` | | **Signature queue** (`/queue`) | parked airgap signing requests (outbox) and whether the device has answered (inbox) — observed, never operated | airgap outbox/inbox listing | | **Incidents & refusals** (`/incidents`) | incident records and signed refusal receipts, verbatim, newest first | `incidents/*.json`, `receipts/*.json` | +| **Estate map** (`/estate`) | the whole endeavour — every repo, service, mirror, loop — with RUNTIME on every entity (always-on / on-demand / not-running / static) | rendering of ESTATE.md's model (drift-guarded by test) | | **Receipt inspector** (`/inspect`) | paste an attestation + transparency receipt + log public key; the verdict, per-signature results, and diagnostics come verbatim from the deployed verifier | `pacta.transparency.verify_receipt` | Every panel also states what it does **not** prove (e.g. the quorum diff --git a/src/pacta/estateview.py b/src/pacta/estateview.py new file mode 100644 index 0000000..f0db9b5 --- /dev/null +++ b/src/pacta/estateview.py @@ -0,0 +1,411 @@ +"""estateview - the estate map as a cockpit view. + +The same model as ESTATE.md (the canonical committed version), rendered +interactively for humans, with RUNTIME as a first-class dimension: every +entity dossier states whether anything is actually running, where, and +when it starts and stops. A sync test guards name-level drift between +this page and ESTATE.md. +""" + +ESTATE_HTML = r'''LTL estate map — repos, services, loops + + +
+

LTL estate map

+
Every persisting entity of the Lean Transparency Log endeavour, arranged as five lanes of custody — click any card for its dossier. The two colored routes are the loops that make this estate hard to hold in one head.
+
+
+ log 13 leaves + root 3488a2d0… + key 874c8a00… + paper v0.9 · 23 pp · camera-ready + attested components 5 + pacta suite 130 green + state as of 2026-07-20 +
+
+ ALWAYS ON droplet: caddy (TLS, static blog) · LTL web service (read-only container) · Forgejo (+ 03:00 mirror cron) + ON-DEMAND operator machine: append/publish/sign ceremonies · cockpit · MCP — exist only while invoked + NOT RUNNING warden: implemented prototype, no deployed instance, no funds watched + everything else: static files or external parties — no process at all +
+
+ extract / feed + attest + append / publish + template (CI-pinned) + serve / deploy + consume + Loop 1 — dogfood signer + Loop 2 — self-attestation +
+ +
+
+ +
+ +
Upstream inputs · frozen
+
+

curve25519-dalek-source

upstream Rust, pinned clone
+

anza-cryptography-source

Solana fork, pinned clone
+

risc0-…-dalek-source

RISC Zero fork, pinned clone
+

betrusted-…-dalek-source

Betrusted fork (+ xous-core, litex-boards context)
+

pasta_curves-source

Pasta curves, pinned clone
+
+
+ +
Verified subjects
+
+

dalek-ed25519-verified

16 certs · leaf 8 (gen 3)
+
attestedsigner source
+

anza-ed25519-verified

16 certs · leaf 9
+
attested
+

risc0-ed25519-verified

16 certs · leaf 10
+
attested
+

betrusted-ed25519-verified

16 certs · leaf 11
+
attested
+

pasta-pallas-verified

field layer proven · curve layer pending
+
not attested
+

ltl-accumulator-verified

61 certs · proofs about the log's own accumulator model
+
attested · entry 13frozen 172a1d0loop 2
+
+
+ +
Machinery & operator-held
+
+
proof-aware-crypto-tooling-agent(pacta)
+
+

Provider service

check → append → publish · site & API code · publish templates
+
templates CI-pinned
+

Dogfood signer

verified-dalek-serial binary — signs every head
+
loop 1
+

Consumer library

verify · pin store · receipts · R0–R5 risk model
+

warden (code)

quorum-custody wallet · MCP · custody card
+

Paper

ltl.tex — v0.9 camera-ready · archives v0.1 / v0.2
+

Course + llms.txt

14 notebooks · agent-readable index
+
+
+
Operator-held · never in git
+
+

Signing key

offline · sole copy + encrypted SD backup
+

Operational log state

transparency-log-main — the true accumulator
+

Evidence archive (offline)

review kits · stamped artifacts
+
+
+
+
+ +
Published faces
+
+

lean-transparency-log

public mirror — leaves, heads, receipts, fail-closed verify.py + selftest
+
generated by publish
+

ltl.zkdefi.org

homepage from live leaves · /v1 API · /paper (+v0.2, v0.1) · key endpoint
+

Forgejo mirror

droplet · nightly 03:00 · full saymrwulf account
+
disaster copy
+

Infra as code (private)

droplet configuration in a private repo — unnamed so this map stays shareable
+

verifying-crypto-with-lean

undergraduate book — educational face, no LTL coupling
+
+
+ +
Consumers
+
+

Offline cloner

git clone → verify.py --all (fails closed) → own witness view
+

warden (runtime)

internal consumer — quorum of 4 attested fork verifiers
+

Agents

MCP tools · custody card with embedded inclusion proofs
+

swisspost-evoting-go-poc

prospective — dalek family-level match only, no receipt code
+
prospective
+

External reviewers

GPT-5.6 + Claude — adversarial consumers of paper, corpus, log
+
+
+ +
+
+ + +
+ +
+ Canonical committed version: ESTATE.md in the pacta repo (prose + Mermaid + the What-is-running table). This page is its human-facing rendering, served read-only by the cockpit. Excluded by design: unrelated saymrwulf repos, and the operator-private detail beneath the three dark cards. +
+ + +''' diff --git a/src/pacta/walletui.py b/src/pacta/walletui.py index d195443..c98a390 100644 --- a/src/pacta/walletui.py +++ b/src/pacta/walletui.py @@ -188,7 +188,8 @@ def inspect_receipt(attestation_text: str, receipt_text: str, # --------------------------------------------------------------------------- _VIEWS = [("/", "Posture"), ("/queue", "Signature queue"), - ("/incidents", "Incidents & refusals"), ("/inspect", "Receipt inspector")] + ("/incidents", "Incidents & refusals"), ("/inspect", "Receipt inspector"), + ("/estate", "Estate map")] def _page(title: str, active: str, body: str, wallet_dir: str) -> str: @@ -370,6 +371,9 @@ def make_handler(wallet_dir: Path): self._send(_page("incidents", "/incidents", body, wd)) elif route == "/inspect": self._send(_page("receipt inspector", "/inspect", render_inspect(None), wd)) + elif route == "/estate": + from .estateview import ESTATE_HTML + self._send(ESTATE_HTML) else: self._send(_page("not found", "", "
No such view.
", wd), 404) diff --git a/tests/test_walletui.py b/tests/test_walletui.py index 788b978..46df3bd 100644 --- a/tests/test_walletui.py +++ b/tests/test_walletui.py @@ -195,3 +195,38 @@ def test_server_routes_and_read_only_guarantee(tmp_path): def test_serve_refuses_non_wallet(tmp_path): with pytest.raises(Exception): serve(tmp_path / "empty") + + +def test_estate_view_served_with_runtime_dimension(tmp_path): + wallet = _seal_wallet(tmp_path) + server = serve(wallet.dir, host="127.0.0.1", port=0) + port = server.server_address[1] + thread = threading.Thread(target=server.serve_forever, daemon=True) + thread.start() + try: + with urllib.request.urlopen(f"http://127.0.0.1:{port}/estate") as resp: + body = resp.read().decode() + assert resp.status == 200 + assert "ALWAYS ON" in body and "ON-DEMAND" in body and "NOT RUNNING" in body + assert "Runtime:" in body # dossier panel wiring + assert "lean-transparency-log" in body and "ltl-accumulator-verified" in body + finally: + server.shutdown() + thread.join(timeout=5) + + +def test_estate_view_and_estate_md_do_not_drift(): + """Name-level sync guard between the cockpit estate page and ESTATE.md + (the published_assets lesson: two renderings of one model need a + tripwire).""" + from pacta.estateview import ESTATE_HTML + estate_md = Path("ESTATE.md").read_text(encoding="utf-8") + for name in ("lean-transparency-log", "ltl-accumulator-verified", + "proof-aware-crypto-tooling-agent", "verifying-crypto-with-lean", + "dalek-ed25519-verified", "pasta-pallas-verified", + "ltl.zkdefi.org", "Forgejo"): + assert name in ESTATE_HTML, f"estate view lost: {name}" + assert name in estate_md, f"ESTATE.md lost: {name}" + # the runtime dimension must exist in BOTH renderings + assert "What is running" in estate_md + assert "ALWAYS ON" in ESTATE_HTML