@hesohq/node 0.4.3 → 0.5.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 (3) hide show
  1. package/index.d.ts +142 -9
  2. package/index.js +9 -1
  3. package/package.json +6 -6
package/index.d.ts CHANGED
@@ -72,9 +72,8 @@ export declare function verify(receiptBytes: Buffer | Uint8Array | string): Acti
72
72
  /** Verify a receipt AND report its trusted-time status separately. */
73
73
  export declare function verifyWithTime(receiptBytesInput: Buffer | Uint8Array | string): ActionVerdictWithTime
74
74
  /**
75
- * Verify a receipt AND re-derive its ERT classification from the embedded taxonomy.
76
- * Uses heso-engine's ClassifyReDeriver (embedded taxonomy). Only available
77
- * when the `process` feature is enabled (pulls heso-engine).
75
+ * Verify a receipt AND re-derive its ERT classification from the embedded taxonomy
76
+ * (heso-engine's ClassifyReDeriver). Only available when `process` is enabled.
78
77
  */
79
78
  export declare function verifyRederiving(receiptBytesInput: Buffer | Uint8Array | string): ActionVerdict
80
79
  /**
@@ -126,6 +125,74 @@ export declare function verifyApprovalToken(token: Buffer, actionCanonical: Buff
126
125
  * `now_unix_secs` — current time as BigInt Unix seconds
127
126
  */
128
127
  export declare function verifyDelegation(wire: Buffer, registeredOperatorKey: Buffer, actionHash: Buffer, approvalToken: Buffer, requiredScope: string, requiredDecision: string, nowUnixSecs: bigint): VerifiedDelegation
128
+ /**
129
+ * The kind-tagged verdict of [`verify_commitment`]. `verdict` is one of
130
+ * `"Valid"`, `"InvalidSignature"`, `"FingerprintMismatch"`, `"WrongAlgorithm"`,
131
+ * `"Malformed"`; the cloud appends ONLY on `"Valid"`. `signer_fpr` carries the
132
+ * recomputed `blake3(pubkey)` fingerprint (only meaningful on `"Valid"`).
133
+ */
134
+ export interface CommitmentVerdict {
135
+ verdict: string
136
+ signerFpr: string
137
+ }
138
+ /**
139
+ * REJECT-MORE-ONLY. Verify a detached commitment-envelope signature received by
140
+ * the cloud: parse the envelope JSON bytes, re-canonicalize VIA THE KERNEL,
141
+ * `verify_strict` the detached Ed25519 signature under
142
+ * `COMMITMENT_SIGNING_DOMAIN`, and confirm the recomputed commitment fingerprint
143
+ * (`blake3(pubkey)`) equals `claimedSignerFpr`. Produces ZERO new canonical/
144
+ * signed bytes. Never throws — every outcome (including malformed input) is a
145
+ * kind-tagged [`CommitmentVerdict`] so the caller fails closed on any
146
+ * non-`"Valid"`.
147
+ *
148
+ * `envelopeBytes` — the envelope as JSON on the wire (Buffer)
149
+ * `operatorPubkeyB64` — the operator Ed25519 public key (base64 standard)
150
+ * `detachedSigB64` — the detached Ed25519 signature (base64 standard)
151
+ * `claimedSignerFpr` — the wire `signer_fpr` (`blake3(pubkey)` 64-hex)
152
+ */
153
+ export declare function verifyCommitment(envelopeBytes: Buffer, operatorPubkeyB64: string, detachedSigB64: string, claimedSignerFpr: string): CommitmentVerdict
154
+ /**
155
+ * PURE. Return the RFC-8785 (JCS) canonical bytes of a commitment envelope JSON
156
+ * string — the exact bytes the detached operator signature is computed over
157
+ * (after the `COMMITMENT_SIGNING_DOMAIN` prefix). Delegates to the single kernel
158
+ * JCS impl; never re-canonicalizes. Throws `[MALFORMED]` if the JSON does not
159
+ * parse as a `CommitmentEnvelope` and `[CANON]` if it cannot be canonicalized.
160
+ */
161
+ export declare function commitmentEnvelopeCanonicalBytes(envelopeJson: string): Buffer
162
+ /**
163
+ * The **commitment fingerprint** of an Ed25519 public key: `blake3(raw_pubkey)`,
164
+ * the full 32-byte digest, lowercase 64-hex, NO prefix. This is the value the
165
+ * producer puts in the wire `signer_fpr` and the cloud joins `approver_keys` on.
166
+ * It is DISTINCT from [`signer_fingerprint`] (the `heso:`-prefixed Grade-0
167
+ * fingerprint). Throws `[MALFORMED]` if `pubkeyB64` is not base64 of 32 bytes.
168
+ */
169
+ export declare function commitmentFingerprint(pubkeyB64: string): string
170
+ /**
171
+ * The `heso:`-prefixed Grade-0 **signer fingerprint** of an Ed25519 public key
172
+ * (`heso_verify::signer_fingerprint`). This is the identity-tier fingerprint —
173
+ * NOT the commitment fingerprint (see [`commitment_fingerprint`]). Exposed here
174
+ * because it is otherwise unexposed in every binding and other surfaces need it.
175
+ * Returns `null` when `pubkeyB64` is not a valid 32-byte Ed25519 key.
176
+ */
177
+ export declare function signerFingerprint(pubkeyB64: string): string | null
178
+ /**
179
+ * Stamp the cross-receipt chain block (`session_id`, `seq`, `prev_receipt_hash`)
180
+ * into an `ActionContent` BEFORE it is signed, then recompute its `action_hash`
181
+ * so the returned content is ready to sign — the producer-side helper that closes
182
+ * the JS verifiable-chain gap (CORE-WIRE design §A.4).
183
+ *
184
+ * `contentJson` — the unstamped `ActionContent` JSON
185
+ * `sessionId` — the chain/session this action is bound to
186
+ * `prevContentJson` — the predecessor receipt's `ActionContent` JSON, or `null`
187
+ * for genesis. The link hash + next `seq` are COMPUTED from
188
+ * it via the kernel's `link_hash` rule (matching `derive.py`).
189
+ *
190
+ * CRYPTO-SAFETY: stamping the chain block changes `action_canonical_bytes` →
191
+ * `action_hash` → the operator signature. This is a SUCCESS-PATH byte change. It
192
+ * is invoked ONLY for chained sessions; a standalone receipt (no call here) stays
193
+ * byte-identical to the existing standalone goldens.
194
+ */
195
+ export declare function bindIntoChainJs(contentJson: string, sessionId: string, prevContentJson?: string | undefined | null): Buffer
129
196
  /**
130
197
  * Verify an ordered array of ActionReceipts as a tamper-evident chain.
131
198
  * Input: array of Buffers (one per receipt) OR a JSON string of an array.
@@ -155,6 +222,49 @@ export declare function verifyConsistencyJs(oldSize: number, oldRootHex: string,
155
222
  export declare function verifyAuditChain(bytes: Buffer | string): boolean
156
223
  /** Return the hex hash of the embedded taxonomy (golden: 9f3bbaaf…). */
157
224
  export declare function taxonomyHash(): string
225
+ /**
226
+ * The derived ERT a `classify` probe returns — the structural classification of
227
+ * observed facts against the taxonomy. Read-only and advisory: it signs/mints
228
+ * nothing and touches NO canonical/signed bytes (the same role as the PyO3
229
+ * `classify`). The string fields are the `snake_case` wire spellings.
230
+ */
231
+ export interface ClassifyErt {
232
+ /** The matched taxonomy resource class id (e.g. `payment_endpoint`). */
233
+ resourceClass: string
234
+ /** The resource effect (`read_only`/`mutating`/`destructive`/…). */
235
+ effect: string
236
+ /** The egress lane (`none`/`internal`/`external`/…). */
237
+ egress: string
238
+ /** The observability lane. */
239
+ observability: string
240
+ /** The coarse verb wire spelling (`delete`/`payment`/`account_change`/…). */
241
+ coarseVerb: string
242
+ }
243
+ /**
244
+ * Classify observed facts against the taxonomy and return the derived ERT.
245
+ *
246
+ * `signal_hints_json`: JSON-encoded `SignalHints` (Buffer, Uint8Array, or string)
247
+ * — the same wire shape as the `signal` field in `ProcessInput`. The target host
248
+ * is read out-of-band from a custom top-level `host` JSON key (SignalHints itself
249
+ * has no host field), exactly as the PyO3 `classify` twin does.
250
+ * `taxonomy_src`: pass `null` for the embedded taxonomy (the pinned
251
+ * `9f3bbaaf…` anchor), or TOML bytes to classify against a custom taxonomy.
252
+ *
253
+ * PURE READ-ONLY: this is an advisory probe — it signs/mints nothing and touches
254
+ * no canonical/signed bytes. It mirrors the fixed PyO3 `classify` byte-for-byte:
255
+ * the recorded enum hints (`effect`/`origin`/`observed_via`) are lowered via the
256
+ * SAME `Effect::parse`/`Origin::parse`/`ObservedVia::parse` the engine uses, so an
257
+ * unrecognized value parses to `None` (never an invented/relaxed lane). Only
258
+ * available with the `process` feature (it links `heso-engine`).
259
+ */
260
+ export declare function classify(signalHintsJson: Buffer | Uint8Array | string, taxonomySrc?: Buffer | undefined | null): ClassifyErt
261
+ /**
262
+ * True when a coarse verb wire spelling trips the credential floor's
263
+ * "destructive" lane — the LOCKED set `{delete, payment, account_change}`. The
264
+ * single source of this mapping for JS callers, mirroring the PyO3 helper so the
265
+ * two bindings agree. Pure read-only.
266
+ */
267
+ export declare function isDestructive(coarseVerb: string): boolean
158
268
  /** Destructively redact fields and return the modified fields JSON. */
159
269
  export declare function redactDestructiveJs(fieldsJson: string, fieldPaths: Array<string>): string
160
270
  /**
@@ -162,6 +272,17 @@ export declare function redactDestructiveJs(fieldsJson: string, fieldPaths: Arra
162
272
  * `salts` is an array of 32-byte Buffers (one per field, in order).
163
273
  */
164
274
  export declare function redactCommitJs(fieldsJson: string, fieldPaths: Array<string>, salts: Array<Buffer>): RedactCommitResult
275
+ /**
276
+ * Verify a single commit-and-reveal field reveal against its signed redaction
277
+ * marker: recompute `BLAKE3(salt ++ field_path ++ value)` and check it equals
278
+ * `marker.commitment`. Pure (no OsRng, no filesystem); returns a bool, never
279
+ * throws on a mismatch. The Node half of "reveal-and-prove a redacted field".
280
+ *
281
+ * `reveal_json` — a `FieldReveal`: `{ field_path, salt_hex, value_json }`.
282
+ * `marker_json` — the matching `RedactionMarker` from the signed receipt's
283
+ * `content.redaction.markers`.
284
+ */
285
+ export declare function verifyRevealJs(revealJson: string, markerJson: string): boolean
165
286
  /**
166
287
  * Construct an OperatorKey from a 32-byte seed (OsRng-free, deterministic).
167
288
  * The preferred/documented entry point.
@@ -202,10 +323,16 @@ export declare function processAction(processInputJson: Buffer | Uint8Array | st
202
323
  * returned ONLY if it opens `Valid(L1)`; any other verdict is surfaced as an
203
324
  * error rather than handing back a receipt the offline verifier would reject.
204
325
  *
205
- * Returns the serialized ActionReceipt JSON bytes. Only available with `process`
206
- * (loads a key from the filesystem; never wasm-reachable).
326
+ * Returns the serialized ActionReceipt JSON bytes WITH the kernel-signed
327
+ * commitment block spliced in as a top-level `commitment` sibling (the same shape
328
+ * the engine `process` path emits, and the shape the SDK finalize consumer lifts
329
+ * via `receipt.get("commitment")`). The commitment is signed over the FINAL L1
330
+ * body by the SAME operator key — the SDK never holds the key (CORE-WIRE design
331
+ * §0.2). `chainHead` is the prior chain head this commitment links to (the SDK
332
+ * reads it off its local chain); absent/empty defaults to genesis. Only available
333
+ * with `process` (loads a key from the filesystem; never wasm-reachable).
207
334
  */
208
- export declare function assembleL1FromParts(suspendedContentJson: string, approverRecordJson: string, approverPubkeyB64: string, coSigB64: string, projectRoot: string, keyPassphrase?: string | undefined | null, relayedAnchorJson?: string | undefined | null): Buffer
335
+ export declare function assembleL1FromParts(suspendedContentJson: string, approverRecordJson: string, approverPubkeyB64: string, coSigB64: string, projectRoot: string, keyPassphrase?: string | undefined | null, relayedAnchorJson?: string | undefined | null, chainHead?: string | undefined | null): Buffer
209
336
  /**
210
337
  * Assemble a complete multi-approver k-of-n QUORUM ActionReceipt from a suspended
211
338
  * L0 body, the gate's `threshold` + `roster`, and the per-approver detached
@@ -224,10 +351,16 @@ export declare function assembleL1FromParts(suspendedContentJson: string, approv
224
351
  * `parts_json` is a JSON array of `{ record, approverPubkeyB64, coSigB64 }`
225
352
  * objects. `roster_json` is a JSON array of base64 approver public keys.
226
353
  *
227
- * Returns the serialized ActionReceipt JSON bytes. Only available with `process`
228
- * (loads a key from the filesystem; never wasm-reachable).
354
+ * Returns the serialized ActionReceipt JSON bytes WITH the kernel-signed commitment
355
+ * block spliced in as a top-level `commitment` sibling (the same shape the engine
356
+ * `process` path emits, and the shape the SDK finalize consumer lifts via
357
+ * `receipt.get("commitment")`). The commitment is signed over the FINAL quorum L1
358
+ * body by the SAME operator key — the SDK never holds the key (§0.2). `chainHead`
359
+ * is the prior chain head this commitment links to; absent/empty defaults to
360
+ * genesis. Only available with `process` (loads a key from the filesystem; never
361
+ * wasm-reachable).
229
362
  */
230
- export declare function assembleQuorumFromParts(suspendedContentJson: string, threshold: number, rosterJson: string, partsJson: string, projectRoot: string, keyPassphrase?: string | undefined | null): Buffer
363
+ export declare function assembleQuorumFromParts(suspendedContentJson: string, threshold: number, rosterJson: string, partsJson: string, projectRoot: string, keyPassphrase?: string | undefined | null, chainHead?: string | undefined | null): Buffer
231
364
  /** A loaded operator key, exposing just the public-key surface. */
232
365
  export declare class OperatorKey {
233
366
  /** Return the base64 standard-alphabet public key. */
package/index.js CHANGED
@@ -310,7 +310,7 @@ if (!nativeBinding) {
310
310
  throw new Error(`Failed to load native binding`)
311
311
  }
312
312
 
313
- const { OperatorKey, verify, verifyWithTime, verifyRederiving, actionCanonicalBytesJs, l1ContentCanonicalBytesJs, contentHash, anchoredContentHashJs, shortHash, chainHashHex, verifyApprovalToken, verifyDelegation, verifyChain, verifySessionChainJs, verifySessionChainWithRotationJs, verifyInclusionJs, verifyConsistencyJs, verifyAuditChain, taxonomyHash, redactDestructiveJs, redactCommitJs, keyFromSeed, generateKey, blake3Hex, processAction, assembleL1FromParts, assembleQuorumFromParts } = nativeBinding
313
+ const { OperatorKey, verify, verifyWithTime, verifyRederiving, actionCanonicalBytesJs, l1ContentCanonicalBytesJs, contentHash, anchoredContentHashJs, shortHash, chainHashHex, verifyApprovalToken, verifyDelegation, verifyCommitment, commitmentEnvelopeCanonicalBytes, commitmentFingerprint, signerFingerprint, bindIntoChainJs, verifyChain, verifySessionChainJs, verifySessionChainWithRotationJs, verifyInclusionJs, verifyConsistencyJs, verifyAuditChain, taxonomyHash, classify, isDestructive, redactDestructiveJs, redactCommitJs, verifyRevealJs, keyFromSeed, generateKey, blake3Hex, processAction, assembleL1FromParts, assembleQuorumFromParts } = nativeBinding
314
314
 
315
315
  module.exports.OperatorKey = OperatorKey
316
316
  module.exports.verify = verify
@@ -324,6 +324,11 @@ module.exports.shortHash = shortHash
324
324
  module.exports.chainHashHex = chainHashHex
325
325
  module.exports.verifyApprovalToken = verifyApprovalToken
326
326
  module.exports.verifyDelegation = verifyDelegation
327
+ module.exports.verifyCommitment = verifyCommitment
328
+ module.exports.commitmentEnvelopeCanonicalBytes = commitmentEnvelopeCanonicalBytes
329
+ module.exports.commitmentFingerprint = commitmentFingerprint
330
+ module.exports.signerFingerprint = signerFingerprint
331
+ module.exports.bindIntoChainJs = bindIntoChainJs
327
332
  module.exports.verifyChain = verifyChain
328
333
  module.exports.verifySessionChainJs = verifySessionChainJs
329
334
  module.exports.verifySessionChainWithRotationJs = verifySessionChainWithRotationJs
@@ -331,8 +336,11 @@ module.exports.verifyInclusionJs = verifyInclusionJs
331
336
  module.exports.verifyConsistencyJs = verifyConsistencyJs
332
337
  module.exports.verifyAuditChain = verifyAuditChain
333
338
  module.exports.taxonomyHash = taxonomyHash
339
+ module.exports.classify = classify
340
+ module.exports.isDestructive = isDestructive
334
341
  module.exports.redactDestructiveJs = redactDestructiveJs
335
342
  module.exports.redactCommitJs = redactCommitJs
343
+ module.exports.verifyRevealJs = verifyRevealJs
336
344
  module.exports.keyFromSeed = keyFromSeed
337
345
  module.exports.generateKey = generateKey
338
346
  module.exports.blake3Hex = blake3Hex
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hesohq/node",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
4
4
  "description": "napi-rs native Node.js addon for the HESO Enterprise trust layer",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -34,10 +34,10 @@
34
34
  },
35
35
  "license": "LicenseRef-Proprietary",
36
36
  "optionalDependencies": {
37
- "@hesohq/node-darwin-arm64": "0.4.3",
38
- "@hesohq/node-darwin-x64": "0.4.3",
39
- "@hesohq/node-linux-arm64-gnu": "0.4.3",
40
- "@hesohq/node-linux-x64-gnu": "0.4.3",
41
- "@hesohq/node-win32-x64-msvc": "0.4.3"
37
+ "@hesohq/node-darwin-arm64": "0.5.0",
38
+ "@hesohq/node-darwin-x64": "0.5.0",
39
+ "@hesohq/node-linux-arm64-gnu": "0.5.0",
40
+ "@hesohq/node-linux-x64-gnu": "0.5.0",
41
+ "@hesohq/node-win32-x64-msvc": "0.5.0"
42
42
  }
43
43
  }