verdifax 1.3.0 → 1.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.
package/dist/index.d.mts CHANGED
@@ -569,6 +569,11 @@ interface RunsExport {
569
569
  * key in the account, with the account's policy documents and changes. */
570
570
  interface AccountRunsExport extends RunsExport {
571
571
  account_id: string;
572
+ /** The account's whole chain of sign-offs, oldest first, as
573
+ * {@link VerdifaxClient.getSignOffHistory} returns it. Only the owner
574
+ * key's export carries it, and the SDK returns it as the server sent
575
+ * it, without checking it: check it with `verdifax-verify`. */
576
+ signoffs?: SignOffRecord[];
572
577
  }
573
578
  /** Returned by {@link VerdifaxClient.exportRunsCSV}. */
574
579
  interface RunsExportCSV {
@@ -755,6 +760,294 @@ interface AdminAPIKey {
755
760
  run_count: number;
756
761
  revoked: boolean;
757
762
  }
763
+ /** The kind of result a sign-off names: a completed run's record, a
764
+ * refused or halted run's receipt, or a whole job by its final step. */
765
+ type SignOffTargetKind = "record" | "receipt" | "job";
766
+ /** An approver's decision on one result. */
767
+ type SignOffDecision = "approve" | "reject";
768
+ /** The exact result a sign-off names, by what its public-log entry
769
+ * covers. */
770
+ interface SignOffTarget {
771
+ kind: SignOffTargetKind;
772
+ /** The run: for a job, the run of its final step. */
773
+ run_id: number;
774
+ /** What the result's public-log entry covers. For a record, its
775
+ * `bundle_anchor.anchored_digest` in the bundle
776
+ * {@link VerdifaxClient.getRunArtifacts} returns. For a receipt, its
777
+ * hash. For a job, the final step's record digest, read the same way
778
+ * as a record's. 64 lowercase hex characters. */
779
+ digest: Hex64;
780
+ /** The job, for a job target only. */
781
+ job_id?: string;
782
+ }
783
+ /** One sign-off, verdifax.signoff.v1, as the server records it and
784
+ * `verdifax-verify --signoff` and `--signoff-history` read it. */
785
+ interface SignOffRecord {
786
+ format: string;
787
+ /** The account's chain, `account-N`. */
788
+ chain_id: string;
789
+ sequence: number;
790
+ /** The sign-off this one follows, or 64 zeros for the account's first. */
791
+ previous_signoff_hash: Hex64;
792
+ target: SignOffTarget;
793
+ decision: SignOffDecision;
794
+ /** SHA-256 of the approver's note, when there was one. The note's text
795
+ * never reaches Verdifax. */
796
+ note_hash?: string;
797
+ /** The base64 Ed25519 public key of the approver who signed. */
798
+ approver_key: string;
799
+ /** Base64 Ed25519 signature by the approver key. */
800
+ signature: string;
801
+ signed_at: string;
802
+ nonce: string;
803
+ recorded_at: string;
804
+ signoff_hash: Hex64;
805
+ /** Where the sign-off was logged on the public log. */
806
+ anchor?: Record<string, unknown>;
807
+ }
808
+ /** What an approver signs against: the account's chain and its newest
809
+ * sign-off. Returned by {@link VerdifaxClient.getNewestSignOff}. */
810
+ interface NewestSignOff {
811
+ ok: boolean;
812
+ /** The account's chain, `account-N`. */
813
+ chain_id: string;
814
+ /** The newest sign-off's hash, or 64 zeros when there is none yet. */
815
+ newest_signoff_hash: Hex64;
816
+ /** The newest sign-off's place in the chain, 0 when there is none. */
817
+ sequence: number;
818
+ }
819
+ /** The approver key's part of a sign-off. */
820
+ interface SignOffSignature {
821
+ /** The base64 Ed25519 public key of the approver. */
822
+ approver_key: string;
823
+ /** Base64 Ed25519 signature by the approver key. */
824
+ signature: string;
825
+ /** RFC 3339 UTC with whole seconds. */
826
+ signed_at: string;
827
+ /** 16 random bytes as 32 lowercase hex characters, fresh per sign-off. */
828
+ nonce: string;
829
+ }
830
+ /** Options for {@link VerdifaxClient.signOff}. */
831
+ interface SignOffOptions {
832
+ /** The approver's note. It is hashed on this machine and only its
833
+ * SHA-256 is sent and signed: the text never reaches Verdifax. Keep the
834
+ * text yourself to show it matches the hash. */
835
+ note?: string;
836
+ /** Use the owner key's routes, /account/signoffs/newest and
837
+ * /account/signoffs, instead of a member key's. */
838
+ asOwner?: boolean;
839
+ }
840
+ /** For a method that serves both a member key's route and the owner
841
+ * key's /account route. */
842
+ interface AsOwnerOptions {
843
+ /** Use the owner key's /account route. */
844
+ asOwner?: boolean;
845
+ }
846
+ /** An approver key's public key and the proof that its holder has the
847
+ * private key, from {@link approverKeyProof}. */
848
+ interface ApproverKeyProof {
849
+ /** Base64 of the raw 32-byte public key. */
850
+ public_key: string;
851
+ /** Base64 Ed25519 signature over verdifax.approver-key.v1, a zero byte
852
+ * and the base64 public key. */
853
+ proof: string;
854
+ }
855
+ /** An approver key registered to an account. A key is not an identity:
856
+ * `name` is the label the owner gave it. */
857
+ interface Approver {
858
+ id: number;
859
+ public_key: string;
860
+ name: string;
861
+ /** The account, `account-N`. */
862
+ account_id: string;
863
+ registered_at: string;
864
+ revoked: boolean;
865
+ revoked_at?: string;
866
+ }
867
+ /** Returned by {@link VerdifaxClient.registerApprover}. */
868
+ interface ApproverRegistration extends Approver {
869
+ ok: boolean;
870
+ }
871
+ /** Returned by {@link VerdifaxClient.listApprovers}: revoked keys
872
+ * included. */
873
+ interface ApproverList {
874
+ ok: boolean;
875
+ account_id: string;
876
+ approvers: Approver[];
877
+ }
878
+ /** Returned by {@link VerdifaxClient.revokeApprover}. */
879
+ interface ApproverRevocation {
880
+ ok: boolean;
881
+ id: number;
882
+ revoked: boolean;
883
+ }
884
+ /** The kind of a control signal. Each is also a CloudEvents type,
885
+ * `com.verdifax.` and the kind. */
886
+ type SignalKind = "run.refused" | "run.halted" | "run.failed" | "policy.changed" | "signoff.recorded" | "approver.registered" | "approver.revoked" | "key.created" | "key.revoked";
887
+ /** The Verdifax event inside a {@link SignalEvent}, verdifax.signal.v1. */
888
+ interface SignalEventData {
889
+ /** `verdifax.signal.v1`. */
890
+ form: string;
891
+ kind: SignalKind | (string & {});
892
+ /** The account, `account-N`. */
893
+ account: string;
894
+ /** The event's place in the account's feed, from 1. */
895
+ sequence: number;
896
+ /** The previous event's `event_hash`, or 64 zeros for the account's
897
+ * first event. */
898
+ previous_signal_hash: Hex64;
899
+ /** {@link signalEventHash} of the kind, the entry's hash and the place. */
900
+ event_hash: Hex64;
901
+ run_id?: number;
902
+ api_key_id?: number;
903
+ /** A short reason a reader can route on, for a refused, halted or
904
+ * failed run. */
905
+ reason?: string;
906
+ /** The sealed entry the event names, in the exact form
907
+ * `verdifax-verify` reads. */
908
+ entry: Record<string, unknown>;
909
+ }
910
+ /** One control signal, as a CloudEvents 1.0 envelope. */
911
+ interface SignalEvent {
912
+ specversion: string;
913
+ /** `account-N/SEQUENCE`. */
914
+ id: string;
915
+ source: string;
916
+ /** `com.verdifax.` and the kind. */
917
+ type: string;
918
+ time: string;
919
+ datacontenttype: string;
920
+ data: SignalEventData;
921
+ }
922
+ /** One page of the feed. Returned by {@link VerdifaxClient.getSignals}. */
923
+ interface SignalPage {
924
+ /** The events after the place asked for, oldest first. */
925
+ events: SignalEvent[];
926
+ /** The place to read from next: the last event's sequence, or the
927
+ * place asked for when the page is empty. */
928
+ next_after: number;
929
+ /** The newest sequence in the account's feed, 0 when it is empty. */
930
+ newest: number;
931
+ }
932
+ /** Options for {@link VerdifaxClient.getSignals}. */
933
+ interface GetSignalsOptions {
934
+ /** The last sequence already read. 0, the default, reads from the start. */
935
+ after?: number;
936
+ /** 1 to 500 events. The server's default is 100. */
937
+ limit?: number;
938
+ /** 0 to 25 seconds to hold the request open when there is no event yet.
939
+ * Defaults to 0. */
940
+ wait?: number;
941
+ /** Read GET /account/signals with the owner key instead of GET /signals
942
+ * with a feed key. */
943
+ asOwner?: boolean;
944
+ }
945
+ /** Options for {@link VerdifaxClient.followSignals}. */
946
+ interface FollowSignalsOptions {
947
+ /** The last sequence already read. 0, the default, reads from the start. */
948
+ after?: number;
949
+ /** 0 to 25 seconds each read waits for the next event. Defaults to 25. */
950
+ wait?: number;
951
+ /** Read GET /account/signals with the owner key instead of GET /signals
952
+ * with a feed key. */
953
+ asOwner?: boolean;
954
+ }
955
+ /** Options for {@link VerdifaxClient.createFeedKey}. */
956
+ interface CreateFeedKeyOptions {
957
+ /** RFC 3339 or YYYY-MM-DD. */
958
+ expiresAt?: string;
959
+ }
960
+ /** A new feed key with its secret, which is shown this once. A feed key
961
+ * reads the account's signal feed and nothing else. Returned by
962
+ * {@link VerdifaxClient.createFeedKey}. */
963
+ type CreatedFeedKey = CreatedAccountKey;
964
+ /** Returned by {@link VerdifaxClient.revokeFeedKey}. */
965
+ interface FeedKeyRevocation {
966
+ ok: boolean;
967
+ id: number;
968
+ revoked: boolean;
969
+ }
970
+ /** Options for {@link VerdifaxClient.createWebhook}. */
971
+ interface CreateWebhookOptions {
972
+ /** The kinds to deliver, each once. Empty or left out takes every kind. */
973
+ types?: SignalKind[];
974
+ }
975
+ /** A webhook subscription, without its secret. */
976
+ interface Webhook {
977
+ id: number;
978
+ url: string;
979
+ /** The kinds it delivers. Empty means every kind. */
980
+ types: SignalKind[];
981
+ created_at: string;
982
+ }
983
+ /** A new webhook subscription with its secret, `whsec_` and base64,
984
+ * which is shown this once. Check each delivery with it using
985
+ * {@link verifyWebhook}. Returned by {@link VerdifaxClient.createWebhook}. */
986
+ interface CreatedWebhook extends Webhook {
987
+ ok: boolean;
988
+ secret: string;
989
+ hint: string;
990
+ }
991
+ /** Returned by {@link VerdifaxClient.listWebhooks}. */
992
+ interface WebhookList {
993
+ ok: boolean;
994
+ webhooks: Webhook[];
995
+ }
996
+ /** Returned by {@link VerdifaxClient.deleteWebhook}. */
997
+ interface WebhookDeletion {
998
+ ok: boolean;
999
+ id: number;
1000
+ deleted: boolean;
1001
+ }
1002
+ /** Options for {@link VerdifaxClient.listWebhookDeliveries}. */
1003
+ interface ListWebhookDeliveriesOptions {
1004
+ /** 1 to 500 deliveries. The server's default is 50. */
1005
+ limit?: number;
1006
+ }
1007
+ /** One delivery of one event to a webhook. A delivery is a copy: the pull
1008
+ * feed and the public log are the record. */
1009
+ interface WebhookDelivery {
1010
+ /** The event's place in the account's feed. */
1011
+ sequence: number;
1012
+ /** `pending`, `delivered` or `failed`. */
1013
+ status: string;
1014
+ attempts: number;
1015
+ last_status_code: number;
1016
+ last_error: string;
1017
+ created_at: string;
1018
+ delivered_at?: string;
1019
+ next_attempt_at?: string;
1020
+ }
1021
+ /** Returned by {@link VerdifaxClient.listWebhookDeliveries}: the newest
1022
+ * deliveries first. */
1023
+ interface WebhookDeliveryList {
1024
+ ok: boolean;
1025
+ webhook_id: number;
1026
+ deliveries: WebhookDelivery[];
1027
+ }
1028
+ /** The headers of a webhook delivery: a fetch `Headers`, or an object such
1029
+ * as Node's `req.headers`. Names are read without regard to case. */
1030
+ type WebhookHeaders = {
1031
+ get(name: string): string | null;
1032
+ } | Record<string, string | string[] | undefined>;
1033
+ /** Options for {@link verifyWebhook}. */
1034
+ interface VerifyWebhookOptions {
1035
+ /** How far, in seconds, `webhook-timestamp` may be from `now` in either
1036
+ * direction. Defaults to 300. */
1037
+ toleranceSeconds?: number;
1038
+ /** The time to check the timestamp against. Defaults to the current
1039
+ * time. */
1040
+ now?: Date;
1041
+ }
1042
+ /** An event's place in its account's feed, for {@link signalEventHash}. */
1043
+ interface SignalEventHashFields {
1044
+ /** The account, `account-N`. */
1045
+ account: string;
1046
+ /** The event's sequence, a whole number. */
1047
+ sequence: number;
1048
+ /** The previous event's hash, or 64 zeros for the account's first. */
1049
+ previousSignalHash: string;
1050
+ }
758
1051
 
759
1052
  /**
760
1053
  * The job helper: runs the steps of one job and keeps the map of step ids
@@ -869,6 +1162,22 @@ declare const MAX_BATCH_ROWS = 1000;
869
1162
  * | `testAccountPolicy(req)` | POST /account/policies/test | owner key |
870
1163
  * | `getAccountPolicyHistory()` | GET /account/policies/history | owner key |
871
1164
  * | `activateAccountPolicy(documentHash)` | POST /account/policies/{document_hash}/activate | owner key |
1165
+ * | `registerApprover(name, approver)` | POST /account/approvers | owner key |
1166
+ * | `listApprovers()` | GET /account/approvers | owner key |
1167
+ * | `revokeApprover(id)` | DELETE /account/approvers/{id} | owner key |
1168
+ * | `signOff(target, decision, approverKey, options)` | POST /signoffs, or POST /account/signoffs with asOwner | required |
1169
+ * | `getNewestSignOff(options)` | GET /signoffs/newest, or GET /account/signoffs/newest with asOwner | required |
1170
+ * | `getSignOffs(runId, options)` | GET /runs/{id}/signoffs, or GET /account/runs/{id}/signoffs with asOwner | required |
1171
+ * | `getSignOffHistory()` | GET /account/signoffs/history | owner key |
1172
+ * | `getSignals(options)` | GET /signals, or GET /account/signals with asOwner | feed key, or owner key |
1173
+ * | `followSignals(options)` | GET /signals page after page, or GET /account/signals with asOwner | feed key, or owner key |
1174
+ * | `createFeedKey(name, options)` | POST /account/feed-keys | owner key |
1175
+ * | `revokeFeedKey(id)` | DELETE /account/feed-keys/{id} | owner key |
1176
+ * | `createWebhook(url, options)` | POST /account/webhooks | owner key |
1177
+ * | `listWebhooks()` | GET /account/webhooks | owner key |
1178
+ * | `deleteWebhook(id)` | DELETE /account/webhooks/{id} | owner key |
1179
+ * | `listWebhookDeliveries(id, options)` | GET /account/webhooks/{id}/deliveries | owner key |
1180
+ * | `getFailureReceipt(id)` | GET /runs/{id}/failure-receipt | required |
872
1181
  * | `job(jobId)` | none, returns a {@link VerdifaxJob} | none |
873
1182
  *
874
1183
  * With the `signingKey` option set, every path to POST /execute carries
@@ -1037,6 +1346,94 @@ declare class VerdifaxClient {
1037
1346
  * `account-N`. The server refuses an unsigned account change, so this
1038
1347
  * needs the `signingKey` option and refuses to send without it. */
1039
1348
  activateAccountPolicy(documentHash: Hex64): Promise<PolicyActivation>;
1349
+ /** Registers an approver key to the owner's account. `approver` is the
1350
+ * approver's signing key, from which the proof is made on this machine,
1351
+ * or the `{ public_key, proof }` that {@link approverKeyProof} made on
1352
+ * the approver's own machine, so the owner need not hold the private
1353
+ * key. A proof that does not verify is refused before sending. The
1354
+ * server refuses a key that is a request key in the same account.
1355
+ * `name` is a label, not an identity. */
1356
+ registerApprover(name: string, approver: Uint8Array | KeyObject | ApproverKeyProof): Promise<ApproverRegistration>;
1357
+ /** The account's approver keys, revoked ones included. */
1358
+ listApprovers(): Promise<ApproverList>;
1359
+ /** Revokes one of the account's approver keys. Its earlier sign-offs
1360
+ * stay on the record. A key that is not an active approver in the
1361
+ * account throws {@link NotFoundError}. */
1362
+ revokeApprover(approverId: number): Promise<ApproverRevocation>;
1363
+ /** What an approver signs against: the account's chain `account-N` and
1364
+ * its newest sign-off (64 zeros when there is none yet). With
1365
+ * `asOwner` it reads the owner key's route. */
1366
+ getNewestSignOff(options?: AsOwnerOptions): Promise<NewestSignOff>;
1367
+ /** Signs an approver's decision, approve or reject, on one exact result
1368
+ * and submits it. It first reads {@link getNewestSignOff} for the
1369
+ * account's chain and its newest sign-off, then signs over them with
1370
+ * `approverKey` on this machine. The approver's private key is never
1371
+ * sent.
1372
+ *
1373
+ * `target.digest` is what the result's public-log entry covers: for a
1374
+ * record, the `bundle_anchor.anchored_digest` of the bundle
1375
+ * {@link getRunArtifacts} returns; for a receipt, its hash; for a job,
1376
+ * the final step's record digest, read as a record's, with `job_id`.
1377
+ *
1378
+ * `note` is hashed here and only its SHA-256 is sent and signed: the
1379
+ * text never reaches Verdifax. With `asOwner` it uses the owner key's
1380
+ * routes. Bad input is refused before anything is sent.
1381
+ *
1382
+ * The record the server returns must carry the signature,
1383
+ * approver_key, decision, previous_signoff_hash and target that were
1384
+ * sent, or this throws {@link VerdifaxError}.
1385
+ *
1386
+ * A later sign-off on the same result supersedes this one, and neither
1387
+ * is deleted. An HTTP 409 means the chain moved or the target is not
1388
+ * this account's result: it throws the usual {@link APIError} and is
1389
+ * not retried. */
1390
+ signOff(target: SignOffTarget, decision: SignOffDecision, approverKey: Uint8Array | KeyObject, options?: SignOffOptions): Promise<SignOffRecord>;
1391
+ /** The sign-offs on one run, oldest first, in the form
1392
+ * `verdifax-verify --signoff FILE` reads: for a member key, a run it
1393
+ * made; with `asOwner`, any run of the account. The latest is the
1394
+ * decision in force. */
1395
+ getSignOffs(runId: number, options?: AsOwnerOptions): Promise<SignOffRecord[]>;
1396
+ /** The account's whole chain of sign-offs, oldest first, in the form
1397
+ * `verdifax-verify --signoff-history FILE` reads. Needs the owner key. */
1398
+ getSignOffHistory(): Promise<SignOffRecord[]>;
1399
+ /** One page of the account's feed: the events after `after`, oldest
1400
+ * first, with `next_after` to read from next. With `wait` the server
1401
+ * holds the request open up to that many seconds for the next event, and
1402
+ * this call's timeout is at least the wait plus 30 seconds. With
1403
+ * `asOwner` it reads GET /account/signals with the owner key. Bad
1404
+ * options are refused before sending. Save the events and check them
1405
+ * with `verdifax-verify --signals`. */
1406
+ getSignals(options?: GetSignalsOptions): Promise<SignalPage>;
1407
+ /** Follows the feed from `after`, yielding each event once, in order,
1408
+ * until you stop with `break` or `return`. Each read starts at the page
1409
+ * before's `next_after`, waits up to `wait` seconds (default 25) when
1410
+ * there is no event, and is retried like any GET. A read that still
1411
+ * fails throws {@link SignalFeedError}, whose `lastSequence` is the last
1412
+ * sequence yielded: follow again from there and nothing is lost. Bad
1413
+ * options are refused here, before anything is sent. */
1414
+ followSignals(options?: FollowSignalsOptions): AsyncGenerator<SignalEvent, void, undefined>;
1415
+ /** Creates a feed key in the owner's account. A feed key reads the
1416
+ * account's signal feed, with {@link getSignals} and
1417
+ * {@link followSignals}, and nothing else. The secret is in the result
1418
+ * this once. */
1419
+ createFeedKey(name: string, options?: CreateFeedKeyOptions): Promise<CreatedFeedKey>;
1420
+ /** Revokes one of the account's feed keys. An id that is not a feed key
1421
+ * of the account throws {@link NotFoundError}. */
1422
+ revokeFeedKey(id: number): Promise<FeedKeyRevocation>;
1423
+ /** Subscribes an https address to the account's signals. `types` are the
1424
+ * kinds to deliver, each once; empty or left out takes every kind. The
1425
+ * secret, `whsec_` and base64, is in the result this once: check each
1426
+ * delivery with {@link verifyWebhook}. A delivery is a copy: the pull
1427
+ * feed and the public log are the record. The server checks the address
1428
+ * too, and refuses an eleventh subscription with HTTP 409. */
1429
+ createWebhook(url: string, options?: CreateWebhookOptions): Promise<CreatedWebhook>;
1430
+ /** The account's webhook subscriptions, without their secrets. */
1431
+ listWebhooks(): Promise<WebhookList>;
1432
+ /** Ends a webhook subscription. Its events stay in the pull feed. */
1433
+ deleteWebhook(id: number): Promise<WebhookDeletion>;
1434
+ /** A webhook's newest deliveries first, up to `limit` (1 to 500; the
1435
+ * server's default is 50). */
1436
+ listWebhookDeliveries(id: number, options?: ListWebhookDeliveriesOptions): Promise<WebhookDeliveryList>;
1040
1437
  getRun(runId: number): Promise<Run>;
1041
1438
  verifyRun(runId: number): Promise<VerifyResponse>;
1042
1439
  listRuns(params?: ListRunsParams): Promise<{
@@ -1073,6 +1470,10 @@ declare class VerdifaxClient {
1073
1470
  getAivpT4HaltReceipt(runId: number): Promise<Record<string, unknown>>;
1074
1471
  getAttestationGapReceipt(runId: number): Promise<Record<string, unknown>>;
1075
1472
  getCESAuditRecord(runId: number): Promise<Record<string, unknown>>;
1473
+ /** A failed run's sealed failure receipt, in the form `verdifax-verify`
1474
+ * reads. A run that failed before failure receipts were sealed has none
1475
+ * and throws {@link NotFoundError}. */
1476
+ getFailureReceipt(runId: number): Promise<Record<string, unknown>>;
1076
1477
  /** The audit report for a run, as JSON. */
1077
1478
  getRunReport(runId: number): Promise<Record<string, unknown>>;
1078
1479
  /** The run's sealed audit bundle as the exact JSON text the server
@@ -1349,6 +1750,71 @@ declare function policyActivationApproval(signingKey: Uint8Array | KeyObject, fi
1349
1750
  signedAt?: string;
1350
1751
  nonce?: string;
1351
1752
  }): PolicyActivationSignature;
1753
+ /** The bytes an approver key signs for one sign-off, matching the
1754
+ * orchestrator's SignOffPreimage: the fields joined with single zero
1755
+ * bytes. `chain_id` and `previous_signoff_hash` come from GET
1756
+ * /signoffs/newest (or /account/signoffs/newest for the owner key), so a
1757
+ * signature cannot be moved to another account, another result or
1758
+ * another point in the chain. `target.job_id` is empty unless the target
1759
+ * is a job, and `note_hash` is empty when there is no note. */
1760
+ declare function signOffPreimage(fields: {
1761
+ chain_id: string;
1762
+ previous_signoff_hash: string;
1763
+ target: SignOffTarget;
1764
+ decision: SignOffDecision;
1765
+ note_hash: string;
1766
+ signed_at: string;
1767
+ nonce: string;
1768
+ }): Buffer;
1769
+ /** The approver key's base64 public key and its proof: its signature over
1770
+ * verdifax.approver-key.v1, a zero byte and the base64 public key, which
1771
+ * shows its holder has the private key. The approver can run this on
1772
+ * their own machine and give the result to the account's owner, who
1773
+ * registers it with {@link VerdifaxClient.registerApprover}, so the owner
1774
+ * never holds the approver's private key. */
1775
+ declare function approverKeyProof(approverKey: Uint8Array | KeyObject): ApproverKeyProof;
1776
+
1777
+ /**
1778
+ * The signal feed: every control signal Verdifax recorded for an account,
1779
+ * in order, each with its sealed entry. The feed cannot show a signal
1780
+ * Verdifax never recorded.
1781
+ *
1782
+ * A feed key reads the feed and nothing else. The owner key reads the same
1783
+ * feed on its /account route and manages feed keys and webhooks. A webhook
1784
+ * delivery is a copy: the pull feed and the public log are the record.
1785
+ *
1786
+ * The request building, the checks made before sending, the follow loop,
1787
+ * webhook verification and the event hash live here; the client's methods
1788
+ * are thin wrappers over them.
1789
+ */
1790
+
1791
+ /**
1792
+ * Checks one webhook delivery under the Standard Webhooks scheme and
1793
+ * returns its CloudEvent. Pass the headers as received, the body as the
1794
+ * exact bytes received (a Buffer, a Uint8Array or a string, never parsed
1795
+ * JSON) and the subscription's `whsec_` secret.
1796
+ *
1797
+ * The signed content is `webhook-id`, a dot, `webhook-timestamp`, a dot and
1798
+ * the body. `webhook-signature` is a space-separated list of `v1,<base64>`
1799
+ * entries, and any one may match; each is compared in constant time. A
1800
+ * timestamp more than `toleranceSeconds` (default 300) from `now` in either
1801
+ * direction is refused. Header names are read without regard to case. The
1802
+ * body must be a JSON object whose top-level `id` is a string equal to
1803
+ * `webhook-id`.
1804
+ *
1805
+ * Throws {@link VerdifaxError} naming the check that failed. The secret is
1806
+ * never placed in an error message. A delivery is a copy: the pull feed and
1807
+ * the public log are the record.
1808
+ */
1809
+ declare function verifyWebhook(headers: WebhookHeaders, body: Uint8Array | string, secret: string, options?: VerifyWebhookOptions): SignalEvent;
1810
+ /**
1811
+ * The hash the next event in an account's feed names, matching the
1812
+ * orchestrator's SignalEventHash: hex SHA-256 of `verdifax.signal.v1`, the
1813
+ * kind, the hash of the event's entry, the account, the decimal sequence
1814
+ * and the previous event's hash, joined by single zero bytes. It makes no
1815
+ * request.
1816
+ */
1817
+ declare function signalEventHash(kind: string, entryHash: string, fields: SignalEventHashFields): string;
1352
1818
 
1353
1819
  /**
1354
1820
  * Input-validation helpers, mirrors the Python SDK's
@@ -1433,5 +1899,17 @@ declare class APIKeyRequiredError extends VerdifaxError {
1433
1899
  readonly name: string;
1434
1900
  constructor();
1435
1901
  }
1902
+ /** Thrown by {@link VerdifaxClient.followSignals} when a read fails or a
1903
+ * page does not follow on from the last one. `lastSequence` is the last
1904
+ * sequence the generator handed out, so the feed is never lost: follow
1905
+ * again with `after: lastSequence`. The error the read threw, after the
1906
+ * client's normal retries, is `cause`. */
1907
+ declare class SignalFeedError extends VerdifaxError {
1908
+ readonly lastSequence: number;
1909
+ readonly name: string;
1910
+ constructor(lastSequence: number, reason: string, options?: {
1911
+ cause?: unknown;
1912
+ });
1913
+ }
1436
1914
 
1437
- export { APIError, APIKeyRequiredError, type Account, type AccountInfo, type AccountKey, type AccountKeyList, type AccountKeyRevocation, type AccountRunsExport, type AdminAPIKey, type AdminCreateAccountOptions, type AdminCreateAccountResponse, type AdminCreateKeyOptions, type AdminCreateKeyResponse, type AdminEraseRequest, type AttestRequest, type AttestationList, AuthError, CRES_ENGINE_VERSION, CRES_PREIMAGE_VERSION, type ClientConfig, type CreateAccountKeyOptions, type CreatedAccountKey, type DCAEProofBundle, type DCAEVerdict, DCAE_PREIMAGE_VERSION, DSE_FORMULA_VERSION, type DeletionReceipt, type DeterminismDiff, type DeterminismRun, EXECUTE_FIELDS, type ExecuteBatchResponse, type ExecuteBatchResult, type ExecuteRequest, type ExecuteResponse, type ExecutionManifest, type ExportRow, type ExportRunsParams, type FormulaEra, type Health, type Hex64, type JobLink, type JobStepOptions, type KeyTier, type ListAttestationsParams, type ListRunsParams, MAX_BATCH_ROWS, NotFoundError, type PDFFormat, type Policy, type PolicyActivation, type PolicyActivationSignature, type PolicyActorType, type PolicyClassification, type PolicyContext, type PolicyList, type PolicyObjectType, type PolicyTestRequest, type PolicyTestResult, type PolicyWithDocument, RUN_STATUSES, type ReproducibilityContext, type RequestKeyChange, type RequestKeyPair, type RequestKeyRegistration, type RequestKeyRegistrationBody, type RequestSignature, type RequestSignatureV2, type Run, type RunStats, type RunStatus, type RunSummary, type RunsExport, type RunsExportCSV, type SearchRunsParams, type SignedRequestBody, VerdifaxClient, VerdifaxError, VerdifaxJob, type VerdifaxVersion, type VerifyDeterminismResponse, type VerifyResponse, captureEnvironment, cresReceiptHash, dcaeClosureHash, dseDispatchHash, formatProviderPayload, fromEnv, generateRequestKeyPair, policyActivationApproval, policyActivationPreimage, requestKeyChangeApproval, requestKeyChangePreimage, requestKeyRegistrationBody, requestSignaturePreimage, requestSignaturePreimageV2, signRequest, signRequestV2, validateHex64, validateJobName, validateRouteId };
1915
+ export { APIError, APIKeyRequiredError, type Account, type AccountInfo, type AccountKey, type AccountKeyList, type AccountKeyRevocation, type AccountRunsExport, type AdminAPIKey, type AdminCreateAccountOptions, type AdminCreateAccountResponse, type AdminCreateKeyOptions, type AdminCreateKeyResponse, type AdminEraseRequest, type Approver, type ApproverKeyProof, type ApproverList, type ApproverRegistration, type ApproverRevocation, type AsOwnerOptions, type AttestRequest, type AttestationList, AuthError, CRES_ENGINE_VERSION, CRES_PREIMAGE_VERSION, type ClientConfig, type CreateAccountKeyOptions, type CreateFeedKeyOptions, type CreateWebhookOptions, type CreatedAccountKey, type CreatedFeedKey, type CreatedWebhook, type DCAEProofBundle, type DCAEVerdict, DCAE_PREIMAGE_VERSION, DSE_FORMULA_VERSION, type DeletionReceipt, type DeterminismDiff, type DeterminismRun, EXECUTE_FIELDS, type ExecuteBatchResponse, type ExecuteBatchResult, type ExecuteRequest, type ExecuteResponse, type ExecutionManifest, type ExportRow, type ExportRunsParams, type FeedKeyRevocation, type FollowSignalsOptions, type FormulaEra, type GetSignalsOptions, type Health, type Hex64, type JobLink, type JobStepOptions, type KeyTier, type ListAttestationsParams, type ListRunsParams, type ListWebhookDeliveriesOptions, MAX_BATCH_ROWS, type NewestSignOff, NotFoundError, type PDFFormat, type Policy, type PolicyActivation, type PolicyActivationSignature, type PolicyActorType, type PolicyClassification, type PolicyContext, type PolicyList, type PolicyObjectType, type PolicyTestRequest, type PolicyTestResult, type PolicyWithDocument, RUN_STATUSES, type ReproducibilityContext, type RequestKeyChange, type RequestKeyPair, type RequestKeyRegistration, type RequestKeyRegistrationBody, type RequestSignature, type RequestSignatureV2, type Run, type RunStats, type RunStatus, type RunSummary, type RunsExport, type RunsExportCSV, type SearchRunsParams, type SignOffDecision, type SignOffOptions, type SignOffRecord, type SignOffSignature, type SignOffTarget, type SignOffTargetKind, type SignalEvent, type SignalEventData, type SignalEventHashFields, SignalFeedError, type SignalKind, type SignalPage, type SignedRequestBody, VerdifaxClient, VerdifaxError, VerdifaxJob, type VerdifaxVersion, type VerifyDeterminismResponse, type VerifyResponse, type VerifyWebhookOptions, type Webhook, type WebhookDeletion, type WebhookDelivery, type WebhookDeliveryList, type WebhookHeaders, type WebhookList, approverKeyProof, captureEnvironment, cresReceiptHash, dcaeClosureHash, dseDispatchHash, formatProviderPayload, fromEnv, generateRequestKeyPair, policyActivationApproval, policyActivationPreimage, requestKeyChangeApproval, requestKeyChangePreimage, requestKeyRegistrationBody, requestSignaturePreimage, requestSignaturePreimageV2, signOffPreimage, signRequest, signRequestV2, signalEventHash, validateHex64, validateJobName, validateRouteId, verifyWebhook };