@dvmkit/sdk 0.1.5-rc.9 → 0.2.1-rc.9

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 (67) hide show
  1. package/README.md +14 -0
  2. package/dist/{chunk-MLRCSJYX.js → chunk-2D75MNNG.js} +178 -550
  3. package/dist/{chunk-BIFLRKMO.js → chunk-2KGG5ORW.js} +1 -1
  4. package/dist/{chunk-27V2ILSR.js → chunk-4A2RAKCW.js} +2 -2
  5. package/dist/{chunk-5URG56JJ.js → chunk-A4CM2BD3.js} +18 -2
  6. package/dist/{chunk-L4OYF4DQ.js → chunk-AJNFXR7J.js} +2 -2
  7. package/dist/{chunk-S3XAHZQY.js → chunk-COYKJRMM.js} +24 -3
  8. package/dist/{chunk-UP2F5RRT.js → chunk-D7YQYLLM.js} +1 -4
  9. package/dist/{chunk-CEOAHV2I.js → chunk-FDKRXOZO.js} +0 -5
  10. package/dist/{chunk-TQWGQCNV.js → chunk-FPOLJRBF.js} +5 -5
  11. package/dist/{chunk-BTZY7VPH.js → chunk-GAIPXGM3.js} +1 -1
  12. package/dist/{chunk-SSSZUVWM.js → chunk-JAHRF5X3.js} +89 -39
  13. package/dist/{chunk-5PBOA25N.js → chunk-JNKQZVZX.js} +472 -617
  14. package/dist/{chunk-U6M3ATSG.js → chunk-MD3H3BF7.js} +40 -6
  15. package/dist/{chunk-CGKZDODG.js → chunk-MG67KXU7.js} +0 -5
  16. package/dist/{chunk-KSQEFVFJ.js → chunk-MMCE7XSR.js} +1 -1
  17. package/dist/{chunk-JZWELPFH.js → chunk-N5B66UOS.js} +4 -16
  18. package/dist/{chunk-BIP6G74V.js → chunk-O6D72KYA.js} +10 -10
  19. package/dist/{chunk-KXCKFIJI.js → chunk-QX52F6IB.js} +1 -1
  20. package/dist/{chunk-RW5LP57K.js → chunk-SDK6KDJN.js} +0 -1
  21. package/dist/{chunk-KVEHHC7W.js → chunk-U5VNEALI.js} +24 -13
  22. package/dist/{chunk-FROTD5XQ.js → chunk-V5ZRATJH.js} +2 -3
  23. package/dist/{chunk-EVBK675R.js → chunk-VA7GT6C6.js} +31 -37
  24. package/dist/{chunk-2UUXIIOC.js → chunk-VIVXB4CD.js} +3 -3
  25. package/dist/{chunk-6BQM7TOW.js → chunk-XMDQOXHO.js} +11 -38
  26. package/dist/{chunk-DMNLFNTW.js → chunk-XRLKGCAW.js} +2 -2
  27. package/dist/{chunk-M7LHFJ5K.js → chunk-XZ7LW4S5.js} +2 -3
  28. package/dist/{chunk-E4EVGPDX.js → chunk-YO56VCTQ.js} +0 -6
  29. package/dist/{credit-ledger-2DFQHNLB.js → credit-ledger-MHA652TV.js} +2 -2
  30. package/dist/{credit-menu-enwMbn55.d.ts → credit-menu-kDA9RVzD.d.ts} +524 -1077
  31. package/dist/{fx-D860pZvP.d.ts → fx-DhyT1Cjh.d.ts} +38 -82
  32. package/dist/index.d.ts +11 -26
  33. package/dist/index.js +2 -2
  34. package/dist/internal/caller.d.ts +644 -2140
  35. package/dist/internal/caller.js +32 -66
  36. package/dist/internal/server.d.ts +40 -90
  37. package/dist/internal/server.js +16 -16
  38. package/dist/{job-store-BUGqvCfL.d.ts → job-store-D3CcZp_g.d.ts} +73 -66
  39. package/dist/{lightning-backend-BozcevPZ.d.ts → lightning-backend-BhsyrBLa.d.ts} +19 -41
  40. package/dist/{memory-credit-ledger-MNUOTQO5.js → memory-credit-ledger-BYBATRN3.js} +3 -3
  41. package/dist/{mpp-secret-state-WNAQQ6K4.js → mpp-secret-state-B5GCILVH.js} +1 -1
  42. package/dist/{mpp-setup-4FJD6ZHV.js → mpp-setup-MPP3ST5X.js} +1 -1
  43. package/dist/{payout-reporter-RG6XNGPI.js → payout-reporter-KEMUXEUO.js} +2 -2
  44. package/dist/{postgres-consumed-credential-store-VHBT4KEA.js → postgres-consumed-credential-store-6N2V5MJN.js} +2 -2
  45. package/dist/postgres-job-store-MZZZMS2B.js +7 -0
  46. package/dist/postgres-kv-store-DXGTKXLU.js +7 -0
  47. package/dist/{postgres-replay-store-UJXRT6VO.js → postgres-replay-store-ZF4JNZOW.js} +2 -2
  48. package/dist/{pricing-4CEB34RM.js → pricing-MU5GNUJZ.js} +1 -1
  49. package/dist/{processed-payment-store-HAA4SFNK.js → processed-payment-store-GKMAWOM3.js} +2 -2
  50. package/dist/revenue-reporter-O75BGYFK.js +7 -0
  51. package/dist/server/index.d.ts +47 -159
  52. package/dist/server/index.js +67 -138
  53. package/dist/{ssrf-DbFkpDv0.d.ts → ssrf-dMooihtY.d.ts} +1 -2
  54. package/dist/{step-cache-5dljDqrQ.d.ts → step-cache-v2yhyhSZ.d.ts} +617 -1532
  55. package/dist/{tempo-charge-store-RIFTALZK.js → tempo-charge-store-SDTUNTKA.js} +2 -2
  56. package/dist/{tempo-lifecycle-DFIXQ54Q.js → tempo-lifecycle-G5SB4HFC.js} +5 -5
  57. package/dist/{tempo-session-store-2JNOKJGX.js → tempo-session-store-WF3VZXNF.js} +2 -2
  58. package/dist/{tempo-wallet-4QKSV65O.js → tempo-wallet-ZFNUDFVO.js} +2 -2
  59. package/dist/testing/index.d.ts +5 -15
  60. package/dist/testing/index.js +4 -11
  61. package/dist/{usd-DoRuAckA.d.ts → usd-Cu9G6xv2.d.ts} +14 -16
  62. package/dist/{wallet-CJC8lwxx.d.ts → wallet-Dwjs5n_M.d.ts} +1 -1
  63. package/dist/{x402-5H27DCBE.js → x402-CI6PSHNO.js} +5 -5
  64. package/package.json +3 -2
  65. package/dist/postgres-job-store-3RAXMNSY.js +0 -7
  66. package/dist/postgres-kv-store-JFBDP5IP.js +0 -7
  67. package/dist/revenue-reporter-ASZ7SHHH.js +0 -7
@@ -1,26 +1,25 @@
1
- import { ab as CashuMode, bK as CreditDrainEnqueue, R as ResolvedCreditConfig, bL as DVMAuthScheme, z as SignedRequestDomain, bM as CreditLedgerLike, bN as X402RefundSettlementGate, bO as CreditSnapshot, bP as DrawResult, bQ as X402SettlementStatus, bR as X402UnresolvedRefund, bS as GrownDrawResult, bT as DrawResolution, bU as FundingRecord, X as FundingReceipt, bV as CreditInvoiceRecord, bW as InvoiceSettlement, bX as BlockedInvoiceCursor, bY as InvoiceReconciliation, bZ as InvoiceWriteOff, b_ as DrawRecord, b$ as StalePendingDrawCursor, c0 as TempoCreditLossEvidence, c1 as CreditLedgerQuerier, c2 as TempoCreditLoss, c3 as X402CreditLossEvidence, c4 as X402CreditLoss, c5 as DrainMethod, c6 as DrainRequestResult, c7 as BitcoinDepositLiability, bo as FundingLot, c8 as CreditDrainRecord, c9 as ChannelDrainCursor, ca as DrainWriteOff, cb as DrainReleaseResult, cc as DrainFulfilment, cd as DrainTransitionResult, Y as JobReceipt, a1 as Message, K as KVStore, F as SignedRequestReplayStore, Z as ZodLike, a as DVMDescriptor } from '../step-cache-5dljDqrQ.js';
2
- export { ce as CLIENT_COMPATIBILITY_HEADERS, d as CanonicalEnvelope, cf as ClientCompatibility, cg as ClientCompatibilityEnv, ch as ClientCompatibilityGate, ci as ClientCompatibilityRequirement, cj as ClientSemVer, e as CreateSignedRequestVerifierOpts, ck as CreditFundingBasis, cl as CreditInvoiceStatus, cm as CreditLedger, cn as CreditLedgerError, co as CreditLedgerErrorCode, cp as CreditLedgerErrorDetails, cq as CreditLedgerPool, cr as CreditStatus, cs as DRAIN_DELIVERY_RESERVE_SATS, ct as DVM_PROTOCOL_VERSION, cu as DrainConflictReason, cv as DrawRailValue, cw as DrawStatus, cx as JobCostReportPayload, cy as PostgresX402ChannelStorage, cz as ReplayStoreBackend, cA as RevenueSkippedNoRailPayload, cB as RevenueSkippedNoRailReason, w as SIGNED_REQUEST_AUTH_ID, x as SIGNED_REQUEST_STATEMENT_VERSION, cC as Secp256k1AuthOpts, y as SignedRequestAudience, B as SignedRequestError, E as SignedRequestFailure, G as SignedRequestSignOpts, H as SignedRequestStatementHeader, M as SignedRequestVerifier, cD as X402ChannelStorageOpts, cE as X402RelayLockHolder, cF as X402RelaySubmissionLock, cG as X402RelaySubmissionLockError, cH as allocateDrawValue, cI as clientCompatibilityAttributes, cJ as clientCompatibilityMiddleware, cK as clientUpgradeRequired, N as createSignedRequestVerifier, cL as parseClientCapabilities, cM as parseClientCompatibility, cN as parseDvmClient, cO as parseProtocolVersion, cP as requireClientCompatibility, cQ as secp256k1Auth, cR as signedRequestInput, T as signedRequestStatementHeader } from '../step-cache-5dljDqrQ.js';
1
+ import { ab as CashuMode, bK as CreditDrainEnqueue, R as ResolvedCreditConfig, bL as DVMAuthScheme, z as SignedRequestDomain, bM as CreditLedgerLike, bN as X402RefundSettlementGate, bO as CreditSnapshot, bP as DrawResult, bQ as X402SettlementStatus, bR as X402UnresolvedRefund, bS as GrownDrawResult, bT as DrawResolution, bU as FundingRecord, X as FundingReceipt, bV as CreditInvoiceRecord, bW as InvoiceSettlement, bX as BlockedInvoiceCursor, bY as InvoiceReconciliation, bZ as InvoiceWriteOff, b_ as DrawRecord, b$ as StalePendingDrawCursor, c0 as TempoCreditLossEvidence, c1 as CreditLedgerQuerier, c2 as TempoCreditLoss, c3 as X402CreditLossEvidence, c4 as X402CreditLoss, c5 as DrainMethod, c6 as DrainRequestResult, c7 as BitcoinDepositLiability, bo as FundingLot, c8 as CreditDrainRecord, c9 as ChannelDrainCursor, ca as DrainWriteOff, cb as DrainReleaseResult, cc as DrainFulfilment, cd as DrainTransitionResult, Y as JobReceipt, a1 as Message, K as KVStore, F as SignedRequestReplayStore, Z as ZodLike, a as DVMDescriptor } from '../step-cache-v2yhyhSZ.js';
2
+ export { ce as CLIENT_COMPATIBILITY_HEADERS, d as CanonicalEnvelope, cf as ClientCompatibility, cg as ClientCompatibilityEnv, ch as ClientCompatibilityGate, ci as ClientCompatibilityRequirement, cj as ClientSemVer, e as CreateSignedRequestVerifierOpts, ck as CreditFundingBasis, cl as CreditInvoiceStatus, cm as CreditLedger, cn as CreditLedgerError, co as CreditLedgerErrorCode, cp as CreditLedgerErrorDetails, cq as CreditLedgerPool, cr as CreditStatus, cs as DRAIN_DELIVERY_RESERVE_SATS, ct as DVM_PROTOCOL_VERSION, cu as DrainConflictReason, cv as DrawRailValue, cw as DrawStatus, cx as JobCostReportPayload, cy as JobTerminalReportPayload, cz as PostgresX402ChannelStorage, cA as ReplayStoreBackend, cB as RevenueSkippedNoRailPayload, cC as RevenueSkippedNoRailReason, w as SIGNED_REQUEST_AUTH_ID, x as SIGNED_REQUEST_STATEMENT_VERSION, cD as Secp256k1AuthOpts, y as SignedRequestAudience, B as SignedRequestError, E as SignedRequestFailure, G as SignedRequestSignOpts, H as SignedRequestStatementHeader, M as SignedRequestVerifier, cE as X402ChannelStorageOpts, cF as X402RelayLockHolder, cG as X402RelaySubmissionLock, cH as X402RelaySubmissionLockError, cI as allocateDrawValue, cJ as clientCompatibilityAttributes, cK as clientCompatibilityMiddleware, cL as clientUpgradeRequired, N as createSignedRequestVerifier, cM as parseClientCapabilities, cN as parseClientCompatibility, cO as parseDvmClient, cP as parseProtocolVersion, cQ as requireClientCompatibility, cR as secp256k1Auth, cS as signedRequestInput, T as signedRequestStatementHeader } from '../step-cache-v2yhyhSZ.js';
3
3
  import { Pool } from 'pg';
4
- import { ak as CreditMenu, b as AppEnv, U as UpfrontPaymentOpts, h as PaymentInfo, al as ReceiptIssuer, am as LightningReceive, an as TempoSettlementReadiness, ao as DVMHostOpts, ap as DVMServeResult } from '../credit-menu-enwMbn55.js';
5
- export { aq as BuildCreditMenuArgs, ar as BuilderIdentity, as as CREDIT_ENVELOPE_KEYS, C as ConsumedCredentialStore, at as CreateX402BatchSettlementServerOpts, au as CreditEnvelope, av as CreditEnvelopeError, aw as CreditFundCommitment, ax as CreditTerms, ay as DEFAULT_INVOICE_TTL_SECONDS, az as DVMHost, aA as JobManager, aB as JobManagerOpts, aC as LightningReceiveConfig, aD as MIN_INVOICE_TTL_SECONDS, aE as MemoryConsumedCredentialStore, aF as MemoryConsumedCredentialStoreOpts, aG as MemoryProcessedPaymentStore, aH as MemoryX402ExactSettlementStore, aI as MountOpts, aJ as OwnerDisplay, aK as PaidJobCompletion, aL as PaymentMode, aM as PlatformReporterOpts, aN as PostgresProcessedPaymentStore, aO as PostgresX402ExactSettlementStore, aP as PriceFiat, aQ as ProcessedPaymentQuerier, aR as ProcessedPaymentRail, aS as ProcessedPaymentRecord, aT as ProcessedPaymentReplayError, aU as ProcessedPaymentStore, aV as X402BatchAcceptance, aW as X402BatchFunding, aX as X402BatchRefusal, aY as X402BatchSettlementServer, aZ as X402ExactAcceptance, a_ as X402ExactIntentConflictError, a$ as X402ExactSettlementAttempt, b0 as X402ExactSettlementChainEvidence, b1 as X402ExactSettlementEffect, b2 as X402ExactSettlementEvidenceMissingError, b3 as X402ExactSettlementEvidenceReader, b4 as X402ExactSettlementIntent, b5 as X402ExactSettlementNotReadyError, b6 as X402ExactSettlementServer, b7 as X402ExactSettlementServerOpts, b8 as X402ExactSettlementStatus, b9 as X402ExactSettlementStore, ba as X402SettlementChainEvidence, bb as X402SettlementEvidenceReader, bc as X402SettlementSubmissionError, bd as X402_BATCH_AUTO_SETTLEMENT, be as X402_BATCH_MIN_WITHDRAW_DELAY_SECONDS, bf as X402_BATCH_SETTLEMENT_NETWORK, bg as attachCreditMenu, bh as buildCreditMenu, bi as createDVMHost, bj as createX402BatchSettlementServer, bk as creditEnvelopeIgnoreFields, bl as drawSettlementRef, bm as extractCreditEnvelope, bn as fundingCommitment, bo as selectPrimaryCredit, bp as stripCreditEnvelope, bq as toCreditView } from '../credit-menu-enwMbn55.js';
4
+ import { ak as CreditMenu, b as AppEnv, U as UpfrontPaymentOpts, h as PaymentInfo, al as ReceiptIssuer, am as LightningReceive, an as TempoSettlementReadiness, ao as DVMHostOpts, ap as DVMServeResult } from '../credit-menu-kDA9RVzD.js';
5
+ export { aq as BuildCreditMenuArgs, ar as BuilderIdentity, as as CREDIT_ENVELOPE_KEYS, C as ConsumedCredentialStore, at as CreateX402BatchSettlementServerOpts, au as CreditEnvelope, av as CreditEnvelopeError, aw as CreditFundCommitment, ax as CreditTerms, ay as DEFAULT_INVOICE_TTL_SECONDS, az as DVMHost, aA as JobManager, aB as JobManagerOpts, aC as LightningReceiveConfig, aD as MIN_INVOICE_TTL_SECONDS, aE as MemoryConsumedCredentialStore, aF as MemoryConsumedCredentialStoreOpts, aG as MemoryProcessedPaymentStore, aH as MemoryX402ExactSettlementStore, aI as MountOpts, aJ as OwnerDisplay, aK as PaidJobCompletion, aL as PaymentMode, aM as PlatformReporterOpts, aN as PostgresProcessedPaymentStore, aO as PostgresX402ExactSettlementStore, aP as PriceFiat, aQ as ProcessedPaymentQuerier, aR as ProcessedPaymentRail, aS as ProcessedPaymentRecord, aT as ProcessedPaymentReplayError, aU as ProcessedPaymentStore, aV as X402BatchAcceptance, aW as X402BatchFunding, aX as X402BatchRefusal, aY as X402BatchSettlementServer, aZ as X402ExactAcceptance, a_ as X402ExactIntentConflictError, a$ as X402ExactSettlementAttempt, b0 as X402ExactSettlementChainEvidence, b1 as X402ExactSettlementEffect, b2 as X402ExactSettlementEvidenceMissingError, b3 as X402ExactSettlementEvidenceReader, b4 as X402ExactSettlementIntent, b5 as X402ExactSettlementNotReadyError, b6 as X402ExactSettlementServer, b7 as X402ExactSettlementServerOpts, b8 as X402ExactSettlementStatus, b9 as X402ExactSettlementStore, ba as X402SettlementChainEvidence, bb as X402SettlementEvidenceReader, bc as X402SettlementSubmissionError, bd as X402_BATCH_AUTO_SETTLEMENT, be as X402_BATCH_MIN_WITHDRAW_DELAY_SECONDS, bf as X402_BATCH_SETTLEMENT_NETWORK, bg as attachCreditMenu, bh as buildCreditMenu, bi as createDVMHost, bj as createX402BatchSettlementServer, bk as creditEnvelopeIgnoreFields, bl as drawSettlementRef, bm as extractCreditEnvelope, bn as fundingCommitment, bo as selectPrimaryCredit, bp as stripCreditEnvelope, bq as toCreditView } from '../credit-menu-kDA9RVzD.js';
6
6
  import { Context } from 'hono';
7
7
  import { z } from 'zod';
8
- import { F as FxFetcher } from '../fx-D860pZvP.js';
9
- import { c as StreamableJobStore, R as ReceiptIssuingStore, J as JobRecord, d as RequestIdClaim, e as RequestIdClaimResult, f as JobRetentionCursor, O as OutgoingMessage, A as AppendOutgoingOptions, P as PaymentCreditDelta, V as VerifyAndCreditResult, g as JobCounters } from '../job-store-BUGqvCfL.js';
10
- export { a as JobStatus, b as JobStore, h as isStreamableJobStore } from '../job-store-BUGqvCfL.js';
11
- export { P as PinnedFetch, S as SSRFError, a as SSRFGuardOpts, b as SSRFReason, c as SSRFResolver, d as assertSafeUrl, e as createPinnedFetch } from '../ssrf-DbFkpDv0.js';
8
+ import { F as FxFetcher } from '../fx-DhyT1Cjh.js';
9
+ import { c as StreamableJobStore, R as ReceiptIssuingStore, J as JobRecord, d as RequestIdClaim, e as RequestIdClaimResult, f as JobRetentionCursor, O as OutgoingMessage, A as AppendOutgoingOptions, P as PaymentCreditDelta, V as VerifyAndCreditResult, g as JobCounters } from '../job-store-D3CcZp_g.js';
10
+ export { a as JobStatus, b as JobStore, h as isStreamableJobStore } from '../job-store-D3CcZp_g.js';
11
+ export { P as PinnedFetch, S as SSRFError, a as SSRFGuardOpts, b as SSRFReason, c as SSRFResolver, d as assertSafeUrl, e as createPinnedFetch } from '../ssrf-dMooihtY.js';
12
12
  import 'mppx';
13
13
  import '@x402/core/server';
14
14
  import '@x402/evm/batch-settlement/server';
15
15
  import 'viem';
16
16
  import '@x402/core/types';
17
17
  import '@cashu/cashu-ts';
18
- import '../lightning-backend-BozcevPZ.js';
18
+ import '../lightning-backend-BhsyrBLa.js';
19
19
 
20
20
  /** Lifetime of a per-call implicit credit before the ledger refuses new draws. */
21
21
  declare const IMPLICIT_CREDIT_TTL_MS: number;
22
22
 
23
- /** Builder-lock and Cashu accumulator opts resolved from environment variables. */
24
23
  interface ResolvedCashuOpts {
25
24
  cashuMode: CashuMode | undefined;
26
25
  lockPubkey: string | undefined;
@@ -34,7 +33,7 @@ interface ResolvedCashuOpts {
34
33
  * variables, initializing DB tables when their prerequisites are met.
35
34
  * Extracted from serve() so DVMs that call createDVMServer directly (cast,
36
35
  * scrape) can wire Cashu and the builder admin surface without using the
37
- * serve() wrapper (internal-review).
36
+ * serve() wrapper.
38
37
  *
39
38
  * @param pool - existing Postgres pool to reuse; pass undefined when no DB is available
40
39
  * @param cashuModeHint - programmatic override for cashu mode (serve()'s opts.cashuMode)
@@ -42,10 +41,7 @@ interface ResolvedCashuOpts {
42
41
  declare function resolveCashuOptsFromEnv(env: Record<string, string>, pool?: Pool, cashuModeHint?: CashuMode): Promise<ResolvedCashuOpts>;
43
42
 
44
43
  /**
45
- * What a terminal drain transition needs in order to book its platform drain
46
- * report (internal-review). Every field is optional because a DVM can legitimately
47
- * run without platform reporting — a `dvmctl dev` server, a self-hosted
48
- * builder, a test host — and a drain must still be fulfillable there.
44
+ * Reporting is optional; an unwired host still runs the money transition.
49
45
  */
50
46
  interface DrainReportWiring {
51
47
  /** The SDK's own Postgres, which holds both the ledger and the reporter's outbox. */
@@ -57,14 +53,8 @@ interface DrainReportWiring {
57
53
  }
58
54
 
59
55
  /**
60
- * Signed body of a `POST /v1/credit` request (internal-review). The op discriminator
61
- * lives **inside** the signed bytes, so a network attacker can't rewrite a
62
- * `balance` read into a `drain`.
63
- *
64
- * Deliberately independent of `credit-envelope.ts`, which parses the credit
65
- * fields riding a `/v1/job` body: that shape pairs `credit_id` with a
66
- * mandatory `draw_id`, and a fund-only top-up has no draw. Two routes, two
67
- * schemas — sharing one would force a top-up to invent a draw id.
56
+ * Authenticate the raw body, including op. Its schema is independent of job-input credit/draw
57
+ * envelopes; normal job schema projection must not define this wire contract.
68
58
  */
69
59
  declare const CREDIT_REQUEST_SCHEMA: z.ZodObject<{
70
60
  op: z.ZodEnum<{
@@ -99,83 +89,48 @@ declare const CREDIT_REQUEST_SCHEMA: z.ZodObject<{
99
89
  timestamp: z.ZodNumber;
100
90
  nonce: z.ZodString;
101
91
  }, z.core.$strip>;
102
- /** Parsed `/v1/credit` body. */
103
92
  type CreditRequest = z.infer<typeof CREDIT_REQUEST_SCHEMA>;
104
- /** Everything the `/v1/credit` handler needs from the server that mounts it. */
105
93
  interface CreditRouteDeps {
106
- /** Resolved credit sizing, or `undefined` when this DVM didn't opt in. */
107
94
  menu: () => Promise<CreditMenu | undefined>;
108
- /** Resolved builder policy; absent and older config fail closed. */
109
95
  creditConfig: ResolvedCreditConfig | undefined;
110
96
  auth: DVMAuthScheme | undefined;
111
97
  /** Exact `/v1/credit` audience and operation expected by the auth gate. */
112
98
  authDomain?: SignedRequestDomain;
113
99
  ledger: CreditLedgerLike;
114
100
  fxFetcher: FxFetcher;
115
- /** Per-DVM + per-request rail wiring, shared with `/v1/job` (see `railVerifyOpts`). */
116
101
  railOpts: (c: Context<AppEnv>) => Promise<UpfrontPaymentOpts>;
117
102
  /**
118
- * Book a committed top-up as a platform deposit (internal-review). A fund-only
119
- * top-up moves real money onto a credit whose draws will each book revenue
120
- * later, so skipping this would report the spending without the money that
121
- * backed it — the DVM's outstanding liability would go negative.
103
+ * Report committed fund-only top-ups as deposits. They have no job terminal to book the
104
+ * liability; replay must not report it twice.
122
105
  */
123
106
  onDeposit: (funding: NonNullable<PaymentInfo["funding"]>) => void;
124
107
  /**
125
- * Platform drain-report wiring (internal-review), used by the cashu pickup — the
126
- * one terminal drain transition that lands on this caller-facing route.
127
- * Empty on a DVM with no platform reporting, which changes nothing about
128
- * the reclaim itself.
108
+ * Optional terminal drain report wiring: Cashu pickup and channel completion commit their
109
+ * ledger transition with its report.
129
110
  */
130
111
  drainReport: DrainReportWiring;
131
112
  /**
132
- * Receipt signer, when this DVM has a receipt key (internal-review). Drain ops
133
- * countersign every reclaim event with it (internal-review); absent, drains still
134
- * work — the ledger stays authoritative, the caller just gets no portable
135
- * evidence artifact.
113
+ * Optional signer for reclaim observations. The ledger transition remains authoritative;
114
+ * signature issuance happens after commit and may fail separately.
136
115
  */
137
116
  receiptIssuer: ReceiptIssuer | undefined;
138
117
  /**
139
- * The Lightning receive leg, when this DVM configured one (internal-review).
140
- * Absent ⇒ `method: "lightning"` is refused with `lightning_unavailable`
141
- * and the funding menu never advertised it in the first place.
142
- *
143
- * Only the *issue* path reaches through this. Settling goes via
144
- * {@link settleLightning}, which is where a settlement books its deposit.
118
+ * Optional receive-only Lightning funding leg. Issuance uses the wallet; polling uses the
119
+ * shared settlement hook. An absent leg refuses method:lightning.
145
120
  */
146
121
  lightning: {
147
122
  receive: LightningReceive;
148
123
  } | undefined;
149
124
  /**
150
125
  * Apply any Lightning invoice this caller has paid since the last check, and
151
- * book the deposit for each one that credits (internal-review). A no-op when the
126
+ * book the deposit for each one that credits. A no-op when the
152
127
  * rail isn't configured. Runs before the read ops so a balance reflects a
153
128
  * top-up that settled out of band, and behind the fund poll so a sibling
154
129
  * invoice on the same credit is swept with it.
155
130
  */
156
131
  settleLightning: (callerPubkey: string, creditId?: string) => Promise<void>;
157
- /** Hosted operator fee-token gate; absent on self-hosted DVMs. */
158
132
  tempoSettlementReadiness?: TempoSettlementReadiness;
159
133
  }
160
- /**
161
- * `POST /v1/credit` — the caller-facing surface of the credits settlement
162
- * layer (internal-review, spec §4/§7). Three ops on one signed, replay-protected
163
- * envelope, mirroring `/v1/job`'s auth discipline exactly:
164
- *
165
- * - **fund** — a top-up with no job attached. The rail artifact rides the same
166
- * headers as `/v1/job` (`X-Cashu` + `X-Cashu-Request-Id`, `X-PAYMENT`,
167
- * `Authorization: Payment …`) and a missing or bad one comes back as the
168
- * same 402 envelope, which is what lets a caller's existing resumable-submit
169
- * machinery drive a top-up with no new client code.
170
- * - **balance** — what do I hold here, including expired credits (their value
171
- * is still the caller's; spec §5), plus the funding menu, so the same read
172
- * also answers what may be added (internal-review).
173
- * - **drain** — reclaim the unspent balance (internal-review, spec §5 tier 3). One
174
- * op is both the request and the poll/pickup: the first call debits the
175
- * available balance into a `pending` liability; re-polling the same
176
- * `drain_id` returns the current state, delivers the parked Cashu token
177
- * when the builder's batch job has parked it, and is idempotent throughout.
178
- */
179
134
  declare function handleCreditRequest(c: Context<AppEnv>, deps: CreditRouteDeps): Promise<Response>;
180
135
 
181
136
  /**
@@ -192,70 +147,29 @@ type InitLockPool = Pick<Pool, "connect"> & {
192
147
  };
193
148
  };
194
149
  /**
195
- * The single session advisory-lock key serializing **all** SDK boot-time
196
- * schema work against concurrent creators — two machines cold-booting one DVM
197
- * against a fresh database, or parallel test files sharing one DB.
198
- *
199
- * Postgres' `IF NOT EXISTS` existence check is not atomic against a concurrent
200
- * creator: two sessions running the same `CREATE TABLE IF NOT EXISTS` at once
201
- * can raise `duplicate key value violates unique constraint
202
- * "pg_type_typname_nsp_index"` (23505) in the loser, which at SDK boot is an
203
- * unhandled throw that kills the machine (internal-review).
204
- *
205
- * Deliberately distinct from `PLATFORM_INIT_ADVISORY_LOCK` (17320917) — a
206
- * DVM's own database is not the platform database — and from the first-party
207
- * DVMs' own keys (cast 17320918, scrape 17320926, scribe 24700919). **A new
208
- * SDK store reuses this key rather than inventing a second one**: one key means
209
- * there is only ever one lock order, so the per-store lock-order inversion that
210
- * deadlocked internal-review can't recur.
150
+ * All SDK boot DDL shares one advisory-lock key. CREATE TABLE IF NOT EXISTS
151
+ * can still race in Postgres system catalogs across machines. Reusing one key
152
+ * also prevents inconsistent lock acquisition order between SDK stores.
211
153
  */
212
154
  declare const SDK_INIT_ADVISORY_LOCK = 17320927;
213
155
  /**
214
- * Run `fn` holding {@link SDK_INIT_ADVISORY_LOCK} on `db`. Every SDK
215
- * boot-path `CREATE TABLE IF NOT EXISTS` goes through here.
216
- *
217
- * Overlapping callers on the same pool share **one** acquisition: the first
218
- * connects and locks, concurrent and nested callers join the held lock, and
219
- * the last one out unlocks and releases the client. That keeps internal-review's
220
- * deliberately-parallel store-init batch parallel — six `init()`s racing each
221
- * other would otherwise queue behind one another — and keeps the uncontended
222
- * cost at one extra round trip per boot phase rather than one per store.
223
- * Sharing is safe for the DDL, which is what this lock is for: it excludes
224
- * *other machines*, and within one process no two inits create the same table.
225
- * It is not by itself a mutex between same-pool callers — two of them
226
- * concurrently running one non-idempotent statement still race, so anything
227
- * riding this lock that isn't `CREATE … IF NOT EXISTS` must carry its own
228
- * conflict handling (`seedLockPubkeyState`'s `ON CONFLICT DO NOTHING`).
229
- *
230
- * Session-level (not `pg_advisory_xact_lock`) because the DDL runs in
231
- * autocommit with no enclosing transaction, so the lock and the unlock ride a
232
- * dedicated pinned client — advisory locks are session-scoped and the unlock
233
- * must land on the backend that holds it. Released in `finally` on every path
234
- * including throws: an SDK boot that died holding this lock would block every
235
- * sibling until its connection closed.
236
- *
237
- * The guarded DDL runs on the pool's *other* connections, so the pool must
238
- * allow at least two — `pg`'s default `max` is 10 and the host never narrows
239
- * it, but a builder-supplied `Pool({ max: 1 })` would starve boot. That one
240
- * deadlocks with no error and reads as a dead database, so it is refused up
241
- * front instead.
156
+ * Overlapping callers on one pool share a pinned session lock and run their
157
+ * guarded work in order. A nested call from the active callback is reentrant.
158
+ * The last caller unlocks, preserving protection against other pools/processes.
159
+ * DDL runs on another connection; pools smaller than two are rejected.
160
+ * The pinned client is released in finally, including guarded failures.
242
161
  */
243
162
  declare function withSdkInitLock<T>(db: InitLockPool, fn: () => Promise<T>): Promise<T>;
244
163
 
245
164
  /**
246
- * In-memory {@link CreditLedgerLike} for pool-less setups — devMode, direct
247
- * `createDVMServer` tests, and the in-process x402 money loop — mirroring the
248
- * `MemoryJobStore` precedent. Same semantics as the Postgres `CreditLedger`
249
- * (two-phase draws, replay-before-expiry, `draw_conflict`, gap-free
250
- * `ledger_seq`), minus durability and cross-machine safety: per-process only,
251
- * so production DVMs must use the Postgres ledger (spec §2 condition 2).
252
- * Every mutating verb is synchronous between awaits, so operations are
253
- * atomic in-process; the `tx` handles are accepted and ignored.
165
+ * Per-process development/test ledger without durability or cross-machine safety. Mutations
166
+ * run synchronously between awaits; accepted tx handles are ignored. Production funding
167
+ * requires a durable ledger.
254
168
  */
255
169
  declare class MemoryCreditLedger implements CreditLedgerLike {
256
170
  /**
257
171
  * Per-process and lost on restart, so a DVM backed by this ledger never
258
- * advertises the funding menu outside devMode (internal-review) — funding on one
172
+ * advertises the funding menu outside devMode — funding on one
259
173
  * machine and drawing on another would `credit_not_found`.
260
174
  */
261
175
  readonly durable = false;
@@ -267,13 +181,10 @@ declare class MemoryCreditLedger implements CreditLedgerLike {
267
181
  private x402Settlements?;
268
182
  /** Internal disposable transaction snapshot. The caller must serialize every ledger access. */
269
183
  forkForTransaction(): MemoryCreditLedger;
270
- /** See {@link CreditLedger.useX402SettlementGate} — same contract (internal-review). */
271
184
  useX402SettlementGate(gate: X402RefundSettlementGate): void;
272
185
  fund(args: Parameters<CreditLedgerLike["fund"]>[0]): Promise<CreditSnapshot>;
273
186
  draw(args: Parameters<CreditLedgerLike["draw"]>[0]): Promise<DrawResult>;
274
- /** See {@link CreditLedger.blockingX402Refund} — same contract (internal-review). */
275
187
  blockingX402Refund(channelId: string | null | undefined, statuses: X402SettlementStatus[]): Promise<X402UnresolvedRefund | undefined>;
276
- /** The unresolved x402 refund that must stop an effect on `creditId` (internal-review). */
277
188
  private blockingRefundForCredit;
278
189
  growDraw(args: Parameters<CreditLedgerLike["growDraw"]>[0]): Promise<GrownDrawResult>;
279
190
  settle(args: Parameters<CreditLedgerLike["settle"]>[0]): Promise<DrawResolution>;
@@ -320,7 +231,6 @@ declare class MemoryCreditLedger implements CreditLedgerLike {
320
231
  private findByPaymentHash;
321
232
  private fundSync;
322
233
  private drawSync;
323
- /** Mid-job top-up growth (internal-review) — see `CreditLedger.growDraw` for the semantics. */
324
234
  private growDrawSync;
325
235
  get(creditId: string, opts?: {
326
236
  nowMs?: number;
@@ -340,7 +250,6 @@ declare class MemoryCreditLedger implements CreditLedgerLike {
340
250
  limit: number;
341
251
  after?: StalePendingDrawCursor;
342
252
  }): Promise<DrawRecord[]>;
343
- /** Settled draws' native value for the credit an x402 channel funded (internal-review). */
344
253
  earnedNativeForX402Channel(channelId: string): Promise<number | undefined>;
345
254
  getCreditByX402Channel(channelId: string): Promise<CreditSnapshot | undefined>;
346
255
  terminalizeTempoCredits(evidence: TempoCreditLossEvidence, _tx?: CreditLedgerQuerier): Promise<TempoCreditLoss[]>;
@@ -435,11 +344,10 @@ declare class PostgresJobStore implements StreamableJobStore, ReceiptIssuingStor
435
344
  constructor(pool: Pool);
436
345
  /** Run the CREATE TABLE migration. Call once at startup. */
437
346
  init(): Promise<void>;
438
- /** The boot DDL itself — always runs under {@link withSdkInitLock} (internal-review). */
439
347
  private createTables;
440
348
  get(id: string): Promise<JobRecord | undefined>;
441
349
  /**
442
- * internal-review. Indexed by `idx_jobs_payment_tx_hash`. `paymentTxHash` is unique
350
+ * Indexed by `idx_jobs_payment_tx_hash`. `paymentTxHash` is unique
443
351
  * per settlement in practice — the accumulator's
444
352
  * `UNIQUE(dvm_id, request_id, proof_secret)` is what makes a second job under
445
353
  * the same request id impossible — but order by `created_at` so a
@@ -455,6 +363,10 @@ declare class PostgresJobStore implements StreamableJobStore, ReceiptIssuingStor
455
363
  /** Persist a job while retaining its mount identity for cost-report recovery. */
456
364
  saveForDvm(record: JobRecord, dvmId: string): Promise<void>;
457
365
  private saveRecord;
366
+ /** Advance only after the reporter durably enqueued or deduplicated the event. */
367
+ markTerminalReported(jobId: string): Promise<void>;
368
+ /** Bounded crash recovery for terminal events not yet queued. */
369
+ listUnreportedTerminalReports(dvmId: string, capabilities: string[] | null, afterJobId?: string): Promise<JobRecord[]>;
458
370
  /**
459
371
  * Read terminal zero-revenue jobs whose latest declared-cost revision has
460
372
  * not yet reached the durable reporter outbox.
@@ -520,7 +432,7 @@ declare class PostgresJobStore implements StreamableJobStore, ReceiptIssuingStor
520
432
  private terminateJob;
521
433
  private fetchCountersTx;
522
434
  /**
523
- * The credit binding on the job row, read inside Tx C (internal-review). Used on the
435
+ * The credit binding on the job row, read inside Tx C. Used on the
524
436
  * paths that don't get it from a `RETURNING` — the `alreadyVerified` skip and
525
437
  * a non-payment inbound.
526
438
  */
@@ -530,17 +442,14 @@ declare class PostgresJobStore implements StreamableJobStore, ReceiptIssuingStor
530
442
  /**
531
443
  * Postgres-backed KVStore. Requires the `pg` package as a peer dependency.
532
444
  *
533
- * Expired rows are filtered on read but never deleted. A periodic cleanup
534
- * mechanism (e.g. `DELETE FROM kv_store WHERE expires_at IS NOT NULL AND
535
- * expires_at < now()`) should be added before production use to prevent
536
- * unbounded table growth.
445
+ * Expired rows are filtered on read and list, but never deleted; callers
446
+ * must arrange their own cleanup to bound physical storage.
537
447
  */
538
448
  declare class PostgresKVStore implements KVStore {
539
449
  private pool;
540
450
  constructor(pool: Pool);
541
451
  /** Run the CREATE TABLE migration. Call once at startup. */
542
452
  init(): Promise<void>;
543
- /** The boot DDL itself — always runs under {@link withSdkInitLock} (internal-review). */
544
453
  private createTables;
545
454
  get<T = unknown>(key: string): Promise<T | undefined>;
546
455
  set(key: string, value: unknown, opts?: {
@@ -550,7 +459,6 @@ declare class PostgresKVStore implements KVStore {
550
459
  list(prefix?: string): Promise<string[]>;
551
460
  }
552
461
 
553
- /** Options for `PostgresReplayStore`. */
554
462
  interface PostgresReplayStoreOpts {
555
463
  /** Table name. Defaults to `"signed_request_replays"`. Must match `/^[a-zA-Z_][a-zA-Z0-9_]*$/`. */
556
464
  tableName?: string;
@@ -568,16 +476,8 @@ interface PostgresReplayStoreOpts {
568
476
  gcSampleRate?: number;
569
477
  }
570
478
  /**
571
- * Postgres-backed replay store implementing {@link SignedRequestReplayStore}.
572
- *
573
- * Cross-machine safe: relies on the PK on `(pubkey, timestamp, nonce)` with
574
- * `INSERT ... ON CONFLICT DO NOTHING` to detect duplicates atomically across
575
- * concurrent inserts from multiple machines. The consumer hands in a `Pool`
576
- * (matching `PostgresJobStore` / `PostgresKVStore`) and manages its lifecycle.
577
- *
578
- * Multi-machine deploys of secp256k1-auth'd DVMs SHOULD use this store to
579
- * close the per-process replay window — see {@link SignedRequestReplayStore}
580
- * for the threat model.
479
+ * The (pubkey, timestamp, nonce) primary key detects concurrent duplicates
480
+ * atomically across machines. The caller owns the pool lifecycle.
581
481
  */
582
482
  declare class PostgresReplayStore implements SignedRequestReplayStore {
583
483
  private pool;
@@ -587,7 +487,7 @@ declare class PostgresReplayStore implements SignedRequestReplayStore {
587
487
  constructor(pool: Pool, opts?: PostgresReplayStoreOpts);
588
488
  /** Run the CREATE TABLE migration. Idempotent — safe to call repeatedly. */
589
489
  init(): Promise<void>;
590
- /** The boot DDL itself — always runs under {@link withSdkInitLock} (internal-review). */
490
+ /** The boot DDL itself — always runs under {@link withSdkInitLock}. */
591
491
  private createTables;
592
492
  checkAndRecord(pubkey: string, timestamp: number, nonce: string, now: number): Promise<boolean>;
593
493
  private gcSweep;
@@ -601,21 +501,9 @@ declare function protocolEnvelopeIgnoreFields(schema: unknown): readonly string[
601
501
  declare function stripProtocolEnvelope(schema: unknown, data: unknown): unknown;
602
502
  /** Read and validate the optional recovery id from a signed request body. */
603
503
  declare function requestIdFromEnvelope(data: unknown): string | undefined;
604
- /** True when the request body carries a request id field but its value is invalid. */
605
504
  declare function hasInvalidRequestId(data: unknown): boolean;
606
505
 
607
- /**
608
- * Convenience one-liner over {@link createDVMHost} (internal-review). For
609
- * single-DVM hosts, `serve(dvm, opts)` is equivalent to
610
- * `createDVMHost(opts).mount(dvm).serve()`. Multi-DVM hosts go through
611
- * `createDVMHost` directly so each mount can carry its own prefix.
612
- *
613
- * This is **shorthand-over-host**, not a parallel code path — every wiring
614
- * step (Cashu/MPP/x402 envelope resolution, platform reporter, db, fx) flows
615
- * through `createDVMHost`. First-party DVMs that use `serve(...)` are NOT
616
- * exposed to the wiring-drift bug class fixed in internal-review/485/511, which was
617
- * about bypassing the host entirely. There is no migration to do.
618
- */
506
+ /** Single-DVM host. Use createDVMHost for multiple mounts with distinct prefixes. */
619
507
  declare function serve<State, InputSchema extends ZodLike | undefined = undefined>(descriptor: DVMDescriptor<State, InputSchema>, opts?: DVMHostOpts): Promise<DVMServeResult>;
620
508
 
621
- export { BlockedInvoiceCursor, CREDIT_REQUEST_SCHEMA, CreditInvoiceRecord, CreditLedgerLike, CreditLedgerQuerier, CreditMenu, type CreditRequest, type CreditRouteDeps, CreditSnapshot, DVMAuthScheme, DVMHostOpts, DVMServeResult, DrawRecord, DrawResolution, DrawResult, FundingRecord, GrownDrawResult, IMPLICIT_CREDIT_TTL_MS, type InitLockPool, InvoiceReconciliation, InvoiceSettlement, InvoiceWriteOff, JobRecord, LightningReceive, MemoryCreditLedger, PostgresJobStore, PostgresKVStore, PostgresReplayStore, type PostgresReplayStoreOpts, REQUEST_ID_FIELD, type ResolvedCashuOpts, SDK_INIT_ADVISORY_LOCK, SignedRequestDomain, SignedRequestReplayStore, StalePendingDrawCursor, StreamableJobStore, handleCreditRequest, hasInvalidRequestId, protocolEnvelopeIgnoreFields, requestIdFromEnvelope, resolveCashuOptsFromEnv, serve, stripProtocolEnvelope, withSdkInitLock };
509
+ export { BitcoinDepositLiability, BlockedInvoiceCursor, CREDIT_REQUEST_SCHEMA, CreditInvoiceRecord, CreditLedgerLike, CreditLedgerQuerier, CreditMenu, type CreditRequest, type CreditRouteDeps, CreditSnapshot, DVMAuthScheme, DVMHostOpts, DVMServeResult, DrawRecord, DrawResolution, DrawResult, FundingRecord, GrownDrawResult, IMPLICIT_CREDIT_TTL_MS, type InitLockPool, InvoiceReconciliation, InvoiceSettlement, InvoiceWriteOff, JobRecord, LightningReceive, MemoryCreditLedger, PostgresJobStore, PostgresKVStore, PostgresReplayStore, type PostgresReplayStoreOpts, REQUEST_ID_FIELD, type ResolvedCashuOpts, SDK_INIT_ADVISORY_LOCK, SignedRequestDomain, SignedRequestReplayStore, StalePendingDrawCursor, StreamableJobStore, handleCreditRequest, hasInvalidRequestId, protocolEnvelopeIgnoreFields, requestIdFromEnvelope, resolveCashuOptsFromEnv, serve, stripProtocolEnvelope, withSdkInitLock };