@haven_ai/sdk 0.1.17-alpha.0 → 0.1.19-alpha.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.cts CHANGED
@@ -1,5 +1,59 @@
1
1
  import { PaymentRequirements } from 'x402/types';
2
2
 
3
+ /**
4
+ * Verifiable payment receipts.
5
+ *
6
+ * A self-contained proof bundle for a settled Haven payment that anyone can
7
+ * verify **independently of Haven**. The anchor is the agent delegate's
8
+ * signature over the on-chain transfer hash: recover the signer and confirm it
9
+ * is the agent's delegate, and you have cryptographic proof the agent authorised
10
+ * exactly this transfer — no need to trust Haven's backend. The on-chain
11
+ * `txHash` is the settlement source of truth (verify on any explorer).
12
+ *
13
+ * This lives in the SDK so agents and users can verify receipts client-side
14
+ * with zero Haven trust.
15
+ */
16
+ declare const RECEIPT_VERSION = "haven-receipt-1";
17
+ interface PaymentReceipt {
18
+ version: typeof RECEIPT_VERSION;
19
+ paymentId: string;
20
+ payment: {
21
+ token: string;
22
+ tokenAddress: string;
23
+ amount: string;
24
+ amountSek: string | null;
25
+ recipient: string;
26
+ safe: string;
27
+ chainId: number;
28
+ settledAt: string | null;
29
+ resourceUrl: string | null;
30
+ };
31
+ /** The agent's cryptographic authorisation — what makes the receipt verifiable. */
32
+ authorization: {
33
+ delegate: string;
34
+ signHash: string;
35
+ signature: string | null;
36
+ };
37
+ onChain: {
38
+ txHash: string | null;
39
+ chainId: number;
40
+ };
41
+ }
42
+ type ReceiptVerification = {
43
+ verified: true;
44
+ recoveredSigner: string;
45
+ } | {
46
+ verified: false;
47
+ reason: 'missing_signature' | 'bad_signature' | 'signer_mismatch';
48
+ recoveredSigner?: string;
49
+ };
50
+ /**
51
+ * Verify a receipt independently: recover the signer from the authorisation and
52
+ * confirm it is the agent's delegate. Pure — `recover` is injectable but
53
+ * defaults to standard ECDSA recovery, so this runs anywhere (no Haven backend).
54
+ */
55
+ declare function verifyPaymentReceipt(receipt: PaymentReceipt, recover?: (hash: string, signature: string) => string): ReceiptVerification;
56
+
3
57
  interface HavenClientConfig {
4
58
  /** Haven API key (sk_agent_xxx) */
5
59
  apiKey: string;
@@ -51,6 +105,25 @@ interface PaymentRequest {
51
105
  interface SignData {
52
106
  /** The hash to sign (keccak256, 0x-prefixed) */
53
107
  hash: string;
108
+ /**
109
+ * Delegation rail: 'eip712_userop' (funding redemption) or
110
+ * 'eip712_delegation' (erc7710 settlement child). Absent = legacy
111
+ * AllowanceModule (raw ECDSA over `hash`). The session rail's
112
+ * 'eip191_userop' is retired (#834).
113
+ *
114
+ * When present, `hash` is NOT what gets signed — `typed_data` is (#1138).
115
+ */
116
+ signature_scheme?: 'eip712_userop' | 'eip712_delegation';
117
+ /**
118
+ * EIP-712 payload the account validates, signed VERBATIM (#829). Present
119
+ * whenever `signature_scheme` is — never reconstruct it from `components`.
120
+ */
121
+ typed_data?: {
122
+ domain: Record<string, unknown>;
123
+ types: Record<string, unknown>;
124
+ primaryType: string;
125
+ message: Record<string, unknown>;
126
+ };
54
127
  /** Breakdown of values that were hashed — useful for debugging */
55
128
  components: {
56
129
  safe: string;
@@ -98,6 +171,23 @@ interface PaymentResult {
98
171
  submittedAt: string | null;
99
172
  confirmedAt: string | null;
100
173
  expiresAt: string;
174
+ /**
175
+ * Platform fee surfaced on the result so it's never silently collected. Dark
176
+ * today (`amount` "0", `applied` false); always present so it's visible the
177
+ * moment fees go live.
178
+ */
179
+ fee?: PaymentFee | null;
180
+ }
181
+ /** The Haven platform fee applied to a payment (#386). */
182
+ interface PaymentFee {
183
+ /** Human-readable fee amount ("0" while the fee module is dark). */
184
+ amount: string;
185
+ /** Token the fee is denominated in. */
186
+ token: string;
187
+ /** Fee as basis points of gross (0 while dark). */
188
+ basisPoints: number;
189
+ /** True when a non-zero fee was actually applied. */
190
+ applied: boolean;
101
191
  }
102
192
  /** Payment requirements from an HTTP 402 response (x402 protocol). */
103
193
  interface X402PaymentRequired {
@@ -195,6 +285,12 @@ interface X402Intent {
195
285
  network: string;
196
286
  /** Haven-authenticated binding over the x402 expected context. */
197
287
  expectedAuth: X402ExpectedAuth;
288
+ /**
289
+ * EIP-712 digest of `signData.typed_data`, present on the delegation rail
290
+ * (#1138). The edge signer needs it to reconstruct the v2 expected-context
291
+ * message that Haven signed.
292
+ */
293
+ expectedTypedDataHash?: string;
198
294
  /** Delegate EOA the funding transfer tops up (the x402 payer). */
199
295
  fundingTo: string;
200
296
  }
@@ -208,9 +304,33 @@ interface X402ExpectedContext {
208
304
  network: string;
209
305
  /** Optional ISO expiry for the funding/quote window. When present, it is bound into the Haven-authenticated context. */
210
306
  expiresAt?: string;
307
+ /**
308
+ * EIP-712 digest of the typed data the account actually validates
309
+ * (delegation rail, #1138). Present ⇒ the context is **version 2** and the
310
+ * signer must sign that typed data, never `payloadHash`.
311
+ *
312
+ * On the delegation rail `payloadHash` is the bare ERC-4337 UserOp hash,
313
+ * which is NOT what the account validates — binding it alone would leave the
314
+ * edge signer unable to verify the payload it is being asked to sign. Binding
315
+ * this digest makes Haven's declaration cover the real payload.
316
+ */
317
+ typedDataHash?: string;
211
318
  }
212
319
  interface X402ExpectedAuth {
213
- version: 1;
320
+ /**
321
+ * 1 = hash-only (legacy rail). 2 = carries `typedDataHash` (delegation rail,
322
+ * #1138).
323
+ *
324
+ * Deliberately `number`, not a literal union (#1143). This is an **inbound**
325
+ * value: a signer parses a context Haven produced, and a signer older than the
326
+ * backend will legitimately receive a version it does not know. A closed union
327
+ * makes that state unrepresentable, which pushed the rejection down to the
328
+ * schema boundary and produced a raw validation error naming neither the cause
329
+ * nor the fix. The supported set lives in the signer
330
+ * (`SUPPORTED_X402_EXPECTED_VERSIONS`), which fails closed on anything outside
331
+ * it with an actionable message.
332
+ */
333
+ version: number;
214
334
  message: string;
215
335
  signature: string;
216
336
  signer: string;
@@ -417,10 +537,17 @@ interface HavenAllowanceSummary {
417
537
  }
418
538
  /**
419
539
  * Affirmative spend-readiness for the authenticated agent, derived from the raw
420
- * agent status plus the on-chain remaining allowance:
421
- * - `ready` — active and at least one token has remaining on-chain allowance.
422
- * - `needs_approval`— active but no remaining allowance to auto-spend; payments
423
- * will be queued for the wallet owner to approve in Haven.
540
+ * agent status plus the remaining spend authority the backend reports per rail
541
+ * (the on-chain AllowanceModule on the legacy rail; the active budget
542
+ * delegation on the delegation rail — #1135):
543
+ * - `ready` — active and at least one token has remaining spend authority.
544
+ * - `needs_approval`— active but no remaining spend authority to auto-spend.
545
+ * The over-budget outcome differs by rail: on the legacy
546
+ * AllowanceModule rail the payment is queued for the wallet
547
+ * owner to approve in Haven; on the delegation rail there is
548
+ * NO approval queue — an over-budget redemption reverts
549
+ * on-chain, so the owner must grant or raise the budget in
550
+ * Haven before the agent can pay.
424
551
  * - `revoked` — the agent's status is not `active`; nothing auto-executes.
425
552
  *
426
553
  * Note: a hard-paused/disabled credential is rejected by the API before this
@@ -660,6 +787,8 @@ interface PaymentStatusResult {
660
787
  expiresAt: string;
661
788
  chainId: number;
662
789
  message: string;
790
+ /** Platform fee surfaced so it's never silently collected (#386). */
791
+ fee?: PaymentFee | null;
663
792
  amountAtomic?: string | null;
664
793
  asset?: string | null;
665
794
  network?: string | null;
@@ -754,8 +883,14 @@ declare class HavenTimeoutError extends HavenError {
754
883
  */
755
884
  /** Base mainnet. The only chain Haven sweeps today. */
756
885
  declare const SWEEP_BASE_CHAIN_ID = 8453;
886
+ /** Base Sepolia testnet — used by the dev environment / QA harness. */
887
+ declare const SWEEP_BASE_SEPOLIA_CHAIN_ID = 84532;
757
888
  /** Canonical Circle USDC on Base (FiatTokenV2_2). */
758
889
  declare const SWEEP_BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
890
+ /** Circle's canonical Base Sepolia testnet USDC. */
891
+ declare const SWEEP_BASE_SEPOLIA_USDC_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
892
+ /** True when the gasless sweep supports a chain (its USDC domain + address are known). */
893
+ declare function isSweepableChain(chainId: number): boolean;
759
894
  /** EIP-712 `TransferWithAuthorization` struct, per EIP-3009. */
760
895
  declare const TRANSFER_WITH_AUTHORIZATION_TYPES: {
761
896
  readonly TransferWithAuthorization: readonly [{
@@ -815,7 +950,13 @@ interface SweepAuthorization {
815
950
  * hosted server pointing `to` at an attacker) before it signs.
816
951
  */
817
952
  interface SweepExpectedAuth {
818
- version: 1;
953
+ /**
954
+ * Currently always 1. Typed as `number` for the same reason as
955
+ * `X402ExpectedAuth.version` (#1143): it is inbound, so a stale signer must be
956
+ * able to *receive* an unknown version in order to report it. The signer's
957
+ * `SUPPORTED_SWEEP_BINDING_VERSIONS` is the authority on what it will sign.
958
+ */
959
+ version: number;
819
960
  message: string;
820
961
  signature: string;
821
962
  signer: string;
@@ -829,7 +970,15 @@ interface SweepPreparation {
829
970
  interface SweepPrepareResponse {
830
971
  /** Present and true when the delegate holds nothing to recover. */
831
972
  nothing_stranded?: boolean;
832
- /** The authorization to sign — absent when nothing is stranded. */
973
+ /**
974
+ * Present and true when the stranded balance is below the sweep floor (#700):
975
+ * it is left on the delegate as dust rather than recovered, because the gas to
976
+ * sweep it would exceed its value. `min_usdc` carries the configured floor. No
977
+ * `authorization` is built.
978
+ */
979
+ below_min?: boolean;
980
+ min_usdc?: string;
981
+ /** The authorization to sign — absent when nothing is stranded or below the floor. */
833
982
  authorization?: SweepAuthorization;
834
983
  /** Haven's binding over the authorization — absent when nothing is stranded. */
835
984
  expected_auth?: SweepExpectedAuth;
@@ -981,6 +1130,16 @@ declare class HavenClient {
981
1130
  * Requires `delegateKey` to be set in the client config.
982
1131
  */
983
1132
  sign(hash: string): string;
1133
+ /**
1134
+ * Sign a payment's `sign_data` with the correct scheme for its rail.
1135
+ *
1136
+ * Dispatching on the server-provided scheme means a caller never has to
1137
+ * know which rail an account is on; an unknown scheme is a hard error,
1138
+ * never a guessed signature. The session rail's 'eip191_userop' is retired
1139
+ * (#834) — the backend refuses those intents with HTTP 410 before any
1140
+ * sign_data reaches a client, so encountering it here is a hard error too.
1141
+ */
1142
+ private signForData;
984
1143
  /**
985
1144
  * Step 3: Submit a signature to execute the payment.
986
1145
  *
@@ -1061,6 +1220,16 @@ declare class HavenClient {
1061
1220
  listReceipts(options?: {
1062
1221
  limit?: number;
1063
1222
  }): Promise<HavenPaymentReceipt[]>;
1223
+ /**
1224
+ * Fetch the verifiable receipt bundle for a settled payment and verify it
1225
+ * locally. The server's own verification is ignored — the receipt is verified
1226
+ * here (independently of Haven) by recovering the signer from the
1227
+ * authorisation, so the result is trustworthy even if the backend lied.
1228
+ */
1229
+ getReceipt(paymentId: string): Promise<{
1230
+ receipt: PaymentReceipt;
1231
+ verification: ReceiptVerification;
1232
+ }>;
1064
1233
  /**
1065
1234
  * Rehydrate the x402/MPP resume-state bundle for a payment id.
1066
1235
  *
@@ -1153,6 +1322,19 @@ declare class HavenClient {
1153
1322
  */
1154
1323
  payMppChallenge(quote: MppQuote, options?: MppAuthorizationOptions): Promise<Response>;
1155
1324
  private retryX402Request;
1325
+ /**
1326
+ * #956: capture the merchant's OWN receipt when the paid response carries
1327
+ * one, and report it to Haven so the reporting feed can attach it next to
1328
+ * the Haven-generated payment evidence (#498). Two supported signals on the
1329
+ * paid response:
1330
+ *
1331
+ * x-receipt-json: base64-encoded JSON receipt document (inline)
1332
+ * x-receipt-url: https URL to the receipt document (reference)
1333
+ *
1334
+ * Strictly best-effort: absence is the normal case, and no failure here may
1335
+ * ever affect the completed payment — the response is already paid for.
1336
+ */
1337
+ private reportMerchantReceipt;
1156
1338
  /**
1157
1339
  * Deliver an already-signed x402 payment header to the merchant and return
1158
1340
  * the merchant's response. Used by the hosted MCP server to complete the
@@ -1327,6 +1509,21 @@ declare const havenTools: {
1327
1509
  * Uses ethers.SigningKey.sign() instead of wallet.signMessage() to avoid the prefix.
1328
1510
  */
1329
1511
  declare function signHash(privateKey: string, hash: string): string;
1512
+ /**
1513
+ * Sign a delegation-rail payment (#829).
1514
+ *
1515
+ * The delegate SMART ACCOUNT validates an EIP-712 signature over the packed
1516
+ * UserOperation — signing the bare 4337 hash would be rejected on-chain. The
1517
+ * backend sends the exact typed data in `sign_data.typed_data`; we sign it
1518
+ * verbatim and never reconstruct it (a second source of truth could drift
1519
+ * from the account's own rules).
1520
+ */
1521
+ declare function signUserOpTypedDataForDelegation(privateKey: string, typedData: {
1522
+ domain: Record<string, unknown>;
1523
+ types: Record<string, unknown>;
1524
+ primaryType: string;
1525
+ message: Record<string, unknown>;
1526
+ }): Promise<string>;
1330
1527
  /**
1331
1528
  * Derive the Ethereum address from a private key.
1332
1529
  */
@@ -1424,13 +1621,13 @@ declare const toolDescriptions: {
1424
1621
  readonly getAgent: {
1425
1622
  readonly summary: "Return the authenticated agent identity AND its live spend authority in one call: Haven wallet, delegate, chain, raw status, a readiness signal, and per-token remaining allowance (atomic + human-readable). The recommended first call in a new session to confirm who you are and whether you can pay right now.";
1426
1623
  readonly selectionGuidance: "Use this as the one-shot orientation/bootstrap at the start of a session, or whenever you need to confirm identity together with whether the agent can spend right now. For a detailed per-token breakdown (configured vs spent vs reset window) use haven_get_allowances.";
1427
- readonly behavior: "Reads identity plus the on-chain AllowanceModule snapshot in one shot. readiness is \"ready\" when at least one token has remaining on-chain allowance, \"needs_approval\" when the agent is active but has no remaining allowance to auto-spend (payments will be queued for the wallet owner to approve in Haven), and \"revoked\" when the credential is not active. allowances[] carries remainingAtomic and remainingDisplay per token. Identity fields (id, name, status, safeAddress, delegateAddress, chainId) are unchanged from before.";
1624
+ readonly behavior: "Reads identity plus the live spend-authority snapshot in one shot — the on-chain AllowanceModule on the legacy rail, the active budget delegation on the delegation rail. readiness is \"ready\" when at least one token has remaining spend authority, \"needs_approval\" when the agent is active but has none, and \"revoked\" when the credential is not active. What an over-budget payment does differs by rail: on the legacy AllowanceModule rail it is queued for the wallet owner to approve in Haven; on the delegation rail there is no approval queue — an over-budget redemption reverts on-chain, so ask the owner to grant or raise the budget in Haven rather than waiting for an approval. allowances[] carries remainingAtomic and remainingDisplay per token. Identity fields (id, name, status, safeAddress, delegateAddress, chainId) are unchanged from before.";
1428
1625
  readonly nextActionGuidance: "";
1429
1626
  };
1430
1627
  readonly getAllowances: {
1431
1628
  readonly summary: "Return configured and on-chain allowance state for the authenticated agent. On-chain allowance is the real spend gate.";
1432
1629
  readonly selectionGuidance: "Use this when the user asks about allowance, budget, spend limit, remaining amount, remaining allowance, remaining budget, daily limit, reset period, what can I spend, or what the agent can still spend.";
1433
- readonly behavior: "Reads the Safe AllowanceModule snapshot per token (allowance, spent, remaining, reset window). Configured amounts from Haven are returned alongside the on-chain truth.";
1630
+ readonly behavior: "Returns the per-token spend authority for the account's rail: the Safe AllowanceModule snapshot (allowance, spent, remaining, reset window) on the legacy rail, or the active budget delegation (remaining = the period budget; over-budget redemptions revert on-chain, nothing queues) on the delegation rail. Configured amounts from Haven are returned alongside.";
1434
1631
  readonly nextActionGuidance: "";
1435
1632
  };
1436
1633
  readonly listReceipts: {
@@ -1439,6 +1636,12 @@ declare const toolDescriptions: {
1439
1636
  readonly behavior: "Returns the agent's recent machine-payment receipts ordered by recency. Proof header values are not returned.";
1440
1637
  readonly nextActionGuidance: "";
1441
1638
  };
1639
+ readonly verifyReceipt: {
1640
+ readonly summary: "Verify a payment receipt offline — confirm the agent authorised the transfer.";
1641
+ readonly selectionGuidance: "Use this to check a receipt you already hold; it needs no network and does not trust Haven. Use the history tool to fetch receipts in the first place.";
1642
+ readonly behavior: "Recovers the signer from the receipt authorisation and confirms it matches the agent delegate. Returns verified true/false with the recovered signer or a reason. Pure and local — no backend call.";
1643
+ readonly nextActionGuidance: "";
1644
+ };
1442
1645
  readonly payMcpTool: {
1443
1646
  readonly summary: "Call a named tool on an MCP merchant that requires an x402 payment, handling the full initialize → pay → retry round trip.";
1444
1647
  readonly selectionGuidance: string;
@@ -1489,6 +1692,75 @@ declare const HAVEN_SKILL_MD = "---\nname: haven-pay\ndescription: Pay for thing
1489
1692
  /** Directory name for the installed skill folder. */
1490
1693
  declare const SKILL_FOLDER_NAME = "haven-pay";
1491
1694
 
1695
+ /**
1696
+ * The Node.js floor Haven's published packages support (#1161).
1697
+ *
1698
+ * ## Why this lives in the SDK
1699
+ *
1700
+ * Three packages need to enforce the same floor — `connect` (at setup),
1701
+ * `signer` and `mcp` (at startup) — and `@haven_ai/sdk` is the only dependency
1702
+ * all three already share. A copy per package is how the floor drifted in the
1703
+ * first place: `engines` said `>=24` everywhere while connect's runtime manifest
1704
+ * enforced `20.0.0`, so a connect run on Node v23 passed the guard, installed
1705
+ * the signer, and signed a real payment. Two numbers for one fact is one number
1706
+ * too many.
1707
+ *
1708
+ * Each consumer still owns its own refusal — the error type, the exit code, the
1709
+ * wording of "what to do next" — because a library must never terminate its
1710
+ * host process. This module only answers *is this version supported* and *what
1711
+ * should we tell the user*.
1712
+ *
1713
+ * ## Why a floor is enforced at all
1714
+ *
1715
+ * `engines` is advisory: npm emits `EBADENGINE` and installs anyway unless the
1716
+ * user happens to have `engine-strict` set. For a normal library that is a
1717
+ * reasonable default. For the **signer** it is not — it holds the delegate key
1718
+ * and produces every payment signature, so a subtle runtime incompatibility
1719
+ * shows up as a wrong or missing signature on a money path. "It seemed to work"
1720
+ * is precisely the evidence that cannot be relied on there.
1721
+ */
1722
+ /**
1723
+ * The minimum supported Node.js version, as `major.minor.patch`.
1724
+ *
1725
+ * MUST equal the `engines.node` floor declared by every published Haven
1726
+ * package. A guard test in each package asserts exactly that against its own
1727
+ * `package.json`, so the two cannot drift again silently.
1728
+ */
1729
+ declare const HAVEN_MINIMUM_NODE_VERSION = "24.0.0";
1730
+ /**
1731
+ * Compare two Node versions. Negative when `left` is older.
1732
+ *
1733
+ * An unparseable version parses to `0.0.0` and therefore compares as older than
1734
+ * any real floor — fail-closed. A version string Haven cannot read is not
1735
+ * evidence of a supported runtime, and treating it as one would reopen exactly
1736
+ * the hole this module closes.
1737
+ */
1738
+ declare function compareNodeVersions(left: string, right: string): number;
1739
+ declare function isSupportedNodeVersion(nodeVersion?: string, minimumNodeVersion?: string): boolean;
1740
+ interface UnsupportedNodeVersionMessageOptions {
1741
+ /**
1742
+ * What is being refused, in the user's terms — "Haven setup", "The Haven
1743
+ * signer". Leads the message so the reader knows what just stopped.
1744
+ */
1745
+ subject: string;
1746
+ nodeVersion?: string;
1747
+ minimumNodeVersion?: string;
1748
+ /** Appended verbatim as the closing line. Used for the re-run instruction. */
1749
+ retryHint?: string;
1750
+ }
1751
+ /**
1752
+ * The refusal text.
1753
+ *
1754
+ * Names the detected version, the required version, and **how to fix it** — the
1755
+ * previous message stopped after the two version numbers, which tells a user
1756
+ * they are stuck without telling them how to get unstuck. The version-manager
1757
+ * lines are the fix for nearly everyone; the closing caveat is there because the
1758
+ * runtime that *spawns* the signer is frequently not the shell that was
1759
+ * upgraded, and a desktop app can keep launching the old Node long after
1760
+ * `node -v` in a terminal says otherwise.
1761
+ */
1762
+ declare function unsupportedNodeVersionMessage(options: UnsupportedNodeVersionMessageOptions): string;
1763
+
1492
1764
  /**
1493
1765
  * x402 protocol support for the Haven SDK.
1494
1766
  *
@@ -1501,6 +1773,36 @@ declare const SKILL_FOLDER_NAME = "haven-pay";
1501
1773
  * (see client.ts) since they need API access and signing.
1502
1774
  */
1503
1775
 
1776
+ /**
1777
+ * Upper bound on the MERCHANT-requested part of the EIP-3009 authorization
1778
+ * window (#715, epic #713). The x402 library sets
1779
+ * `validBefore = now + maxTimeoutSeconds` straight from the MERCHANT's 402
1780
+ * challenge — without a cap, a malicious or sloppy merchant can request a
1781
+ * year-long window and a leaked signed authorization stays spendable that
1782
+ * whole time. 600 s is generous for any facilitator settle (typical is
1783
+ * 30–60 s); we CLAMP rather than reject so payments keep flowing while
1784
+ * exposure stays bounded. `validBefore` is a deadline, not a demand —
1785
+ * settling earlier is always valid.
1786
+ */
1787
+ declare const X402_MAX_AUTHORIZATION_WINDOW_SECONDS = 600;
1788
+ /**
1789
+ * Forward margin ADDED on top of the (clamped) merchant timeout when the
1790
+ * authorization is actually signed (#1256). The x402 verify rule requires
1791
+ * `validBefore ≥ now + maxTimeoutSeconds` AT THE FACILITATOR — but the
1792
+ * upstream library computes `validBefore = now + maxTimeoutSeconds` at
1793
+ * SIGNING time, leaving zero forward margin. Haven's flow guarantees elapsed
1794
+ * time between the two (the funding UserOp confirms before the merchant
1795
+ * retry, ~1 min plus latency), so every purchase against a merchant whose
1796
+ * `maxTimeoutSeconds` exceeded that latency failed structurally — measured
1797
+ * live on Base mainnet: Anchor requires 300 s, and 226 s remained at verify.
1798
+ *
1799
+ * 300 s covers funding + retry latency with room to spare. The #715 exposure
1800
+ * ceiling becomes clamped-timeout + margin ≤ 900 s total forward — a
1801
+ * deliberate widening from 600 s, recorded on #1256: an authorization that
1802
+ * cannot pass verify protects no one, and 900 s is still bounded by the same
1803
+ * clamp discipline.
1804
+ */
1805
+ declare const X402_SETTLEMENT_FORWARD_MARGIN_SECONDS = 300;
1504
1806
  /**
1505
1807
  * Parse an HTTP 402 response into x402 PaymentRequired data.
1506
1808
  *
@@ -1534,6 +1836,22 @@ declare function selectPaymentOption(accepts: X402PaymentOption[]): X402PaymentO
1534
1836
  */
1535
1837
  declare function selectStandardPaymentOption(accepts: X402PaymentOption[]): X402PaymentOption | null;
1536
1838
  declare function x402AuthorizationAmount(option: X402PaymentOption): string;
1839
+ /**
1840
+ * Canonical Haven-authenticated x402 expected context, recomputed byte-for-byte
1841
+ * by the edge signer before it signs anything.
1842
+ *
1843
+ * **Two versions, and the version is derived — never passed in (#1138).**
1844
+ * `typedDataHash` present ⇒ v2, absent ⇒ v1. A v1 message is byte-identical to
1845
+ * what shipped before, so existing signers keep verifying legacy-rail bindings
1846
+ * unchanged.
1847
+ *
1848
+ * The version lives in both the header line and the payload so neither can be
1849
+ * reinterpreted as the other: a v2 context cannot be replayed as a v1 one that
1850
+ * drops the typed-data commitment, and a v1 context cannot be presented as v2.
1851
+ * That downgrade is exactly the attack the digest exists to stop — see
1852
+ * `assertExpectedBinding` in `@haven_ai/signer`, which refuses to raw-sign a
1853
+ * hash under a v2 binding and refuses to sign typed data without one.
1854
+ */
1537
1855
  declare function buildX402ExpectedMessage(context: X402ExpectedContext): string;
1538
1856
  declare function toStandardPaymentRequirements(paymentRequired: X402PaymentRequired, option: X402PaymentOption): PaymentRequirements;
1539
1857
  /**
@@ -1597,4 +1915,4 @@ declare function encodeBase64Json(value: unknown): string;
1597
1915
  */
1598
1916
  declare function decodeBase64Json<T>(value: string, label?: string): T;
1599
1917
 
1600
- export { AGENT_PAYMENT_FAILURE_CODE_VALUES, AGENT_PAYMENT_NEXT_ACTION_VALUES, AGENT_PAYMENT_PHASE_VALUES, AGENT_PAYMENT_RAIL_VALUES, type AgentPaymentEnumSchema, AgentPaymentFailureCode, AgentPaymentFailureCodeDescriptions, AgentPaymentFailureCodeSchema, AgentPaymentNextAction, AgentPaymentNextActionDescriptions, AgentPaymentNextActionSchema, AgentPaymentPhase, AgentPaymentPhaseDescriptions, AgentPaymentPhaseSchema, AgentPaymentRail, AgentPaymentRailDescriptions, AgentPaymentRailSchema, type ClaudeTool, HAVEN_SKILL_MD, type HavenAgent, type HavenAgentAllowanceSummary, type HavenAgentReadiness, type HavenAgentSummary, type HavenAllowance, type HavenAllowanceSummary, HavenApiError, type HavenCatalogEntry, HavenClient, type HavenClientConfig, HavenError, type HavenPaymentReceipt, HavenPaymentStateError, HavenSigningError, HavenTimeoutError, type MachinePaymentChallenge, type MachinePaymentRail, type MachinePaymentReceipt, type MppAuthorizationOptions, type MppQuote, type MppResumeState, type OpenAITool, type PaymentIntent, type PaymentNextAction, type PaymentPhase, type PaymentRequest, type PaymentResult, type PaymentResumeState, type PaymentStatus, type PaymentStatusResult, type PendingApproval, type ResumeAuthorizedMppInput, type ResumeAuthorizedX402Input, type ResumeMppPaymentInput, type ResumeX402PaymentInput, SKILL_FOLDER_NAME, SWEEP_BASE_CHAIN_ID, SWEEP_BASE_USDC_ADDRESS, type SharedToolKey, type SignData, type SweepAuthorization, type SweepEip712Domain, type SweepEntry, type SweepExpectedAuth, type SweepPreparation, type SweepPrepareResponse, type SweepResult, type SweepSubmitResponse, type SweepSubmitResult, type SweepTypedData, TRANSFER_WITH_AUTHORIZATION_TYPES, type ToolDescription, type X402AuthorizationOptions, type X402ExpectedAuth, type X402ExpectedContext, type X402Intent, type X402McpTransport, type X402PaymentOption, type X402PaymentRequired, type X402Quote, type X402Receipt, type X402RequestSnapshot, type X402ResumeState, addressFromKey, buildMachinePaymentIdempotencyKey, buildSweepAuthorizationMessage, buildSweepTypedData, buildX402ExpectedMessage, composeDescription, decodeBase64Json, decodeBase64Utf8, encodeBase64Json, encodeBase64Utf8, encodeMachinePaymentProof, encodePaymentProof, havenTools, parseMachinePaymentChallenge, parseMachinePaymentChallengeResponse, parsePaymentRequired, parsePaymentRequiredResponse, selectPaymentOption, selectStandardPaymentOption, signHash, sweepUsdcAddress, sweepUsdcDomain, toStandardPaymentRequirements, toolDescriptions, verifySignature, x402AuthorizationAmount };
1918
+ export { AGENT_PAYMENT_FAILURE_CODE_VALUES, AGENT_PAYMENT_NEXT_ACTION_VALUES, AGENT_PAYMENT_PHASE_VALUES, AGENT_PAYMENT_RAIL_VALUES, type AgentPaymentEnumSchema, AgentPaymentFailureCode, AgentPaymentFailureCodeDescriptions, AgentPaymentFailureCodeSchema, AgentPaymentNextAction, AgentPaymentNextActionDescriptions, AgentPaymentNextActionSchema, AgentPaymentPhase, AgentPaymentPhaseDescriptions, AgentPaymentPhaseSchema, AgentPaymentRail, AgentPaymentRailDescriptions, AgentPaymentRailSchema, type ClaudeTool, HAVEN_MINIMUM_NODE_VERSION, HAVEN_SKILL_MD, type HavenAgent, type HavenAgentAllowanceSummary, type HavenAgentReadiness, type HavenAgentSummary, type HavenAllowance, type HavenAllowanceSummary, HavenApiError, type HavenCatalogEntry, HavenClient, type HavenClientConfig, HavenError, type HavenPaymentReceipt, HavenPaymentStateError, HavenSigningError, HavenTimeoutError, type MachinePaymentChallenge, type MachinePaymentRail, type MachinePaymentReceipt, type MppAuthorizationOptions, type MppQuote, type MppResumeState, type OpenAITool, type PaymentFee, type PaymentIntent, type PaymentNextAction, type PaymentPhase, type PaymentReceipt, type PaymentRequest, type PaymentResult, type PaymentResumeState, type PaymentStatus, type PaymentStatusResult, type PendingApproval, RECEIPT_VERSION, type ReceiptVerification, type ResumeAuthorizedMppInput, type ResumeAuthorizedX402Input, type ResumeMppPaymentInput, type ResumeX402PaymentInput, SKILL_FOLDER_NAME, SWEEP_BASE_CHAIN_ID, SWEEP_BASE_SEPOLIA_CHAIN_ID, SWEEP_BASE_SEPOLIA_USDC_ADDRESS, SWEEP_BASE_USDC_ADDRESS, type SharedToolKey, type SignData, type SweepAuthorization, type SweepEip712Domain, type SweepEntry, type SweepExpectedAuth, type SweepPreparation, type SweepPrepareResponse, type SweepResult, type SweepSubmitResponse, type SweepSubmitResult, type SweepTypedData, TRANSFER_WITH_AUTHORIZATION_TYPES, type ToolDescription, type UnsupportedNodeVersionMessageOptions, type X402AuthorizationOptions, type X402ExpectedAuth, type X402ExpectedContext, type X402Intent, type X402McpTransport, type X402PaymentOption, type X402PaymentRequired, type X402Quote, type X402Receipt, type X402RequestSnapshot, type X402ResumeState, X402_MAX_AUTHORIZATION_WINDOW_SECONDS, X402_SETTLEMENT_FORWARD_MARGIN_SECONDS, addressFromKey, buildMachinePaymentIdempotencyKey, buildSweepAuthorizationMessage, buildSweepTypedData, buildX402ExpectedMessage, compareNodeVersions, composeDescription, decodeBase64Json, decodeBase64Utf8, encodeBase64Json, encodeBase64Utf8, encodeMachinePaymentProof, encodePaymentProof, havenTools, isSupportedNodeVersion, isSweepableChain, parseMachinePaymentChallenge, parseMachinePaymentChallengeResponse, parsePaymentRequired, parsePaymentRequiredResponse, selectPaymentOption, selectStandardPaymentOption, signHash, signUserOpTypedDataForDelegation, sweepUsdcAddress, sweepUsdcDomain, toStandardPaymentRequirements, toolDescriptions, unsupportedNodeVersionMessage, verifyPaymentReceipt, verifySignature, x402AuthorizationAmount };