@ar.io/proof 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +104 -52
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,54 +1,106 @@
1
1
  # @ar.io/proof
2
2
 
3
- > TypeScript kernel of the ar.io verification stack verify a Verifiable Event
4
- > Envelope with no ar.io service in the trust path.
5
-
6
- The verification primitives for the envelope family specified in
7
- `ar-io-agent/docs/envelope-spec.md` (ario.agent/v1 profile per `artifact.md`):
8
-
9
- - **RFC 8785 (JCS)** canonicalization (`jcs`)
10
- - **SHA-256** (`sha256Hex`) via WebCrypto
11
- - **Ed25519** signature verification (`ed25519Verify`, via `@noble/ed25519` with
12
- the SHA-512 hook wired to WebCrypto)
13
- - **`verifyEnvelope(env, expectedContentHash?)`** — the three load-bearing checks
14
- (spec-version registry, `payload_hash` recompute, Ed25519 over the signed
15
- scope) plus the optional content-hash bind
16
- - **`contentHashes(env)`** — which payload hash(es) an envelope commits to, by
17
- event type (the reverse-provenance join keys)
18
- - **RFC 9162 binary Merkle tree** (`leafHash`, `nodeHash`, `merkleRoot`,
19
- `auditPath`, `verifyInclusion`, `EMPTY_TREE_ROOT_HEX`) — §2.1 domain
20
- separation, largest-power-of-two split (not the Bitcoin duplicate-leaf
21
- variant), conformance-gated against the corpus's 7 Merkle vectors; parity
22
- with the Python kernel's `ario_proof.merkle`
23
-
24
- This is the TypeScript sibling of the Python [`ar-io-proof`](https://github.com/ar-io/ar-io-proof)
25
- kernel and the Go reference (`ar-io-agent/pkg/proof`). All three are independent
26
- implementations of the same algorithm, each conformance-gated **byte-for-byte**
27
- against the shared `test-vectors-v1.0` corpus — that mutual gate is the
28
- product's core claim: verification needs no ar.io code in the trust path.
29
-
30
- ## Signed scope
31
-
32
- The primary signature covers `JCS(envelope minus signature minus co_signatures)`
33
- (envelope-spec §2, §7.1). The `co_signatures` carve-out lets a countersignature
34
- be added without invalidating the primary signature; the field is reserved and
35
- default-absent, and its absence is never a failure.
36
-
37
- ## Spec-version acceptance
38
-
39
- Fail-closed registry (`specVersionSupported`): exactly the accepted majors
40
- `ario.agent/v1` and additive minors within it (`ario.agent/v1.<minor>`),
41
- matching the Go reference's semantics. Unknown majors and other profiles are
42
- rejected. The mlflow profile (`ario.mlflow/v1`) is a deliberate later one-entry
43
- addition, **not** implemented here — mlflow-dialect behaviors (e.g. the
44
- underscore-key strip) must not leak into the agent profile.
45
-
46
- ## Workspace status
47
-
48
- Lives as an npm workspace inside `ar-io-proof-checker` (v1.2 wave decision
49
- no separate repo yet); the checker consumes it as its verifier. **Not yet
50
- published to npm.** Before any publish: confirm the real npm scope (`@ar.io/`
51
- vs `@ar-io/`), flip `exports` to the built `dist/` output (`npm run build`
52
- emits ESM + type declarations), and get the coordinator's green light.
53
-
54
- MIT verification must be open. See `LICENSE`.
3
+ Verify [ar.io verification-stack](https://github.com/ar-io) provenance records — **with no ar.io code or service in the trust path**.
4
+
5
+ This is the TypeScript verification kernel for the *Verifiable Event Envelope* family: the signed JSON records that tools like the [`ariod` verification agent](https://github.com/ar-io/ar-io-agent) and the [MLflow plugin](https://github.com/ar-io/ar-io-mlflow) anchor permanently to Arweave. Given an envelope (fetched from any Arweave gateway), this package answers: *is it authentic, and does it commit to the bytes I'm holding?*
6
+
7
+ - **RFC 8785 (JCS)** canonicalization
8
+ - **SHA-256** payload binding (WebCrypto)
9
+ - **Ed25519** signature verification ([`@noble/ed25519`](https://github.com/paulmillr/noble-ed25519))
10
+ - **RFC 9162** binary Merkle inclusion proofs (checkpoint leaves)
11
+ - Zero config, two small dependencies, ESM, browser + Node ≥ 20
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ npm install @ar.io/proof
17
+ ```
18
+
19
+ ## Verify an envelope
20
+
21
+ Fetch the raw transaction from any Arweave gateway and verify it client-side:
22
+
23
+ ```ts
24
+ import { verifyEnvelope } from "@ar.io/proof";
25
+
26
+ const env = await (await fetch("https://arweave.net/raw/<tx_id>")).json();
27
+ const result = await verifyEnvelope(env);
28
+
29
+ result.ok; // spec_version + payload_hash + Ed25519 all passed
30
+ result.signatureOk; // Ed25519 over the signed scope, against env.public_key
31
+ result.payloadHashOk; // SHA-256(JCS(payload)) === env.payload_hash
32
+ result.errors; // [] when ok machine-readable reasons otherwise
33
+ ```
34
+
35
+ `verifyEnvelope` never throws on hostile input a malformed envelope (or a lying gateway) yields `ok: false` with reasons, not an exception.
36
+
37
+ ## Bind an envelope to bytes you hold (reverse provenance)
38
+
39
+ The check that defeats a lying gateway: Arweave *tags* are unsigned search hints, so after finding a candidate envelope, confirm it actually commits to your artifact's hash:
40
+
41
+ ```ts
42
+ import { sha256Hex, verifyEnvelope, contentHashes } from "@ar.io/proof";
43
+
44
+ const myHash = await sha256Hex(fileBytes); // 64-char lowercase hex
45
+
46
+ const result = await verifyEnvelope(env, myHash);
47
+ result.contentHashOk; // true ⇔ the envelope commits to exactly these bytes
48
+ result.contentRole; // how it commits: e.g. the registered baseline,
49
+ // an observed (tampered) hash,
50
+
51
+ contentHashes(env); // all content hashes an envelope commits to, by event type
52
+ ```
53
+
54
+ ## Verify a Merkle inclusion proof
55
+
56
+ Agents close daily checkpoints over per-cycle leaves (RFC 9162, §2.1 domain separation — not the Bitcoin duplicate-leaf variant). Verify a leaf's inclusion against an anchored root:
57
+
58
+ ```ts
59
+ import { leafHash, verifyInclusion, hexToBytes } from "@ar.io/proof";
60
+
61
+ const ok = await verifyInclusion(
62
+ await leafHash(leafBytes), // Uint8Array leaf hash
63
+ leafIndex, // 0-based position
64
+ totalLeaves,
65
+ auditPath.map(hexToBytes), // sibling hashes, leaf → root
66
+ hexToBytes(expectedRootHex),
67
+ );
68
+ ```
69
+
70
+ ## API
71
+
72
+ | Export | What it does |
73
+ |---|---|
74
+ | `verifyEnvelope(env, expectedContentHash?)` | The three load-bearing checks (spec-version registry, payload-hash recompute, Ed25519 over the signed scope) + optional content bind. Returns `VerificationResult`. |
75
+ | `contentHashes(env)` | The content hash(es) an envelope commits to, by event type — the reverse-provenance join keys. |
76
+ | `specVersionSupported(v)` | Fail-closed accept-check: `ario.agent/v1` and additive minors (`ario.agent/v1.<n>`). Unknown majors/profiles are rejected. |
77
+ | `jcs(value)` | RFC 8785 canonical JSON bytes. |
78
+ | `sha256Hex(bytes)` / `sha256Bytes(bytes)` | SHA-256 via WebCrypto. |
79
+ | `ed25519Verify(sig, msg, pubKey)` | Raw Ed25519 verification. |
80
+ | `leafHash` / `nodeHash` / `merkleRoot` / `auditPath` / `verifyInclusion` / `EMPTY_TREE_ROOT_HEX` | RFC 9162 binary Merkle tree primitives. |
81
+ | `utf8` / `bytesToHex` / `hexToBytes` | Encoding helpers. |
82
+ | `Envelope` / `VerificationResult` / `ContentRole` / `Subject` | Types. |
83
+
84
+ ### Signed scope
85
+
86
+ The primary signature covers `JCS(envelope minus signature minus co_signatures)` ([envelope-spec](https://github.com/ar-io/ar-io-proof/blob/main/specs/envelope-spec.md) §2/§7.1). The reserved `co_signatures` carve-out lets countersignatures be added later without invalidating the primary signature.
87
+
88
+ ## Why you can trust it (without trusting us)
89
+
90
+ Three **independent implementations** of this kernel exist — this package, the Python [`ar-io-proof`](https://pypi.org/project/ar-io-proof/) (PyPI), and the Go reference ([`ar-io-agent/pkg/proof`](https://github.com/ar-io/ar-io-agent/tree/main/pkg/proof), MIT-carved) — and every one is conformance-gated **byte-for-byte** in CI against the shared, frozen [`test-vectors-v1.0` corpus](https://github.com/ar-io/ar-io-proof/tree/main/test-vectors) (per-file SHA-256 pins). The [proof-checker web app](https://github.com/ar-io/ar-io-proof-checker) additionally runs this kernel and a WASM build of the Go reference against each other live, asserting identical verdicts across the corpus plus adversarial negatives.
91
+
92
+ That mutual gate is the point: anyone can verify ar.io provenance records with **no ar.io code in the trust path** — write your own verifier against the [public specs](https://github.com/ar-io/ar-io-proof/tree/main/specs) and the corpus will tell you if it's conformant.
93
+
94
+ ## What this package deliberately does NOT do
95
+
96
+ - **Single-envelope scope.** Chain walking (`previous_hash`), checkpoint reconciliation, and gateway/transport logic are consumer-layer concerns composed above the kernel.
97
+ - **Provenance is history, not endorsement.** A verified envelope proves *these bytes have this signed, anchored history* — never "safe," "approved," or "currently in production."
98
+ - **Key identity is out-of-band.** The kernel proves the signature matches `env.public_key`; binding that key to a real-world identity is yours to establish.
99
+
100
+ ## Requirements
101
+
102
+ ESM-only. Needs WebCrypto (`globalThis.crypto.subtle`): any modern browser, Node.js ≥ 20 (≥ 19 works), Deno, Bun, workers.
103
+
104
+ ## License
105
+
106
+ MIT — verification must be open.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ar.io/proof",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "TypeScript kernel of the ar.io verification stack: RFC 8785 (JCS) canonicalization, SHA-256, and Ed25519 verification for Verifiable Event Envelopes (ario.agent/v1 profile). Conformance-gated byte-for-byte against the test-vectors-v1.0 corpus.",
5
5
  "license": "MIT",
6
6
  "type": "module",