verifyhash 0.1.0

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 (154) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +883 -0
  3. package/cli/abi/ContributionRegistry.json +881 -0
  4. package/cli/agent.js +2173 -0
  5. package/cli/anchor-artifact.js +853 -0
  6. package/cli/anchor.js +400 -0
  7. package/cli/claim.js +881 -0
  8. package/cli/core/agent-commit.js +448 -0
  9. package/cli/core/agent-session.js +598 -0
  10. package/cli/core/anchor-binding.js +663 -0
  11. package/cli/core/attestation.js +580 -0
  12. package/cli/core/evidence-plans.js +495 -0
  13. package/cli/core/fixtures/evidence-plans/baseline.json +19 -0
  14. package/cli/core/fulfill-intake.js +1082 -0
  15. package/cli/core/go-live-preflight.js +481 -0
  16. package/cli/core/license.js +534 -0
  17. package/cli/core/manifest.js +243 -0
  18. package/cli/core/packetseal.js +591 -0
  19. package/cli/core/registryArtifact.js +49 -0
  20. package/cli/core/revocation.js +539 -0
  21. package/cli/core/rfc3161.js +389 -0
  22. package/cli/core/timestamp.js +482 -0
  23. package/cli/core/trust-asof.js +479 -0
  24. package/cli/dataset.js +2950 -0
  25. package/cli/evidence.js +2227 -0
  26. package/cli/fulfill-webhook-http.js +438 -0
  27. package/cli/git.js +220 -0
  28. package/cli/hash.js +550 -0
  29. package/cli/identity.js +1072 -0
  30. package/cli/journal-cli.js +1110 -0
  31. package/cli/journal-log.js +454 -0
  32. package/cli/journal.js +334 -0
  33. package/cli/lineage.js +447 -0
  34. package/cli/list.js +287 -0
  35. package/cli/parcel.js +1509 -0
  36. package/cli/proof.js +578 -0
  37. package/cli/prove.js +300 -0
  38. package/cli/receipt.js +631 -0
  39. package/cli/registry.js +331 -0
  40. package/cli/reputation.js +344 -0
  41. package/cli/revocation.js +495 -0
  42. package/cli/serve-verify-http.js +298 -0
  43. package/cli/serve-verify.js +333 -0
  44. package/cli/show.js +339 -0
  45. package/cli/verify.js +383 -0
  46. package/cli/vh.js +3927 -0
  47. package/docs/ADOPT.md +183 -0
  48. package/docs/ADOPTION.json +11 -0
  49. package/docs/AGENTTRACE.md +247 -0
  50. package/docs/ANCHORING.md +167 -0
  51. package/docs/AUDIT.md +55 -0
  52. package/docs/CONFORMANCE.md +107 -0
  53. package/docs/DATALEDGER.md +638 -0
  54. package/docs/DECIDE.md +47 -0
  55. package/docs/DECISIONS-PENDING.md +27 -0
  56. package/docs/DEPLOY-PUBLIC-SITE.md +301 -0
  57. package/docs/ENGINE-LEDGER.json +12 -0
  58. package/docs/EVIDENCE.md +519 -0
  59. package/docs/GO-LIVE.md +66 -0
  60. package/docs/IDENTITY.md +123 -0
  61. package/docs/INDEPENDENT-VERIFICATION.md +377 -0
  62. package/docs/INTEGRITY-JOURNAL.md +337 -0
  63. package/docs/KEY-LIFECYCLE.md +179 -0
  64. package/docs/LICENSING.md +46 -0
  65. package/docs/LINEAGE.md +307 -0
  66. package/docs/LOOP-AUDIT-2026-07-03.json +580 -0
  67. package/docs/LOOP-HARDENING-PLAN.md +44 -0
  68. package/docs/MERKLE-LEAVES.md +113 -0
  69. package/docs/METRICS.jsonl +31 -0
  70. package/docs/MORNING.md +204 -0
  71. package/docs/PILOT.md +444 -0
  72. package/docs/PROOFPARCEL.md +227 -0
  73. package/docs/PROOFS.md +262 -0
  74. package/docs/RECEIPTS.md +341 -0
  75. package/docs/REPUTATION.md +158 -0
  76. package/docs/SDK.md +301 -0
  77. package/docs/STRATEGY-ARCHIVE.md +5055 -0
  78. package/docs/SUPERVISOR-RUNBOOK.md +52 -0
  79. package/docs/TRUST-BOUNDARIES.md +335 -0
  80. package/docs/TRUSTLEDGER.md +1976 -0
  81. package/docs/USAGE-BUDGET.json +121 -0
  82. package/docs/VERIFY-SERVICE.md +168 -0
  83. package/index.js +160 -0
  84. package/package.json +41 -0
  85. package/trustledger/build-standalone.js +796 -0
  86. package/trustledger/cli.js +3179 -0
  87. package/trustledger/close.js +391 -0
  88. package/trustledger/corpus.js +159 -0
  89. package/trustledger/dist/BUILD-PROVENANCE.json +99 -0
  90. package/trustledger/dist/trustledger-standalone.html +6197 -0
  91. package/trustledger/dist/trustledger-standalone.html.sha256 +1 -0
  92. package/trustledger/door-core.js +442 -0
  93. package/trustledger/fixtures/bank.csv +7 -0
  94. package/trustledger/fixtures/bank.malformed.csv +3 -0
  95. package/trustledger/fixtures/bank.noalias.csv +5 -0
  96. package/trustledger/fixtures/bank.ofx +34 -0
  97. package/trustledger/fixtures/bank.real.csv +5 -0
  98. package/trustledger/fixtures/corpus/_shared/prior-close.json +22 -0
  99. package/trustledger/fixtures/corpus/bank-book-mismatch--benign-twin/inputs.json +14 -0
  100. package/trustledger/fixtures/corpus/bank-book-mismatch--benign-twin/meta.json +7 -0
  101. package/trustledger/fixtures/corpus/bank-book-mismatch--out-of-trust/inputs.json +14 -0
  102. package/trustledger/fixtures/corpus/bank-book-mismatch--out-of-trust/meta.json +7 -0
  103. package/trustledger/fixtures/corpus/continuity-break--benign-twin/inputs.json +15 -0
  104. package/trustledger/fixtures/corpus/continuity-break--benign-twin/meta.json +7 -0
  105. package/trustledger/fixtures/corpus/continuity-break--out-of-trust/inputs.json +15 -0
  106. package/trustledger/fixtures/corpus/continuity-break--out-of-trust/meta.json +7 -0
  107. package/trustledger/fixtures/corpus/negative-tenant-ledger--benign-twin/inputs.json +13 -0
  108. package/trustledger/fixtures/corpus/negative-tenant-ledger--benign-twin/meta.json +7 -0
  109. package/trustledger/fixtures/corpus/negative-tenant-ledger--out-of-trust/inputs.json +13 -0
  110. package/trustledger/fixtures/corpus/negative-tenant-ledger--out-of-trust/meta.json +7 -0
  111. package/trustledger/fixtures/corpus/owner-overdraw--benign-twin/inputs.json +15 -0
  112. package/trustledger/fixtures/corpus/owner-overdraw--benign-twin/meta.json +7 -0
  113. package/trustledger/fixtures/corpus/owner-overdraw--out-of-trust/inputs.json +15 -0
  114. package/trustledger/fixtures/corpus/owner-overdraw--out-of-trust/meta.json +7 -0
  115. package/trustledger/fixtures/corpus/security-deposit-segregation--benign-twin/inputs.json +16 -0
  116. package/trustledger/fixtures/corpus/security-deposit-segregation--benign-twin/meta.json +7 -0
  117. package/trustledger/fixtures/corpus/security-deposit-segregation--out-of-trust/inputs.json +13 -0
  118. package/trustledger/fixtures/corpus/security-deposit-segregation--out-of-trust/meta.json +7 -0
  119. package/trustledger/fixtures/corpus/subledger-out-of-balance--benign-twin/inputs.json +13 -0
  120. package/trustledger/fixtures/corpus/subledger-out-of-balance--benign-twin/meta.json +7 -0
  121. package/trustledger/fixtures/corpus/subledger-out-of-balance--out-of-trust/inputs.json +13 -0
  122. package/trustledger/fixtures/corpus/subledger-out-of-balance--out-of-trust/meta.json +7 -0
  123. package/trustledger/fixtures/e2e/bank.aliased.csv +4 -0
  124. package/trustledger/fixtures/e2e/bank.csv +4 -0
  125. package/trustledger/fixtures/e2e/bank.nsf.csv +4 -0
  126. package/trustledger/fixtures/e2e/quickbooks.csv +6 -0
  127. package/trustledger/fixtures/e2e/quickbooks.nsf.csv +8 -0
  128. package/trustledger/fixtures/e2e/rentroll.csv +6 -0
  129. package/trustledger/fixtures/e2e/rentroll.nsf.csv +8 -0
  130. package/trustledger/fixtures/e2e/rentroll.short.csv +5 -0
  131. package/trustledger/fixtures/plans/baseline.json +25 -0
  132. package/trustledger/fixtures/plans/price-binding.example.json +27 -0
  133. package/trustledger/fixtures/policy/ambiguous-deposit-example.json +12 -0
  134. package/trustledger/fixtures/policy/baseline.json +19 -0
  135. package/trustledger/fixtures/policy/ca-example.json +12 -0
  136. package/trustledger/fixtures/policy/negative-tenant-ledger-example.json +12 -0
  137. package/trustledger/fixtures/policy/owner-overdraw-example.json +12 -0
  138. package/trustledger/fixtures/quickbooks.csv +7 -0
  139. package/trustledger/fixtures/quickbooks.real.csv +5 -0
  140. package/trustledger/fixtures/rentroll.csv +6 -0
  141. package/trustledger/fixtures/rentroll.real.csv +4 -0
  142. package/trustledger/ingest.js +1163 -0
  143. package/trustledger/lib/policy-bundled-loader.js +44 -0
  144. package/trustledger/lib/sha256-vendored.js +227 -0
  145. package/trustledger/license.js +563 -0
  146. package/trustledger/match.js +551 -0
  147. package/trustledger/plans.js +551 -0
  148. package/trustledger/policy.js +398 -0
  149. package/trustledger/public/index.html +512 -0
  150. package/trustledger/reconcile.js +1486 -0
  151. package/trustledger/report.js +887 -0
  152. package/trustledger/seal.js +854 -0
  153. package/trustledger/server.js +391 -0
  154. package/trustledger/valueproof.js +350 -0
package/docs/PILOT.md ADDED
@@ -0,0 +1,444 @@
1
+ # The verifyhash Pilot — a buyer-facing runbook
2
+
3
+ This is the runbook a prospective **design partner** (and their security team) follows to run the
4
+ verifyhash pilot kit, see the two sellable journeys work end to end, and understand — precisely — what
5
+ each artifact **proves**, what it **does not**, and **where they independently verify it**. It is
6
+ written so a **non-author** can follow it without reading the source, and so a partner can explain it
7
+ to a colleague.
8
+
9
+ Nothing in this pilot touches a real key, a timestamp authority, an RPC endpoint, or any network. It
10
+ runs **offline** and writes **only** to a throwaway workspace.
11
+
12
+ ---
13
+
14
+ ## 1. What you are evaluating
15
+
16
+ verifyhash turns "a set of files, byte-for-byte unaltered, and who vouched for them" into a
17
+ **tamper-evident, independently-verifiable artifact**. The pilot drives the **two** journeys we sell:
18
+
19
+ - **Evidence packets** — seal a folder of compliance / audit / incident / hand-off files into one
20
+ `*.vhevidence.json`, hand it to a counterparty, and let them confirm offline that it is exactly the
21
+ set you sealed (and who signed it).
22
+ - **TrustLedger reconciliation seals** — reconcile a bank statement, a ledger export, and a rent roll
23
+ into a dated audit packet, then seal it so an examiner can confirm **byte-for-byte** that this is the
24
+ exact packet the tool produced.
25
+
26
+ Both ride the **same** provenance core and the **same** independent verifier, so confidence in one
27
+ transfers to the other.
28
+
29
+ > A third, packet-shaped journey — **AgentTrace** agent-session evidence (`vh agent`: seal an ordered
30
+ > AI-agent session log into one tamper-evident, selectively-redactable `*.vhagent.json`) — rides that
31
+ > same core and the same independent verifier, though this kit's script does not drive it. Its
32
+ > buyer-facing spec, honest trust boundary (log unaltered since seal; NOT what the agent actually did;
33
+ > not a trusted timestamp without **P-3**), and a committed map → seal → redact → verify → prove
34
+ > example are in [`AGENTTRACE.md`](AGENTTRACE.md) and
35
+ > [`../examples/agent-session/`](../examples/agent-session/).
36
+
37
+ ---
38
+
39
+ ## 2. Run the kit (zero setup)
40
+
41
+ From a checkout of the repository (run `npm install` once):
42
+
43
+ ```bash
44
+ node pilot/run-pilot.js
45
+ ```
46
+
47
+ You should see two labelled sections — `VERTICAL A — EVIDENCE` and `VERTICAL B — RECONCILE` — each
48
+ listing `[PASS]` checks, then a single final line:
49
+
50
+ ```
51
+ VERDICT: PASS — N/N checks passed (evidence + reconcile).
52
+ ```
53
+
54
+ The process exits **0** on an all-PASS run (CI-gateable). It writes its artifacts to a fresh OS temp
55
+ directory; set `PILOT_OUT=<dir>` to choose where, or `PILOT_KEEP=1` to keep the workspace so you can
56
+ open the produced files. It **never** writes into the repository, and the committed sample inputs are
57
+ **read-only** — the tamper step always hits a throwaway copy.
58
+
59
+ ### Run it on YOUR OWN folder (the question every partner asks first)
60
+
61
+ The default run above seals the committed sample. To watch the **exact same** journey — license-gated
62
+ `--sign` → independent `verify-vh` ACCEPT → TAMPER → REJECT — run against **your own** evidence folder,
63
+ point the evidence vertical at it in **one command**:
64
+
65
+ ```bash
66
+ node pilot/run-pilot.js --evidence-dir /path/to/your/folder
67
+ # …or, equivalently, via the environment:
68
+ PILOT_EVIDENCE_DIR=/path/to/your/folder node pilot/run-pilot.js
69
+ ```
70
+
71
+ **The kit does NOT modify your files.** It **copies** your folder into the throwaway workspace and seals,
72
+ verifies, and tampers **only the copy**; your originals are **read-only** and are never written, renamed,
73
+ or deleted (their bytes and mtimes are unchanged after the run — this is asserted by the test suite). If
74
+ the folder is **missing, empty, or unreadable**, the kit **hard-errors with a clear message before it
75
+ seals anything** — never a misleading PASS over no data. On a valid folder you get the same single
76
+ `VERDICT: PASS` line, computed on *your* data.
77
+
78
+ Folder size doesn't matter: the demo mints an **ephemeral, throwaway** license that grants the full paid
79
+ evidence surface (`evidence_signed` + `evidence_unlimited`), so a realistic evidence/audit folder with
80
+ dozens of files runs to the same all-PASS verdict — you are never gated by the free-sample size in the
81
+ pilot. (In production, sealing more than the free sample is the paid tier; here the demo license simply
82
+ unlocks it for you so you can watch the whole journey on your real data.)
83
+
84
+ > Operator quick reference (knobs, file map, how it can't rot):
85
+ > [`pilot/README.md`](../pilot/README.md).
86
+
87
+ ### The link-shaped first contact (evidence vertical — one page in their browser, no Node)
88
+
89
+ The very first touch does not even need a terminal — on either side. Send the prospect **one committed
90
+ file**, [`../verifier/dist/verify-vh-standalone.html`](../verifier/dist/verify-vh-standalone.html)
91
+ (it is also in the verifyhash.com site publish set — `site/publish-set.json`; uploading the assembled
92
+ webroot to the live site remains the standing human-owned deploy step). They double-click it and the
93
+ page opens in their browser with the **60-second challenge built in**: click **"Load the sample packet
94
+ & verify"** (**ACCEPT**), change ONE character of the editable sample file on the page, re-verify
95
+ (**REJECT** — the page names the file changed) — then drag a REAL sealed packet + its files in for the
96
+ same verdict + per-file tamper localization the CLI prints. The privacy claim is verifiable, not a
97
+ promise: the file contains **no network API at all**, so their bytes never leave their machine — the
98
+ browser **devtools Network tab** stays empty. The boundary is §5's, unchanged and stated on the page
99
+ itself; for CI/production gating use the node standalone (`verify-vh-standalone.js`) — the §4 merge
100
+ gate, not the browser page, is what lives in a pipeline. The guided walkthrough (browser path first,
101
+ node path as the CI-shaped variant) is [`../challenge/README.md`](../challenge/README.md).
102
+
103
+ ### Evaluate it with ZERO install first (the 10-second no-clone path)
104
+
105
+ Before you check out the repo at all, you can drive the **whole** evidence journey — seal → hand-off →
106
+ verify — from **two self-contained files**, with **no clone, no `npm install`, no account, no key** on
107
+ either side. Save [`../verifier/dist/seal-vh-standalone.js`](../verifier/dist/seal-vh-standalone.js) and
108
+ [`../verifier/dist/verify-vh-standalone.js`](../verifier/dist/verify-vh-standalone.js) (each depends on
109
+ nothing but Node core), then:
110
+
111
+ ```bash
112
+ # 1. Seal up to 25 of YOUR OWN files into one tamper-evident packet:
113
+ node seal-vh-standalone.js /path/to/your/folder -o packet.vhevidence.json # exit 0 = sealed
114
+
115
+ # 2. Hand packet.vhevidence.json + the folder to a counterparty; they run the FREE verifier:
116
+ node verify-vh-standalone.js packet.vhevidence.json --dir /path/to/your/folder # 0 = verifies, 3 = REJECTED
117
+ ```
118
+
119
+ That is the same organic loop a real counterparty would run, on your own data, before any sales call. The
120
+ free seal proves **tamper-evidence + offline-recompute** — and **NOT** a trusted "sealed at T" (that still
121
+ requires **P-3** — see §5). The free seal is **UNSIGNED** and **capped at 25 files**; **SIGNING** (so a
122
+ counterparty can pin you with `--vendor`) and **UNLIMITED** sealing are the PAID upgrade —
123
+ `vh evidence seal --sign` / the `evidence_unlimited` entitlement. Full round-trip in
124
+ [`../verifier/README.md`](../verifier/README.md) §0a and
125
+ [`INDEPENDENT-VERIFICATION.md`](INDEPENDENT-VERIFICATION.md) §0a. The `node pilot/run-pilot.js` kit above
126
+ is the deeper, license-gated evaluation; this zero-install loop is the fastest first taste.
127
+
128
+ ### Zero-install: the offline app (TrustLedger — email them ONE file)
129
+
130
+ The TrustLedger vertical has an even shorter zero-install path — **no terminal at all, on either
131
+ side**. You **email ONE file** to the design partner (or hand it over on a USB stick):
132
+ [`../trustledger/dist/trustledger-standalone.html`](../trustledger/dist/trustledger-standalone.html).
133
+ The partner **double-clicks** it — it opens as an ordinary page in their browser — then **drags their
134
+ REAL exports** onto the page's three file inputs (the **bank statement**, the **QuickBooks trust
135
+ ledger**, and the **rent roll**; the same in-page "Check this file" inspect/map onboarding fixes a
136
+ file that won't load), and **reads the same tie-out report** the installed product produces: the
137
+ PASS/FAIL verdict, the three balances, the exceptions, and the downloadable HTML + CSV audit packet.
138
+
139
+ Run **month-1**'s three files, then **month-2**'s — **two INDEPENDENT monthly tie-outs on real
140
+ data**, a FREE, zero-install willingness-to-pay signal that the recurring monthly product ties out on
141
+ the partner's own exports (part of the sharpened P-5 ask's "run their REAL month-1 + month-2 files"
142
+ step). The offline app runs **each month independently** — its UI has only the three file pickers, so
143
+ the **machine-checked continuity roll-forward** (month-1's signed close carried into month 2 with **no
144
+ `CONTINUITY_BREAK`**, via `--emit-close` / `--prior-close`) is **not** in the offline app; it stays an
145
+ **installed-CLI** capability. The engine inlined in the file is pinned **byte-identical** to the
146
+ installed one — *including* on exactly that two-month **prior-close** clean roll-forward at the
147
+ **payload level**, which proves the bundle's *engine* supports the roll-forward, not that the app's UI
148
+ delivers it ([`../test/trustledger.standalone.test.js`](../test/trustledger.standalone.test.js)).
149
+
150
+ The privacy claim — the #1 objection with live trust-account data — is **honest and verifiable, not
151
+ a promise**: the page makes **NO network request**, because the file **contains no network API at
152
+ all** (no `fetch(`, no `XMLHttpRequest`, no `WebSocket`/`EventSource`/`sendBeacon`, no dynamic
153
+ `import(`) — **check the browser devtools Network tab yourself**: it stays empty, so the partner's
154
+ trust-account data **never leaves their machine**. A recipient can confirm the received file is the
155
+ published one with `sha256sum -c trustledger-standalone.html.sha256`.
156
+
157
+ The honesty boundary, stated plainly: the offline app is the FREE funnel tier — per-state policy
158
+ tables, sealing, and licensing/fulfillment run in the installed product, and P-5's CPA/counsel
159
+ review, vendor-key provisioning, pricing, and publishing steps remain HUMAN-OWNED and UNCHANGED (no
160
+ new needs-human item, no relaxed gate). Requesting a paid surface in the offline app yields the
161
+ **same named `license_required` refusal** the web door gives — the gate is reused, never weakened.
162
+ The deeper spec is in [`TRUSTLEDGER.md`](TRUSTLEDGER.md) › *Zero-install: the offline app*.
163
+
164
+ ---
165
+
166
+ ## 3. What each artifact proves — and where you independently verify it
167
+
168
+ The pilot produces three kinds of artifact. For each, here is the claim it carries and **how a partner
169
+ checks it themselves, without trusting us**.
170
+
171
+ ### 3a. The evidence packet (`*.vhevidence.json`)
172
+
173
+ - **What it proves.** This exact set of files, byte-for-byte. The packet is a content-addressed
174
+ keccak Merkle root over `(relPath, content)` pairs, optionally wrapped in an EIP-191 signature that
175
+ binds **who** vouched (the operator key).
176
+ - **Where you verify it independently.** Run the standalone verifier on the bytes you were handed:
177
+
178
+ ```bash
179
+ node verifier/verify-vh.js --dir <evidence-folder> --vendor <0xOperatorAddress> <packet>.vhevidence.json
180
+ ```
181
+
182
+ Exit **0** = the folder matches the packet and the signature recovers to the address you pinned;
183
+ exit **3** = REJECTED, and the output **localizes** which file CHANGED / MISSING / UNEXPECTED. The
184
+ verifier is in its own [`verifier/`](../verifier/) tree with near-zero dependencies (`js-sha3`
185
+ only — **no** `ethers`, **no** `hardhat`), so you are not installing our producer stack to check our
186
+ claim. **Zero-install option:** for a counterparty who was handed only a packet, save the single
187
+ self-contained file [`verifier/dist/verify-vh-standalone.js`](../verifier/dist/verify-vh-standalone.js)
188
+ (optionally check its published `verify-vh-standalone.js.sha256`) and run
189
+ `node verify-vh-standalone.js <packet> --vendor <0xOperator>` — no clone, no `npm install`, no account;
190
+ it is byte-for-byte the same verifier and proves the same **tamper-evidence + signer-pin**, NOT a
191
+ trusted "sealed at T" (that still requires **P-3**). See [`verifier/README.md`](../verifier/README.md)
192
+ §0 and [`INDEPENDENT-VERIFICATION.md`](INDEPENDENT-VERIFICATION.md) §0.
193
+ - **And confirm the VERIFIER itself rejects what it should** — run the adversarial conformance corpus
194
+ (`node challenge/corpus/run-corpus.js`, exit 0 = every poisoned input REJECTED by every shipped
195
+ verifier) in place of trusting our claim; it proves REJECT of every *enumerated* tamper class (NOT the
196
+ absence of unknown ones, and a REJECT is tamper-evidence NOT a trusted timestamp without **P-3**). See
197
+ [`CONFORMANCE.md`](CONFORMANCE.md).
198
+
199
+ ### 3b. The TrustLedger reconciliation seal
200
+
201
+ - **What it proves.** The three balances tied out to a single PASS/FAIL on a stated date, and the
202
+ sealed packet (sources + every emitted file + the verdict/role header) is byte-for-byte the packet
203
+ the tool produced — any edit, rename, add, or removed input REJECTS.
204
+ - **Where you verify it independently.** The **same** verifier re-derives the keccak root from the
205
+ source bytes you hold:
206
+
207
+ ```bash
208
+ node verifier/verify-vh.js --dir <reconcile-folder> <reconciliation-...-seal>.json
209
+ ```
210
+
211
+ Exit **0** = the root re-derives from the bytes on disk; exit **3** = REJECTED, localized to the
212
+ changed source. (The pilot's reconciliation seal is **unsigned**, so you do not pin `--vendor` for
213
+ it — an unsigned artifact cannot be signer-pinned.)
214
+
215
+ - **And confirm the GATE itself is correct — run this in place of trusting our disclaimer.** A seal proves
216
+ the packet is byte-for-byte unaltered; it does **not** tell you whether a **FAIL really means out of
217
+ trust**. To confirm the reconciliation **gate** is correct — that it FAILs the canonical trust-account
218
+ frauds and PASSes their benign twins — run the committed **correctness corpus**, one read-only command,
219
+ no setup:
220
+
221
+ ```bash
222
+ vh trust corpus # exit 0 = CORPUS OK (every scenario matches); exit 3 = CORPUS DRIFT
223
+ ```
224
+
225
+ It drives a committed library of out-of-trust scenarios (an un-segregated security deposit, a
226
+ sub-ledger out of balance, a negative individual ledger, an owner over-draw, a bank-short mismatch, a
227
+ broken roll-forward) **and** their benign near-twins through the **same** engine path the real
228
+ `reconcile` exit uses, and prints a per-scenario table (control, expected vs **actual** verdict,
229
+ `OK`/`MISMATCH`) plus the trust-law **principle** under each row. This is what a CPA or broker **runs**
230
+ to confirm the gate is correct **in place of trusting our disclaimer** (see
231
+ [`TRUSTLEDGER.md`](TRUSTLEDGER.md) › *The correctness corpus*). It **confirms the gate's behaviour** —
232
+ it does **NOT** certify a jurisdiction or constitute legal advice; for TrustLedger a PASS does **not**
233
+ imply legal compliance, the broker remains the responsible legal custodian, and that meaning stays
234
+ CPA/counsel-reviewed under **P-5** (§5).
235
+
236
+ ### 3c. The licence (`*.vhlicense.json`)
237
+
238
+ - **What it proves.** It is the **access credential** that unlocks the paid surface (`evidence
239
+ seal --sign`, `reconcile --seal`). It is signed by the vendor key and verified offline; a wrong,
240
+ expired, or under-entitled licence is a **hard refuse**, never a silent downgrade. The pilot proves
241
+ this gate is **real** by showing the paid surface refused with **no** licence and refused again with
242
+ a licence pinned to the **wrong** vendor.
243
+ - **What it is NOT.** Not a token, not tradeable, not an appreciating asset. Income is a subscription
244
+ / licence for delivered software value — the credential is just the key to the door.
245
+
246
+ ### 3d. The pilot result certificate — your SHAREABLE deliverable (`--certificate`)
247
+
248
+ When you run the pilot on your own folder (§2), the terminal `VERDICT: PASS` is the proof *on your
249
+ machine*. To turn "the demo passed on my machine" into a **forwardable, tamper-evident record** your
250
+ security and procurement teams can check for themselves, add one flag and the kit seals the run into a
251
+ portable `*.vhevidence.json` **certificate**:
252
+
253
+ ```bash
254
+ node pilot/run-pilot.js --evidence-dir /path/to/your/folder --certificate ./pilot-result.vhevidence.json
255
+ ```
256
+
257
+ This writes two things alongside each other — the certificate `pilot-result.vhevidence.json` and its
258
+ companion `pilot-result.files/` directory (the sealed result bytes). **Forward both together.** Anyone
259
+ you hand them to verifies the certificate **independently**, with **no clone, no `npm install`, no
260
+ account, no key**, using the zero-install single-file verifier
261
+ [`../verifier/dist/verify-vh-standalone.js`](../verifier/dist/verify-vh-standalone.js):
262
+
263
+ ```bash
264
+ # they save verify-vh-standalone.js, then run it on the bytes you forwarded:
265
+ node verify-vh-standalone.js --dir ./pilot-result.files ./pilot-result.vhevidence.json # exit 0 = ACCEPT, 3 = REJECT
266
+ ```
267
+
268
+ Exit **0** = the certificate's keccak root re-derives from the bytes on disk — the result record is
269
+ exactly what the pilot produced; exit **3** = REJECTED, localized to the byte that changed. The kit
270
+ prints the precise verify command (and, for a signed certificate, the operator address to pin with
271
+ `--vendor`) after the verdict line. That is what turns a one-off demo into a record your team can carry
272
+ into a procurement review and confirm without trusting you — or us.
273
+
274
+ **Then READ the verdict out of the bytes you just verified — the certificate is a self-contained
275
+ procurement record, not just a checksum.** The whole point of a forwardable certificate is that the
276
+ reviewer who confirmed exit `0` does **not** then have to take a sales claim about *what the run checked*
277
+ on faith: the **machine-readable result record** — `verdict`, the `passed`/`total` counts, and the full
278
+ **labelled checklist** of every gate the pilot exercised — lives **inside** `pilot-result.files/pilot-result.json`,
279
+ which is the **exact byte stream the keccak root commits to**. So once verify-vh ACCEPTs, the contents of
280
+ that file are *part of what was proven unaltered*. Read the headline with one Node-only line (no extra
281
+ install, no `jq` needed):
282
+
283
+ ```bash
284
+ # the same file the certificate's root commits to — its contents are part of what you just verified:
285
+ node -e 'const r=require("./pilot-result.files/pilot-result.json"); console.log(r.verdict+" — "+r.passed+"/"+r.total+" checks; evidenceSource="+r.evidenceSource)'
286
+ # → PASS — 24/24 checks; evidenceSource=partner
287
+
288
+ # and read the FULL labelled checklist of what was actually exercised (open it, or list the labels):
289
+ node -e 'require("./pilot-result.files/pilot-result.json").checks.forEach(c=>console.log((c.ok?"[PASS] ":"[FAIL] ")+c.label))'
290
+ ```
291
+
292
+ `evidenceSource` reads `partner` when the pilot ran on the partner's **own** folder (§2) and `canned` on
293
+ the committed sample — so a procurement reviewer can see at a glance whether the forwarded certificate was
294
+ produced on real data or the demo set, **from the verified bytes themselves**. (`jq -r '.verdict' pilot-result.files/pilot-result.json`
295
+ works identically if your reviewer prefers it.) This is the leverage of the certificate over a bare
296
+ PASS/FAIL screenshot: the verdict, the counts, and the precise list of checks are a tamper-evident,
297
+ forwardable **artifact** a security/procurement team reads and re-confirms on its own — the screenshot is
298
+ not.
299
+
300
+ **The HONEST boundary (read this before you forward it).** The certificate proves WHAT the pilot run
301
+ checked and that the result bytes are unaltered — it is tamper-evidence over the run record, NOT a
302
+ trusted "the pilot ran at time T" without P-3, and NOT a legal/compliance verdict. The pilot signs
303
+ with **ephemeral throwaway keys only**, so any date inside the record is self-asserted input, not an
304
+ independent attestation of *when* — a trusted "ran at time T" still requires the human-owned trust-root
305
+ of **P-3** (§5). And it is tamper-evidence over a run record, not an opinion: it makes no legal or
306
+ compliance claim (for TrustLedger a PASS does not imply legal compliance — that meaning stays
307
+ CPA/counsel-reviewed under **P-5**, §5).
308
+
309
+ ---
310
+
311
+ ## 4. Wire it into your pipeline (this is how the pilot lives in your release process)
312
+
313
+ A pilot you run once is a demo; a pilot that **lives in your CI** is a dependency. The same independent
314
+ `verify-vh` you ran by hand in §3 drops into your build as a **merge gate**: the moment a sealed
315
+ artifact is tampered, forged, or signed by the wrong key, the build goes **red** and the merge is
316
+ **blocked**. You do not install our producer stack to do this — the gate runs the standalone verifier
317
+ (`js-sha3` only, **no** `ethers`, **no** `hardhat`).
318
+
319
+ We ship the snippet so this is **one paste**, not a project. A non-author wires it in like so:
320
+
321
+ 1. Copy [`../verifier/ci/verify-vh.generic.sh`](../verifier/ci/verify-vh.generic.sh) into your repo (a
322
+ portable `set -e` shell gate for GitLab CI, CircleCI, Jenkins, a Makefile recipe, or a git hook), or
323
+ drop [`../verifier/ci/verify-vh.github-actions.yml`](../verifier/ci/verify-vh.github-actions.yml) at
324
+ `.github/workflows/verify-vh.yml` for GitHub Actions.
325
+ 2. Add **three lines** to the pipeline step that runs it — the producer address you pin out-of-band, the
326
+ artifact(s) or release manifest, and the call:
327
+
328
+ ```bash
329
+ export VH_VENDOR=0xYOUR_PRODUCERS_SIGNER_ADDRESS # pinned out-of-band
330
+ export VH_MANIFEST=release.manifest # or VH_ARTIFACTS="dist/packet.vhevidence.json"
331
+ ./verifier/ci/verify-vh.generic.sh # exit 0 = green/merge; non-zero = red/blocked
332
+ ```
333
+
334
+ 3. Read the gate: a **green** check *means* every sealed artifact still matches the bytes the producer
335
+ signed (exit `0`). A **red** gate *means* a `3` (REJECTED — a sealed byte changed / wrong signer,
336
+ localized to the offending artifact and file), a `2` (usage error), or a `1` (an artifact could not
337
+ even be read) — and your merge is **blocked** until it is resolved. A non-zero verdict never slips
338
+ through as a silent pass.
339
+
340
+ **The boundary stays explicit even in CI: verification is FREE, sealing is PAID.** The gate above — and
341
+ every `verify-vh` invocation — costs nothing and needs no licence; anyone may verify forever, offline.
342
+ The licence (§3c) gates only the **paid sealing surface** (`evidence seal --sign`, `reconcile --seal`)
343
+ on the **producer** side. So your pipeline can gate on our proofs without buying anything; what your
344
+ counterparty pays for is the right to **produce** sealed artifacts, not your right to **check** them.
345
+
346
+ The shipped snippets are **examples the loop never runs**, but their exact gate command is mechanically
347
+ tested ([`../test/verifier.ci-snippet.test.js`](../test/verifier.ci-snippet.test.js)): it must exit `0`
348
+ on a good release and `3` on a tampered one, so the snippet you copy is known-good, not aspirational.
349
+ The deeper spec is in [`../verifier/README.md`](../verifier/README.md) §2b and
350
+ [`INDEPENDENT-VERIFICATION.md`](INDEPENDENT-VERIFICATION.md) §4b.
351
+
352
+ > **And that is where the pilot ends:** not at "it worked once on a demo," but wired into your release
353
+ > process, failing your build the day someone hands you a seal that no longer matches its bytes.
354
+
355
+ ---
356
+
357
+ ## 5. The honest trust boundary (read this before you rely on anything)
358
+
359
+ The pilot is deliberately conservative about what it claims:
360
+
361
+ - **It proves tamper-evidence + offline-recompute + signer-pin.** "These are exactly those files" and
362
+ "this address vouched for them" — both checkable by you, offline, with the independent verifier.
363
+ - **It does NOT prove a trusted timestamp.** There is **no trusted "sealed on date T" without P-3.**
364
+ A trustworthy "existed by date T" requires a **human-owned trust-root** — a self-managed signing
365
+ key, an independent RFC-3161 timestamp authority, or an on-chain anchor — which is **P-3** in
366
+ [`STRATEGY.md`](../STRATEGY.md). The pilot uses **ephemeral throwaway keys only**, so it asserts
367
+ nothing about *when*; any date you see in a licence window or report is self-asserted input, not an
368
+ independent attestation.
369
+ - **It is NOT a legal or compliance opinion.** The evidence packet makes no domain claim beyond
370
+ tamper-evidence; for TrustLedger, a PASS does **not** imply legal compliance (that meaning is
371
+ CPA/counsel-reviewed — P-5).
372
+ - **The pilot ends at the explicit human handoff** and overclaims nothing. The handoff (provision a
373
+ real key / TSA, choose a price, run the partner) is the human go-to-market ask, consolidated as
374
+ **P-8** below.
375
+
376
+ This boundary is not a footnote — it is the product. We sell verifiable *tamper-evidence and
377
+ provenance*, and we are explicit that *trusted time* is a separate, human-owned upgrade.
378
+
379
+ ---
380
+
381
+ ## 6. The single go-to-market ask (P-8)
382
+
383
+ Everything above is **built, tested, and green**. The one thing the loop cannot do — and the one thing
384
+ a human must — is **land a design partner and run a pilot**. That precondition was scattered across
385
+ four proposals (P-3 trust-root, P-5 TrustLedger legal/CPA/design-partner, P-6 TrustLedger licence
386
+ delivery + pricing, P-7 evidence vertical go-to-market). It is now **consolidated into one
387
+ decision-ready ask, P-8**, in [`STRATEGY.md`](../STRATEGY.md) → *Proposals — needs-human*, whose
388
+ **deliverable is this very kit**. Read P-8 to see the precise human steps and how running this pilot
389
+ de-risks all four gates at once.
390
+
391
+ The first artifact that ask sends a cold prospect can now be **link-shaped**: the browser challenge
392
+ page in §2 — one file, `verify-vh-standalone.html`, no Node, no install, nothing to type — with the
393
+ node standalone as the CI-shaped follow-up. That changes the *first contact*, not the ask: every human
394
+ step above stays human-owned and unchanged.
395
+
396
+ ### The pilot success contract (the measured WTP instrument)
397
+
398
+ A pilot that ends at "the partner liked it" leaves the money question — **"is this worth paying for ON MY
399
+ data?"** — to a relational hunch. The TrustLedger pilot's success contract is therefore a **measured**
400
+ one, run on the partner's **own already-closed period**: **`vh trust value-proof`**. The partner runs a
401
+ month they **already reconciled by hand and signed off**, and the command compares the **same** reconcile
402
+ gate against that manual close and prints **one of three outcomes**, exit-coded so the pilot can read the
403
+ result without interpretation:
404
+
405
+ ```bash
406
+ vh trust value-proof <bank> <ledger> <rentroll> --period <label>
407
+ # exit 3 = out_of_trust_missed — the dollars the gate caught that the manual close LET THROUGH (the WTP case)
408
+ # exit 4 = data_gap_only — fix-my-data-and-re-run; NOT (yet) evidence the money is gone
409
+ # exit 0 = clean_confirmed — a signed, independent confirmation of a clean trust account
410
+ ```
411
+
412
+ Every count and dollar figure is read **verbatim** off the period's reconciliation — the **same**
413
+ numbers `vh trust reconcile --json` shows — so the value-proof is the **same** verdict path the paying
414
+ broker's licensed gate runs, not a narrower one. The deeper spec is in
415
+ [`TRUSTLEDGER.md`](TRUSTLEDGER.md) › *The value-proof*. This is the **measured** form of P-5 #3's
416
+ two-month WTP validation: it turns "their willingness to keep using it is the WTP signal" into a dollar
417
+ figure a broker reads on **their own** month.
418
+
419
+ > **The value-proof COMPARES the gate to the manual close — it does NOT certify a jurisdiction or
420
+ > constitute legal advice.** It quantifies what the gate found that the broker's manual close did not; it
421
+ > does not certify that any state's trust-fund rules are satisfied and is not legal/accounting/audit
422
+ > advice. The standing TrustLedger pilot posture is unchanged: a **PASS does not imply legal compliance**,
423
+ > the broker remains the **responsible legal custodian**, and that meaning stays CPA/counsel-reviewed
424
+ > under **P-5**.
425
+
426
+ ---
427
+
428
+ ## 7. Why this is trustworthy to run
429
+
430
+ - **Offline + no key + no network.** No real private key is ever created, held, persisted, read, or
431
+ echoed; every key in the run is an in-process `Wallet.createRandom()`. No socket is opened.
432
+ - **Read-only of your inputs.** Whether you run the canned sample or `--evidence-dir <your folder>`, the
433
+ source is read-only; the kit copies it and every seal/tamper hits the copy. Your originals are never
434
+ written, renamed, or deleted. And even on your own data the boundary is unchanged: the seal proves
435
+ **tamper-evidence + signer-pin**, NOT a trusted "sealed at T" (that still requires **P-3**).
436
+ - **Cannot silently rot.** The journey is gated by
437
+ [`test/pilot.evidence.test.js`](../test/pilot.evidence.test.js) +
438
+ [`test/pilot.reconcile.test.js`](../test/pilot.reconcile.test.js), and this runbook's claims are
439
+ gated by [`test/pilot.docs.test.js`](../test/pilot.docs.test.js), all under the project's unchanged
440
+ `npx hardhat test`. If the behaviour or the claims drift, the suite fails.
441
+
442
+
443
+ ---
444
+ <sub>© 2026 verifyhash.com · Licensed under Apache-2.0 (SPDX-License-Identifier: Apache-2.0) — see the [LICENSE](https://verifyhash.com/LICENSE) and [NOTICE](https://verifyhash.com/NOTICE) served with this file.</sub>