@hesohq/node 0.5.1-dev.127 → 0.5.1-dev.131

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 +363 -318
  2. package/index.js +570 -295
  3. package/package.json +17 -17
package/index.d.ts CHANGED
@@ -1,7 +1,17 @@
1
- /* tslint:disable */
1
+ /* auto-generated by NAPI-RS */
2
2
  /* eslint-disable */
3
+ /** A loaded operator key, exposing just the public-key surface. */
4
+ export declare class OperatorKey {
5
+ /** Return the base64 standard-alphabet public key. */
6
+ publicKeyB64(): string
7
+ }
3
8
 
4
- /* auto-generated by NAPI-RS */
9
+ /**
10
+ * Return the RFC-8785 (JCS) canonical bytes of an ActionContent JSON string,
11
+ * with `action_hash` stripped. Single source of canonical bytes — never
12
+ * reimplement JCS in TS.
13
+ */
14
+ export declare function actionCanonicalBytesJs(contentJson: string): Buffer
5
15
 
6
16
  /** The verdict returned by all single-receipt verify functions. */
7
17
  export interface ActionVerdict {
@@ -10,6 +20,7 @@ export interface ActionVerdict {
10
20
  /** The re-derived trust level: "L0" or "L1" (only meaningful when verdict == "Valid"). */
11
21
  trustLevel: string
12
22
  }
23
+
13
24
  /** Extended verdict that also includes the trusted-time status. */
14
25
  export interface ActionVerdictWithTime {
15
26
  verdict: string
@@ -17,18 +28,10 @@ export interface ActionVerdictWithTime {
17
28
  /** "NoTrustedTime" or "AnchoredRfc3161:<gen_time>". */
18
29
  timeStatus: string
19
30
  }
20
- /** Outcome of a chain verification. */
21
- export interface ChainResult {
22
- ok: boolean
23
- /** Number of receipts verified (only set when ok == true). */
24
- length?: number
25
- /** Error kind string (only set when ok == false). */
26
- error?: string
27
- /** The seq at which the error occurred (only set when ok == false). */
28
- seq?: number
29
- /** Human-readable detail (only set when ok == false). */
30
- detail?: string
31
- }
31
+
32
+ /** Pre-anchor BLAKE3 hash (excludes `time_anchor` from the canonical bytes). */
33
+ export declare function anchoredContentHashJs(contentJson: string): string
34
+
32
35
  /** Decoded claims from a verified approval token. */
33
36
  export interface ApprovalTokenClaims {
34
37
  /** The 32-byte random nonce as a Buffer. */
@@ -42,35 +45,203 @@ export interface ApprovalTokenClaims {
42
45
  /** Base64-encoded Ed25519 public key of the approver. */
43
46
  approverPublicKey: string
44
47
  }
45
- /** The verified, decoded result of a delegation envelope. */
46
- export interface VerifiedDelegation {
47
- /** The authorized key `K` (raw 32-byte Ed25519 public key) as a Buffer. */
48
- authorizedKey: Buffer
49
- /** The subject string the operator stamped onto the delegation. */
50
- sub: string
51
- /** The scope the delegated authority was bound to. */
52
- scope: string
53
- /** The envelope's expiry as Unix seconds (BigInt). */
54
- expiryUnixSecs: bigint
55
- /** The envelope's not_before as Unix seconds (BigInt). */
56
- notBeforeUnixSecs: bigint
48
+
49
+ /**
50
+ * Assemble a complete L1 ActionReceipt from a suspended L0 body and an approver's
51
+ * detached co-signature, operator-signing locally with the project's key.
52
+ *
53
+ * MANDATORY-1 is enforced in-core: the loaded operator key MUST equal the
54
+ * suspended body's `agent_identity`, else `assemble_l1_from_parts` fails closed
55
+ * with `OperatorKeyMismatch`. After assembly the receipt is verified locally and
56
+ * returned ONLY if it opens `Valid(L1)`; any other verdict is surfaced as an
57
+ * error rather than handing back a receipt the offline verifier would reject.
58
+ *
59
+ * Returns the serialized ActionReceipt JSON bytes WITH the kernel-signed
60
+ * commitment block spliced in as a top-level `commitment` sibling (the same shape
61
+ * the engine `process` path emits, and the shape the SDK finalize consumer lifts
62
+ * via `receipt.get("commitment")`). The commitment is signed over the FINAL L1
63
+ * body by the SAME operator key — the SDK never holds the key (CORE-WIRE design
64
+ * §0.2). `chainHead` is the prior chain head this commitment links to (the SDK
65
+ * reads it off its local chain); absent/empty defaults to genesis. Only available
66
+ * with `process` (loads a key from the filesystem; never wasm-reachable).
67
+ */
68
+ 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
69
+
70
+ /**
71
+ * Assemble a complete multi-approver k-of-n QUORUM ActionReceipt from a suspended
72
+ * L0 body, the gate's `threshold` + `roster`, and the per-approver detached
73
+ * co-signatures — operator-signing locally with the project's key. The result
74
+ * derives and embeds `L1` WITH a `multi_approval` block (a quorum is not a higher
75
+ * level than single-approver L1).
76
+ *
77
+ * MANDATORY-1 is enforced in-core: the loaded operator key MUST equal the
78
+ * suspended body's `agent_identity`, else assembly fails closed with
79
+ * `OperatorKeyMismatch` (surfaced as the discriminable `[OperatorKeyMismatch]`
80
+ * prefix the SDK's key-rotation catch keys on). After assembly the receipt is
81
+ * verified locally and returned ONLY if it opens `Valid(L1)` with a quorum block;
82
+ * any other verdict is surfaced as an error rather than handing back a receipt the
83
+ * offline verifier would reject.
84
+ *
85
+ * `parts_json` is a JSON array of `{ record, approverPubkeyB64, coSigB64 }`
86
+ * objects. `roster_json` is a JSON array of base64 approver public keys.
87
+ *
88
+ * Returns the serialized ActionReceipt JSON bytes WITH the kernel-signed commitment
89
+ * block spliced in as a top-level `commitment` sibling (the same shape the engine
90
+ * `process` path emits, and the shape the SDK finalize consumer lifts via
91
+ * `receipt.get("commitment")`). The commitment is signed over the FINAL quorum L1
92
+ * body by the SAME operator key — the SDK never holds the key (§0.2). `chainHead`
93
+ * is the prior chain head this commitment links to; absent/empty defaults to
94
+ * genesis. Only available with `process` (loads a key from the filesystem; never
95
+ * wasm-reachable).
96
+ */
97
+ export declare function assembleQuorumFromParts(suspendedContentJson: string, threshold: number, rosterJson: string, partsJson: string, projectRoot: string, keyPassphrase?: string | undefined | null, chainHead?: string | undefined | null): Buffer
98
+
99
+ /**
100
+ * Stamp the cross-receipt chain block (`session_id`, `seq`, `prev_receipt_hash`)
101
+ * into an `ActionContent` BEFORE it is signed, then recompute its `action_hash`
102
+ * so the returned content is ready to sign — the producer-side helper that closes
103
+ * the JS verifiable-chain gap (CORE-WIRE design §A.4).
104
+ *
105
+ * `contentJson` — the unstamped `ActionContent` JSON
106
+ * `sessionId` — the chain/session this action is bound to
107
+ * `prevContentJson` — the predecessor receipt's `ActionContent` JSON, or `null`
108
+ * for genesis. The link hash + next `seq` are COMPUTED from
109
+ * it via the kernel's `link_hash` rule (matching `derive.py`).
110
+ *
111
+ * CRYPTO-SAFETY: stamping the chain block changes `action_canonical_bytes` →
112
+ * `action_hash` → the operator signature. This is a SUCCESS-PATH byte change. It
113
+ * is invoked ONLY for chained sessions; a standalone receipt (no call here) stays
114
+ * byte-identical to the existing standalone goldens.
115
+ */
116
+ export declare function bindIntoChainJs(contentJson: string, sessionId: string, prevContentJson?: string | undefined | null): Buffer
117
+
118
+ /**
119
+ * BLAKE3 (64-hex) of arbitrary bytes — the result-hash primitive the Node SDK
120
+ * binds a tool result under, keeping "zero crypto in TS" (Node's crypto has no
121
+ * BLAKE3). Always available (no OsRng); the JS-side `recordResult` calls this.
122
+ */
123
+ export declare function blake3Hex(data: Buffer | Uint8Array | string): string
124
+
125
+ /**
126
+ * Compute a domain-separated BLAKE3 chain-link digest from two 64-hex hashes.
127
+ * Maps to the display helper used by the web's crypto.ts.
128
+ */
129
+ export declare function chainHashHex(prevHex: string, actionHex: string): string
130
+
131
+ /** Outcome of a chain verification. */
132
+ export interface ChainResult {
133
+ ok: boolean
134
+ /** Number of receipts verified (only set when ok == true). */
135
+ length?: number
136
+ /** Error kind string (only set when ok == false). */
137
+ error?: string
138
+ /** The seq at which the error occurred (only set when ok == false). */
139
+ seq?: number
140
+ /** Human-readable detail (only set when ok == false). */
141
+ detail?: string
57
142
  }
58
- /** Result of a commit-and-reveal redaction. */
59
- export interface RedactCommitResult {
60
- /** The modified fields map as JSON. */
61
- fields: string
62
- /** The RedactionRecord as JSON. */
63
- redactionRecord: string
64
- /** The redaction sidecar (salts + reveals) as JSON. */
65
- sidecar: string
143
+
144
+ /**
145
+ * Classify observed facts against the taxonomy and return the derived ERT.
146
+ *
147
+ * `signal_hints_json`: JSON-encoded `SignalHints` (Buffer, Uint8Array, or string)
148
+ * — the same wire shape as the `signal` field in `ProcessInput`. The target host
149
+ * is read out-of-band from a custom top-level `host` JSON key (SignalHints itself
150
+ * has no host field), exactly as the PyO3 `classify` twin does.
151
+ * `taxonomy_src`: pass `null` for the embedded taxonomy (the pinned
152
+ * `9f3bbaaf…` anchor), or TOML bytes to classify against a custom taxonomy.
153
+ *
154
+ * PURE READ-ONLY: this is an advisory probe — it signs/mints nothing and touches
155
+ * no canonical/signed bytes. It mirrors the fixed PyO3 `classify` byte-for-byte:
156
+ * the recorded enum hints (`effect`/`origin`/`observed_via`) are lowered via the
157
+ * SAME `Effect::parse`/`Origin::parse`/`ObservedVia::parse` the engine uses, so an
158
+ * unrecognized value parses to `None` (never an invented/relaxed lane). Only
159
+ * available with the `process` feature (it links `heso-engine`).
160
+ */
161
+ export declare function classify(signalHintsJson: Buffer | Uint8Array | string, taxonomySrc?: Buffer | undefined | null): ClassifyErt
162
+
163
+ /**
164
+ * The derived ERT a `classify` probe returns — the structural classification of
165
+ * observed facts against the taxonomy. Read-only and advisory: it signs/mints
166
+ * nothing and touches NO canonical/signed bytes (the same role as the PyO3
167
+ * `classify`). The string fields are the `snake_case` wire spellings.
168
+ */
169
+ export interface ClassifyErt {
170
+ /** The matched taxonomy resource class id (e.g. `payment_endpoint`). */
171
+ resourceClass: string
172
+ /** The resource effect (`read_only`/`mutating`/`destructive`/…). */
173
+ effect: string
174
+ /** The egress lane (`none`/`internal`/`external`/…). */
175
+ egress: string
176
+ /** The observability lane. */
177
+ observability: string
178
+ /** The coarse verb wire spelling (`delete`/`payment`/`account_change`/…). */
179
+ coarseVerb: string
66
180
  }
181
+
67
182
  /**
68
- * Verify a single ActionReceipt from its raw JSON bytes (Buffer, Uint8Array, or string).
69
- * Never panics structural failures become `Malformed:…`.
183
+ * PURE. Return the RFC-8785 (JCS) canonical bytes of a commitment envelope JSON
184
+ * stringthe exact bytes the detached operator signature is computed over
185
+ * (after the `COMMITMENT_SIGNING_DOMAIN` prefix). Delegates to the single kernel
186
+ * JCS impl; never re-canonicalizes. Throws `[MALFORMED]` if the JSON does not
187
+ * parse as a `CommitmentEnvelope` and `[CANON]` if it cannot be canonicalized.
70
188
  */
71
- export declare function verify(receiptBytes: Buffer | Uint8Array | string): ActionVerdict
72
- /** Verify a receipt AND report its trusted-time status separately. */
73
- export declare function verifyWithTime(receiptBytesInput: Buffer | Uint8Array | string): ActionVerdictWithTime
189
+ export declare function commitmentEnvelopeCanonicalBytes(envelopeJson: string): Buffer
190
+
191
+ /**
192
+ * The **commitment fingerprint** of an Ed25519 public key: `blake3(raw_pubkey)`,
193
+ * the full 32-byte digest, lowercase 64-hex, NO prefix. This is the value the
194
+ * producer puts in the wire `signer_fpr` and the cloud joins `approver_keys` on.
195
+ * It is DISTINCT from [`signer_fingerprint`] (the `heso:`-prefixed Grade-0
196
+ * fingerprint). Throws `[MALFORMED]` if `pubkeyB64` is not base64 of 32 bytes.
197
+ */
198
+ export declare function commitmentFingerprint(pubkeyB64: string): string
199
+
200
+ /**
201
+ * The kind-tagged verdict of [`verify_commitment`]. `verdict` is one of
202
+ * `"Valid"`, `"InvalidSignature"`, `"FingerprintMismatch"`, `"WrongAlgorithm"`,
203
+ * `"Malformed"`; the cloud appends ONLY on `"Valid"`. `signer_fpr` carries the
204
+ * recomputed `blake3(pubkey)` fingerprint (only meaningful on `"Valid"`).
205
+ */
206
+ export interface CommitmentVerdict {
207
+ verdict: string
208
+ signerFpr: string
209
+ }
210
+
211
+ /** BLAKE3 (64-hex) of the canonical bytes — the value that goes into `action_hash`. */
212
+ export declare function contentHash(contentJson: string): string
213
+
214
+ /**
215
+ * Generate a fresh random OperatorKey using OS entropy (native-only).
216
+ * Do NOT call from any wasm-reachable path.
217
+ */
218
+ export declare function generateKey(): OperatorKey
219
+
220
+ /**
221
+ * True when a coarse verb wire spelling trips the credential floor's
222
+ * "destructive" lane — the LOCKED set `{delete, payment, account_change}`. The
223
+ * single source of this mapping for JS callers, mirroring the PyO3 helper so the
224
+ * two bindings agree. Pure read-only.
225
+ */
226
+ export declare function isDestructive(coarseVerb: string): boolean
227
+
228
+ /**
229
+ * Construct an OperatorKey from a 32-byte seed (OsRng-free, deterministic).
230
+ * The preferred/documented entry point.
231
+ */
232
+ export declare function keyFromSeed(seed: Buffer): OperatorKey
233
+
234
+ /**
235
+ * Promote a suspended L0 `ActionContent` to its L1 body (embed the approver
236
+ * record, recompute `action_hash`) and return that body's RFC-8785 (JCS)
237
+ * canonical bytes — the exact bytes the operator and approver sign.
238
+ *
239
+ * Key-free (`build_l1_content` is pure), so this is always compiled. It lets
240
+ * the SDK reproduce the L1 signing payload off-process and assert byte-parity
241
+ * with the native mint without ever touching a key.
242
+ */
243
+ export declare function l1ContentCanonicalBytesJs(suspendedContentJson: string, approverRecordJson: string): Buffer
244
+
74
245
  /**
75
246
  * The base verdict + the rendered signed metrics + the offline-recomputed cost.
76
247
  *
@@ -120,56 +291,118 @@ export interface MetricsVerdict {
120
291
  /** Whether the passed-in card is the one the receipt named. */
121
292
  cardIdMatches: boolean
122
293
  }
294
+
123
295
  /**
124
- * Verify a single `ActionReceipt` AND render its signed metrics + recompute cost
125
- * from the passed-in public rate card — the node mirror of the WASM
126
- * `verifyActionReceiptWithRates`.
296
+ * Process an action through the compliance pipeline (in-process, no subprocess).
127
297
  *
128
- * Runs the EXISTING offline verify for the base outcome + trust level (so that
129
- * path is unchanged), then renders the signed metrics and recomputes the cost via
130
- * the SHARED `heso_action::metrics_view` glue. Never throws on a malformed receipt
131
- * or card — those degrade to `has_metrics: false` / `priced: false` exactly as the
132
- * WASM export does. The cost render is purely informational and NEVER masks a
133
- * verify failure: a tampered metric flips the `action_hash`, so `verdict` is a
134
- * non-`Valid` tag while the (meaningless) recompute still reflects whatever bytes
135
- * are present — the caller branches on `verdict`, never the dollar figure.
298
+ * `process_input_json`: JSON-encoded `ProcessInput` (Buffer, Uint8Array, or string).
299
+ * `project_root`: path to the project root holding `heso.toml` and `heso-local-data/`
300
+ * (operator key, audit log, approval queue) the same layout the PyO3 wheel reads.
136
301
  *
137
- * `receipt_bytes` the raw `ActionReceipt` JSON bytes (Buffer/Uint8Array/string).
138
- * `rate_card_json` the public rate-card JSON the cost is recomputed from.
302
+ * Returns JSON-encoded `ProcessOutput` bytes, tagged on `status`
303
+ * (`allowed`/`blocked`/`suspended`). Only available with the `process` feature.
304
+ *
305
+ * Named `process_action` (JS `processAction`) — NOT `process` — because a napi
306
+ * export named `process` shadows Node's global `process` in the generated loader.
139
307
  */
140
- export declare function verifyWithRates(receiptBytes: Buffer | Uint8Array | string, rateCardJson: string): MetricsVerdict
308
+ export declare function processAction(processInputJson: Buffer | Uint8Array | string, projectRoot: string): Buffer
309
+
141
310
  /**
142
- * Verify a receipt AND re-derive its ERT classification from the embedded taxonomy
143
- * (heso-engine's ClassifyReDeriver). Only available when `process` is enabled.
311
+ * Append an approver/ledger-signed decision link to a session's chain. Mirrors the
312
+ * PyO3 `process_append_decision` body 1:1.
313
+ *
314
+ * `kind`: one of `"approved"` / `"denied"` / `"escalated"` / `"expired"`. **Fails
315
+ * closed** without a `decision.key` unless `INSECURE_DECISION_KEY_ENV` is set
316
+ * (see `load_decision_signer`) — the approver key is cloud-custodied in prod.
144
317
  */
145
- export declare function verifyRederiving(receiptBytesInput: Buffer | Uint8Array | string): ActionVerdict
318
+ export declare function processAppendDecision(projectRoot: string, sessionId: string, kind: string, reason?: string | undefined | null, decidedAt?: string | undefined | null): void
319
+
146
320
  /**
147
- * Return the RFC-8785 (JCS) canonical bytes of an ActionContent JSON string,
148
- * with `action_hash` stripped. Single source of canonical bytes — never
149
- * reimplement JCS in TS.
321
+ * Read the current lifecycle state of a session chain (the head link's kind).
322
+ * Mirrors the PyO3 `process_read_chain_head` body 1:1.
323
+ *
324
+ * Returns the head kind as a lowercase string (`"suspended"` / `"approved"` /
325
+ * `"denied"` / `"expired"` / `"completed"` / `"escalated"`), or `None` if no chain
326
+ * exists yet.
150
327
  */
151
- export declare function actionCanonicalBytesJs(contentJson: string): Buffer
328
+ export declare function processReadChainHead(projectRoot: string, sessionId: string): string | null
329
+
152
330
  /**
153
- * Promote a suspended L0 `ActionContent` to its L1 body (embed the approver
154
- * record, recompute `action_hash`) and return that body's RFC-8785 (JCS)
155
- * canonical bytes the exact bytes the operator and approver sign.
331
+ * Resume a suspended session: re-read the chain, apply the decision, fire-or-replay.
332
+ * Mirrors the PyO3 `process_resume` body 1:1. On `Fire` it mints + appends the
333
+ * `completed` link under `ACTION_SIGNING_DOMAIN` and advances the cursor.
156
334
  *
157
- * Key-free (`build_l1_content` is pure), so this is always compiled. It lets
158
- * the SDK reproduce the L1 signing payload off-process and assert byte-parity
159
- * with the native mint without ever touching a key.
335
+ * Returns JSON bytes `{"decision": str, "committed": bool, "kind"?: str,
336
+ * "reason"?: str}` where `decision` is one of
337
+ * `fire`/`replay`/`pending`/`terminal`/`uncertain`/`refused`.
160
338
  */
161
- export declare function l1ContentCanonicalBytesJs(suspendedContentJson: string, approverRecordJson: string): Buffer
162
- /** BLAKE3 (64-hex) of the canonical bytes — the value that goes into `action_hash`. */
163
- export declare function contentHash(contentJson: string): string
164
- /** Pre-anchor BLAKE3 hash (excludes `time_anchor` from the canonical bytes). */
165
- export declare function anchoredContentHashJs(contentJson: string): string
339
+ export declare function processResume(processInputJson: Buffer | Uint8Array | string, projectRoot: string, sessionId: string, presentedToken: string, contextBlob: Buffer): Buffer
340
+
341
+ /**
342
+ * Suspend a gated action: mint the signed `suspended` chain link and return the
343
+ * raw resume token (returned ONCE) plus the action spec hash. Mirrors the PyO3
344
+ * `process_suspend` body 1:1 — the ProcessInput MUST carry `reclassify=false` so
345
+ * the descriptor is signed verbatim and stays byte-stable across the lifecycle.
346
+ *
347
+ * Returns JSON bytes:
348
+ * `{"session_id": str, "resume_token": str, "action_spec": str, "chain_path": str}`.
349
+ */
350
+ export declare function processSuspend(processInputJson: Buffer | Uint8Array | string, projectRoot: string, sessionId: string, sla: string, expiresAt: string, onTimeout: string, contextScheme: string, contextBlob: Buffer, toolVersionHash?: string | undefined | null): Buffer
351
+
352
+ /**
353
+ * Commit-and-reveal redaction.
354
+ * `salts` is an array of 32-byte Buffers (one per field, in order).
355
+ */
356
+ export declare function redactCommitJs(fieldsJson: string, fieldPaths: Array<string>, salts: Array<Buffer>): RedactCommitResult
357
+
358
+ /** Result of a commit-and-reveal redaction. */
359
+ export interface RedactCommitResult {
360
+ /** The modified fields map as JSON. */
361
+ fields: string
362
+ /** The RedactionRecord as JSON. */
363
+ redactionRecord: string
364
+ /** The redaction sidecar (salts + reveals) as JSON. */
365
+ sidecar: string
366
+ }
367
+
368
+ /** Destructively redact fields and return the modified fields JSON. */
369
+ export declare function redactDestructiveJs(fieldsJson: string, fieldPaths: Array<string>): string
370
+
166
371
  /** Return a short display form of a 64-hex BLAKE3 hash: `{prefix}:{first8}`. */
167
372
  export declare function shortHash(hex: string, prefix?: string | undefined | null): string
373
+
168
374
  /**
169
- * Compute a domain-separated BLAKE3 chain-link digest from two 64-hex hashes.
170
- * Maps to the display helper used by the web's crypto.ts.
375
+ * The `heso:`-prefixed Grade-0 **signer fingerprint** of an Ed25519 public key
376
+ * (`heso_verify::signer_fingerprint`). This is the identity-tier fingerprint
377
+ * NOT the commitment fingerprint (see [`commitment_fingerprint`]). Exposed here
378
+ * because it is otherwise unexposed in every binding and other surfaces need it.
379
+ * Returns `null` when `pubkeyB64` is not a valid 32-byte Ed25519 key.
171
380
  */
172
- export declare function chainHashHex(prevHex: string, actionHex: string): string
381
+ export declare function signerFingerprint(pubkeyB64: string): string | null
382
+
383
+ /** Return the hex hash of the embedded taxonomy (golden: 9f3bbaaf…). */
384
+ export declare function taxonomyHash(): string
385
+
386
+ /** The verified, decoded result of a delegation envelope. */
387
+ export interface VerifiedDelegation {
388
+ /** The authorized key `K` (raw 32-byte Ed25519 public key) as a Buffer. */
389
+ authorizedKey: Buffer
390
+ /** The subject string the operator stamped onto the delegation. */
391
+ sub: string
392
+ /** The scope the delegated authority was bound to. */
393
+ scope: string
394
+ /** The envelope's expiry as Unix seconds (BigInt). */
395
+ expiryUnixSecs: bigint
396
+ /** The envelope's not_before as Unix seconds (BigInt). */
397
+ notBeforeUnixSecs: bigint
398
+ }
399
+
400
+ /**
401
+ * Verify a single ActionReceipt from its raw JSON bytes (Buffer, Uint8Array, or string).
402
+ * Never panics — structural failures become `Malformed:…`.
403
+ */
404
+ export declare function verify(receiptBytes: Buffer | Uint8Array | string): ActionVerdict
405
+
173
406
  /**
174
407
  * Verify an approval token. Throws a napi Error with a `[CODE]` prefix on failure.
175
408
  *
@@ -178,30 +411,19 @@ export declare function chainHashHex(prevHex: string, actionHex: string): string
178
411
  * rejected `[OutOfDecision]`.
179
412
  */
180
413
  export declare function verifyApprovalToken(token: Buffer, actionCanonical: Buffer, nowUnixSecs: bigint, seenNonces: Array<Buffer>, requiredScope: string, requiredDecision: string, registeredKeysB64: Array<string>): ApprovalTokenClaims
414
+
181
415
  /**
182
- * Verify a delegation envelope and its human co-sign. Throws a napi Error with a
183
- * `[CODE]` prefix on failure (mirrors `verifyApprovalToken`).
184
- *
185
- * `wire` — raw delegation envelope bytes (Buffer)
186
- * `registered_operator_key` — the org-registered operator public key (raw 32-byte Buffer)
187
- * `action_hash` — the raw 32-byte BLAKE3 action digest being authorized (Buffer)
188
- * `approval_token` — the human co-sign bearer token presented by K (Buffer)
189
- * `required_scope` — the required scope string
190
- * `required_decision` — the verdict the co-sign must carry ("approved"/"rejected"),
191
- * NON-DEFAULTED (same SEC-02 binding as the approver path)
192
- * `now_unix_secs` — current time as BigInt Unix seconds
416
+ * Verify a BLAKE3 audit chain from its raw JSONL bytes (Buffer or string).
417
+ * Returns true if every link hashes correctly, false on any break.
193
418
  */
194
- export declare function verifyDelegation(wire: Buffer, registeredOperatorKey: Buffer, actionHash: Buffer, approvalToken: Buffer, requiredScope: string, requiredDecision: string, nowUnixSecs: bigint): VerifiedDelegation
419
+ export declare function verifyAuditChain(bytes: Buffer | string): boolean
420
+
195
421
  /**
196
- * The kind-tagged verdict of [`verify_commitment`]. `verdict` is one of
197
- * `"Valid"`, `"InvalidSignature"`, `"FingerprintMismatch"`, `"WrongAlgorithm"`,
198
- * `"Malformed"`; the cloud appends ONLY on `"Valid"`. `signer_fpr` carries the
199
- * recomputed `blake3(pubkey)` fingerprint (only meaningful on `"Valid"`).
422
+ * Verify an ordered array of ActionReceipts as a tamper-evident chain.
423
+ * Input: array of Buffers (one per receipt) OR a JSON string of an array.
200
424
  */
201
- export interface CommitmentVerdict {
202
- verdict: string
203
- signerFpr: string
204
- }
425
+ export declare function verifyChain(receiptsBytes: Array<Buffer> | string): ChainResult
426
+
205
427
  /**
206
428
  * REJECT-MORE-ONLY. Verify a detached commitment-envelope signature received by
207
429
  * the cloud: parse the envelope JSON bytes, re-canonicalize VIA THE KERNEL,
@@ -218,61 +440,25 @@ export interface CommitmentVerdict {
218
440
  * `claimedSignerFpr` — the wire `signer_fpr` (`blake3(pubkey)` 64-hex)
219
441
  */
220
442
  export declare function verifyCommitment(envelopeBytes: Buffer, operatorPubkeyB64: string, detachedSigB64: string, claimedSignerFpr: string): CommitmentVerdict
443
+
444
+ /** RFC-6962 consistency proof verification. */
445
+ export declare function verifyConsistencyJs(oldSize: number, oldRootHex: string, newSize: number, newRootHex: string, proofHashes: Array<string>): boolean
446
+
221
447
  /**
222
- * PURE. Return the RFC-8785 (JCS) canonical bytes of a commitment envelope JSON
223
- * string the exact bytes the detached operator signature is computed over
224
- * (after the `COMMITMENT_SIGNING_DOMAIN` prefix). Delegates to the single kernel
225
- * JCS impl; never re-canonicalizes. Throws `[MALFORMED]` if the JSON does not
226
- * parse as a `CommitmentEnvelope` and `[CANON]` if it cannot be canonicalized.
227
- */
228
- export declare function commitmentEnvelopeCanonicalBytes(envelopeJson: string): Buffer
229
- /**
230
- * The **commitment fingerprint** of an Ed25519 public key: `blake3(raw_pubkey)`,
231
- * the full 32-byte digest, lowercase 64-hex, NO prefix. This is the value the
232
- * producer puts in the wire `signer_fpr` and the cloud joins `approver_keys` on.
233
- * It is DISTINCT from [`signer_fingerprint`] (the `heso:`-prefixed Grade-0
234
- * fingerprint). Throws `[MALFORMED]` if `pubkeyB64` is not base64 of 32 bytes.
235
- */
236
- export declare function commitmentFingerprint(pubkeyB64: string): string
237
- /**
238
- * The `heso:`-prefixed Grade-0 **signer fingerprint** of an Ed25519 public key
239
- * (`heso_verify::signer_fingerprint`). This is the identity-tier fingerprint —
240
- * NOT the commitment fingerprint (see [`commitment_fingerprint`]). Exposed here
241
- * because it is otherwise unexposed in every binding and other surfaces need it.
242
- * Returns `null` when `pubkeyB64` is not a valid 32-byte Ed25519 key.
243
- */
244
- export declare function signerFingerprint(pubkeyB64: string): string | null
245
- /**
246
- * Stamp the cross-receipt chain block (`session_id`, `seq`, `prev_receipt_hash`)
247
- * into an `ActionContent` BEFORE it is signed, then recompute its `action_hash`
248
- * so the returned content is ready to sign — the producer-side helper that closes
249
- * the JS verifiable-chain gap (CORE-WIRE design §A.4).
250
- *
251
- * `contentJson` — the unstamped `ActionContent` JSON
252
- * `sessionId` — the chain/session this action is bound to
253
- * `prevContentJson` — the predecessor receipt's `ActionContent` JSON, or `null`
254
- * for genesis. The link hash + next `seq` are COMPUTED from
255
- * it via the kernel's `link_hash` rule (matching `derive.py`).
448
+ * Verify a delegation envelope and its human co-sign. Throws a napi Error with a
449
+ * `[CODE]` prefix on failure (mirrors `verifyApprovalToken`).
256
450
  *
257
- * CRYPTO-SAFETY: stamping the chain block changes `action_canonical_bytes` →
258
- * `action_hash` the operator signature. This is a SUCCESS-PATH byte change. It
259
- * is invoked ONLY for chained sessions; a standalone receipt (no call here) stays
260
- * byte-identical to the existing standalone goldens.
261
- */
262
- export declare function bindIntoChainJs(contentJson: string, sessionId: string, prevContentJson?: string | undefined | null): Buffer
263
- /**
264
- * Verify an ordered array of ActionReceipts as a tamper-evident chain.
265
- * Input: array of Buffers (one per receipt) OR a JSON string of an array.
266
- */
267
- export declare function verifyChain(receiptsBytes: Array<Buffer> | string): ChainResult
268
- /** Verify a session chain (lifecycle role + transition checks). */
269
- export declare function verifySessionChainJs(receiptsBytes: Array<Buffer> | string): ChainResult
270
- /**
271
- * Verify a session chain with key-rotation as-of-position enforcement.
272
- * `producer_key` is the base64 genesis producer key (TOFU pin).
273
- * `decision_key` is the optional base64 genesis decision key.
451
+ * `wire` — raw delegation envelope bytes (Buffer)
452
+ * `registered_operator_key` the org-registered operator public key (raw 32-byte Buffer)
453
+ * `action_hash` — the raw 32-byte BLAKE3 action digest being authorized (Buffer)
454
+ * `approval_token` — the human co-sign bearer token presented by K (Buffer)
455
+ * `required_scope` — the required scope string
456
+ * `required_decision` — the verdict the co-sign must carry ("approved"/"rejected"),
457
+ * NON-DEFAULTED (same SEC-02 binding as the approver path)
458
+ * `now_unix_secs` — current time as BigInt Unix seconds
274
459
  */
275
- export declare function verifySessionChainWithRotationJs(receiptsBytes: Array<Buffer> | string, producerKey: string, decisionKey?: string | undefined | null): ChainResult
460
+ export declare function verifyDelegation(wire: Buffer, registeredOperatorKey: Buffer, actionHash: Buffer, approvalToken: Buffer, requiredScope: string, requiredDecision: string, nowUnixSecs: bigint): VerifiedDelegation
461
+
276
462
  /**
277
463
  * RFC-6962 inclusion proof verification (SHA-256 Merkle tree).
278
464
  * `leaf_value_hex` is the 64-hex `action_hash`; raw bytes are the leaf value.
@@ -280,65 +466,13 @@ export declare function verifySessionChainWithRotationJs(receiptsBytes: Array<Bu
280
466
  * `root_hex` is the 64-hex SHA-256 tree root.
281
467
  */
282
468
  export declare function verifyInclusionJs(leafValueHex: string, index: number, size: number, rootHex: string, proofHashes: Array<string>): boolean
283
- /** RFC-6962 consistency proof verification. */
284
- export declare function verifyConsistencyJs(oldSize: number, oldRootHex: string, newSize: number, newRootHex: string, proofHashes: Array<string>): boolean
285
- /**
286
- * Verify a BLAKE3 audit chain from its raw JSONL bytes (Buffer or string).
287
- * Returns true if every link hashes correctly, false on any break.
288
- */
289
- export declare function verifyAuditChain(bytes: Buffer | string): boolean
290
- /** Return the hex hash of the embedded taxonomy (golden: 9f3bbaaf…). */
291
- export declare function taxonomyHash(): string
292
- /**
293
- * The derived ERT a `classify` probe returns — the structural classification of
294
- * observed facts against the taxonomy. Read-only and advisory: it signs/mints
295
- * nothing and touches NO canonical/signed bytes (the same role as the PyO3
296
- * `classify`). The string fields are the `snake_case` wire spellings.
297
- */
298
- export interface ClassifyErt {
299
- /** The matched taxonomy resource class id (e.g. `payment_endpoint`). */
300
- resourceClass: string
301
- /** The resource effect (`read_only`/`mutating`/`destructive`/…). */
302
- effect: string
303
- /** The egress lane (`none`/`internal`/`external`/…). */
304
- egress: string
305
- /** The observability lane. */
306
- observability: string
307
- /** The coarse verb wire spelling (`delete`/`payment`/`account_change`/…). */
308
- coarseVerb: string
309
- }
310
- /**
311
- * Classify observed facts against the taxonomy and return the derived ERT.
312
- *
313
- * `signal_hints_json`: JSON-encoded `SignalHints` (Buffer, Uint8Array, or string)
314
- * — the same wire shape as the `signal` field in `ProcessInput`. The target host
315
- * is read out-of-band from a custom top-level `host` JSON key (SignalHints itself
316
- * has no host field), exactly as the PyO3 `classify` twin does.
317
- * `taxonomy_src`: pass `null` for the embedded taxonomy (the pinned
318
- * `9f3bbaaf…` anchor), or TOML bytes to classify against a custom taxonomy.
319
- *
320
- * PURE READ-ONLY: this is an advisory probe — it signs/mints nothing and touches
321
- * no canonical/signed bytes. It mirrors the fixed PyO3 `classify` byte-for-byte:
322
- * the recorded enum hints (`effect`/`origin`/`observed_via`) are lowered via the
323
- * SAME `Effect::parse`/`Origin::parse`/`ObservedVia::parse` the engine uses, so an
324
- * unrecognized value parses to `None` (never an invented/relaxed lane). Only
325
- * available with the `process` feature (it links `heso-engine`).
326
- */
327
- export declare function classify(signalHintsJson: Buffer | Uint8Array | string, taxonomySrc?: Buffer | undefined | null): ClassifyErt
328
- /**
329
- * True when a coarse verb wire spelling trips the credential floor's
330
- * "destructive" lane — the LOCKED set `{delete, payment, account_change}`. The
331
- * single source of this mapping for JS callers, mirroring the PyO3 helper so the
332
- * two bindings agree. Pure read-only.
333
- */
334
- export declare function isDestructive(coarseVerb: string): boolean
335
- /** Destructively redact fields and return the modified fields JSON. */
336
- export declare function redactDestructiveJs(fieldsJson: string, fieldPaths: Array<string>): string
469
+
337
470
  /**
338
- * Commit-and-reveal redaction.
339
- * `salts` is an array of 32-byte Buffers (one per field, in order).
471
+ * Verify a receipt AND re-derive its ERT classification from the embedded taxonomy
472
+ * (heso-engine's ClassifyReDeriver). Only available when `process` is enabled.
340
473
  */
341
- export declare function redactCommitJs(fieldsJson: string, fieldPaths: Array<string>, salts: Array<Buffer>): RedactCommitResult
474
+ export declare function verifyRederiving(receiptBytesInput: Buffer | Uint8Array | string): ActionVerdict
475
+
342
476
  /**
343
477
  * Verify a single commit-and-reveal field reveal against its signed redaction
344
478
  * marker: recompute `BLAKE3(salt ++ field_path ++ value)` and check it equals
@@ -350,124 +484,35 @@ export declare function redactCommitJs(fieldsJson: string, fieldPaths: Array<str
350
484
  * `content.redaction.markers`.
351
485
  */
352
486
  export declare function verifyRevealJs(revealJson: string, markerJson: string): boolean
487
+
488
+ /** Verify a session chain (lifecycle role + transition checks). */
489
+ export declare function verifySessionChainJs(receiptsBytes: Array<Buffer> | string): ChainResult
490
+
353
491
  /**
354
- * Construct an OperatorKey from a 32-byte seed (OsRng-free, deterministic).
355
- * The preferred/documented entry point.
356
- */
357
- export declare function keyFromSeed(seed: Buffer): OperatorKey
358
- /**
359
- * Generate a fresh random OperatorKey using OS entropy (native-only).
360
- * Do NOT call from any wasm-reachable path.
361
- */
362
- export declare function generateKey(): OperatorKey
363
- /**
364
- * BLAKE3 (64-hex) of arbitrary bytes — the result-hash primitive the Node SDK
365
- * binds a tool result under, keeping "zero crypto in TS" (Node's crypto has no
366
- * BLAKE3). Always available (no OsRng); the JS-side `recordResult` calls this.
367
- */
368
- export declare function blake3Hex(data: Buffer | Uint8Array | string): string
369
- /**
370
- * Process an action through the compliance pipeline (in-process, no subprocess).
371
- *
372
- * `process_input_json`: JSON-encoded `ProcessInput` (Buffer, Uint8Array, or string).
373
- * `project_root`: path to the project root holding `heso.toml` and `heso-local-data/`
374
- * (operator key, audit log, approval queue) — the same layout the PyO3 wheel reads.
375
- *
376
- * Returns JSON-encoded `ProcessOutput` bytes, tagged on `status`
377
- * (`allowed`/`blocked`/`suspended`). Only available with the `process` feature.
378
- *
379
- * Named `process_action` (JS `processAction`) — NOT `process` — because a napi
380
- * export named `process` shadows Node's global `process` in the generated loader.
381
- */
382
- export declare function processAction(processInputJson: Buffer | Uint8Array | string, projectRoot: string): Buffer
383
- /**
384
- * Assemble a complete L1 ActionReceipt from a suspended L0 body and an approver's
385
- * detached co-signature, operator-signing locally with the project's key.
386
- *
387
- * MANDATORY-1 is enforced in-core: the loaded operator key MUST equal the
388
- * suspended body's `agent_identity`, else `assemble_l1_from_parts` fails closed
389
- * with `OperatorKeyMismatch`. After assembly the receipt is verified locally and
390
- * returned ONLY if it opens `Valid(L1)`; any other verdict is surfaced as an
391
- * error rather than handing back a receipt the offline verifier would reject.
392
- *
393
- * Returns the serialized ActionReceipt JSON bytes WITH the kernel-signed
394
- * commitment block spliced in as a top-level `commitment` sibling (the same shape
395
- * the engine `process` path emits, and the shape the SDK finalize consumer lifts
396
- * via `receipt.get("commitment")`). The commitment is signed over the FINAL L1
397
- * body by the SAME operator key — the SDK never holds the key (CORE-WIRE design
398
- * §0.2). `chainHead` is the prior chain head this commitment links to (the SDK
399
- * reads it off its local chain); absent/empty defaults to genesis. Only available
400
- * with `process` (loads a key from the filesystem; never wasm-reachable).
401
- */
402
- 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
403
- /**
404
- * Assemble a complete multi-approver k-of-n QUORUM ActionReceipt from a suspended
405
- * L0 body, the gate's `threshold` + `roster`, and the per-approver detached
406
- * co-signatures — operator-signing locally with the project's key. The result
407
- * derives and embeds `L1` WITH a `multi_approval` block (a quorum is not a higher
408
- * level than single-approver L1).
409
- *
410
- * MANDATORY-1 is enforced in-core: the loaded operator key MUST equal the
411
- * suspended body's `agent_identity`, else assembly fails closed with
412
- * `OperatorKeyMismatch` (surfaced as the discriminable `[OperatorKeyMismatch]`
413
- * prefix the SDK's key-rotation catch keys on). After assembly the receipt is
414
- * verified locally and returned ONLY if it opens `Valid(L1)` with a quorum block;
415
- * any other verdict is surfaced as an error rather than handing back a receipt the
416
- * offline verifier would reject.
417
- *
418
- * `parts_json` is a JSON array of `{ record, approverPubkeyB64, coSigB64 }`
419
- * objects. `roster_json` is a JSON array of base64 approver public keys.
420
- *
421
- * Returns the serialized ActionReceipt JSON bytes WITH the kernel-signed commitment
422
- * block spliced in as a top-level `commitment` sibling (the same shape the engine
423
- * `process` path emits, and the shape the SDK finalize consumer lifts via
424
- * `receipt.get("commitment")`). The commitment is signed over the FINAL quorum L1
425
- * body by the SAME operator key — the SDK never holds the key (§0.2). `chainHead`
426
- * is the prior chain head this commitment links to; absent/empty defaults to
427
- * genesis. Only available with `process` (loads a key from the filesystem; never
428
- * wasm-reachable).
429
- */
430
- export declare function assembleQuorumFromParts(suspendedContentJson: string, threshold: number, rosterJson: string, partsJson: string, projectRoot: string, keyPassphrase?: string | undefined | null, chainHead?: string | undefined | null): Buffer
431
- /**
432
- * Suspend a gated action: mint the signed `suspended` chain link and return the
433
- * raw resume token (returned ONCE) plus the action spec hash. Mirrors the PyO3
434
- * `process_suspend` body 1:1 — the ProcessInput MUST carry `reclassify=false` so
435
- * the descriptor is signed verbatim and stays byte-stable across the lifecycle.
436
- *
437
- * Returns JSON bytes:
438
- * `{"session_id": str, "resume_token": str, "action_spec": str, "chain_path": str}`.
439
- */
440
- export declare function processSuspend(processInputJson: Buffer | Uint8Array | string, projectRoot: string, sessionId: string, sla: string, expiresAt: string, onTimeout: string, contextScheme: string, contextBlob: Buffer, toolVersionHash?: string | undefined | null): Buffer
441
- /**
442
- * Resume a suspended session: re-read the chain, apply the decision, fire-or-replay.
443
- * Mirrors the PyO3 `process_resume` body 1:1. On `Fire` it mints + appends the
444
- * `completed` link under `ACTION_SIGNING_DOMAIN` and advances the cursor.
445
- *
446
- * Returns JSON bytes `{"decision": str, "committed": bool, "kind"?: str,
447
- * "reason"?: str}` where `decision` is one of
448
- * `fire`/`replay`/`pending`/`terminal`/`uncertain`/`refused`.
492
+ * Verify a session chain with key-rotation as-of-position enforcement.
493
+ * `producer_key` is the base64 genesis producer key (TOFU pin).
494
+ * `decision_key` is the optional base64 genesis decision key.
449
495
  */
450
- export declare function processResume(processInputJson: Buffer | Uint8Array | string, projectRoot: string, sessionId: string, presentedToken: string, contextBlob: Buffer): Buffer
496
+ export declare function verifySessionChainWithRotationJs(receiptsBytes: Array<Buffer> | string, producerKey: string, decisionKey?: string | undefined | null): ChainResult
497
+
451
498
  /**
452
- * Append an approver/ledger-signed decision link to a session's chain. Mirrors the
453
- * PyO3 `process_append_decision` body 1:1.
499
+ * Verify a single `ActionReceipt` AND render its signed metrics + recompute cost
500
+ * from the passed-in public rate card — the node mirror of the WASM
501
+ * `verifyActionReceiptWithRates`.
454
502
  *
455
- * `kind`: one of `"approved"` / `"denied"` / `"escalated"` / `"expired"`. **Fails
456
- * closed** without a `decision.key` unless [`INSECURE_DECISION_KEY_ENV`] is set
457
- * (see `load_decision_signer`) the approver key is cloud-custodied in prod.
458
- */
459
- export declare function processAppendDecision(projectRoot: string, sessionId: string, kind: string, reason?: string | undefined | null, decidedAt?: string | undefined | null): void
460
- /**
461
- * Read the current lifecycle state of a session chain (the head link's kind).
462
- * Mirrors the PyO3 `process_read_chain_head` body 1:1.
503
+ * Runs the EXISTING offline verify for the base outcome + trust level (so that
504
+ * path is unchanged), then renders the signed metrics and recomputes the cost via
505
+ * the SHARED `heso_action::metrics_view` glue. Never throws on a malformed receipt
506
+ * or card — those degrade to `has_metrics: false` / `priced: false` exactly as the
507
+ * WASM export does. The cost render is purely informational and NEVER masks a
508
+ * verify failure: a tampered metric flips the `action_hash`, so `verdict` is a
509
+ * non-`Valid` tag while the (meaningless) recompute still reflects whatever bytes
510
+ * are present — the caller branches on `verdict`, never the dollar figure.
463
511
  *
464
- * Returns the head kind as a lowercase string (`"suspended"` / `"approved"` /
465
- * `"denied"` / `"expired"` / `"completed"` / `"escalated"`), or `None` if no chain
466
- * exists yet.
512
+ * `receipt_bytes` — the raw `ActionReceipt` JSON bytes (Buffer/Uint8Array/string).
513
+ * `rate_card_json` the public rate-card JSON the cost is recomputed from.
467
514
  */
468
- export declare function processReadChainHead(projectRoot: string, sessionId: string): string | null
469
- /** A loaded operator key, exposing just the public-key surface. */
470
- export declare class OperatorKey {
471
- /** Return the base64 standard-alphabet public key. */
472
- publicKeyB64(): string
473
- }
515
+ export declare function verifyWithRates(receiptBytes: Buffer | Uint8Array | string, rateCardJson: string): MetricsVerdict
516
+
517
+ /** Verify a receipt AND report its trusted-time status separately. */
518
+ export declare function verifyWithTime(receiptBytesInput: Buffer | Uint8Array | string): ActionVerdictWithTime