Commit graph

4 commits

Author SHA1 Message Date
962c0fdd41 verify.py template: check the additive SLH-DSA head signature, fail-closed where it counts
The consumer verifier now judges the slh_dsa block on every head. The status
taxonomy is the design decision, so it is spelled out and each arm tested:

  ABSENT     head predates the second signature — allowed (additive posture,
             operator decision 2026-08-06); an append-only log keeps history.
  VALID      verified against provider.slhdsa.pub.
  INVALID    present and wrong — HARD FAILURE. A bad signature is never a
             degradation.
  WRONG-KEY  head names a different key than the mirror ships — hard failure.
  NO-PUBKEY  head claims the signature, mirror ships no key — broken
             publication, hard failure.
  TOOLING    OpenSSL < 3.5 cannot read SLH-DSA keys — honest degradation:
             one loud NOTE, never counted as verified, never failed; the
             required Ed25519 checks still gate the result.

verify_selftest.py gains two adversarial cases, both mutating a full mirror
copy: one flipped signature byte must fail naming slh_dsa:INVALID; deleting
provider.slhdsa.pub while heads claim the signature must fail NO-PUBKEY. On
mirrors without slh blocks the cases record as not-applicable rather than
silently passing. First selftest run caught my own marker bug — the case
grepped for the stored failure string, which is never printed, instead of
the printed status; the printed line is now the assertion target.

README template: SLH-DSA key row, honesty paragraph (verification proven for
both algorithms, signing for neither; leaves Ed25519-signed at issuance
only), and the hardcoded head size is GONE — the README now names no tree
size at all, so this staleness class dies with the instance (it said "tree
size 13" and would have shipped that under a 19-leaf head).

Template is deliberately ahead of the published mirror until the next
publication, which overwrites the mirror from here (the sync rule's
intended direction for pre-publication work). Proven against the scratch
19-leaf mirror: verify.py --all RESULT OK [full] with ABSENT on heads 8-13
and VALID on 14-19; selftest 13/13 GREEN. Backward compat proven against a
copy of the live 13-leaf mirror: RESULT OK [full], selftest GREEN with the
slh cases n/a. Suite 152/0/0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-07 15:16:58 +02:00
2587cc018b publish assets: sync the fail-open time bomb; llms/course/test docs refreshed (doc audit 2026-07-19)
REAL DEFECT found by the operator-ordered doc-freshness audit:
published_assets.py still carried the PRE-HARDENING fail-open verify.py
and the pre-Tier-2 README as the templates that log-publish drops into
the mirror — the next publish would have silently overwritten the
round-13-hardened fail-closed verifier and the corrected README with
the old versions. Fixed:
- published_assets.py regenerated from the canonical mirror files
  (byte-identity verified by round-trip exec), now also carrying
  verify_selftest.py; SYNC RULE documented in the module docstring.
- transparency_log.publish() now writes verify_selftest.py too.
- NEW tests/test_published_assets.py pins the security-critical markers
  (fail-closed FATAL, RECEIPT_TYPE, verify_receipt, --all receipt
  coverage, required fingerprint) so template drift fails CI instead of
  shipping.
- test_web_and_witness updated to the hardened verifier's markers —
  the published test log now passes FULL signature mode end to end
  ('RESULT: OK [full]'), a stronger assertion than the old string.

Doc refresh in the same pass:
- llms.txt: thirteen leaves + entry-13 self-attestation + fail-closed
  verifier; paper line -> new title, 23 pages, v0.2/v0.1 archives.
- Course (generator + generated 06b notebook): 'the git hash IS the
  content hash' -> 'the commit pins the exact source tree';
  'irrevocably part of the log every other agent sees' -> 'committed to
  the log's signed view, which any agent can compare' (the two Tier-2
  scope corrections had never reached the teaching material).
- test_paper_verifiers.py docstring rescoped: its 164k counts are the
  archived v0.2 report's citation; the current paper cites the corpus
  harness and makes no extensional-equality claim.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 13:10:55 +02:00
47dfb61a7f Move the log service to ltl.zkdefi.org (root path); keep path-mount support
- serve/webdocs/cli default to base_path='' (own subdomain, root serving)
- webdocs link builder handles the empty base like web.py already did
- all docs, paper, notebook 06b, and published-mirror README point at
  https://ltl.zkdefi.org; DEPLOY.md rewritten for subdomain + redirect
- tests: root mount is the production shape; one test keeps exercising
  the path-mounted variant

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 19:14:52 +02:00
fbe40c3dfe The log goes public: git-published mirror, online service, witnesses
Three synchronized faces of one log - transport orthogonal to trust:

- PUBLISHED GIT MIRROR: log-publish exports the public face (one file
  per leaf so git history mirrors log history; the FULL STH history as
  the witness channel; per-component attestations + receipts; the
  provider public key; a standalone stdlib-only verify.py and customer
  README). Live at github.com/saymrwulf/lean-transparency-log (genesis:
  8 leaves incl. the honest failed-run entries, dogfood-signed head).
- ONLINE SERVICE (pacta_provider serve): read-only, zero-dependency
  HTTP with CT-style endpoints under a base path for
  zkdefi.org/lean-transparency-log - /v1/sth, /v1/sth-history,
  /v1/sth-consistency?first=N, /v1/proof, /v1/attestation, /v1/entries,
  /v1/metadata, /healthz - plus self-contained customer documentation
  at /docs (current state, attested components, API, the verify-
  without-trusting-this-site path, and the means/does-NOT-mean
  boundary). The process never loads private keys: heads are signed
  offline; a compromised server can withhold or replay (pinning +
  freshness detect both) but never forge. STH history now recorded
  append-only by the provider (with a backfill head signed for the
  existing log).
- AGENT ONLINE CLIENT: pacta log-fetch (download evidence; explicitly
  UNVERIFIED until receipt-verify runs - transport is not trust) and
  pacta sth-refresh (fetch head, verify signature, advance the pin via
  an online consistency proof from the pinned size; fail closed).
- WITNESSES: pacta witness-audit over a clone of the published mirror
  recomputes every prefix root from the public leaves and checks every
  historical head + signature - no consistency proofs needed when the
  leaves are public. Tampering one published entry trips both the
  leaf-hash check and the prefix-root check (tested). verify.py gives
  customers the same audit with zero installation.
- DEPLOY.md: the complete server-session checklist for zkdefi.org -
  reconstruct the servable log FROM the published mirror (the server
  stays in witness trust-position), hardened systemd unit, nginx/Caddy
  path routing, Forgejo mirror setup, the provider->world update
  cycle, and remote smoke tests.

Validated end-to-end on the REAL log: all 10 endpoints, online-fetched
proof re-verified locally through the dogfood verifier with pinning,
online pin refresh, publish + witness audit green, tamper caught,
standalone verify.py green in the published clone. 54/54 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 16:05:20 +02:00