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/SDK.md ADDED
@@ -0,0 +1,301 @@
1
+ # verifyhash SDK — the stable, semver-guarded public API
2
+
3
+ `require("verifyhash")` gives a downstream program the **exact same** functions the `vh` CLI runs — no
4
+ fork, no second implementation. `index.js` is a *thin, identity re-export* of the already-built,
5
+ already-tested core (proven by `test/sdk.index.test.js`): every symbol below is the same function object
6
+ the corresponding `cli/…` module exports, so a seal built with `sdk.buildSeal(...)` verifies (`ACCEPTED`)
7
+ with `sdk.verifySeal(...)` and a one-byte tamper is `REJECTED` — identical to `vh evidence seal` /
8
+ `vh evidence verify`.
9
+
10
+ This file is the **canonical reference for the SDK's public surface**, and it is machine-checked: the
11
+ [machine-checked surface descriptor](#machine-checked-surface-semver--abi-contract) below is *generated*
12
+ from the live `index.js` exports by [`scripts/gen-sdk-surface.cjs`](../scripts/gen-sdk-surface.cjs) and
13
+ byte-matched against them by [`test/sdk.contract.test.js`](../test/sdk.contract.test.js), so it cannot
14
+ silently drift from the code.
15
+
16
+ ---
17
+
18
+ ## Stability & semver policy
19
+
20
+ The **ABI** re-exported from `index.js` **is** the package's stability contract. The guard pins the
21
+ contract a downstream program *actually integrates against* — not just symbol names, but the three things
22
+ whose silent drift would break a consumer without a loud rename:
23
+
24
+ - **Anything listed below is PUBLIC.** Removing it, renaming it, or moving it between namespaces is a
25
+ **breaking change** and requires a **semver-major** version bump. So is changing its *kind*
26
+ (e.g. a `function` becoming a `string`).
27
+ - **Function arity is pinned** (`name : function/<arity>`). Adding a *required* parameter to an exported
28
+ function — e.g. `verifySeal(seal, entries)` → `verifySeal(seal, entries, opts)` — changes its **call
29
+ signature** and is a breaking change, even though the name and kind are unchanged.
30
+ - **Frozen wire values are pinned** (`name : string="…"` / `number=…`). The seal **kind tag**
31
+ (`seal.KIND`), the **schema versions** (`seal.SCHEMA_VERSION`, `receipts.SCHEMA_VERSION`), the receipt
32
+ kind tags, and the `TRUST_NOTE` are constants a consumer hard-codes or branches on; bumping one is a
33
+ wire-format change, so the pin catches it. (A schema bump 1→2 keeps `number` as the kind — a name-only
34
+ guard would miss it; this one does not.)
35
+ - **The `verifySeal` result shape is pinned** (`#verifySeal.result : <sorted keys>`). A consumer
36
+ destructures `{ verdict, accepted, changed, … }`; dropping or renaming a result key is a breaking
37
+ change to the return contract, and the descriptor's behavioral tail catches it.
38
+ - **Adding a new symbol** is a minor (backward-compatible) change.
39
+ - A **patch/minor** release may freely change a symbol's *behavior-preserving internals* or bump the
40
+ version string. The version is the **one** value intentionally left un-pinned: `apiVersion` is rendered
41
+ by *kind only* (`string`, never its value), so a version bump alone never trips the guard.
42
+ - **`apiVersion`** mirrors `package.json`'s `version` field and is the single source of truth for the
43
+ surface's semver number. It is a `string`.
44
+ - **Deep `cli/*` internals are NOT part of the stable surface.** Only what `index.js` re-exports (and what
45
+ the `exports` map in `package.json` resolves) is guaranteed. Reaching into `verifyhash/cli/...` is
46
+ reaching into unstable, internal code that may change in any release without a major bump — the
47
+ `exports` map deliberately blocks importing those subpaths by name.
48
+
49
+ ### Changing the surface (one command)
50
+
51
+ The machine-checked descriptor is **generated, never hand-edited**. When you deliberately change the
52
+ surface:
53
+
54
+ ```sh
55
+ npm run sdk:surface -- --write # regenerate the descriptor block in this file from index.js
56
+ npm run sdk:surface -- --check # CI drift gate: exit 1 if this doc has drifted from the exports
57
+ npm run sdk:surface # print the current descriptor to stdout
58
+ ```
59
+
60
+ Then paste the regenerated block into the `EXPECTED_SURFACE` pin in
61
+ [`test/sdk.contract.test.js`](../test/sdk.contract.test.js) in the **same commit**. The contract test
62
+ fails loudly if this document, that pin, and the live `index.js` exports ever disagree — keeping doc ==
63
+ pin == code.
64
+
65
+ ---
66
+
67
+ ## The public surface
68
+
69
+ Grouped for humans. Every function is the **identity** re-export of its `cli/…` source; the flat
70
+ top-level names (`buildSeal`, `verifySeal`, …) are the same objects as the grouped ones (`seal.buildSeal`,
71
+ `seal.verifySeal`, …), provided for convenience.
72
+
73
+ ### Top level
74
+
75
+ | Symbol | Kind | Meaning |
76
+ | --- | --- | --- |
77
+ | `apiVersion` | string | Semver version of this public surface; mirrors `package.json` `version`. |
78
+ | `seal` | namespace | The evidence-seal SDK (see below). |
79
+ | `signed` | namespace | The SIGNED / vendor-pinned verify SDK — the embedded twin of `vh evidence verify-signed` (see below). |
80
+ | `receipts` | namespace | The anchor/claim receipt codec + manifest diff (see below). |
81
+ | `hashing` | namespace | The keccak/Merkle hashing primitives (see below). |
82
+
83
+ The flat convenience re-exports at the top level are exactly the members of the four namespaces:
84
+ `buildSeal`, `validateSeal`, `serializeSeal`, `readSeal`, `verifySeal`, `PacketSealError` (from `seal`);
85
+ `signSealWith`, `validateSignedSeal`, `verifySignedSeal`, `verifySignedSealAttestation`, `recoverSigner`,
86
+ `verifySignedAttestation` (from `signed`);
87
+ `buildReceipt`, `buildAnchorReceipt`, `writeReceipt`, `readReceipt`, `diffManifest` (from `receipts`);
88
+ `hashBytes`, `hashFile`, `hashEntries`, `hashDir`, `hashPath`, `buildTree` (from `hashing`).
89
+
90
+ ### `seal` — build / verify a tamper-evident evidence seal
91
+
92
+ | Symbol | Kind | Meaning |
93
+ | --- | --- | --- |
94
+ | `seal.KIND` | string | The seal document kind tag. |
95
+ | `seal.SCHEMA_VERSION` | number | The seal schema version. |
96
+ | `seal.TRUST_NOTE` | string | The one-line trust-boundary note carried in every seal. |
97
+ | `seal.buildSeal` | function | `buildSeal(entries)` → seal object, from a flat `{ relPath, bytes }` list. |
98
+ | `seal.validateSeal` | function | `validateSeal(seal)` → throws on structural / root-mismatch problems. |
99
+ | `seal.serializeSeal` | function | `serializeSeal(seal)` → canonical, byte-deterministic JSON. |
100
+ | `seal.readSeal` | function | `readSeal(jsonOrObject)` → parsed + strictly validated seal. |
101
+ | `seal.verifySeal` | function | `verifySeal(seal, entries)` → `{ verdict, accepted, … }`; RE-DERIVES the root. |
102
+ | `seal.PacketSealError` | function | The error class the generic seal core throws (advanced / custom products). |
103
+
104
+ ### `signed` — verify a SIGNED / vendor-address-pinned seal in-process
105
+
106
+ The embedded twin of `vh evidence verify-signed`: identity re-exports of the already-shipped, CLI-run
107
+ signed-verify functions, so an embedder verifies a **signed, address-pinned** seal in-process with **no
108
+ shell-out** to the `vh` binary — the same code path, so it accepts / rejects byte-identically.
109
+
110
+ | Symbol | Kind | Meaning |
111
+ | --- | --- | --- |
112
+ | `signed.KIND` | string | The signed-seal container kind tag (`vh.evidence-seal-signed`). |
113
+ | `signed.TRUST_NOTE` | string | The one-line signed-verify trust-boundary note (a signature proves WHO vouched, not WHEN). |
114
+ | `signed.signSealWith` | function | `signSealWith(seal, signer)` → a signed-seal container WRAPPING the canonical seal bytes. |
115
+ | `signed.validateSignedSeal` | function | `validateSignedSeal(container)` → strict structural validation of a signed container. |
116
+ | `signed.verifySignedSeal` | function | `verifySignedSeal({container, expectedSigner, expectedCanonical})` → the PURE core verdict (recover signer; optional pin/bind). |
117
+ | `signed.verifySignedSealAttestation` | function | `verifySignedSealAttestation({container, expectedSigner, dir})` → the strict signed-verify the CLI runs (`--signer` / `--dir`). |
118
+ | `signed.recoverSigner` | function | `recoverSigner(container)` → the address the signature recovers to (offline, key-free). |
119
+ | `signed.verifySignedAttestation` | function | The generic, product-agnostic signed-attestation verifier the evidence path is bound to. |
120
+
121
+ **Trust boundary (signed path).** A valid signature proves the holder of `signer`'s key **vouched for
122
+ THIS sealed packet** — it is **NOT** a trusted timestamp ("signed since T" rides the human-owned trust-root,
123
+ [STRATEGY.md](../STRATEGY.md) P-3) and **NOT** a legal opinion. Verification is offline / key-free: it
124
+ recovers a **public** address from the signature, holds no private key, and contacts nothing. Pin the
125
+ `expectedSigner` to the vendor address you trust out-of-band (e.g. a published `vh identity` card).
126
+
127
+ ### `receipts` — anchor/claim receipt codec + path-bound manifest diff
128
+
129
+ | Symbol | Kind | Meaning |
130
+ | --- | --- | --- |
131
+ | `receipts.SCHEMA_VERSION` | number | The receipt schema version. |
132
+ | `receipts.CLAIM_RECEIPT_KIND` | string | Kind tag for a commit–reveal claim receipt. |
133
+ | `receipts.ANCHOR_RECEIPT_KIND` | string | Kind tag for a one-shot anchor receipt. |
134
+ | `receipts.buildReceipt` | function | Build a claim receipt. |
135
+ | `receipts.buildAnchorReceipt` | function | Build an anchor receipt. |
136
+ | `receipts.writeReceipt` | function | Serialize a receipt to disk (canonical form). |
137
+ | `receipts.readReceipt` | function | Read + strictly validate a receipt. |
138
+ | `receipts.diffManifest` | function | Path-bound diff of two manifests (ADDED / REMOVED / CHANGED). |
139
+
140
+ ### `hashing` — the keccak / Merkle primitives every seal + receipt is built on
141
+
142
+ | Symbol | Kind | Meaning |
143
+ | --- | --- | --- |
144
+ | `hashing.hashBytes` | function | Hash a byte buffer. |
145
+ | `hashing.hashFile` | function | Hash a file on disk. |
146
+ | `hashing.hashEntries` | function | Hash a list of `{ relPath, bytes }` entries. |
147
+ | `hashing.hashDir` | function | Hash a directory tree. |
148
+ | `hashing.hashPath` | function | Hash a file-or-directory path. |
149
+ | `hashing.buildTree` | function | Build the Merkle tree over leaves. |
150
+
151
+ ---
152
+
153
+ ## Machine-checked surface (semver / ABI contract)
154
+
155
+ The block below is the **canonical ABI descriptor** of the entire exported surface — one `path : abi` line
156
+ per symbol, where `abi` is:
157
+
158
+ - `function/<arity>` for a function (the trailing number is its **parameter count** — part of the call
159
+ signature);
160
+ - `<kind>=<value>` for a frozen constant (`string="…"`, `number=…`) — the exact **wire value** a consumer
161
+ hard-codes (`apiVersion` is the sole exception: rendered `string`, value un-pinned, so a version bump is
162
+ free);
163
+ - `namespace` for a grouped object; and a trailing `#verifySeal.result : <sorted keys>` line pinning the
164
+ **result shape** a consumer destructures from `verifySeal`.
165
+
166
+ [`scripts/gen-sdk-surface.cjs`](../scripts/gen-sdk-surface.cjs) generates this exact block from the live
167
+ `index.js` exports (`npm run sdk:surface -- --write`), and [`test/sdk.contract.test.js`](../test/sdk.contract.test.js)
168
+ asserts it BYTE-MATCHES both this document and the frozen pin in the test. If you change the surface, the
169
+ test prints the drifted line so you can regenerate this block and update the pin together.
170
+
171
+ <!-- SDK-SURFACE:BEGIN (generated by scripts/gen-sdk-surface.cjs — run `npm run sdk:surface -- --write`) -->
172
+ ```text
173
+ PacketSealError : function/1
174
+ apiVersion : string
175
+ buildAnchorReceipt : function/1
176
+ buildReceipt : function/1
177
+ buildSeal : function/1
178
+ buildTree : function/1
179
+ diffManifest : function/2
180
+ hashBytes : function/1
181
+ hashDir : function/1
182
+ hashEntries : function/1
183
+ hashFile : function/1
184
+ hashPath : function/1
185
+ hashing : namespace
186
+ hashing.buildTree : function/1
187
+ hashing.hashBytes : function/1
188
+ hashing.hashDir : function/1
189
+ hashing.hashEntries : function/1
190
+ hashing.hashFile : function/1
191
+ hashing.hashPath : function/1
192
+ readReceipt : function/1
193
+ readSeal : function/1
194
+ receipts : namespace
195
+ receipts.ANCHOR_RECEIPT_KIND : string="verifyhash.anchor-receipt"
196
+ receipts.CLAIM_RECEIPT_KIND : string="verifyhash.claim-receipt"
197
+ receipts.SCHEMA_VERSION : number=4
198
+ receipts.buildAnchorReceipt : function/1
199
+ receipts.buildReceipt : function/1
200
+ receipts.diffManifest : function/2
201
+ receipts.readReceipt : function/1
202
+ receipts.writeReceipt : function/2
203
+ recoverSigner : function/1
204
+ seal : namespace
205
+ seal.KIND : string="vh.evidence-seal"
206
+ seal.PacketSealError : function/1
207
+ seal.SCHEMA_VERSION : number=1
208
+ seal.TRUST_NOTE : string="This evidence seal is TAMPER-EVIDENT + OFFLINE-RECOMPUTABLE, NOT a trusted timestamp. Its Merkle `root` commits to the full set of (relPath, content) pairs in the directory: any edit, rename, add, or remove changes the root, and verify RE-DERIVES the root from the bytes you hold and LOCALIZES the change to the exact file (MATCH / CHANGED / MISSING / UNEXPECTED). It does NOT prove WHEN the sealing happened (\"sealed at T\" rides the human-owned signing/timestamp trust-root, STRATEGY.md P-3) and it is NOT a legal opinion. The packet is an UNTRUSTED transport container: verify never trusts the packet's own stored hashes."
209
+ seal.buildSeal : function/1
210
+ seal.readSeal : function/1
211
+ seal.serializeSeal : function/1
212
+ seal.validateSeal : function/1
213
+ seal.verifySeal : function/2
214
+ serializeSeal : function/1
215
+ signSealWith : function/2
216
+ signed : namespace
217
+ signed.KIND : string="vh.evidence-seal-signed"
218
+ signed.TRUST_NOTE : string="A valid signature proves the HOLDER OF `signer`'s key vouched for THIS evidence seal (the embedded root + the full set of (relPath, content) pairs). It does NOT by itself prove a trustworthy TIMESTAMP: \"sealed/vouched since a date T\" still needs the human-owned signing/timestamp trust-root (needs-human, P-3). It is NOT a legal opinion. This evidence seal is TAMPER-EVIDENT + OFFLINE-RECOMPUTABLE, NOT a trusted timestamp. Its Merkle `root` commits to the full set of (relPath, content) pairs in the directory: any edit, rename, add, or remove changes the root, and verify RE-DERIVES the root from the bytes you hold and LOCALIZES the change to the exact file (MATCH / CHANGED / MISSING / UNEXPECTED). It does NOT prove WHEN the sealing happened (\"sealed at T\" rides the human-owned signing/timestamp trust-root, STRATEGY.md P-3) and it is NOT a legal opinion. The packet is an UNTRUSTED transport container: verify never trusts the packet's own stored hashes."
219
+ signed.recoverSigner : function/1
220
+ signed.signSealWith : function/2
221
+ signed.validateSignedSeal : function/1
222
+ signed.verifySignedAttestation : function/1
223
+ signed.verifySignedSeal : function/1
224
+ signed.verifySignedSealAttestation : function/1
225
+ validateSeal : function/1
226
+ validateSignedSeal : function/1
227
+ verifySeal : function/2
228
+ verifySignedAttestation : function/1
229
+ verifySignedSeal : function/1
230
+ verifySignedSealAttestation : function/1
231
+ writeReceipt : function/2
232
+ #verifySeal.result : accepted,changed,counts,matched,missing,recomputedRoot,rootMatches,sealedRoot,unexpected,verdict
233
+ ```
234
+ <!-- SDK-SURFACE:END -->
235
+
236
+ ---
237
+
238
+ ## Consume the verifier over HTTP (`vh serve-verify`)
239
+
240
+ The SDK verifies **in-process**. For a CI pipeline or another microservice that would rather **POST a seal
241
+ and read an ACCEPT/REJECT** — the *"CI plugin that imports rather than shells out"* — verifyhash ships a
242
+ tiny, dependency-free (Node-core `http` only) **verify service**:
243
+
244
+ ```bash
245
+ vh serve-verify [--port <n>] [--host <h>] # default 127.0.0.1:4180, loopback-only, verify-only
246
+ # POST /verify -> JSON verdict on a CI-mappable status (200 ACCEPTED / 422 REJECTED / 400 bad request)
247
+ # GET /healthz -> { ok: true, ... }
248
+ ```
249
+
250
+ It reuses the **same** `verifySeal` / `verifySignedSeal` cores documented above — no fork. It is
251
+ **verify-only** (never signs, holds no key, writes nothing) and binds **loopback** by default; exposing it
252
+ publicly is a **human** deploy step (STRATEGY.md **P-9**). The request/response schema, the full status
253
+ mapping, and the trust boundary are documented in **[docs/VERIFY-SERVICE.md](./VERIFY-SERVICE.md)**.
254
+
255
+ Drop it in with:
256
+
257
+ - a dependency-free client — [`examples/verify-service-client.js`](../examples/verify-service-client.js)
258
+ (boots the service, POSTs a clean seal → ACCEPT, then a tampered one → REJECT, exits 0);
259
+ - a shell CI gate — [`verifier/ci/verify-service.generic.sh`](../verifier/ci/verify-service.generic.sh);
260
+ - a GitHub Actions gate — [`verifier/ci/verify-service.github-actions.yml`](../verifier/ci/verify-service.github-actions.yml).
261
+
262
+ ## Verify continuously over time (`vh journal`)
263
+
264
+ The SDK and the service both answer *"do these bytes match RIGHT NOW?"* and exit. To prove an artifact has
265
+ verified **continuously across runs**, verifyhash ships an **append-only, hash-chained integrity journal**:
266
+ each run appends one verify verdict, and the log is **itself tamper-evident** — a deleted / edited /
267
+ reordered / inserted past entry **breaks the chain** and `vh journal verify` **localizes the first break**.
268
+
269
+ ```bash
270
+ vh journal append <artifact> --to <journalfile> [--dir <d>] [--ts <ISO>] # record ONE verdict (additive)
271
+ vh journal verify <journalfile> # PASS / BROKEN / DRIFTED
272
+ # exit 0 PASS (unbroken + every observation ACCEPTED) / 3 broken-or-drifted / 2 usage / 1 IO
273
+ ```
274
+
275
+ It reuses the **same** keccak/Merkle hashing documented above — no fork, no new crypto — and the core
276
+ (`cli/journal.js`) is **pure** (no disk I/O, no socket, no key). The `ts` on each entry is **self-asserted**
277
+ (the verifier's own wall clock), **NOT a trusted timestamp** — the journal never claims *"unaltered since date
278
+ T"* on its own; that claim rides the human-owned trust-root (STRATEGY.md **P-3**). The schema, the chain
279
+ guarantee, the 0/3 contract, and the full honesty boundary are documented in
280
+ **[docs/INTEGRITY-JOURNAL.md](./INTEGRITY-JOURNAL.md)**.
281
+
282
+ The journal also carries **transparency-log proofs** (RFC-6962 / Certificate-Transparency lineage):
283
+ `vh journal tree-head` publishes a `{ size, root }` head, `prove-inclusion` / `prove-consistency` emit
284
+ compact proof artifacts, and `vh journal check-proof` verifies them **offline** (no journal, no key, no
285
+ network — though today via the **producer package**, not the standalone, zero-dependency `verifier/` bundle a
286
+ seal enjoys) — the head is **self-asserted** until a P-3 trust-root signs it. See
287
+ [docs/INTEGRITY-JOURNAL.md](./INTEGRITY-JOURNAL.md) § "Transparency-log proofs (publish a tree head;
288
+ auditors verify offline)".
289
+
290
+ Drop it in with:
291
+
292
+ - a dependency-free runnable step — [`examples/journal-ci.js`](../examples/journal-ci.js)
293
+ (appends two hash-chained entries, verifies an unbroken chain, exits 0);
294
+ - a shell CI gate — [`verifier/ci/journal.generic.sh`](../verifier/ci/journal.generic.sh);
295
+ - a GitHub Actions gate — [`verifier/ci/journal.github-actions.yml`](../verifier/ci/journal.github-actions.yml).
296
+
297
+ ## Trust boundary (unchanged from the CLI — the SDK adds nothing)
298
+
299
+ A seal proves **tamper-evidence + offline re-compute** ("these exact bytes are what was sealed"), NOT a
300
+ trusted timestamp and NOT who authored the bytes. `verifySeal` re-derives the Merkle root from the bytes
301
+ **you** supply — never the seal's own stored hashes. See [docs/TRUST-BOUNDARIES.md](./TRUST-BOUNDARIES.md).