@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,12 +1,12 @@
1
1
  import {
2
2
  PostgresReplayStore
3
- } from "../chunk-L4OYF4DQ.js";
3
+ } from "../chunk-AJNFXR7J.js";
4
4
  import {
5
5
  PostgresJobStore
6
- } from "../chunk-SSSZUVWM.js";
6
+ } from "../chunk-JAHRF5X3.js";
7
7
  import {
8
8
  PostgresKVStore
9
- } from "../chunk-FROTD5XQ.js";
9
+ } from "../chunk-V5ZRATJH.js";
10
10
  import {
11
11
  SSRFError,
12
12
  assertSafeUrl,
@@ -21,10 +21,10 @@ import {
21
21
  parseNwcUri,
22
22
  validateX402Env,
23
23
  withNwcPool
24
- } from "../chunk-CEOAHV2I.js";
24
+ } from "../chunk-FDKRXOZO.js";
25
25
  import {
26
26
  MemoryKVStore
27
- } from "../chunk-RW5LP57K.js";
27
+ } from "../chunk-SDK6KDJN.js";
28
28
  import {
29
29
  AccumulatorReplayError,
30
30
  CLIENT_COMPATIBILITY_HEADERS,
@@ -78,16 +78,16 @@ import {
78
78
  stripProtocolEnvelope,
79
79
  toCreditView,
80
80
  unknownRouteNotFound
81
- } from "../chunk-5PBOA25N.js";
81
+ } from "../chunk-JNKQZVZX.js";
82
82
  import {
83
83
  MemoryProcessedPaymentStore,
84
84
  PostgresProcessedPaymentStore,
85
85
  ProcessedPaymentReplayError
86
- } from "../chunk-DMNLFNTW.js";
86
+ } from "../chunk-XRLKGCAW.js";
87
87
  import "../chunk-BQ2NMWKE.js";
88
88
  import {
89
89
  MemoryCreditLedger
90
- } from "../chunk-KVEHHC7W.js";
90
+ } from "../chunk-U5VNEALI.js";
91
91
  import {
92
92
  SignedRequestError,
93
93
  createDefaultReplayStore,
@@ -96,12 +96,12 @@ import {
96
96
  } from "../chunk-H2MEFVH6.js";
97
97
  import {
98
98
  isStreamableJobStore
99
- } from "../chunk-U6M3ATSG.js";
99
+ } from "../chunk-MD3H3BF7.js";
100
100
  import {
101
101
  generateEphemeralReceiptKey,
102
102
  isTestMintUrl,
103
103
  receiptPubkeyFromSecret
104
- } from "../chunk-KXCKFIJI.js";
104
+ } from "../chunk-QX52F6IB.js";
105
105
  import {
106
106
  X402_DEFAULT_FACILITATOR,
107
107
  X402_DEFAULT_NETWORK,
@@ -110,7 +110,7 @@ import {
110
110
  } from "../chunk-Z4BNLUZF.js";
111
111
  import {
112
112
  IMPLICIT_CREDIT_TTL_MS
113
- } from "../chunk-5URG56JJ.js";
113
+ } from "../chunk-A4CM2BD3.js";
114
114
  import {
115
115
  resolveRpcOverride
116
116
  } from "../chunk-MKI6OVW4.js";
@@ -121,10 +121,10 @@ import {
121
121
  } from "../chunk-KXZUCCEY.js";
122
122
  import {
123
123
  initLoggers
124
- } from "../chunk-E4EVGPDX.js";
124
+ } from "../chunk-YO56VCTQ.js";
125
125
  import "../chunk-66HGCPBU.js";
126
126
  import "../chunk-FUJ36YDV.js";
127
- import "../chunk-27V2ILSR.js";
127
+ import "../chunk-4A2RAKCW.js";
128
128
  import "../chunk-AT6V3SY7.js";
129
129
  import {
130
130
  CreditLedger,
@@ -133,11 +133,11 @@ import {
133
133
  PostgresX402ChannelStorage,
134
134
  X402RelaySubmissionLockError,
135
135
  allocateDrawValue
136
- } from "../chunk-MLRCSJYX.js";
136
+ } from "../chunk-2D75MNNG.js";
137
137
  import {
138
138
  SDK_INIT_ADVISORY_LOCK,
139
139
  withSdkInitLock
140
- } from "../chunk-S3XAHZQY.js";
140
+ } from "../chunk-COYKJRMM.js";
141
141
  import {
142
142
  applyRetryToPool
143
143
  } from "../chunk-C3MTFLC6.js";
@@ -147,7 +147,7 @@ import {
147
147
  TEMPO_SETTLEMENT_DEFAULT_LOW_BALANCE_MICRO,
148
148
  TempoSettlementReadiness,
149
149
  resolveTempoNetwork
150
- } from "../chunk-M7LHFJ5K.js";
150
+ } from "../chunk-XZ7LW4S5.js";
151
151
 
152
152
  // src/sdk/server/cashu-env.ts
153
153
  async function resolveCashuOptsFromEnv(env, pool, cashuModeHint) {
@@ -221,6 +221,7 @@ async function resolveCashuOptsFromEnv(env, pool, cashuModeHint) {
221
221
  error: err instanceof Error ? err.message : String(err)
222
222
  })
223
223
  );
224
+ if (cashuMode === "p2pk-accumulator") throw err;
224
225
  db = void 0;
225
226
  }
226
227
  }
@@ -320,7 +321,6 @@ var PlatformLightningRailHealth = class {
320
321
  lastAttemptAtMs;
321
322
  inFlight;
322
323
  ceilingLoggedForMs;
323
- /** Prime the signal during boot without making a menu request wait for it. */
324
324
  async refresh() {
325
325
  if (this.inFlight) return this.inFlight;
326
326
  this.lastAttemptAtMs = this.now();
@@ -332,7 +332,6 @@ var PlatformLightningRailHealth = class {
332
332
  this.inFlight = void 0;
333
333
  }
334
334
  }
335
- /** Answer from cache and begin a non-blocking refresh once it is due. */
336
335
  available() {
337
336
  const nowMs = this.now();
338
337
  if (this.lastAttemptAtMs === void 0 || nowMs - this.lastAttemptAtMs >= this.refreshTtlMs) {
@@ -463,16 +462,10 @@ var LightningReceive = class _LightningReceive {
463
462
  permissionRefusal;
464
463
  railHealth;
465
464
  /**
466
- * Validate the configured connection and build the receive leg, or return
467
- * `undefined` when this DVM didn't configure one.
468
- *
469
- * **Throws on a credential that is wrong, degrades on one that is merely
470
- * unreachable.** A wallet outage at boot must not stop a DVM whose other
471
- * rails are fine — the menu simply omits `lightning` until a later probe
472
- * succeeds. A connection that can spend, or one that can't state what it can
473
- * do, is a different thing entirely: it is a standing money risk that no
474
- * amount of retrying fixes, so it fails the boot loudly with the fix in the
475
- * message.
465
+ * Return undefined when unconfigured. Permission/URI failures refuse construction with a
466
+ * corrective message; wallet transport failure constructs an unavailable receive leg so
467
+ * other rails can still boot. Recovery must validate method scope before advertising
468
+ * Lightning.
476
469
  */
477
470
  static async create(config) {
478
471
  const invoiceTtlSeconds = resolveInvoiceTtl(config.invoiceTtlSeconds);
@@ -528,26 +521,17 @@ var LightningReceive = class _LightningReceive {
528
521
  );
529
522
  }
530
523
  /**
531
- * Whether `lightning` belongs on the funding menu right now.
532
- *
533
- * Reads the cached observation and never blocks; a stale one kicks off a
534
- * background refresh and answers with what we last knew. Advertising a rail
535
- * whose wallet is down would hand the caller an option that 402s on use —
536
- * the §4 posture is to drop it and let the sale survive on the others.
524
+ * Answer from cached wallet and optional rail-health observations without blocking. A stale
525
+ * wallet observation starts a background refresh.
537
526
  */
538
527
  available() {
539
528
  if (Date.now() - this.checkedAtMs > HEALTH_TTL_MS) void this.refresh();
540
529
  return this.health === "healthy" && (this.railHealth?.available() ?? true);
541
530
  }
542
531
  /**
543
- * Issue (or re-issue) the bolt11 funding `(creditId, fundId)`.
544
- *
545
- * The invoice is minted **for** the credit and amount named in the caller's
546
- * signed body — that binding is the internal-review condition-3 commitment on this
547
- * rail, and it is why no artifact hash rides the request: there is no
548
- * caller-supplied artifact to hash. A re-poll returns the stored row rather
549
- * than minting again; a second bolt11 for one `fund_id` would leave two
550
- * payable invoices against a funding that can only be credited once.
532
+ * Return the stored invoice on retry: two payable bolt11s for one fund ID could charge
533
+ * twice while only one credits. Caller and amount are bound to the recorded credit/funding
534
+ * pair, without a caller-supplied artifact hash.
551
535
  */
552
536
  async issue(ledger, args) {
553
537
  const existing = await ledger.getInvoice({ creditId: args.creditId, fundId: args.fundId });
@@ -582,9 +566,8 @@ var LightningReceive = class _LightningReceive {
582
566
  fundId: args.fundId,
583
567
  callerPubkey: args.callerPubkey,
584
568
  currency: args.currency,
585
- // Both amounts are pinned here and never recomputed at settle time: a
586
- // rate that moved between issuance and payment must not change what the
587
- // caller was quoted (the internal-review shape).
569
+ // Pin fiat and millisatoshi amounts at issue time; settlement does not reprice them
570
+ // after FX changes.
588
571
  amountMicro: args.amountMicro,
589
572
  amountMsats: created.amountMsats || args.amountMsats,
590
573
  paymentHash: created.paymentHash,
@@ -593,24 +576,9 @@ var LightningReceive = class _LightningReceive {
593
576
  });
594
577
  }
595
578
  /**
596
- * Ask the wallet whether one payment hash is paid, and when (internal-review).
597
- *
598
- * The operator's reconcile verb runs this before it credits anything. A
599
- * `blocked` row implies payment — {@link applyOne} returns above the block
600
- * classification when the lookup says unpaid — but that is *this fleet's
601
- * belief, recorded possibly weeks ago*, and the verb it gates mints balance
602
- * against it. One round trip turns the belief into a fact and recovers the
603
- * true settlement instant for `settled_at`, which a blocked row never got to
604
- * write.
605
- *
606
- * Unlike {@link settlePending} this **throws**: there is no request whose
607
- * latency it protects, and crediting on an unverifiable wallet is exactly
608
- * what it exists to prevent. `NOT_FOUND` is the one exception, and it is not
609
- * an outage — it is the wallet saying it has never seen this hash, the same
610
- * reading {@link applyOne} and the caller-side reconcile in `src/lib/nwc.ts`
611
- * take. It comes back as `known: false` because the operator's repair for it
612
- * ("you are pointed at a different wallet than the one that minted this")
613
- * is not the repair for an unpaid invoice, and certainly not for a retry.
579
+ * Re-observe the wallet payment before an operator credits a blocked invoice and recover
580
+ * its settlement instant. Unlike settlePending, lookup failures throw. NOT_FOUND returns
581
+ * known:false, distinguishing the wrong wallet/unknown hash from an unpaid known invoice.
614
582
  */
615
583
  async lookupSettlement(paymentHash) {
616
584
  try {
@@ -627,23 +595,12 @@ var LightningReceive = class _LightningReceive {
627
595
  }
628
596
  }
629
597
  /**
630
- * Consult the wallet about this caller's outstanding invoices and credit the
631
- * ones that settled — the pull half of pull-based crediting.
632
- *
633
- * The pending rows are read locally first, so the common case (nothing
634
- * outstanding) costs one indexed SELECT and no network at all. Bounded to
635
- * {@link MAX_SETTLE_CHECKS} invoices on a short deadline, and **never throws
636
- * into the request**: a wallet failure here means the caller's balance is
637
- * merely not updated yet, which the ordinary `insufficient_credit` path
638
- * already states honestly.
598
+ * Read pending invoices locally, then check at most MAX_SETTLE_CHECKS on bounded wallet
599
+ * deadlines. Log failures without throwing into the request.
639
600
  *
640
- * **Each invoice gets its own failure boundary.** The sweep window is a few
641
- * rows wide, so a row that fails on its own terms — a `fund_id` the caller
642
- * reused on another rail, a credit someone else opened first — must not take
643
- * the rest of the pass down with it: the next invoice in the window may be
644
- * the paid one, and it would never be looked up. Only a transport failure
645
- * ends the pass early, because there the wallet itself is gone and the
646
- * remaining lookups would just spend the caller's latency confirming it.
601
+ * An invoice-specific failure must not suppress payable siblings; wallet transport failure
602
+ * ends the pass. Deterministic refusals retire that row as blocked for operator repair,
603
+ * while transient failures remain pending.
647
604
  */
648
605
  async settlePending(ledger, args) {
649
606
  let pending;
@@ -683,14 +640,6 @@ var LightningReceive = class _LightningReceive {
683
640
  }
684
641
  return settled;
685
642
  }
686
- // ── Internal ───────────────────────────────────────────────────────────
687
- /**
688
- * One invoice's settlement check. Returns the applied settlement, or
689
- * `undefined` when nothing changed (still unpaid, or retired unpaid).
690
- *
691
- * Throws whatever the wallet or the ledger threw — classifying that is
692
- * {@link retireOrLog}'s job, so this stays one invoice's happy path.
693
- */
694
643
  async applyOne(ledger, backend, invoice, opts) {
695
644
  let status;
696
645
  try {
@@ -741,18 +690,9 @@ var LightningReceive = class _LightningReceive {
741
690
  });
742
691
  }
743
692
  /**
744
- * Decide what one invoice's failure means, and retire the invoice when the
745
- * answer is "this can never succeed".
746
- *
747
- * The split that matters is permanent-versus-transient, because it decides
748
- * whether the row keeps a slot in the sweep window. A transient failure — the
749
- * database blinked, the wallet answered oddly — leaves it `pending` and the
750
- * caller's next request retries it. A **permanent** one means the ledger will
751
- * refuse this invoice identically forever, so leaving it pending costs a
752
- * `lookup_invoice` on every subsequent request and, at
753
- * {@link MAX_SETTLE_CHECKS} of them, fills the window so a genuinely payable
754
- * invoice behind them is never even looked up. Those get `blocked`, which
755
- * drops them out of the sweep and hands the operator the payment hash.
693
+ * Retire a deterministic uncreditable payment as blocked so it no longer occupies the
694
+ * bounded sweep window. Transient failures stay pending for a later request; report the
695
+ * payment hash for operator repair.
756
696
  */
757
697
  async retireOrLog(ledger, invoice, err) {
758
698
  const reason = await this.blockingReason(ledger, invoice, err);
@@ -785,21 +725,10 @@ var LightningReceive = class _LightningReceive {
785
725
  );
786
726
  }
787
727
  /**
788
- * The reason this invoice can never be credited, or `undefined` if the
789
- * failure was transient.
790
- *
791
- * Every code here is decided by state a retry cannot move — a row the ledger
792
- * has already committed (a `credit_fundings` entry at this
793
- * `(credit_id, fund_id)`, or a `credits` row whose owner, denomination or
794
- * rail disagrees with the invoice), or the basis this module rebuilds
795
- * identically from the invoice row on every pass. None of them is a race.
796
- *
797
- * `funding_replayed` is the one that needs a second read to classify.
798
- * Usually it *is* benign — a concurrent check won the race and the money is
799
- * credited either way — but the key is `(credit_id, fund_id)` and `fund_id`
800
- * is **caller-chosen**: reuse it on cashu or x402 after this bolt11 was
801
- * minted and the row that collided is a different payment entirely, so the
802
- * sats this invoice received have nowhere to land.
728
+ * Classify funding_replayed by reading the existing funding’s rail. A Lightning row can
729
+ * represent a concurrent applied check; another rail at this caller-chosen key is a
730
+ * different payment, leaving the invoice’s sats uncredited. A failed diagnostic read
731
+ * remains transient, never a guessed permanent refusal.
803
732
  */
804
733
  async blockingReason(ledger, invoice, err) {
805
734
  if (!(err instanceof CreditLedgerError)) return void 0;
@@ -835,7 +764,6 @@ var LightningReceive = class _LightningReceive {
835
764
  throw err;
836
765
  }
837
766
  }
838
- /** Record activity without letting it promote an unvalidated connection. */
839
767
  noteOperationOk() {
840
768
  if (this.health !== "healthy") return;
841
769
  this.checkedAtMs = Date.now();
@@ -1028,7 +956,6 @@ var PostgresTempoSettlementReadinessStore = class {
1028
956
  address;
1029
957
  token;
1030
958
  now;
1031
- /** Create the shared latch table under the SDK-wide boot migration lock. */
1032
959
  async init() {
1033
960
  await withSdkInitLock(this.pool, async () => {
1034
961
  await this.pool.query(`
@@ -1181,7 +1108,7 @@ function createDVMHost(opts = {}) {
1181
1108
  const dbRequired = !opts.jobStore && !opts.devMode && !opts.pool;
1182
1109
  if (!databaseUrl && dbRequired) {
1183
1110
  throw new Error(
1184
- "createDVMHost requires a Postgres database. Pass `database` opt or set DATABASE_URL env. See public design rationale (internal-review)."
1111
+ "createDVMHost requires a Postgres database. Pass `database` opt or set DATABASE_URL env."
1185
1112
  );
1186
1113
  }
1187
1114
  let store = opts.store ?? new MemoryKVStore();
@@ -1200,13 +1127,13 @@ function createDVMHost(opts = {}) {
1200
1127
  });
1201
1128
  applyRetryToPool(pool, "dvm-host");
1202
1129
  pgPool = pool;
1203
- const { PostgresJobStore: PostgresJobStore2 } = await import("../postgres-job-store-3RAXMNSY.js");
1130
+ const { PostgresJobStore: PostgresJobStore2 } = await import("../postgres-job-store-MZZZMS2B.js");
1204
1131
  const pgJobStore = new PostgresJobStore2(pool);
1205
1132
  pendingInits.push(pgJobStore.init(), pgJobStore.initStreaming());
1206
1133
  jobStore = pgJobStore;
1207
1134
  pgStreamStore = pgJobStore;
1208
1135
  if (!opts.store) {
1209
- const { PostgresKVStore: PostgresKVStore2 } = await import("../postgres-kv-store-JFBDP5IP.js");
1136
+ const { PostgresKVStore: PostgresKVStore2 } = await import("../postgres-kv-store-DXGTKXLU.js");
1210
1137
  const pgKvStore = new PostgresKVStore2(pool);
1211
1138
  pendingInits.push(pgKvStore.init());
1212
1139
  store = pgKvStore;
@@ -1238,7 +1165,7 @@ function createDVMHost(opts = {}) {
1238
1165
  if (testMints.length > 0) {
1239
1166
  if (!envFlag(envMaybe.DVMKIT_ALLOW_TEST_MINTS)) {
1240
1167
  throw new Error(
1241
- `[FATAL] Refusing to boot: platform-hosted DVM configured with test mint(s) [${testMints.join(", ")}]. A test/FakeWallet mint settles no real money \u2014 every payment would silently no-op and revenue would read $0. If this is intentional (dev stack, smoke test, or the staging fleet), set DVMKIT_ALLOW_TEST_MINTS=true. (internal-review)`
1168
+ `[FATAL] Refusing to boot: platform-hosted DVM configured with test mint(s) [${testMints.join(", ")}]. A test/FakeWallet mint settles no real money \u2014 every payment would silently no-op and revenue would read $0. If this is intentional (dev stack, smoke test, or the staging fleet), set DVMKIT_ALLOW_TEST_MINTS=true.`
1242
1169
  );
1243
1170
  }
1244
1171
  console.warn(
@@ -1246,7 +1173,7 @@ function createDVMHost(opts = {}) {
1246
1173
  level: "warn",
1247
1174
  event: "platform_hosted_test_mint_allowed",
1248
1175
  mints: testMints,
1249
- message: "Platform-hosted DVM booting with test mint(s) because DVMKIT_ALLOW_TEST_MINTS=true \u2014 payments settle no real money. (internal-review)"
1176
+ message: "Platform-hosted DVM booting with test mint(s) because DVMKIT_ALLOW_TEST_MINTS=true \u2014 payments settle no real money."
1250
1177
  })
1251
1178
  );
1252
1179
  }
@@ -1291,11 +1218,11 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1291
1218
  let tempoChargeBackend = "user-supplied";
1292
1219
  const mppTempoRecipient = envMaybe.DVMKIT_TEMPO_RECIPIENT;
1293
1220
  if (!mpp && mppTempoRecipient) {
1294
- const { createMppFromOpts, createDualKeyMppxFromOpts, parseMppMethodsAllowlist } = await import("../mpp-setup-4FJD6ZHV.js");
1221
+ const { createMppFromOpts, createDualKeyMppxFromOpts, parseMppMethodsAllowlist } = await import("../mpp-setup-MPP3ST5X.js");
1295
1222
  tempoChargeBackend = pgPool ? "postgres" : "memory";
1296
1223
  let tempoCharge;
1297
1224
  if (pgPool) {
1298
- const { PostgresTempoChargeStore } = await import("../tempo-charge-store-RIFTALZK.js");
1225
+ const { PostgresTempoChargeStore } = await import("../tempo-charge-store-SDTUNTKA.js");
1299
1226
  const chargeStore = new PostgresTempoChargeStore(pgPool);
1300
1227
  pendingInits.push(chargeStore.init());
1301
1228
  tempoCharge = { store: chargeStore };
@@ -1314,7 +1241,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1314
1241
  { createPublicClient, createWalletClient, erc20Abi, http },
1315
1242
  { tempo: tempoMainnet, tempoModerato }
1316
1243
  ] = await Promise.all([
1317
- import("../tempo-session-store-2JNOKJGX.js"),
1244
+ import("../tempo-session-store-WF3VZXNF.js"),
1318
1245
  import("viem/accounts"),
1319
1246
  import("viem"),
1320
1247
  import("viem/chains")
@@ -1372,7 +1299,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1372
1299
  chain: selectedChain,
1373
1300
  // Trimmed, so a blank DVMKIT_TEMPO_RPC_URL falls back to the
1374
1301
  // chain's bundled endpoint rather than becoming the transport
1375
- // target (internal-review).
1302
+ // target.
1376
1303
  transport: http(tempoRpc)
1377
1304
  });
1378
1305
  },
@@ -1415,7 +1342,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1415
1342
  applyMppSecretRotation,
1416
1343
  loadMppSecretState,
1417
1344
  DEFAULT_ROTATION_WINDOW_MS
1418
- } = await import("../mpp-secret-state-WNAQQ6K4.js");
1345
+ } = await import("../mpp-secret-state-B5GCILVH.js");
1419
1346
  await initMppSecretStateTable(pgPool);
1420
1347
  const rotation = await applyMppSecretRotation(
1421
1348
  pgPool,
@@ -1445,7 +1372,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1445
1372
  }
1446
1373
  }
1447
1374
  const fxSource = envMaybe.DVMKIT_FX_SOURCE;
1448
- const { createFxFetcher, resolveFxSourceFromEnv, warmFxSnapshot } = await import("../pricing-4CEB34RM.js");
1375
+ const { createFxFetcher, resolveFxSourceFromEnv, warmFxSnapshot } = await import("../pricing-MU5GNUJZ.js");
1449
1376
  const fxFetcher = opts.fx ?? createFxFetcher({ source: resolveFxSourceFromEnv(envMaybe) });
1450
1377
  const hostRailConfigured = (opts.paymentMethods?.length ?? 0) > 0 || (effectiveMints?.length ?? 0) > 0 || !!x402WithDualServe || !!mpp;
1451
1378
  if (mounts.some((entry) => mountNeedsFx(entry, hostRailConfigured))) warmFxSnapshot(fxFetcher);
@@ -1455,7 +1382,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1455
1382
  assertReceiptIdentity(envMaybe, opts.builder, receiptKey, cashuOpts.dvmId, opts.devMode);
1456
1383
  let sharedPgReplayStore;
1457
1384
  if (pgPool) {
1458
- const { PostgresReplayStore: PostgresReplayStore2 } = await import("../postgres-replay-store-UJXRT6VO.js");
1385
+ const { PostgresReplayStore: PostgresReplayStore2 } = await import("../postgres-replay-store-ZF4JNZOW.js");
1459
1386
  const store2 = new PostgresReplayStore2(pgPool);
1460
1387
  pendingInits.push(store2.init());
1461
1388
  sharedPgReplayStore = store2;
@@ -1467,7 +1394,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1467
1394
  const backend = auth.resolveReplayStore ? auth.resolveReplayStore({ postgresStore: sharedPgReplayStore }) : "user-supplied";
1468
1395
  replayStoreSummaries.push({ mount: entry.descriptor.name, backend });
1469
1396
  if (backend === "memory" && !opts.devMode) {
1470
- const msg = `secp256k1Auth on "${entry.descriptor.name}" fell back to the in-memory replay store. Multi-machine deploys MUST use a cross-machine store (e.g. PostgresReplayStore) \u2014 each machine's per-process window otherwise lets an attacker replay a captured signed envelope once per machine via the load balancer. Set DATABASE_URL or pass \`replayStore\` to secp256k1Auth(). (internal-review)`;
1397
+ const msg = `secp256k1Auth on "${entry.descriptor.name}" fell back to the in-memory replay store. Multi-machine deploys MUST use a cross-machine store (e.g. PostgresReplayStore) \u2014 each machine's per-process window otherwise lets an attacker replay a captured signed envelope once per machine via the load balancer. Set DATABASE_URL or pass \`replayStore\` to secp256k1Auth().`;
1471
1398
  if (failFast) {
1472
1399
  throw new Error(`[FATAL] ${msg}`);
1473
1400
  }
@@ -1483,24 +1410,24 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1483
1410
  }
1484
1411
  let sharedPgConsumedStore;
1485
1412
  if (pgPool) {
1486
- const { PostgresConsumedCredentialStore } = await import("../postgres-consumed-credential-store-VHBT4KEA.js");
1413
+ const { PostgresConsumedCredentialStore } = await import("../postgres-consumed-credential-store-6N2V5MJN.js");
1487
1414
  const consumedStore = new PostgresConsumedCredentialStore(pgPool);
1488
1415
  pendingInits.push(consumedStore.init());
1489
1416
  sharedPgConsumedStore = consumedStore;
1490
1417
  }
1491
1418
  if (pgPool) {
1492
- const { CreditLedger: CreditLedger2 } = await import("../credit-ledger-2DFQHNLB.js");
1419
+ const { CreditLedger: CreditLedger2 } = await import("../credit-ledger-MHA652TV.js");
1493
1420
  const pgLedger = new CreditLedger2(pgPool, tempoSessionStore);
1494
1421
  pendingInits.push(pgLedger.init());
1495
1422
  creditLedger = pgLedger;
1496
- const { PostgresProcessedPaymentStore: PostgresProcessedPaymentStore2 } = await import("../processed-payment-store-HAA4SFNK.js");
1423
+ const { PostgresProcessedPaymentStore: PostgresProcessedPaymentStore2 } = await import("../processed-payment-store-GKMAWOM3.js");
1497
1424
  const pgProcessed = new PostgresProcessedPaymentStore2(pgPool);
1498
1425
  pendingInits.push(pgProcessed.init());
1499
1426
  processedPayments = pgProcessed;
1500
1427
  } else {
1501
- const { MemoryCreditLedger: MemoryCreditLedger2 } = await import("../memory-credit-ledger-MNUOTQO5.js");
1428
+ const { MemoryCreditLedger: MemoryCreditLedger2 } = await import("../memory-credit-ledger-BYBATRN3.js");
1502
1429
  creditLedger = disposableCashu?.ledger ?? new MemoryCreditLedger2();
1503
- const { MemoryProcessedPaymentStore: MemoryProcessedPaymentStore2 } = await import("../processed-payment-store-HAA4SFNK.js");
1430
+ const { MemoryProcessedPaymentStore: MemoryProcessedPaymentStore2 } = await import("../processed-payment-store-GKMAWOM3.js");
1504
1431
  processedPayments = new MemoryProcessedPaymentStore2();
1505
1432
  }
1506
1433
  await Promise.all(pendingInits);
@@ -1509,7 +1436,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1509
1436
  const checkStoreFallback = (label, event, active, backend, hazardHint) => {
1510
1437
  storeSummaries.push({ label, backend });
1511
1438
  if (active && backend === "memory" && !opts.devMode) {
1512
- const msg = `The ${label} store fell back to in-memory. Multi-machine deploys MUST use a cross-machine store (set DATABASE_URL) \u2014 each machine's per-process window otherwise lets an attacker ${hazardHint} once per machine via the load balancer. (internal-review)`;
1439
+ const msg = `The ${label} store fell back to in-memory. Multi-machine deploys MUST use a cross-machine store (set DATABASE_URL) \u2014 each machine's per-process window otherwise lets an attacker ${hazardHint} once per machine via the load balancer.`;
1513
1440
  if (failFast) {
1514
1441
  throw new Error(`[FATAL] ${msg}`);
1515
1442
  }
@@ -1691,8 +1618,9 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1691
1618
  replayStores: replayStoreSummaries,
1692
1619
  stores: storeSummaries
1693
1620
  });
1694
- return new Promise((resolvePromise) => {
1621
+ return new Promise((resolvePromise, rejectPromise) => {
1695
1622
  const server = honoServe({ fetch: app.fetch, port }, (info) => {
1623
+ server.off("error", rejectPromise);
1696
1624
  const url = `http://{authority}`.replace("{authority}", `localhost:${info.port}`);
1697
1625
  nodeServer = server;
1698
1626
  const portBindMs = Date.now() - bootStart;
@@ -1708,7 +1636,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1708
1636
  level: "dvm_boot_phase_timings",
1709
1637
  totalMsToPortBind: portBindMs,
1710
1638
  phaseMs: deltas
1711
- // internal-review removed the pre-`listen` `mint_wait` phase: mint health
1639
+ // removed the pre-`listen` `mint_wait` phase: mint health
1712
1640
  // is now validated by the runtime tracker after the port binds, so
1713
1641
  // `totalMsToPortBind` no longer carries the mint-probe tail.
1714
1642
  })
@@ -1722,6 +1650,7 @@ ${config.facilitatorAuth?.keyId ?? ""}`;
1722
1650
  }
1723
1651
  });
1724
1652
  });
1653
+ server.once("error", rejectPromise);
1725
1654
  });
1726
1655
  }
1727
1656
  async function serveFn(serveOpts) {
@@ -2071,7 +2000,7 @@ function secp256k1Auth(opts = {}) {
2071
2000
  replayStore: null,
2072
2001
  driftSeconds,
2073
2002
  now,
2074
- // internal-review: the caller signs over the credit envelope, so it has to be in
2003
+ // the caller signs over the credit envelope, so it has to be in
2075
2004
  // the canonical bytes — but it is protocol-level, not capability input, so
2076
2005
  // the builder's schema must not have to tolerate it. Resolved once per
2077
2006
  // schema, cached with the verifier below.
@@ -26,7 +26,6 @@ type SSRFResolver = (host: string) => Promise<{
26
26
  * baseline denylist; extra entries compose with (never replace) the defaults.
27
27
  */
28
28
  interface SSRFGuardOpts {
29
- /** Custom DNS resolver — typically a test stub. */
30
29
  resolver?: SSRFResolver;
31
30
  /** Additional exact hostnames to deny on top of the defaults (lowercased on input). */
32
31
  extraHostnamesExact?: Iterable<string>;
@@ -61,7 +60,7 @@ interface SSRFGuardOpts {
61
60
  * link-local IP ranges, the AWS / GCP metadata IP, Fly's `*.internal`
62
61
  * service-discovery names, and a small denylist of obviously-internal
63
62
  * hostnames. Defence-in-depth — full mitigation belongs at the egress firewall
64
- * and at fetch-time IP pinning (`createPinnedFetch`, internal-review).
63
+ * and at fetch-time IP pinning (`createPinnedFetch`).
65
64
  *
66
65
  * Throws `SSRFError` with a `reason` discriminator so callers can branch onto
67
66
  * their own typed error taxonomy.