Releases: EslaM-X/piproof
Release list
v0.19.0 — The Open Protocol Phase
PiProof v0.19.0 — The Open Protocol Phase
The role reversal release: every version before this made the
implementation stronger; this one makes the specification strong
enough that the implementation stops being special.
The thesis, stated plainly
Pi is an adapter, not a dependency. (SPEC.md §11)
And proven by execution: test/pi-independent.test.js runs the full
pipeline — registry, signing, epoch-bound proof, tamper rejection,
replay burn — for acme-logistics / container-42, a namespace with
zero Pi semantics.
What's new
SPEC.md — the standalone specification
Canonical Profile v1.1 · PEP/1 events · registry format · G1–G9 with
normative error codes · h1: pseudonyms · PiProof/1 + Passport/1
envelopes · court wire format · conformance criteria · versioning
policy. Written to be implemented without reading any source code.
Four languages + WebAssembly, one vector suite
| Channel | Path | Conformance |
|---|---|---|
| Node.js (reference) | src/ |
152/152 tests · fuzz · vectors byte-reproducible |
| Python package | sdk/python/ — now pip install ./sdk/python |
16/16 vectors + pipeline negatives (test_sdk.py) |
| Go module | sdk/go/ |
full conformance matrix |
| Rust crate (new) | sdk/rust/ |
16/16 canonical vectors + end-to-end in CI (rust-conformance, Ubuntu+Windows) |
| WASM (new) | wasm/ |
accept / replay-burn across calls / tamper (wasm-build job) |
The Rust crate implements the canonicalizer with exact lexical rules and
UTF-16 key ordering; NFC arrives via the ecosystem-standard
unicode-normalization crate (the same reason Go needed x/text). G9 is
reported honestly as UNVERIFIABLE when stateless.
npm publish-readiness
files, per-module exports, dual bin, engines pinned; stable public
entry src/index.js. Tarball: 88 files, ~152 kB.
External-proof phase
- docs/EXTERNAL_IMPLEMENTATION.md — the published bar for third-party
verifiers: implement from SPEC.md alone, submission checklist,
differential-fuzzing gate. - ADOPTERS.md — every row links to re-runnable CI proof; the
third-party section is honestly empty. - SECURITY_REVIEW.md — scope, methods, public findings ledger.
- docs/DISTRIBUTION.md — seven channels, one table.
- docs/HTTP_API.md — hosted-verifier contract.
- docs/EVIDENCE_INFRASTRUCTURE.md — Agent Evidence as general-purpose
infrastructure.
CI grows three jobs
python-package (3.10/3.12 × OS) · rust-conformance (× OS) ·
wasm-build (× OS) — the verification surface now spans four language
ecosystems on two operating systems, 21 checks per push.
Honest boundaries
- crates.io publication deferred until after external review (the v1.0 gate)
- author-overlap remains: four languages, one maintainer — which is
exactly why the external implementation kit exists - local Rust execution is impossible on locked-down Windows sandboxes
(Application Control); CI is the authoritative ground — documented in
sdk/rust/README.md
Full changelog: CHANGELOG.md · Spec: SPEC.md
PiProof v0.18.0 — The Arbitration Court
PiProof v0.18.0 — The Arbitration Court: Decentralized Verifiable Adjudication
The Dispute Engine's honest disclaimer — no judge quorum, no challenge
periods, no arbitration market, no on-chain settlement — becomes an honest
implementation of exactly those things.
Highlights
Judges are keys, verdicts are mathematics
- Judge roster in the registry: Ed25519 keys with declared stake,
capabilities (judge/referee) and earned reputation. - Weighted quorum tallies over signed ballots — every vote is an
attestation over the exact tally inputs. - No single key can settle: a settlement exists only as an
N-of-panel multi-signature over canonical certificate bytes; strip one
signature and it stops verifying.
Trustless by construction
replayArbitration()re-verifies every signature and recomputes every
tally purely (no mutation) — tampering anywhere surfaces as a named
difference, never silence.- The v0.18 tests pin this hard: the naive (mutating) re-tally silently
laundered tampered tallies; the pure split is enforced by test. - Challenge periods where a challenge IS a replay: proving corruption
reopens deliberation; frivolous challenges cost reputation.
The AI division ("agent court")
- Disputes whose defendant is
agent://…get their own fee class and rules. - AI referees submit signed advisory opinions, recorded as evidence and
hash-pinned into settlements — but a referee key can never vote. - Constitutional rule, enforced by the capability system, not by policy:
AI argues; keys decide.
Arbitration market & settlement
- Deterministic panel assignment by published fee books → reputation → id.
- Reputation flows: +2 consensus at settlement, −1 rejected challenge.
- Byte-deterministic anchor payloads (pre-commitment tested) with an
explicit chain-adapter contract; broadcasting stays a deployment concern.
Surfaces & spec
- Live UI at
/court(strict CSP) ·/api/court/{state,demo-case,file,ballot,settle}·
pep court-demoCLI walkthrough of a full case. - Normative specification: docs/COURT.md.
Verification
149/149 tests · layers clean (26 modules / 72 edges) · 20/20 attacks ·
16/16 canonical vectors ×3 languages · FUZZ OK · conformance 4/4 · TLC green
· all 13 CI checks passed on Node 18/20/22 + Python + Go + TLA+.
PiProof v0.17.0 — Offline Verification Gateway & Privacy Phase
PiProof v0.17.0 — Public Offline Verification Gateway & Privacy Phase
The killer-use gap closes: anyone can now verify a document with
cryptographic certainty and zero disclosure — the document never leaves
the verifier's browser.
Highlights
Pure-JS RFC 8032 crypto core (src/web-ed25519.js)
- Ed25519 verification + SHA-512, from scratch, BigInt JavaScript,
browser-safe, verify-only by construction. - Every magic constant is derived: SHA-512's H/K tables computed from
fractional roots of primes; Ed25519'sd, base point and √-1 derived
from2^255-19alone. - Strict decoding: non-canonical
S ≥ Lrejected; decompression failures
are hard rejections. - Exhaustively cross-checked against node:crypto in CI (random keys ×
sizes, bit-flips of msg/R/S, wrong keys, malleable signatures).
In-browser G1–G9 pipeline (src/offline-verifier.js)
- Same canonical fixed-point rule, same error codes as the Node pipeline —
run entirely locally against the public registry export. - Honesty centerpiece: NONCE_REPLAY is gold-labeled UNVERIFIABLE offline,
never green-washed; epoch binding likewise.
The gateway (/gateway)
- Strict CSP page (
default-src 'none'; script-src 'self'— no inline
script anywhere). - Accepts paste / file / deep link for signed events, PiProof envelopes and
Evidence Passports; gate-by-gate verdict table. - Displays the SHA-256 fingerprint of the exact registry bytes every verdict
was computed against.
Host hardening
- Global security headers on every response ·
GET /healthz· public
GET /registry.jsonexport · whitelist-only/gateway-src/route
(traversal-proof).
Normative privacy model — docs/PRIVACY_MODEL.md
Data inventory (who sees what), keyed-pseudonym rotation story (h1: →
h2:), the gateway's five-point honesty contract, and honest limits
(intra-deployment tag stability, mirror registries, ZK out of scope for
frozen PEP/1).
Verification
139/139 tests · layers clean (25 modules / 69 edges) · 20/20 attacks ·
16/16 canonical vectors ×3 languages · FUZZ OK · conformance 4/4 · TLC green
· all 13 CI checks passed on Node 18/20/22 + Python + Go + TLA+.
Full details:
CHANGELOG ·
docs/PRIVACY_MODEL.md
PiProof v0.16.1 — Mechanized Verification Goes Live
PiProof v0.16.1 — Mechanized Verification Goes Live
The TLA+ model is no longer hand-checked. TLC now runs on every push and
PR, and CI fails unless it reports "Model checking completed. No error
has been found."
What shipped
- CI job
formal-tlc: Temurin 21 via pinnedactions/setup-javaSHA +
tla2tools.jarv1.7.4 verified against the official release SHA1
(bee4a54f3ee3d4afc347c3240ec2d9e93b075104) before use. - Verified result: the complete state space — 122 distinct states — with
TypeOK,AtMostOneAccept(INV-04),AcceptImpliesBurn, and
BurnOnlyOnPass(INV-05) all holding.
The first machine run earned its keep immediately
Two real modeling flaws, caught by TLC before any human reviewer:
EXTENDS Naturals→Integers— unary minus (the rejection-code
encoding) is not defined in pureNaturals.- The G8 environment choice was separable from its consequence; a verifier
could read a snapshot before the environment committed, producing a stuck
path that TLC's deadlock analysis exposed. G8's choice and outcome are
now one atomic action, and clean termination is an explicit
TerminalStutteraction — preserving deadlock detection for genuinely
stuck mid-pipeline states rather than disabling it with-deadlock.
Maturity movement
Row #14 (mechanized verification): drafted → partially held. The
stateful core of G1–G9 is machine-checked continuously; extending coverage
toward the full INV-01…12 set remains open work.
v1.0 remains gated on external review. Details:
CHANGELOG ·
formal/README.md ·
docs/MATURITY.md
PiProof v0.16.0 — Third Implementation & Normative Conformance
PiProof v0.16.0 — Third Implementation & Normative Conformance
The protocol core now exists as three independent codebases — Node.js,
pure-Python, and from-scratch Go — agreeing byte-for-byte on every interop
vector, and anyone claiming "PiProof compatible" has one command to prove it.
Highlights
Go protocol core (sdk/go/)
- From scratch: Canonical Profile v1.1 (NFC-form sort, UTF-16 ordering),
closed event schema, G1–G9 pipeline with exact error-code parity, RFC 8032
via stdlibcrypto/ed25519. - One pinned auxiliary dependency (
golang.org/x/text) — Go ships no Unicode
normalization tables; it plays the roleunicodedataplays in Python. - Ordered JSON parsing preserves key order (Go maps randomize it).
- CANC/PARSE fuzz driver speaking the same line protocol as Python's.
- Tests: 16 interop vectors byte-exact · fixed-point INV-01 pin · valid
vector ACCEPTS · all 20 attacks reject with exact codes · INV-05/INV-08 pins.
Normative conformance suite (npm run conformance + docs/CONFORMANCE.md)
- Four-row matrix: Node vectors / Python canonicalizer / Go protocol core /
Python Ed25519. - Claim rules: publish raw matrix output + vector commit SHA; say "passes
the PiProof conformance matrix at commit<sha>" — never "certified". - Graceful SKIP for absent toolchains;
--strictturns skips into failures.
TLA+ model of the stateful gate core (formal/)
- Two verifiers racing one shared nonce authority; G8 snapshot eligibility
and atomic G9 test-and-set modeled explicitly. - INV-04 (at-most-one-accept), INV-05 (burn-on-pass-only), TypeOK,
AcceptImpliesBurn as TLC invariants. Hand-checked pending CI tooling —
stated honestly in formal/README.md.
Fuzzing: seventh campaign go-diff
- Node vs Go differential through the driver protocol: canonical bytes AND
parse shapes. Clean SKIP without a Go toolchain.
Corrections to v0.15's Unicode story
v0.15 claimed canon-012 pinned the amended NFC-form sort order. Wrong on
Unicode facts: ligatures have no canonical decomposition, so canon-012's
emission order is identical under both sort rules. The true discriminator is
new vector canon-016 (Ç U+00C7 vs Å-sign U+212B): raw-sort emits Ç
first; v1.1 NFC-form emits Å first. Suite is now 16 vectors, and
cross-canonical.py was moved from raw-sort to NFC-form sort (it silently
disagreed with v1.1 on flip-class pairs while passing the old set).
Verification
132/132 tests · layers clean (23 modules / 64 edges / 0 violations) ·
20/20 attacks · 16/16 canonical vectors ×3 languages · FUZZ OK incl.
go-diff · conformance matrix 4/4 · go vet clean · CI green on
Node 18/20/22 + Python 3.10/3.12 × ubuntu/windows + Go on both OSes.
Maturity movement
- Row #13 (independent implementation): partially held — spec proven
reimplementable in a third language; author-independence remains open. - Row #14 (mechanized verification): drafted — TLC-runnable model shipped.
v1.0 remains gated on external review. Full details:
CHANGELOG ·
docs/CONFORMANCE.md ·
docs/MATURITY.md
v0.15.0 — Adversarial Depth & Formal Structure
PiProof v0.15.0 — Adversarial Depth & Formal Structure
Second external-review hardening release: machinery that finds its own bugs, and documents that make claims checkable. It paid for itself immediately — the fuzzing suite found a real canonicalization bug before any consumer did.
Found & fixed: Canonical Profile v1.1
Raw-key sort + NFC serialization made canonicalization deterministic but not idempotent: canon(parse(c)) !== c for some already-canonical documents, silently breaking isCanonical() on output the protocol itself produced. v1.1 sorts NFC forms so the emitted text IS the sort key — fixed-point by construction. No previously signed payload changes meaning (the collision rule excludes unstable pairs). Interop vector canon-012 pins the amended order; all 15 vectors regenerated byte-exact in Node + Python.
Added
Seeded fuzzing suite (scripts/fuzz.mjs, npm run fuzz) — six campaigns:
- canonicalization properties (determinism, idempotence, reject-only-
CanonicalError) with Node↔Python cross-examination of every anomaly - schema fail-closed under random mutation of valid events,
__proto__injection included - Unicode NFC equivalence / collision rejection
- byte-level Node↔Python differential parsing via a persistent stdlib driver (
scripts/fuzz-diff-driver.py) - K real OS processes racing one nonce → exactly one winner, every round
- V8 runtime-parser anomalies are classified separately from protocol violations (
FUZZ_STRICT=1makes them fatal; default CI stays deterministic across Node builds)
Layer governance (scripts/check-layers.mjs, normative docs/LAYERS.md) — modules classified L0 primitives → L4 presentation; one mechanical rule (depLayer ≤ myLayer); unclassified files are violations. Enforced in CI. Current state: 23 modules, 64 edges, 0 violations.
Engineering formal model (docs/FORMAL_MODEL.md) — the G1–G9 verification pipeline as an ordered fail-closed state machine; twelve security invariants (INV-01…INV-12) each with enforced-by / verified-by traceability; crash-failure semantics of the claim path; a normative implementer MUST list. A paper model, honestly labeled as one.
Liveness-aware nonce-lock ownership (FileNonceStore) — lockfiles record {pid, host, acquiredAt}; a lock held by a live same-host process is never stolen regardless of age; provably dead owners may be taken after the staleness window; foreign-host/legacy locks keep time-based fallback. Closes the stale-lock-timeout double-entry race. Pinned by 6 new tests including K-process races.
V8 JSON.parse divergence disclosed (SECURITY.md) — under allocation churn Node can mis-parse byte-identical JSON (phantom-key shape differences vs Python's json.loads). Documented as a runtime defect with full impact analysis: PiProof's schema-pinned key sets make it unreachable in every protocol path.
Verification
132/132 tests · layer check 23 modules / 64 edges / 0 violations · 20/20 attacks rejected · 15/15 canonical vectors byte-exact ×2 languages · FUZZ OK (quick + full)
Status
v1.0 remains gated on external security review (issue #2). New deliberately-open evidence rows in MATURITY.md: #13 independent third-party implementation, #14 mechanized verification.
v0.14.0 — Developer Layer
The developer layer — "Verify with PiProof" in five minutes.
Any Pi application — merchant, marketplace, game, agent, community — now calls one deterministic surface instead of building its own verification plumbing:
const pi = createVerifier({ registry, nonceStore });
const d = pi.decide(proof, { policy: 'merchant-verification-v1' });
if (d.decision === 'ALLOW') allowAction();What ships
- JS SDK (
src/sdk.js, zero deps) —verifyProof/verifyPassport/decidewith reasons, violations, binding class and resolved policy name; unknown presets deny cleanly asPOLICY_PRESET_UNKNOWN. - Named policy presets (
src/policy-presets.js) — frozen versioned defaults callable by name:merchant-verification-v1·marketplace-seller-v1·agent-payment-v1·community-member-v1·reward-eligibility-v1. Auditable data; a change means a new version. Deliberately not a "policy marketplace" — no signing, no discovery protocol. - Decision API —
POST /api/decideshares the Explorer's nonce state so replays are caught across every endpoint;GET /api/policies; preset references accepted by all verify endpoints;/api/sharereturns self-containedpiproof://v1?p=…proof links next to short links. - Python SDK (
sdk/python/piproof_sdk.py, stdlib only) — independent implementation of the same pipeline: from-scratch Ed25519, PiProof Canonical Profile v1 with raw-key sort parity, envelope + epoch binding, nonce state files, presets, narrowing policy subset. Library API + CLI. - CLI —
pep policiesandpep decide --proof p.json --policy agent-payment-v1 --nonces nonces.jsonl.
Verification
- 126/126 tests (+16)
- attack suite 20/20 rejected
- canonical vectors 15/15 byte-exact × 2 languages
- Node↔Python SDK agreement tested end-to-end in CI
Guide: docs/SDK.md · Full changelog: v0.13.0...v0.14.0
v0.13.0 — External-Review Hardening
Converts a professional external critique into normative documentation, protocol-level distinctions, and cross-language interop proof. No frozen-core semantics changed — everything is additive.
The six critiques → the six answers
| # | Critique | Fix in v0.13 |
|---|---|---|
| 5 | "JCS-subset" invites JCS conformance expectations | docs/CANONICALIZATION.md — PiProof Canonical Profile v1 vs RFC 8785, rationale per deviation, 6 conformance requirements + 15 interop vectors agreed byte-exact by two independent implementations (Node + from-scratch Python stdlib), CI'd on Py3.10/3.12 × Linux/Windows — incl. the raw-sort divergence case and NFC key-collision rejection |
| 7 | FileNonceStore is not distributed replay protection | docs/NONCE_STORES.md — normative deployment matrix per store × topology; Redis single-strongly-consistent-authority requirements; eventually-consistent backends unsupported by design; safe multi-region patterns |
| 13 | optional registry_root conflates portability with state trust | protocol-level binding classes: every verdict carries EPOCH_BOUND / LOCAL; policy rule require_epoch_bound; passport weakest-link aggregation (EPOCH_BOUND/LOCAL/MIXED); dispute question IS_THE_PROOF_EPOCH_BOUND (document-intrinsic); CLI proof-export --epoch-bound & passport-create --require-epoch-bound |
| 17 | "Dispute Engine" risks overclaim | repositioned everywhere as a deterministic evidence adjudication layer — no quorum, no challenge periods, no arbitration market, no settlement |
| 18 | Policy engine simpler than its name | docs/POLICY_MODEL.md — v1 grammar table, evaluation order, monotone-narrowing guarantee, explicit non-goals (no AND/OR, no nesting, no delegation) |
| 19 | HMAC pseudonymization ≠ anonymity | SECURITY.md section: keyed tags are non-invertible outside the issuer but NOT unlinkable; per-app uid secrets are load-bearing |
Maturity honesty (#21)
docs/MATURITY.md: reference implementation ✅ · security-engineering prototype ✅ · production infrastructure ❌ — with a 12-row missing-evidence register and presentation language rules. Linked from the top of the README.
Verification
- 110/110 tests (7 new binding tests)
- attack suite 20/20 rejected
- canonical vectors 15/15 byte-exact in Node AND independent Python
- pure-Python Ed25519 cross-verify unchanged: 1 valid accepted, 20 attacks rejected
Full changelog: v0.12.0...v0.13.0
v0.12.0 — Observability hooks + transparency-log draft
The last pre-review release: everything the v1.0 external review needs is now on the table.
📈 Observability hooks — opt-in, pure, dependency-free
\src/observability.js\ with three hard rules:
- No global state — registries are passed explicitly; a verdict can never depend on whether observation is enabled.
- Telemetry is fail-open — recording never throws into the verification path.
- Bounded memory — latency ring capped at 10k samples; hostile load cannot grow the process.
\�erifySignedEvent, \�erifyPiProof, \�erifyPassport\ accept optional \metrics. Snapshots are stable-keyed JSON (\AUREVIA-Metrics/1: totals, ok/fail, rejection-code breakdown, p50/p95/p99). The demo server exposes live counters at read-only \GET /api/metrics.
📜 Signed registry transparency-log — design draft
[\docs/TRANSPARENCY_LOG_DESIGN.md](docs/TRANSPARENCY_LOG_DESIGN.md) — the concrete artifact closing Open Question #1 by design (implementation deliberately deferred until after review):
- Append-only epoch entries hashed over the existing canonical bytes — zero new serialization
- prev-hash chaining · m-of-n witness cosigning · split-view detection
- Five-step pure verification reusing only canonicalize + Ed25519 + SHA-256; any failure ⇒ UNVERIFIABLE, never a pass
- Additive migration from today's
egistry_root; reserved \TL_*\ codes; privacy analysis; five open questions for reviewers
Explicitly NON-NORMATIVE until the external v1.0 review concludes.
✅ Verification
npm test 103/103 (+4) · attacks 20/20 rejected · vectors byte-checked · CI green Node 18/20/22 × Ubuntu/Windows + Python cross-verify.
Roadmap: v0.1.x–v0.12 shipped · v1.0 = frozen after external security review & public feedback — nothing else stands in front of it.
v0.11.0 — Distributed replay state, real throughput numbers, the honest register
Answers the ten hardest open questions about this project — two with code, all ten in writing.
🌐 Distributed nonce state — zero dependencies
\RedisNonceStore\ (\src/redis-nonces.js): N load-balanced verifier instances now share one replay-protection domain through atomic Redis \SET NX\ claims.
- Hand-written RESP2 client + worker-thread bridge that keeps the interface synchronous via \Atomics.wait\ (the same fail-closed pattern as FileNonceStore) — \�erifySignedEvent/\�erifyPiProof\ work unchanged.
- Optional TTL = safe GC: claims only need to outlive TIMESTAMP_FRESHNESS.
- Fail-closed: unreachable server ⇒ throw, never allow a claim through.
- Privacy: only opaque nonce keys (\�pp_id:hex32) ever leave the process.
📊 Production-scale evidence — reproducible
\
$ npm run bench
Full 9-step pipeline : ~7,300 verified proofs/sec (single core, sequential)
verified 3,000/3,000 · p50 0.125ms · p95 0.17ms · p99 0.43ms
InMemory claims : ~5.5M/sec
Durable file claims : ~700/sec (lock+append+fsync per claim)
\
No mocks — every counted verification passed every step, including fresh Ed25519 and an atomic nonce claim.
📋 docs/OPEN_QUESTIONS.md
The ten hardest questions — registry authenticity at protocol level, distributed state, external audit, adoption, recency, breadth vs validation, forked-vs-authored, production evidence, agent-evidence depth, complexity growth — each answered with status, existing mitigations, and exactly what closes it. Two are closed by this release; registry authenticity is deliberately parked as the v1.0 review centerpiece.
✅ Verification
npm test 99/99 (+6) · attacks 20/20 rejected · CI green Node 18/20/22 × Ubuntu/Windows + Python cross-verify.
Proofs you can carry. Evidence anyone can verify.