@dvmkit/sdk 0.2.0-rc.9 → 0.3.0-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 (58) hide show
  1. package/README.md +2 -0
  2. package/dist/{chunk-V7EVFLAK.js → chunk-2D75MNNG.js} +154 -523
  3. package/dist/{chunk-BIFLRKMO.js → chunk-2KGG5ORW.js} +1 -1
  4. package/dist/{chunk-5URG56JJ.js → chunk-A4CM2BD3.js} +18 -2
  5. package/dist/{chunk-FT6HTUM4.js → chunk-AJNFXR7J.js} +1 -1
  6. package/dist/{chunk-S3XAHZQY.js → chunk-COYKJRMM.js} +24 -3
  7. package/dist/{chunk-UP2F5RRT.js → chunk-D7YQYLLM.js} +1 -4
  8. package/dist/{chunk-OMIQMMME.js → chunk-FPOLJRBF.js} +3 -3
  9. package/dist/{chunk-QP53RWAD.js → chunk-HHTL3ZFT.js} +9 -6
  10. package/dist/{chunk-PCUQZDZA.js → chunk-LTAIBLS2.js} +537 -321
  11. package/dist/{chunk-JDT5LCJC.js → chunk-MD3H3BF7.js} +1 -1
  12. package/dist/{chunk-KSQEFVFJ.js → chunk-MMCE7XSR.js} +1 -1
  13. package/dist/{chunk-MRAGS5VP.js → chunk-N5B66UOS.js} +4 -16
  14. package/dist/{chunk-2ATUAUAO.js → chunk-O6D72KYA.js} +2 -2
  15. package/dist/{chunk-KXCKFIJI.js → chunk-QX52F6IB.js} +1 -1
  16. package/dist/{chunk-PHHAYRQV.js → chunk-U5VNEALI.js} +23 -10
  17. package/dist/{chunk-JLXYOV4Y.js → chunk-V5ZRATJH.js} +1 -1
  18. package/dist/{chunk-6GRIKOFB.js → chunk-VA7GT6C6.js} +5 -16
  19. package/dist/{chunk-O2X2CCKH.js → chunk-VIVXB4CD.js} +1 -1
  20. package/dist/{chunk-L67WTZX2.js → chunk-XMDQOXHO.js} +10 -33
  21. package/dist/{chunk-QT4ONTST.js → chunk-XRLKGCAW.js} +1 -1
  22. package/dist/{chunk-KMZXTBLA.js → chunk-XZ7LW4S5.js} +0 -1
  23. package/dist/{chunk-XQXJKJ3P.js → chunk-YO56VCTQ.js} +0 -4
  24. package/dist/{credit-ledger-5ZEJRI46.js → credit-ledger-MHA652TV.js} +2 -2
  25. package/dist/{credit-menu-D4Gcdgc4.d.ts → credit-menu-BlCL7gZx.d.ts} +175 -533
  26. package/dist/{fx-B0SLBe5x.d.ts → fx-DhyT1Cjh.d.ts} +1 -1
  27. package/dist/index.d.ts +5 -17
  28. package/dist/internal/caller.d.ts +109 -698
  29. package/dist/internal/caller.js +10 -12
  30. package/dist/internal/server.d.ts +17 -42
  31. package/dist/internal/server.js +16 -15
  32. package/dist/{job-store-B2uZvga4.d.ts → job-store-D3CcZp_g.d.ts} +6 -10
  33. package/dist/{lightning-backend-CQBnQgsT.d.ts → lightning-backend-BhsyrBLa.d.ts} +1 -15
  34. package/dist/{memory-credit-ledger-ZOH6C3N4.js → memory-credit-ledger-BYBATRN3.js} +3 -3
  35. package/dist/{mpp-secret-state-WNAQQ6K4.js → mpp-secret-state-B5GCILVH.js} +1 -1
  36. package/dist/{mpp-setup-IOJBF7DB.js → mpp-setup-MPP3ST5X.js} +1 -1
  37. package/dist/{payout-reporter-5PIRYFVQ.js → payout-reporter-KEMUXEUO.js} +2 -2
  38. package/dist/{postgres-consumed-credential-store-ISRHBMOU.js → postgres-consumed-credential-store-6N2V5MJN.js} +1 -1
  39. package/dist/postgres-job-store-VE2JRUEC.js +7 -0
  40. package/dist/postgres-kv-store-DXGTKXLU.js +7 -0
  41. package/dist/{postgres-replay-store-IZFLTTAC.js → postgres-replay-store-ZF4JNZOW.js} +2 -2
  42. package/dist/{processed-payment-store-FIDI3RNH.js → processed-payment-store-GKMAWOM3.js} +2 -2
  43. package/dist/revenue-reporter-O75BGYFK.js +7 -0
  44. package/dist/server/index.d.ts +37 -140
  45. package/dist/server/index.js +64 -127
  46. package/dist/{step-cache-CXg7ziML.d.ts → step-cache-v2yhyhSZ.d.ts} +359 -1112
  47. package/dist/{tempo-charge-store-76TDAF34.js → tempo-charge-store-SDTUNTKA.js} +2 -2
  48. package/dist/{tempo-lifecycle-DXM7QXJQ.js → tempo-lifecycle-G5SB4HFC.js} +4 -4
  49. package/dist/{tempo-session-store-2JNOKJGX.js → tempo-session-store-WF3VZXNF.js} +2 -2
  50. package/dist/{tempo-wallet-O67H5M4N.js → tempo-wallet-ZFNUDFVO.js} +1 -1
  51. package/dist/testing/index.d.ts +2 -2
  52. package/dist/testing/index.js +2 -2
  53. package/dist/{usd-BNDg1715.d.ts → usd-Cu9G6xv2.d.ts} +1 -1
  54. package/dist/{x402-7S2EFINY.js → x402-CI6PSHNO.js} +4 -4
  55. package/package.json +2 -2
  56. package/dist/postgres-job-store-OGQ6IT4U.js +0 -7
  57. package/dist/postgres-kv-store-D5E2EZ24.js +0 -7
  58. package/dist/revenue-reporter-NNCNRY4C.js +0 -7
@@ -1,16 +1,15 @@
1
- import { ah as FundingMethod, o as PaymentMethod, bM as CreditLedgerLike, a1 as Message, X as FundingReceipt, bO as CreditSnapshot, Y as JobReceipt, S as SDKJobContext, aw as StepCache, u as ResponseContent, P as PaymentContent, a2 as MessageType, bj as X402Receipt, aE as X402Config, bi as X402ExactVersionSupport, cT as X402SettlementIntent, aq as PaymentRequirementsV2, c1 as CreditLedgerQuerier, cU as X402SettlementCursor, bQ as X402SettlementStatus, cV as X402SettlementWriteOff, bN as X402RefundSettlementGate, cW as X402FacilitatorAuth, cX as X402BatchSettlementConfig, cz as PostgresX402ChannelStorage, cY as X402PayoutObserver, br as MppxServer, ab as CashuMode, cZ as CreditDepositEnqueue, c_ as X402SettlementReconciliationReason, ao as PaymentRequirements, a0 as MppxCredential, bm as CreditDepositPayload, bP as DrawResult, cn as CreditLedgerError, a6 as ReceiptCredit, ae as DrainReceiptEvent, ad as DrainReceipt, K as KVStore, y as SignedRequestAudience, c$ as CreditDrawReleaseEnqueue, cx as JobCostReportPayload, cy as JobTerminalReportPayload, cB as RevenueSkippedNoRailPayload, Z as ZodLike, a as DVMDescriptor, bV as CreditInvoiceRecord, bW as InvoiceSettlement, ch as ClientCompatibilityGate, cf as ClientCompatibility, bu as PayoutReporter, R as ResolvedCreditConfig, g as CreditView } from './step-cache-CXg7ziML.js';
1
+ import { ah as FundingMethod, o as PaymentMethod, bM as CreditLedgerLike, a1 as Message, X as FundingReceipt, bO as CreditSnapshot, Y as JobReceipt, S as SDKJobContext, aw as StepCache, u as ResponseContent, P as PaymentContent, a2 as MessageType, bj as X402Receipt, aE as X402Config, bi as X402ExactVersionSupport, cT as X402SettlementIntent, aq as PaymentRequirementsV2, c1 as CreditLedgerQuerier, cU as X402SettlementCursor, bQ as X402SettlementStatus, cV as X402SettlementWriteOff, bN as X402RefundSettlementGate, cW as X402FacilitatorAuth, cX as X402BatchSettlementConfig, cz as PostgresX402ChannelStorage, cY as X402PayoutObserver, br as MppxServer, ab as CashuMode, cZ as CreditDepositEnqueue, c_ as X402SettlementReconciliationReason, ao as PaymentRequirements, a0 as MppxCredential, bm as CreditDepositPayload, bP as DrawResult, cn as CreditLedgerError, a6 as ReceiptCredit, ae as DrainReceiptEvent, ad as DrainReceipt, K as KVStore, y as SignedRequestAudience, c$ as CreditDrawReleaseEnqueue, cx as JobCostReportPayload, cy as JobTerminalReportPayload, cB as RevenueSkippedNoRailPayload, Z as ZodLike, a as DVMDescriptor, bV as CreditInvoiceRecord, bW as InvoiceSettlement, ch as ClientCompatibilityGate, cf as ClientCompatibility, bu as PayoutReporter, R as ResolvedCreditConfig, g as CreditView } from './step-cache-v2yhyhSZ.js';
2
2
  import { ProofLike, SerializedDLEQ, Proof } from '@cashu/cashu-ts';
3
3
  import { Hono, Context } from 'hono';
4
4
  import { Pool } from 'pg';
5
- import { b as FxRateSnapshot, F as FxFetcher } from './fx-B0SLBe5x.js';
6
- import { g as LockPubkey, f as CheckMintHealthOptions, b as LightningBackend, A as AttestationPayload } from './lightning-backend-CQBnQgsT.js';
7
- import { T as TopUpCapUnenforcedReason, A as AppendOutgoingOptions, J as JobRecord, b as JobStore } from './job-store-B2uZvga4.js';
5
+ import { b as FxRateSnapshot, F as FxFetcher } from './fx-DhyT1Cjh.js';
6
+ import { g as LockPubkey, f as CheckMintHealthOptions, b as LightningBackend, A as AttestationPayload } from './lightning-backend-BhsyrBLa.js';
7
+ import { T as TopUpCapUnenforcedReason, A as AppendOutgoingOptions, J as JobRecord, b as JobStore } from './job-store-D3CcZp_g.js';
8
8
  import { Challenge } from 'mppx';
9
9
  import { SettleResponse, SupportedResponse } from '@x402/core/types';
10
10
  import { Channel, AutoSettlementConfig } from '@x402/evm/batch-settlement/server';
11
11
  import { FacilitatorClient } from '@x402/core/server';
12
12
 
13
- /** A row in the per-DVM `wallet_accumulator` table. */
14
13
  interface WalletAccumulatorRow {
15
14
  id: string;
16
15
  dvmId: string;
@@ -36,11 +35,8 @@ interface WalletAccumulatorRow {
36
35
  * rows created before the column existed.
37
36
  */
38
37
  meltQuoteId: string | null;
39
- /**
40
- * NUT-11 locktime captured at accept time (ms since epoch). Null when the
41
- * accepted proof has no `locktime` tag. Drives oldest-first
42
- * ordering and the future `wallet_accumulator_batch_expiring_soon` monitor.
43
- */
38
+ /** NUT-11 locktime at acceptance, in epoch ms; null without a tag.
39
+ * Drives oldest-first ordering and expiring-soon monitoring. */
44
40
  tExpire: number | null;
45
41
  }
46
42
  /**
@@ -174,7 +170,6 @@ interface DisposableCashuCommit {
174
170
  commit(requestId: string, proofs: Proof[], account: (ledger: CreditLedgerLike) => Promise<void>): Promise<void>;
175
171
  }
176
172
 
177
- /** How often the sweep runs, and how long after boot its first pass fires. */
178
173
  interface CreditExpirySweepOpts {
179
174
  /** Sweep period. Defaults to {@link DEFAULT_SWEEP_INTERVAL_MS}; `0` disables the timer. */
180
175
  intervalMs?: number;
@@ -183,21 +178,52 @@ interface CreditExpirySweepOpts {
183
178
  * disables the boot pass, leaving only the interval.
184
179
  */
185
180
  bootDelayMs?: number;
186
- /** Credits released per pass. Passed straight to the ledger. */
187
181
  limit?: number;
188
182
  }
189
183
 
190
- /** Promise resolver for a pending client prompt response. */
184
+ interface HostingControlConfig {
185
+ /** Dedicated management key. Use at least 32 random bytes; never reuse a caller or builder key. */
186
+ secret: string;
187
+ /** Deployment scope shared by the platform and this DVM, independent of its caller origin. */
188
+ scope: string;
189
+ }
190
+ interface HostingControlCommand {
191
+ action: "drain" | "resume" | "status";
192
+ scope: string;
193
+ dvmId: string;
194
+ timestampMs: number;
195
+ nonce: string;
196
+ generation?: number;
197
+ deadlineMs?: number;
198
+ }
199
+ /** The ordered JSON array is the version-one wire signing contract. */
200
+ declare function signHostingControl(secret: string, command: HostingControlCommand): string;
201
+ interface HostingControlStatus {
202
+ state: "accepting" | "draining";
203
+ generation: number;
204
+ deadlineMs: number | null;
205
+ activeJobIds: string[];
206
+ unownedActiveJobIds: string[];
207
+ pendingAdmissionCount: number;
208
+ pendingAdmissions: {
209
+ admissionId: string;
210
+ workId: string;
211
+ }[];
212
+ unresolvedAdmissionCount: number;
213
+ unresolvedAdmissions: {
214
+ admissionId: string;
215
+ jobId: string;
216
+ }[];
217
+ }
218
+
191
219
  interface PromptResolver {
192
220
  resolve: (value: ResponseContent) => void;
193
221
  reject: (reason: Error) => void;
194
222
  }
195
- /** Promise resolver for a pending client payment. */
196
223
  interface PaymentResolver {
197
224
  resolve: (value: PaymentContent) => void;
198
225
  reject: (reason: Error) => void;
199
226
  }
200
- /** In-memory representation of a running job. */
201
227
  interface ServerJob {
202
228
  id: string;
203
229
  tags: string[];
@@ -262,17 +288,13 @@ interface ServerJob {
262
288
  /** Chain transaction returned to callers recovering x402 or Tempo acceptance. */
263
289
  paymentTransactionHash?: string;
264
290
  /**
265
- * Rail-native amount accumulated across all successful credits on this
266
- * job (sats for mpp, USDC microunits for x402). The single
267
- * `revenue_events` row written at completion uses this as `gross_native`,
268
- * so multi-credit jobs sum the per-credit native amounts.
269
- * The upfront credit initializes this value; mid-job credits accumulate same-rail
270
- * and reset on a cross-rail switch (see `processIncomingPayment`).
291
+ * Rail-native atomic units accumulated across same-rail credits: Tempo and
292
+ * x402 use stablecoin micro-units. A rail switch resets this amount; Cashu
293
+ * revenue is derived from paidMsats instead.
271
294
  */
272
295
  nativeAmount?: number;
273
296
  /** Native asset tag paired with `nativeAmount`. */
274
297
  nativeAsset?: "sats" | "usdc" | "usdc.e" | "usd-cents";
275
- /** Cashu flow discriminator written into `revenue_events.metadata.cashu_flow`. */
276
298
  cashuFlow?: "p2pk_accumulator";
277
299
  /**
278
300
  * What this job cost the **builder** to serve, in 1e-6 of
@@ -316,8 +338,8 @@ interface ServerJob {
316
338
  * nonce issued by `requestPayment` and stamped onto the outbound x402
317
339
  * envelope; the caller signs `TransferWithAuthorization` against this exact
318
340
  * `bytes32`. Verification rejects an incoming `x402_payment` whose decoded
319
- * authorization nonce differs, blocking a cross-job replay before the
320
- * facilitator settles. Cleared on successful credit.
341
+ * authorization nonce differs before crediting the job. Cleared on
342
+ * successful credit.
321
343
  */
322
344
  pendingX402Nonce?: string;
323
345
  /**
@@ -415,9 +437,8 @@ interface ServerJob {
415
437
  /** Unix ms timestamp of last activity (message, yield, terminal). */
416
438
  lastActivityAt: number;
417
439
  }
418
- /** Extract the persistent fields from a ServerJob into a JobRecord. */
419
440
  declare function toJobRecord(job: ServerJob): JobRecord;
420
- /** Reconstitute a ServerJob from a persisted JobRecord with fresh runtime fields. */
441
+ /** Restored snapshots receive fresh process-local listeners, cancellation and prompt state. */
421
442
  declare function fromJobRecord(record: JobRecord): ServerJob;
422
443
  /**
423
444
  * Signal cancellation to a running handler. Idempotent — aborting an
@@ -433,40 +454,14 @@ declare function abortJob(job: ServerJob, reason: string): void;
433
454
  declare class JobCancelledError extends Error {
434
455
  constructor(message?: string);
435
456
  }
436
- /** Append a provider-sent message to the job and notify SSE listeners. */
437
457
  declare function providerMessage(job: ServerJob, type: MessageType, content: Record<string, unknown> | object): void;
438
458
  declare function isTerminal(status: ServerJob["status"]): boolean;
439
- /** Check if a message is a yield point (ends the provider's turn). */
440
459
  declare function isYieldMessage(msg: Message): boolean;
441
460
 
442
- /**
443
- * Per-DVM runtime mint-health tracker. Alongside the platform's
444
- * durable mint-health cron, probes every configured
445
- * mint on a timer, tracks consecutive failures, and flips a mint to `sick`
446
- * once the threshold is crossed. The SDK uses the resulting view to:
447
- *
448
- * 1. Filter `/v1/info`'s advertised `mints` to currently-healthy ones.
449
- * 2. Reject new accumulator receives at sick mints before they touch the
450
- * DB (`cashu_mint_sick` 503 from `verifyAccumulatorReceipt`).
451
- *
452
- * Since this tracker is the sole owner of mint health: boot no longer
453
- * runs a fail-fast check before binding the port. To preserve what boot used
454
- * to guarantee it (a) treats a mint as healthy only when it's reachable AND
455
- * NUT-compliant (reproducing `assertNutSupport` via `nutCompliant`), and (b)
456
- * exposes `initialProbeComplete()` so the paid path holds calls at
457
- * `mint_health_pending` until the first probe validates ≥1 mint.
458
- *
459
- * Existing accumulator entries are not touched — they're P2PK-locked to the
460
- * original mint and stay put until `dvmctl melt-pending` drains them. The
461
- * accumulator monitor's `wallet_accumulator_batch_expiring_soon` already
462
- * pages the builder when a stuck batch nears `t_expire`.
463
- *
464
- * In-memory only — no DB persistence. The platform cron keeps the durable
465
- * record + email path; the SDK only needs fresh in-process state
466
- * to make routing decisions.
467
- */
461
+ /** In-process mint health gates advertising and new receives. Paid calls wait for
462
+ * the first probe; NUT incompatibility fails immediately, transient failures
463
+ * use a consecutive threshold. Existing accumulator proofs remain at their mint. */
468
464
 
469
- /** Per-mint runtime view exposed by `snapshot()`. */
470
465
  interface MintHealthSnapshot {
471
466
  /** Last-observed wall-clock latency of the probe in ms. */
472
467
  latencyMs?: number;
@@ -486,9 +481,7 @@ interface MintHealthSnapshot {
486
481
  * never resolves without a config/mint change.
487
482
  */
488
483
  nutIncompatible?: boolean;
489
- /** Mint version reported by the last successful probe. */
490
484
  version?: string;
491
- /** Error category from the most recent failed probe. */
492
485
  errorCode?: string;
493
486
  }
494
487
  interface MintHealthTrackerOptions {
@@ -508,22 +501,9 @@ interface MintHealthTrackerOptions {
508
501
  consecutiveFailuresToSick?: number;
509
502
  fetchImpl?: typeof fetch;
510
503
  now?: () => number;
511
- /**
512
- * Per-probe timeout / retry / backoff, forwarded to {@link checkMintHealth}.
513
- * Defaults to that function's own defaults — 3 attempts with `[200, 500]`
514
- * backoff, which is what a real tick should do.
515
- *
516
- * Tests that drive several failing ticks set `backoffMs: [0]`: a failing
517
- * probe otherwise costs 700ms of real `setTimeout`, and four of them put a
518
- * unit test within a loaded CI runner's reach of the 5s default timeout.
519
- * `fetchImpl` is set on the tracker, not here.
520
- */
504
+ /** Forwarded to checkMintHealth; fetchImpl is supplied on the tracker. */
521
505
  probe?: Omit<CheckMintHealthOptions, "fetchImpl">;
522
506
  }
523
- /**
524
- * Runtime mint-health tracker. Owns its own timer; `start()` runs an initial
525
- * probe immediately so the first received call doesn't see a stale snapshot.
526
- */
527
507
  declare class MintHealthTracker {
528
508
  private readonly mints;
529
509
  private readonly tickIntervalMs;
@@ -569,60 +549,31 @@ declare class MintHealthTracker {
569
549
  * where a merely-flapping mint is still published.
570
550
  */
571
551
  isNutIncompatible(mintUrl: string): boolean;
572
- /** Plain-object snapshot keyed by mint URL — for tests + observability. */
573
552
  snapshot(): Record<string, MintHealthSnapshot>;
574
553
  private applyResult;
575
- /**
576
- * One-shot structured summary emitted after the first probe tick. Replaces
577
- * the boot check's per-mint `cashu_mint_startup_health` lines and surfaces an
578
- * all-mints-unhealthy warning — the operator alert that the Fly restart-loop
579
- * used to be before boot stopped refusing to start.
580
- */
554
+ /** One boot summary, including an all-unhealthy warning. */
581
555
  private logBootHealth;
582
556
  }
583
557
 
584
558
  /**
585
- * Credit fields carried inside the signed request body.
586
- *
587
- * An explicit draw references the credit INSIDE the secp256k1/Schnorr-signed
588
- * `body.data` — no new caller crypto. Wire field names (snake_case, matching
589
- * the rest of the wire surface):
590
- *
591
- * - `credit_id` — the credit to draw against.
592
- * - `draw_id` — client-generated draw id; the ledger's idempotency key.
593
- * - `fund` — optional `{ amount_micro, commitment }` funding commitment:
594
- * present iff a funding artifact (X-Cashu / X-PAYMENT / mpp credential)
595
- * rides the same request. `commitment` is the SHA-256 hex over the raw
596
- * artifact bytes, binding the header-borne proof — which sits OUTSIDE the
597
- * signed body — to the credit its sender intended (the funding-commitment rule).
559
+ * Credit fields belong to the raw signed body. The funding commitment hashes the header
560
+ * artifact, binding money outside that body to its intended credit.
598
561
  *
599
- * These are envelope-level fields, not capability input: **the SDK** removes
600
- * them before any builder-owned schema parses ({@link stripCreditEnvelope} in
601
- * `JobManager.parseInput` and on the quote path; {@link
602
- * creditEnvelopeIgnoreFields} feeding the auth verifier's own schema check), so
603
- * handlers never see them and a top-level `.strict()` capability schema is
604
- * fine. Relying on Zod's default strip mode instead was the trap:
605
- * `.strict()` rejects unknown keys, so an explicit draw 400'd at parse before
606
- * the envelope was ever extracted.
607
- *
608
- * The strip never touches the canonical signing bytes. Every auth call site
609
- * verifies the raw wire body (`signedRequestInput`), so the credit
610
- * fields are in the verified bytes because they were never taken out of them —
611
- * the strip is only ever applied to what a schema is about to parse.
562
+ * Schema projection strips undeclared protocol keys before builder input parsing, without
563
+ * changing canonical signing bytes. Signature verification must use the original wire body; a
564
+ * parsed projection may omit credit fields.
612
565
  */
613
566
  interface CreditEnvelope {
614
567
  creditId: string;
615
568
  drawId: string;
616
569
  fund?: CreditFundCommitment;
617
570
  }
618
- /** The signed funding commitment for a fund-and-draw request. */
619
571
  interface CreditFundCommitment {
620
572
  /** Funding amount in 1e-6 units of the credit's currency. */
621
573
  amountMicro: number;
622
574
  /** SHA-256 hex over the raw funding artifact bytes. */
623
575
  commitment: string;
624
576
  }
625
- /** Wire keys reserved for the credit envelope inside `body.data`. */
626
577
  declare const CREDIT_ENVELOPE_KEYS: readonly ["credit_id", "draw_id", "fund"];
627
578
  /**
628
579
  * Thrown by {@link extractCreditEnvelope} on a structurally invalid credit
@@ -640,28 +591,16 @@ declare class CreditEnvelopeError extends Error {
640
591
  */
641
592
  declare function extractCreditEnvelope(data: unknown): CreditEnvelope | undefined;
642
593
  /**
643
- * The reserved keys `schema` does not itself declare — the ones the SDK is
644
- * free to remove before handing it an input.
645
- *
646
- * A capability schema declares none of them, so all three are removable. The
647
- * one exception this exists for is `/v1/credit`'s own `CREDIT_REQUEST_SCHEMA`,
648
- * where `credit_id` and `fund` are real fields on a different wire shape and
649
- * removing them would empty the request. It is not an escape hatch for a
650
- * capability: the three names stay reserved on `body.data`, and declaring one
651
- * doesn't win a builder their own value — `app.ts` runs
652
- * {@link extractCreditEnvelope} over the raw body on every submit, so a
653
- * capability that declares `fund` answers `invalid_credit_fields` instead.
594
+ * Return protocol keys not declared by the schema. Schema-declared keys remain available,
595
+ * including /v1/credit’s differently shaped credit_id and fund fields. Submit separately
596
+ * extracts and validates the credit envelope from raw body.data; declaring a key does not
597
+ * bypass that validation.
654
598
  */
655
599
  declare function creditEnvelopeIgnoreFields(schema: unknown): readonly string[];
656
600
  /**
657
- * Remove the reserved credit keys from `data` before `schema` parses it, so a
658
- * strict schema doesn't reject the protocol's own envelope. Keys
659
- * `schema` declares are left alone — see {@link creditEnvelopeIgnoreFields}.
660
- *
661
- * Returns `data` unchanged when it isn't a plain object or carries none of the
662
- * removable keys, so the ordinary no-credit request allocates nothing. Never
663
- * use the result to derive canonical signing bytes: those cover the wire form,
664
- * credit fields included (`signedRequestInput`).
601
+ * Remove undeclared credit keys before schema parsing. Preserve nonobject/array inputs and
602
+ * objects with no removable keys. Never derive signing bytes from this projection; signatures
603
+ * cover the raw wire body.
665
604
  */
666
605
  declare function stripCreditEnvelope(schema: unknown, data: unknown): unknown;
667
606
 
@@ -904,18 +843,8 @@ declare function derivedFundCreditId(callerPubkey: string, fundId: string): stri
904
843
  declare function drawSettlementRef(dvmId: string, creditId: string, drawId: string): string;
905
844
 
906
845
  /**
907
- * Durable marker for a rail payment that already funded the credit ledger
908
- * (the funding-commitment rule). The x402 and mpp rails have no dvmkit-side
909
- * commit point of their own — the money moves at the facilitator / the payer's
910
- * mpp server — so the marker row, inserted in the SAME transaction as
911
- * `CreditLedger.fund` + `draw`, is what makes a crash-replayed credential
912
- * unable to fund twice: the second attempt collides on the primary key and
913
- * surfaces as {@link ProcessedPaymentReplayError}, which the verifier routes
914
- * into the recovery gates instead of a second fund.
915
- *
916
- * The Cashu rail does not use this store — its accumulator insert is already
917
- * the durable commit point, and its replay key (the `X-Cashu-Request-Id`
918
- * regime) must stay exactly as-is (dual-idempotency rule, the signed credit contract).
846
+ * x402/Tempo marker, funding and draw commit in one transaction so a retry
847
+ * cannot fund twice. Cashu retains its separate accumulator replay regime.
919
848
  */
920
849
  interface ProcessedPaymentStore {
921
850
  /**
@@ -941,11 +870,8 @@ interface ProcessedPaymentStore {
941
870
  paymentId: string;
942
871
  }): Promise<ProcessedPaymentRecord | undefined>;
943
872
  /**
944
- * Run `fn` inside one transaction (Postgres: BEGIN → fn → COMMIT, rollback
945
- * on throw). The verifier funds and draws the ledger inside `fn`, passing
946
- * the handle through to `record` / `CreditLedger.fund` / `draw` so all
947
- * three commit atomically. The memory implementation invokes `fn` with no
948
- * handle — its operations are synchronous-atomic in-process.
873
+ * Postgres supplies a transaction for marker, fund and draw; failure rolls it
874
+ * back. Memory invokes fn without a transactional handle or rollback.
949
875
  */
950
876
  withTx<T>(fn: (tx?: ProcessedPaymentQuerier) => Promise<T>): Promise<T>;
951
877
  }
@@ -1024,7 +950,6 @@ declare class MemoryProcessedPaymentStore implements ProcessedPaymentStore {
1024
950
  */
1025
951
  type AccumulatorRejectionCode = "missing_request_id" | "missing_lock_pubkey" | "not_p2pk_locked" | "wrong_lock_pubkey" | "proof_not_unspent" | "proof_pending" | "replay_rejected" | "mint_unreachable" | "invalid_token";
1026
952
 
1027
- /** Durable state of one exact x402 authorization. */
1028
953
  type X402ExactSettlementStatus = "prepared" | "submitting" | "settled" | "local_committed" | "ambiguous" | "rejected" | "complete";
1029
954
  /** Serializable local economic effect that follows an exact settlement. */
1030
955
  interface X402ExactSettlementEffect {
@@ -1073,7 +998,6 @@ interface X402ExactAuthorizationFacts {
1073
998
  nonce: string;
1074
999
  fingerprint: string;
1075
1000
  }
1076
- /** One durable exact-x402 settlement intent. */
1077
1001
  interface X402ExactSettlementIntent extends X402ExactAuthorizationFacts {
1078
1002
  id: string;
1079
1003
  dvmId: string;
@@ -1128,11 +1052,9 @@ interface X402ExactSettlementStore {
1128
1052
  }): Promise<X402ExactSettlementIntent[]>;
1129
1053
  attempts(dvmId: string, intentId: string): Promise<X402ExactSettlementAttempt[]>;
1130
1054
  }
1131
- /** Postgres-backed exact settlement intent store. */
1132
1055
  declare class PostgresX402ExactSettlementStore implements X402ExactSettlementStore {
1133
1056
  private readonly pool;
1134
1057
  constructor(pool: Pick<Pool, "query" | "connect">);
1135
- /** Create the exact settlement tables. */
1136
1058
  init(): Promise<void>;
1137
1059
  prepare(intent: Omit<X402ExactSettlementIntent, "status" | "createdAt" | "updatedAt" | "resolvedAt">): Promise<X402ExactSettlementIntent>;
1138
1060
  get(dvmId: string, intentId: string): Promise<X402ExactSettlementIntent | undefined>;
@@ -1241,7 +1163,6 @@ type X402ExactAcceptance<T> = {
1241
1163
  intentId: string;
1242
1164
  reason: string;
1243
1165
  };
1244
- /** Dependencies for the durable exact x402 settlement coordinator. */
1245
1166
  interface X402ExactSettlementServerOpts {
1246
1167
  store: X402ExactSettlementStore;
1247
1168
  evidence?: X402ExactSettlementEvidenceReader;
@@ -1264,13 +1185,11 @@ declare class X402ExactSettlementServer {
1264
1185
  effect?: X402ExactSettlementEffect;
1265
1186
  commit: (receipt: X402Receipt, tx?: ProcessedPaymentQuerier, effect?: X402ExactSettlementEffect) => Promise<T>;
1266
1187
  }): Promise<X402ExactAcceptance<T>>;
1267
- /** Read the operator queue. */
1268
1188
  list(args: {
1269
1189
  dvmId: string;
1270
1190
  limit: number;
1271
1191
  includeResolved?: boolean;
1272
1192
  }): Promise<X402ExactSettlementIntent[]>;
1273
- /** Read durable attempt evidence for one intent. */
1274
1193
  attempts(dvmId: string, intentId: string): Promise<X402ExactSettlementAttempt[]>;
1275
1194
  /** Reconcile and finish one intent from chain evidence. */
1276
1195
  reconcile(dvmId: string, intentId: string): Promise<{
@@ -1614,7 +1533,6 @@ interface CreateX402BatchSettlementServerOpts {
1614
1533
  */
1615
1534
  declare function createX402BatchSettlementServer(opts: CreateX402BatchSettlementServerOpts): Promise<X402BatchSettlementServer>;
1616
1535
 
1617
- /** Payment state from upfront token verification. */
1618
1536
  interface PaymentInfo {
1619
1537
  /**
1620
1538
  * Rail value this payment contributes to the job, in millisatoshis.
@@ -1647,12 +1565,10 @@ interface PaymentInfo {
1647
1565
  /** Chain transaction returned to a caller recovering this accepted request. */
1648
1566
  paymentTransactionHash?: string;
1649
1567
  /**
1650
- * Rail-native payment amount in atomic units. Sats for mpp,
1651
- * USDC microunits for x402. Cashu leaves it unset — the existing
1652
- * `paidMsats / 1000` derivation in the platform callback covers it.
1568
+ * Stablecoin micro-units for Tempo and x402. Cashu leaves this unset; its revenue is derived
1569
+ * from paidMsats.
1653
1570
  */
1654
1571
  nativeAmount?: number;
1655
- /** Native asset tag matching `revenue_events.native_asset`. */
1656
1572
  nativeAsset?: "sats" | "usdc" | "usdc.e" | "usd-cents";
1657
1573
  /**
1658
1574
  * Discriminator written into `revenue_events.metadata.cashu_flow` so ops
@@ -1801,7 +1717,6 @@ interface UpfrontPaymentOpts {
1801
1717
  * no per-process replay protection beyond mppx's own expiry check.
1802
1718
  */
1803
1719
  consumedCredentialStore?: ConsumedCredentialStore;
1804
- /** Cashu receive mode. Routes the receive path. */
1805
1720
  cashuMode?: CashuMode;
1806
1721
  /** Per-DVM Postgres pool — required for the `p2pk-accumulator` path. */
1807
1722
  accumulatorDb?: AccumulatorPool;
@@ -1834,12 +1749,9 @@ interface UpfrontPaymentOpts {
1834
1749
  */
1835
1750
  fxFetcher?: FxFetcher;
1836
1751
  /**
1837
- * Credit ledger every payment funds and draws through (the credit lifecycle contract):
1838
- * an attached rail payment is an implicit N=1 funding — `fund` the paid
1839
- * amount + `draw` it, atomically with the rail commit. When absent (or
1840
- * when the price can't be fiat-denominated), the payment is accepted with
1841
- * legacy semantics and a structured warning — money is never refused
1842
- * because the ledger is unavailable.
1752
+ * Attached payments fund and draw an implicit per-job credit atomically with
1753
+ * rail accounting. Omitting the ledger uses the legacy ledgerless path;
1754
+ * a configured ledger requires a fiat-denominated price before acceptance.
1843
1755
  */
1844
1756
  creditLedger?: CreditLedgerLike;
1845
1757
  /**
@@ -1917,7 +1829,6 @@ interface FundOnlyRequest {
1917
1829
  */
1918
1830
  commitment: string;
1919
1831
  }
1920
- /** Structured payment validation error detail carried through `PaymentValidationError`. */
1921
1832
  interface PaymentErrorDetail {
1922
1833
  body: Record<string, unknown>;
1923
1834
  status: number;
@@ -2065,7 +1976,6 @@ declare function hasPaymentProof(content: Record<string, unknown>): boolean;
2065
1976
  * surfaces always keep charge.
2066
1977
  */
2067
1978
  declare function issueUpfrontChallenges(mpp: MppxServer, requiredMsats: number, resourcePath: string, btcUsdRate: number, sessionIssuable?: boolean, allowOneShotStablecoin?: unknown, priceFiat?: PriceFiat): Promise<Challenge.Challenge[]>;
2068
- /** Verify an upfront payment on job submission (Cashu, x402, or MPP). */
2069
1979
  declare function verifyUpfrontPayment(opts: UpfrontPaymentOpts): Promise<PaymentResult>;
2070
1980
  /**
2071
1981
  * A management credential signed for a channel other than the one required
@@ -2117,25 +2027,9 @@ declare function verifyTempoSessionManagementCredential(args: {
2117
2027
  */
2118
2028
  type PaymentErrorCode = "payment_invalid" | "x402_not_offered" | "x402_settlement_ambiguous" | "cashu_unavailable" | "cashu_not_p2pk_locked" | "mint_health_pending" | "cashu_mint_sick" | "payment_insufficient" | "payment_unapplied" | "insufficient_credit" | "credit_expired" | "credit_unbacked" | "credit_not_found" | "tempo_channel_closing" | "settlement_pending" | "draw_conflict" | "funding_commitment_mismatch" | "credit_not_supported" | "one_shot_credit_not_supported" | "credit_below_min" | "below_rail_minimum" | "credit_over_max" | "credit_id_unavailable" | "nothing_to_drain" | "drain_below_dust" | "drain_not_found" | "drain_conflict" | "drain_method_unsupported" | "tempo_channel_exit_required" | "x402_settlement_submission_failed" | X402SettlementReconciliationReason | "lightning_settlement_pending" | "lightning_invoice_expired" | "lightning_unavailable" | AccumulatorRejectionCode;
2119
2029
  /**
2120
- * Build a flat payment-error body carrying the four agent-facing fields every
2121
- * payment error must have: the machine `code`, the operator-facing
2122
- * `message`, and the `display`/`hint`/`retryable` copy an agent relays to a
2123
- * human and branches retries on. `display`, `hint`, and `retryable` default from
2124
- * {@link PAYMENT_ERROR_COPY} keyed on `code`; `message` is the per-site operator
2125
- * log line. The prose fields can be overridden for dynamic cases (e.g.
2126
- * `cashu_mint_sick` naming the currently-healthy mints, or a retained deposit
2127
- * distinguishing "not spent" from "not paid"). `extra` carries a code's ad-hoc
2128
- * fields (`mints`, `required_msats`, `received_msats`) and is merged last so
2129
- * those are preserved.
2130
- *
2131
- * `retryable` overrides on the same terms, and for the same reason: a code that
2132
- * covers more than one refusal can be terminal for one of them and clear on its
2133
- * own for another — `drain_conflict` is both. Override it only
2134
- * alongside the `hint`, since the two are one answer: a hint that says retry
2135
- * under `retryable: false` is the disagreement this exists to prevent.
2136
- *
2137
- * Upstream of {@link buildPaymentErrorResponse}, which serializes the body onto
2138
- * a `Response` — this shapes it.
2030
+ * Per-code display, hint and retryability may be overridden for a particular
2031
+ * refusal. Keep the hint and retry decision consistent. Extra fields merge
2032
+ * last, so callers can supply code-specific amounts and alternatives.
2139
2033
  */
2140
2034
  declare function paymentErrorBody(code: PaymentErrorCode, opts: {
2141
2035
  message: string;
@@ -2216,14 +2110,9 @@ interface IncomingPaymentOpts {
2216
2110
  creditTtlMs?: number;
2217
2111
  }
2218
2112
  /**
2219
- * Pure verification of an incoming mid-job payment. Runs the
2220
- * rail-specific verify path and returns the credit shape; does not mutate
2221
- * the job. The caller (`JobManager.processPayment`) applies the result
2222
- * inside Tx C so verify+credit land atomically.
2223
- *
2224
- * `snapshot` carries the read-only job state the verification path needs
2225
- * (`pendingPaymentMsats` for amount checks, the MPP/x402 per-job bindings,
2226
- * `paymentRail` for the same-rail accumulator check).
2113
+ * Job state read by incoming-payment verification; the job itself is not mutated. Rail
2114
+ * acceptance and ledger funding can still occur before the caller applies the returned credit in
2115
+ * Tx C.
2227
2116
  */
2228
2117
  interface VerifyIncomingSnapshot {
2229
2118
  pendingPaymentMsats?: number;
@@ -2326,16 +2215,8 @@ declare function verifyIncomingPayment(body: {
2326
2215
  */
2327
2216
  declare function applyPaymentInfoToJob(job: ServerJob, info: VerifiedIncomingPayment): void;
2328
2217
  /**
2329
- * Process an incoming payment message. Returns an error body on failure.
2330
- *
2331
- * **The isolate-runtime path, and deliberately ledger-less** (the isolate-runtime rule). Its
2332
- * only caller is `platform/isolate-job-manager.ts`; isolate DVMs have no
2333
- * Postgres of their own, so they run implicit N=1 with today's semantics
2334
- * preserved and never advertise credit. The credits-carrying mid-job path is
2335
- * {@link verifyIncomingPayment} + `JobManager.processPayment` (Tx C), where
2336
- * wired `fund` + `growDraw`. Wiring a ledger here would need a
2337
- * platform-side ledger leg with its own funding-atomicity and receipt-key
2338
- * story — the trust-surface expansion exists to decide.
2218
+ * Legacy ledgerless payment path. Mutates the job on acceptance; durable credit hosts use
2219
+ * verifyIncomingPayment and apply its result in Tx C.
2339
2220
  */
2340
2221
  declare function processIncomingPayment(job: ServerJob, body: {
2341
2222
  type: MessageType;
@@ -2414,14 +2295,8 @@ interface ReceiptIssuerOpts {
2414
2295
  dvmId: string;
2415
2296
  }
2416
2297
  /**
2417
- * Signs job receipts for one DVM.
2418
- *
2419
- * Constructed only when a receipt key is wired, so the presence of an issuer
2420
- * *is* the "this DVM emits receipts" signal that `/v1/info` advertises. Pure:
2421
- * it holds the key and the slug and turns a terminal `JobRecord` plus an
2422
- * allocated sequence number into signed bytes — sequence allocation and
2423
- * persistence belong to the store, which is what makes issuance idempotent
2424
- * across machines.
2298
+ * An issuer indicates receipt support. Sequence allocation and write-once
2299
+ * persistence belong to the store; signing alone does not provide idempotency.
2425
2300
  */
2426
2301
  declare class ReceiptIssuer {
2427
2302
  /** x-only pubkey this issuer signs under; the attested `receipt_pubkey`. */
@@ -2431,20 +2306,10 @@ declare class ReceiptIssuer {
2431
2306
  private readonly dvmId;
2432
2307
  constructor(opts: ReceiptIssuerOpts);
2433
2308
  /**
2434
- * Build and sign the receipt for a terminal job. `seq` comes from
2435
- * `JobStore.claimReceiptSeq`; `issuedAt` is epoch seconds and defaults to now.
2436
- *
2437
- * Free jobs get receipts too, with `paid.msats: 0` — they still consume a
2438
- * sequence number and still attest an outcome. Whether feedback is
2439
- * paid-only is the feedback layer's call, not this one's.
2440
- *
2441
- * Timing and attribution come from the committed terminal row, not signing
2442
- * time or handler input. Legacy rows without those durable inputs omit the
2443
- * optional blocks rather than inventing historical evidence.
2444
- *
2445
- * `credit` is the resolved draw block — present on every job
2446
- * whose payment funded/drew the ledger, absent otherwise. Signature-
2447
- * compatible either way: `canonicalize` omits absent keys.
2309
+ * seq is store-allocated; issuedAt is epoch seconds. Free jobs also consume a
2310
+ * sequence and attest their outcome. Timing/attribution comes from the committed
2311
+ * terminal row; legacy rows omit unknown historical fields. credit is present
2312
+ * only for a resolved ledger draw.
2448
2313
  */
2449
2314
  issue(record: JobRecord, seq: number, issuedAt?: number, credit?: ReceiptCredit): JobReceipt;
2450
2315
  /**
@@ -2544,9 +2409,9 @@ interface JobManagerOpts {
2544
2409
  env: Record<string, string>;
2545
2410
  store: KVStore;
2546
2411
  mints?: string[];
2547
- /** Persistent backing store for job records. Default: in-memory. */
2412
+ /** Durable in production; defaults to memory only in development/test mode. */
2548
2413
  jobStore?: JobStore;
2549
- /** When true, payment messages auto-credit without verification. */
2414
+ /** Skips payment only when no payment rail is configured. Wired rails still verify. */
2550
2415
  devMode?: boolean;
2551
2416
  /** Payment methods this DVM accepts. Default: derived by the server from configured rails. */
2552
2417
  paymentMethods?: PaymentMethod[];
@@ -2555,9 +2420,7 @@ interface JobManagerOpts {
2555
2420
  x402ExactSettlement?: X402ExactSettlementServer;
2556
2421
  /** Live facilitator capabilities for version-specific mid-job payment handling. */
2557
2422
  x402FacilitatorHealth?: X402FacilitatorHealthLike;
2558
- /** MPP multi-rail payment handle (built via `createMppFromOpts`). */
2559
2423
  mpp?: MppxServer;
2560
- /** Cashu receive mode. */
2561
2424
  cashuMode?: CashuMode;
2562
2425
  /** Builder's NUT-11 P2PK lock pubkey. Required for accumulator mode. */
2563
2426
  lockPubkey?: string;
@@ -2693,16 +2556,10 @@ interface JobManagerOpts {
2693
2556
  */
2694
2557
  onRevenueSkippedNoRail?: (info: RevenueSkippedNoRailPayload) => void | Promise<void>;
2695
2558
  /**
2696
- * Stale-job sweep threshold in ms. Jobs in a non-terminal status
2697
- * (`processing` / `working` / `awaiting-input`) whose `lastActivityAt` is
2698
- * older than this are force-cancelled with reason `stale_no_terminal_status`,
2699
- * so callers always reach a terminal status instead of polling forever after
2700
- * a worker crash, OOM, or silent `messageAppender` failure. Default:
2701
- * `2 × descriptor.idleTimeout + STALE_JOB_WATCHDOG_HEADROOM_MS`, which keeps
2702
- * the default beyond scrape's `JOB_TIMEOUT_MS`.
2703
- * Builders whose per-handler wall-clock bound exceeds 90s must override
2704
- * this — otherwise the watchdog fires on a legitimate in-flight handler.
2705
- * Set to `0` to disable (test seam).
2559
+ * Awaiting-input age in milliseconds before cancellation. Defaults to
2560
+ * twice descriptor.idleTimeout (seconds), converted to milliseconds, plus
2561
+ * STALE_JOB_WATCHDOG_HEADROOM_MS. Set to 0 to disable this arm; processing
2562
+ * jobs use processingWatchdogMs.
2706
2563
  */
2707
2564
  staleJobTimeoutMs?: number;
2708
2565
  /**
@@ -2907,9 +2764,7 @@ declare class JobManager<State, InputSchema extends ZodLike | undefined> {
2907
2764
  * never promise something `issueReceipt` silently declines to do.
2908
2765
  */
2909
2766
  get receiptsEnabled(): boolean;
2910
- /** True when the named capability exists on this descriptor. */
2911
2767
  hasCapability(name: string): boolean;
2912
- /** Names of every capability this descriptor exposes — used for error envelopes. */
2913
2768
  capabilityNames(): string[];
2914
2769
  /**
2915
2770
  * Resolve a capability's static `price` to msats.
@@ -3101,9 +2956,7 @@ declare class JobManager<State, InputSchema extends ZodLike | undefined> {
3101
2956
  * `artifact`'s NOTIFY silently drops the artifact.
3102
2957
  */
3103
2958
  private wireMessageAppender;
3104
- /** Start (or restart) the idle timer for a job. */
3105
2959
  startIdleTimer(job: ServerJob): void;
3106
- /** Clear the idle timer for a job. */
3107
2960
  clearIdleTimer(id: string): void;
3108
2961
  /** Cancel a job due to idle timeout. Exposed for the reactivation path's idle-expiry guard. */
3109
2962
  cancelJobIdle(job: ServerJob): Promise<void>;
@@ -3609,7 +3462,6 @@ declare class JobManager<State, InputSchema extends ZodLike | undefined> {
3609
3462
  private reportTerminalJob;
3610
3463
  private terminalReportRecoveryCursor?;
3611
3464
  private recoverTerminalReports;
3612
- /** Handle job reaching terminal state (completed, failed, cancelled). */
3613
3465
  private handleJobTerminal;
3614
3466
  /**
3615
3467
  * Re-enqueue terminal cost-only rows left between the job commit and outbox
@@ -3671,19 +3523,16 @@ declare class JobManager<State, InputSchema extends ZodLike | undefined> {
3671
3523
  private bookRevenue;
3672
3524
  /** Schedule job removal from activeJobs after a delay so clients can still poll final status. */
3673
3525
  scheduleCleanup(job: ServerJob): void;
3674
- /** Clear all timers. Called on server shutdown to allow clean exit. */
3675
3526
  shutdown(): void;
3676
3527
  }
3677
3528
 
3678
3529
  /** Cached liveness signal for a platform-hosted DVM's Lightning receive rail. */
3679
3530
  interface LightningRailHealth {
3680
- /** Whether the receive rail may be advertised at this instant. */
3681
3531
  available(): boolean;
3682
3532
  /** Prime the cached signal at boot when the source supports it. */
3683
3533
  refresh?(): Promise<void>;
3684
3534
  }
3685
3535
 
3686
- /** Builder-facing wiring for the Lightning receive leg. */
3687
3536
  interface LightningReceiveConfig {
3688
3537
  /**
3689
3538
  * Receive-only NWC connection URI (`DVMKIT_NWC_RECEIVE_URI`). Validated at
@@ -3722,25 +3571,14 @@ declare const DEFAULT_INVOICE_TTL_SECONDS = 900;
3722
3571
  */
3723
3572
  declare const MIN_INVOICE_TTL_SECONDS = 600;
3724
3573
  /**
3725
- * The builder-side Lightning receive leg for funding prepaid credit.
3574
+ * Prepaid Lightning funding over a receive-safe NWC connection. URI construction validates
3575
+ * the advertised method allowlist, refusing spending or unknown authority; the injected
3576
+ * backend seam bypasses that probe. Receive-safe methods include invoice, read and
3577
+ * hold-invoice operations.
3726
3578
  *
3727
- * Issues a bolt11 over a **receive-only** NWC connection while the DVM is
3728
- * awake serving the 402, and credits the ledger when a later request observes
3729
- * settlement. Two properties are load-bearing:
3730
- *
3731
- * - **It never holds a send credential.** `pay_invoice` on this connection is
3732
- * refused at construction, so a compromised DVM can mint invoices and
3733
- * nothing else. The drain/refund sender is a separate, budgeted
3734
- * connection by rule.
3735
- * - **Crediting is pull-based — there is no settlement watcher.** The caller's
3736
- * next request drives `lookup_invoice`, which is what makes this work on a
3737
- * suspend-to-zero fleet: a machine that is asleep has nothing to miss.
3738
- * Wallet downtime at that moment delays crediting; it never loses money,
3739
- * because the invoice→credit binding is a durable row.
3740
- *
3741
- * Reachability is **cached**, never probed per request: the funding menu is
3742
- * assembled on every quote and every 402, so a live NIP-47 round trip there
3743
- * would put a nostr relay in the latency path of every priced call.
3579
+ * Crediting is pull-based: later requests observe settlement against the durable invoice
3580
+ * binding, so sleeping hosts need no watcher. Reachability is cached and refreshed in the
3581
+ * background for funding menus.
3744
3582
  */
3745
3583
  declare class LightningReceive {
3746
3584
  private readonly source;
@@ -3753,36 +3591,21 @@ declare class LightningReceive {
3753
3591
  private constructor();
3754
3592
  private readonly railHealth;
3755
3593
  /**
3756
- * Validate the configured connection and build the receive leg, or return
3757
- * `undefined` when this DVM didn't configure one.
3758
- *
3759
- * **Throws on a credential that is wrong, degrades on one that is merely
3760
- * unreachable.** A wallet outage at boot must not stop a DVM whose other
3761
- * rails are fine — the menu simply omits `lightning` until a later probe
3762
- * succeeds. A connection that can spend, or one that can't state what it can
3763
- * do, is a different thing entirely: it is a standing money risk that no
3764
- * amount of retrying fixes, so it fails the boot loudly with the fix in the
3765
- * message.
3594
+ * Return undefined when unconfigured. Permission/URI failures refuse construction with a
3595
+ * corrective message; wallet transport failure constructs an unavailable receive leg so
3596
+ * other rails can still boot. Recovery must validate method scope before advertising
3597
+ * Lightning.
3766
3598
  */
3767
3599
  static create(config: LightningReceiveConfig): Promise<LightningReceive | undefined>;
3768
3600
  /**
3769
- * Whether `lightning` belongs on the funding menu right now.
3770
- *
3771
- * Reads the cached observation and never blocks; a stale one kicks off a
3772
- * background refresh and answers with what we last knew. Advertising a rail
3773
- * whose wallet is down would hand the caller an option that 402s on use —
3774
- * the §4 posture is to drop it and let the sale survive on the others.
3601
+ * Answer from cached wallet and optional rail-health observations without blocking. A stale
3602
+ * wallet observation starts a background refresh.
3775
3603
  */
3776
3604
  available(): boolean;
3777
3605
  /**
3778
- * Issue (or re-issue) the bolt11 funding `(creditId, fundId)`.
3779
- *
3780
- * The invoice is minted **for** the credit and amount named in the caller's
3781
- * signed body — that binding is the condition-3 commitment on this
3782
- * rail, and it is why no artifact hash rides the request: there is no
3783
- * caller-supplied artifact to hash. A re-poll returns the stored row rather
3784
- * than minting again; a second bolt11 for one `fund_id` would leave two
3785
- * payable invoices against a funding that can only be credited once.
3606
+ * Return the stored invoice on retry: two payable bolt11s for one fund ID could charge
3607
+ * twice while only one credits. Caller and amount are bound to the recorded credit/funding
3608
+ * pair, without a caller-supplied artifact hash.
3786
3609
  */
3787
3610
  issue(ledger: CreditLedgerLike, args: {
3788
3611
  creditId: string;
@@ -3794,24 +3617,9 @@ declare class LightningReceive {
3794
3617
  description?: string;
3795
3618
  }): Promise<CreditInvoiceRecord>;
3796
3619
  /**
3797
- * Ask the wallet whether one payment hash is paid, and when.
3798
- *
3799
- * The operator's reconcile verb runs this before it credits anything. A
3800
- * `blocked` row implies payment — {@link applyOne} returns above the block
3801
- * classification when the lookup says unpaid — but that is *this fleet's
3802
- * belief, recorded possibly weeks ago*, and the verb it gates mints balance
3803
- * against it. One round trip turns the belief into a fact and recovers the
3804
- * true settlement instant for `settled_at`, which a blocked row never got to
3805
- * write.
3806
- *
3807
- * Unlike {@link settlePending} this **throws**: there is no request whose
3808
- * latency it protects, and crediting on an unverifiable wallet is exactly
3809
- * what it exists to prevent. `NOT_FOUND` is the one exception, and it is not
3810
- * an outage — it is the wallet saying it has never seen this hash, the same
3811
- * reading {@link applyOne} and the caller-side reconcile in `src/lib/nwc.ts`
3812
- * take. It comes back as `known: false` because the operator's repair for it
3813
- * ("you are pointed at a different wallet than the one that minted this")
3814
- * is not the repair for an unpaid invoice, and certainly not for a retry.
3620
+ * Re-observe the wallet payment before an operator credits a blocked invoice and recover
3621
+ * its settlement instant. Unlike settlePending, lookup failures throw. NOT_FOUND returns
3622
+ * known:false, distinguishing the wrong wallet/unknown hash from an unpaid known invoice.
3815
3623
  */
3816
3624
  lookupSettlement(paymentHash: string): Promise<{
3817
3625
  settled: boolean;
@@ -3819,23 +3627,12 @@ declare class LightningReceive {
3819
3627
  known: boolean;
3820
3628
  }>;
3821
3629
  /**
3822
- * Consult the wallet about this caller's outstanding invoices and credit the
3823
- * ones that settled — the pull half of pull-based crediting.
3824
- *
3825
- * The pending rows are read locally first, so the common case (nothing
3826
- * outstanding) costs one indexed SELECT and no network at all. Bounded to
3827
- * {@link MAX_SETTLE_CHECKS} invoices on a short deadline, and **never throws
3828
- * into the request**: a wallet failure here means the caller's balance is
3829
- * merely not updated yet, which the ordinary `insufficient_credit` path
3830
- * already states honestly.
3630
+ * Read pending invoices locally, then check at most MAX_SETTLE_CHECKS on bounded wallet
3631
+ * deadlines. Log failures without throwing into the request.
3831
3632
  *
3832
- * **Each invoice gets its own failure boundary.** The sweep window is a few
3833
- * rows wide, so a row that fails on its own terms — a `fund_id` the caller
3834
- * reused on another rail, a credit someone else opened first — must not take
3835
- * the rest of the pass down with it: the next invoice in the window may be
3836
- * the paid one, and it would never be looked up. Only a transport failure
3837
- * ends the pass early, because there the wallet itself is gone and the
3838
- * remaining lookups would just spend the caller's latency confirming it.
3633
+ * An invoice-specific failure must not suppress payable siblings; wallet transport failure
3634
+ * ends the pass. Deterministic refusals retire that row as blocked for operator repair,
3635
+ * while transient failures remain pending.
3839
3636
  */
3840
3637
  settlePending(ledger: CreditLedgerLike, args: {
3841
3638
  callerPubkey: string;
@@ -3845,49 +3642,21 @@ declare class LightningReceive {
3845
3642
  enqueueCreditDeposit?: CreditDepositEnqueue;
3846
3643
  nowMs?: number;
3847
3644
  }): Promise<InvoiceSettlement[]>;
3848
- /**
3849
- * One invoice's settlement check. Returns the applied settlement, or
3850
- * `undefined` when nothing changed (still unpaid, or retired unpaid).
3851
- *
3852
- * Throws whatever the wallet or the ledger threw — classifying that is
3853
- * {@link retireOrLog}'s job, so this stays one invoice's happy path.
3854
- */
3855
3645
  private applyOne;
3856
3646
  /**
3857
- * Decide what one invoice's failure means, and retire the invoice when the
3858
- * answer is "this can never succeed".
3859
- *
3860
- * The split that matters is permanent-versus-transient, because it decides
3861
- * whether the row keeps a slot in the sweep window. A transient failure — the
3862
- * database blinked, the wallet answered oddly — leaves it `pending` and the
3863
- * caller's next request retries it. A **permanent** one means the ledger will
3864
- * refuse this invoice identically forever, so leaving it pending costs a
3865
- * `lookup_invoice` on every subsequent request and, at
3866
- * {@link MAX_SETTLE_CHECKS} of them, fills the window so a genuinely payable
3867
- * invoice behind them is never even looked up. Those get `blocked`, which
3868
- * drops them out of the sweep and hands the operator the payment hash.
3647
+ * Retire a deterministic uncreditable payment as blocked so it no longer occupies the
3648
+ * bounded sweep window. Transient failures stay pending for a later request; report the
3649
+ * payment hash for operator repair.
3869
3650
  */
3870
3651
  private retireOrLog;
3871
3652
  /**
3872
- * The reason this invoice can never be credited, or `undefined` if the
3873
- * failure was transient.
3874
- *
3875
- * Every code here is decided by state a retry cannot move — a row the ledger
3876
- * has already committed (a `credit_fundings` entry at this
3877
- * `(credit_id, fund_id)`, or a `credits` row whose owner, denomination or
3878
- * rail disagrees with the invoice), or the basis this module rebuilds
3879
- * identically from the invoice row on every pass. None of them is a race.
3880
- *
3881
- * `funding_replayed` is the one that needs a second read to classify.
3882
- * Usually it *is* benign — a concurrent check won the race and the money is
3883
- * credited either way — but the key is `(credit_id, fund_id)` and `fund_id`
3884
- * is **caller-chosen**: reuse it on cashu or x402 after this bolt11 was
3885
- * minted and the row that collided is a different payment entirely, so the
3886
- * sats this invoice received have nowhere to land.
3653
+ * Classify funding_replayed by reading the existing funding’s rail. A Lightning row can
3654
+ * represent a concurrent applied check; another rail at this caller-chosen key is a
3655
+ * different payment, leaving the invoice’s sats uncredited. A failed diagnostic read
3656
+ * remains transient, never a guessed permanent refusal.
3887
3657
  */
3888
3658
  private blockingReason;
3889
3659
  private withBackend;
3890
- /** Record activity without letting it promote an unvalidated connection. */
3891
3660
  private noteOperationOk;
3892
3661
  private notePermissionsOk;
3893
3662
  private notePermissionRefused;
@@ -3910,7 +3679,7 @@ interface OwnerDisplay {
3910
3679
  avatarUrl?: string | null;
3911
3680
  type: "builder" | "org";
3912
3681
  }
3913
- /** Optional builder identity surfaced on `/v1/info` (forward-compatible stub). */
3682
+ /** Builder identity advertised on /v1/info. */
3914
3683
  interface BuilderIdentity {
3915
3684
  id?: string;
3916
3685
  name?: string;
@@ -3935,7 +3704,6 @@ interface PlatformReporterOpts {
3935
3704
  /** Platform internal URL. Defaults to `DVMKIT_PLATFORM_URL` env. */
3936
3705
  url?: string;
3937
3706
  }
3938
- /** Running host handle returned by serve(). */
3939
3707
  interface DVMServeResult {
3940
3708
  url: string;
3941
3709
  close: () => Promise<void>;
@@ -3943,6 +3711,8 @@ interface DVMServeResult {
3943
3711
  paymentModes: PaymentMode[];
3944
3712
  }
3945
3713
  interface DVMHostOpts {
3714
+ /** Dedicated hosting-management authority for each mounted DVM. Requires durable Postgres. */
3715
+ hostingControl?: HostingControlConfig;
3946
3716
  /**
3947
3717
  * Postgres connection string. Defaults to `DATABASE_URL` env.
3948
3718
  * Required at runtime. Boot fails when missing unless `jobStore`
@@ -3957,7 +3727,6 @@ interface DVMHostOpts {
3957
3727
  * to ambient process variables.
3958
3728
  */
3959
3729
  env?: Record<string, string>;
3960
- /** Builder identity for `/v1/info` (forward-compatible). */
3961
3730
  builder?: BuilderIdentity;
3962
3731
  /** Owner display identity for `/v1/info#owner`. Falls back to env vars. */
3963
3732
  owner?: OwnerDisplay;
@@ -3985,7 +3754,6 @@ interface DVMHostOpts {
3985
3754
  pool?: Pool;
3986
3755
  /** Cashu mints accepted. Defaults to env `DVMKIT_CASHU_MINTS`. */
3987
3756
  mints?: string[];
3988
- /** Cashu receive mode override. */
3989
3757
  cashuMode?: CashuMode;
3990
3758
  /** MPP handle override. Defaults to env-resolved via `createMppFromOpts`. */
3991
3759
  mpp?: MppxServer;
@@ -4008,9 +3776,7 @@ interface DVMHostOpts {
4008
3776
  onPaidJobCompleted?: (event: PaidJobCompletion) => void | Promise<void>;
4009
3777
  /** When true, payment is skipped only when no payment rail is configured. */
4010
3778
  devMode?: boolean;
4011
- /** Consumed-credential store override (test seam). */
4012
3779
  consumedCredentialStore?: ConsumedCredentialStore;
4013
- /** Mint-health tracker override (test seam). */
4014
3780
  mintHealthTracker?: MintHealthTracker;
4015
3781
  /** Operator-alert boundary for failed terminal-job retention passes. */
4016
3782
  onJobRetentionSweepFailed?: JobManagerOpts["onJobRetentionSweepFailed"];
@@ -4023,12 +3789,10 @@ interface DVMHostOpts {
4023
3789
  */
4024
3790
  wrapRouteClientCompatibility?: (sdkGate: ClientCompatibilityGate) => ClientCompatibilityGate;
4025
3791
  }
4026
- /** Per-mount options. Currently only `prefix` is supported. */
4027
3792
  interface MountOpts {
4028
3793
  /** Path prefix for this DVM's protocol routes (e.g. `/delete-feed`). */
4029
3794
  prefix?: string;
4030
3795
  }
4031
- /** Live DVM host. Single wiring locus for the SDK. */
4032
3796
  interface DVMHost {
4033
3797
  /**
4034
3798
  * Underlying Hono app for custom non-protocol routes that belong to the
@@ -4057,7 +3821,6 @@ interface DVMHost {
4057
3821
  * a single mount with no prefix attaches at root.
4058
3822
  */
4059
3823
  mount<S, I extends ZodLike | undefined>(descriptor: DVMDescriptor<S, I>, opts?: MountOpts): void;
4060
- /** Start listening. Returns the live server handle. */
4061
3824
  serve(opts?: {
4062
3825
  port?: number;
4063
3826
  }): Promise<DVMServeResult>;
@@ -4101,22 +3864,10 @@ interface TempoObserverHealth {
4101
3864
  /** Prime the cached signal at boot. */
4102
3865
  refresh?(): Promise<void>;
4103
3866
  /**
4104
- * Register a mount's `tempo/session` **capability** so the poll can carry it
4105
- * back to the platform.
4106
- *
4107
- * The platform's `dvms.tempo_session_advertised_at` — the only filter on the
4108
- * close observer's payee-fallback rung 2 — was written once per container
4109
- * deploy and never refreshed, so a builder flipping sessions on with
4110
- * `dvmctl env --set` stayed invisible to the fallback indefinitely. That is a
4111
- * `no_route` on the first close of that DVM's first channel, which is exactly
4112
- * the race the rung exists to cover.
4113
- *
4114
- * The reader must answer from **configuration**, never from
4115
- * {@link TempoObserverHealth.available} — a fail-closed gate blip must not
4116
- * de-stamp the DVM, which is the failure through a new door.
4117
- *
4118
- * Returns a disposer the mount calls on shutdown, so a torn-down capability
4119
- * stops voting in the OR below.
3867
+ * Report the OR of mounted session capabilities to keep the platform's
3868
+ * observer watch signal current. Readers must use configuration, not current
3869
+ * availability: an observer outage must not erase the capability it watches.
3870
+ * The returned disposer removes a mount's contribution on shutdown.
4120
3871
  */
4121
3872
  declareSessionCapability?(read: () => boolean): () => void;
4122
3873
  }
@@ -4164,7 +3915,6 @@ interface TempoSettlementReadinessStateStore {
4164
3915
  clearFailureIfRefilled(version: string, balanceMicro: bigint, lowBalanceMicro: bigint): Promise<boolean>;
4165
3916
  clearFailureAfterSuccessfulTransaction(version: string): Promise<boolean>;
4166
3917
  }
4167
- /** Construction inputs for {@link TempoSettlementReadiness}. */
4168
3918
  interface TempoSettlementReadinessOptions {
4169
3919
  address: `0x${string}`;
4170
3920
  network: string;
@@ -4211,7 +3961,6 @@ declare class TempoSettlementReadiness {
4211
3961
  start(): void;
4212
3962
  /** Stop the cadence without affecting any in-flight reading. */
4213
3963
  stop(): void;
4214
- /** Read and report the configured fee-token balance now. */
4215
3964
  checkBalance(opts?: {
4216
3965
  successfulTransaction?: boolean;
4217
3966
  recoveryVersion?: string;
@@ -4234,24 +3983,11 @@ declare class TempoSettlementReadiness {
4234
3983
  private notify;
4235
3984
  }
4236
3985
 
4237
- /**
4238
- * Options for the revenue reporter readiness assertion.
4239
- *
4240
- * The check branches on `platformUrl` presence — that's the unambiguous
4241
- * "platform-hosted" signal. `failFast` stays on the opts as a general SDK
4242
- * strict-mode flag but is not consulted by this assertion.
4243
- */
4244
3986
  interface RevenueBootCheckOpts {
4245
3987
  /**
4246
- * General SDK strict-mode flag, sourced from `DVMKIT_FAIL_FAST` at the host
4247
- * boundary. Reserved for future warning-vs-fatal SDK checks; the
4248
- * reporter check itself ignores it, hence optional.
3988
+ * Reporter readiness ignores this host strict-mode flag.
4249
3989
  */
4250
3990
  failFast?: boolean;
4251
- /**
4252
- * The SDK's canonical "this is a dev/test run" signal. Exempts the boot from
4253
- * the platform-hosted wiring requirement — see below.
4254
- */
4255
3991
  devMode?: boolean;
4256
3992
  platformToken: string | undefined;
4257
3993
  platformUrl: string | undefined;
@@ -4355,11 +4091,11 @@ interface SDKServerOpts {
4355
4091
  canonicalDvmId?: string;
4356
4092
  /** Postgres pool for builder admin state and wallet accumulator persistence. */
4357
4093
  db?: Pool;
4094
+ /** Enables authenticated, durable hosting admission and bounded drain. Requires Postgres and dvmId. */
4095
+ hostingControl?: HostingControlConfig;
4358
4096
  /**
4359
- * General SDK strict-mode flag, sourced from `DVMKIT_FAIL_FAST` at
4360
- * the host boundary. Reserved for future warning-vs-fatal SDK checks; the
4361
- * revenue-reporter boot check is gated on platform context, not on this
4362
- * flag.
4097
+ * Host strict-mode flag. Reporter readiness follows hosted context regardless
4098
+ * of this value.
4363
4099
  */
4364
4100
  failFast?: boolean;
4365
4101
  /** Agent-wallet: per-DVM identifier — drives the monitor advisory lock + replay key. */
@@ -4486,12 +4222,6 @@ interface SDKServerOpts {
4486
4222
  */
4487
4223
  creditExpirySweep?: CreditExpirySweepOpts;
4488
4224
  }
4489
- /**
4490
- * Builds a Hono sub-app for one DVM descriptor, wires payment verification,
4491
- * auto-wires `RevenueReporter` when platform env + db + dvmId are present, and
4492
- * runs the platform-hosted partial-wiring assertion — gated on
4493
- * `DVMKIT_PLATFORM_URL` presence, independent of `DVMKIT_FAIL_FAST`.
4494
- */
4495
4225
  declare function createDVMServer<State, InputSchema extends ZodLike | undefined>(descriptor: DVMDescriptor<State, InputSchema>, opts: SDKServerOpts): Promise<{
4496
4226
  app: Hono<AppEnv>;
4497
4227
  authAudience?: SignedRequestAudience;
@@ -4533,13 +4263,8 @@ interface AppEnv {
4533
4263
  declare function unknownRouteNotFound(c: Context): Response;
4534
4264
 
4535
4265
  /**
4536
- * The public prepaid-credit terms a DVM advertises before a caller identifies
4537
- * itself. Snake_case: this is the wire shape.
4538
- *
4539
- * This type deliberately excludes the per-caller echo. `/v1/info` is public
4540
- * and cacheable, so its type must make a caller credit ID or balance
4541
- * unrepresentable rather than relying on the current handler not to ask for
4542
- * one.
4266
+ * Public, cacheable prepaid terms exclude caller IDs and balances. toCreditTerms explicitly
4267
+ * whitelists this shape so later caller-specific menu fields cannot leak into /v1/info.
4543
4268
  */
4544
4269
  interface CreditTerms {
4545
4270
  /** Smallest funding accepted, in 1e-6 units of `currency`. */
@@ -4552,7 +4277,10 @@ interface CreditTerms {
4552
4277
  currency: string;
4553
4278
  /** Rails a top-up may be funded over. */
4554
4279
  funding: FundingMethod[];
4555
- /** MPP instruments offered or temporarily withheld for credit funding. */
4280
+ /**
4281
+ * Tempo methods are actionable. withheld names configured but temporarily unavailable
4282
+ * instruments, preserving capability discovery without advertising them for funding.
4283
+ */
4556
4284
  tempo?: {
4557
4285
  methods: {
4558
4286
  method: string;
@@ -4564,63 +4292,32 @@ interface CreditTerms {
4564
4292
  reason: string;
4565
4293
  }[];
4566
4294
  };
4567
- /** x402 flavours accepted for credit funding. */
4295
+ /**
4296
+ * Present with offered x402 funding. Reusable batch settlement is enabled by default; exact
4297
+ * requires explicit acceptance of its manual refund obligation.
4298
+ */
4568
4299
  x402?: {
4569
4300
  schemes: {
4570
4301
  scheme: string;
4571
4302
  network: string;
4572
4303
  }[];
4573
4304
  };
4574
- /** Smallest Lightning funding accepted, in 1e-6 units of `currency`. */
4305
+ /**
4306
+ * Configured Lightning receive floor in micro-units of currency, including the advertised
4307
+ * FX margin. Issuance checks the raw sats floor at current rates; arbitrary drift can still
4308
+ * make the advertised amount insufficient.
4309
+ */
4575
4310
  lightning_min_micro?: number;
4576
4311
  }
4577
4312
  /**
4578
- * The **funding menu** a DVM advertises on `/v1/quote` and in every 402;
4579
- * this is the snake_case wire shape.
4580
- *
4581
- * `min_micro` / `max_micro` / `ttl_ms` are the DVM's sizing terms — `max_micro`
4582
- * binds the **residual balance**, not a funding amount, so a job priced above
4583
- * it still clears as fund-and-immediately-draw. `funding` is the rail list a
4584
- * top-up may arrive on — a {@link FundingMethod}, not a `PaymentMethod`, since
4585
- * `lightning` funds a credit without ever being an attached-proof wire method.
4586
- * A rail whose backing wallet is unreachable drops out and the sale survives
4587
- * on the others.
4313
+ * Funding options and sizing in the wire denomination. max_micro limits residual balance,
4314
+ * not a job’s price; fund-and-draw can spend a larger payment immediately. Lightning funds
4315
+ * credit but is not an attached-proof payment method.
4588
4316
  *
4589
- * The `credit_id` / `balance_micro` / `remaining_micro` / `expiry_ms` echo
4590
- * appears only for an authenticated caller who already holds a live credit —
4591
- * so one round trip answers "what does this cost, and what do I have left?"
4592
- * through the signed credit endpoint.
4317
+ * An authenticated caller’s live credit may add an echo with funded and spendable balance;
4318
+ * pending holds are included only in the funded figure.
4593
4319
  */
4594
4320
  interface CreditMenu extends CreditTerms {
4595
- /**
4596
- * MPP instruments accepted for this credit, reusable sessions first when
4597
- * available.
4598
- *
4599
- * `withheld` names an instrument this DVM is configured for and is not
4600
- * offering at this instant, with the reason. Two audiences read
4601
- * it. An agent gets to relay *why* `tempo/session` vanished instead of
4602
- * inferring the DVM never had it. And the platform's deploy probe reads
4603
- * capability from `methods ∪ withheld`, so a deploy landing during an
4604
- * observer blip no longer stamps `tempo_session_advertised_at` NULL and
4605
- * drops the DVM out of the close observer's payee fallback permanently.
4606
- * `methods` stays the list a caller acts on — never widen it to include a
4607
- * withheld instrument.
4608
- */
4609
- /**
4610
- * Which x402 flavours a top-up may arrive on, and the chain each rides
4611
- * Present exactly when `funding` lists `x402`. Reusable
4612
- * `batch-settlement` is admitted by default; one-payment `exact` appears
4613
- * only when the builder explicitly accepts its manual refund obligation.
4614
- */
4615
- /**
4616
- * Smallest funding the `lightning` rail accepts, in 1e-6 units of
4617
- * `currency`. Present only when `funding` lists `lightning`. This is the
4618
- * deployment's sats-physical receive floor rendered into fiat
4619
- * with a ×{@link LIGHTNING_FLOOR_FX_MARGIN} margin absorbing rate drift
4620
- * between menu fetch and funding — issuance enforces the *raw* floor at
4621
- * request-time rates, so funding exactly this figure always clears. Rails
4622
- * without an entry (cashu) have no floor beyond `min_micro`.
4623
- */
4624
4321
  /** The caller's credit this echo describes. Present only with the echo. */
4625
4322
  credit_id?: string;
4626
4323
  /** Funded balance, pending holds NOT subtracted. */
@@ -4630,7 +4327,6 @@ interface CreditMenu extends CreditTerms {
4630
4327
  /** Absolute expiry of the echoed credit, ms since epoch. */
4631
4328
  expiry_ms?: number;
4632
4329
  }
4633
- /** Everything {@link buildCreditMenu} needs, assembled per request. */
4634
4330
  interface BuildCreditMenuArgs {
4635
4331
  /**
4636
4332
  * Which runtime is answering. `"isolate"` is refused unconditionally — see
@@ -4640,13 +4336,8 @@ interface BuildCreditMenuArgs {
4640
4336
  /** The DVM's resolved `credit` block; `undefined` means it didn't opt in. */
4641
4337
  config: ResolvedCreditConfig | undefined;
4642
4338
  /**
4643
- * Currency the menu — and the credit it funds — denominates in: the DVM's
4644
- * declared `DVMConfig.currency`, which every call site reads off the single
4645
- * `DVMServer.creditCurrency()`. Deliberately *not* the currency of
4646
- * the response this menu rides on: a quote priced elsewhere is refused before
4647
- * it reaches here, so the two agree, and sourcing it from the response is
4648
- * what left `POST /v1/credit` — which has no response to read — funding in
4649
- * hardwired USD at a DVM whose jobs draw in something else.
4339
+ * Use the DVM’s declared denomination, including /v1/credit where no quote response supplies
4340
+ * it. Quote validation refuses a different denomination before menu construction.
4650
4341
  */
4651
4342
  currency: string;
4652
4343
  /** Rails this DVM settles over — the menu's funding options. */
@@ -4662,31 +4353,19 @@ interface BuildCreditMenuArgs {
4662
4353
  intent: "charge" | "session";
4663
4354
  reason: string;
4664
4355
  }[];
4665
- /**
4666
- * x402 flavours this DVM can actually accept a top-up on — one
4667
- * server read, so what the sub-block advertises is what `/v1/credit` will
4668
- * answer a 402 with.
4669
- */
4670
4356
  x402Schemes?: {
4671
4357
  scheme: string;
4672
4358
  network: string;
4673
4359
  }[];
4674
4360
  /**
4675
- * The deployment's Lightning receive floor in sats, when `lightning` is on
4676
- * the menu — rendered into `lightning_min_micro`. An fx failure during that
4677
- * rendering drops `lightning` from `funding` rather than suppressing the
4678
- * menu: a rail whose minimum we can't state honestly is a rail we must not
4679
- * advertise, but the other rails' sale survives.
4361
+ * Configured raw receive floor in sats, rendered with an FX margin for the menu. Failure
4362
+ * omits Lightning while allowing the rest of the menu; issuance checks the raw floor at
4363
+ * current request-time rates.
4680
4364
  */
4681
4365
  lightningFundingMinSats?: number;
4682
4366
  /**
4683
- * Whether this DVM has at least one accepted Cashu mint configured
4684
- * Without one, no Bitcoin funding rail may be advertised — see
4685
- * the filter in {@link buildCreditMenu}.
4686
- *
4687
- * Read off the **configured** mint list, never the health-filtered
4688
- * advertised one: a mint blip must not make a funding rail appear and
4689
- * disappear between quotes.
4367
+ * Read the configured accepted mint list, not its health-filtered advertisement. Non-channel
4368
+ * Bitcoin refunds need a mint, but configuration alone does not establish refund solvency.
4690
4369
  */
4691
4370
  hasAcceptedMint?: boolean;
4692
4371
  fxFetcher: FxFetcher;
@@ -4699,50 +4378,18 @@ interface BuildCreditMenuArgs {
4699
4378
  callerPubkey?: string;
4700
4379
  }
4701
4380
  /**
4702
- * Assemble the funding menu, or return `undefined` when this DVM must not
4703
- * advertise credit. **The refusal ladder is the feature**; each rung exists
4704
- * because advertising anyway would misadvertise:
4705
- *
4706
- * 1. **Isolate runtime** (the isolate-runtime rule) — checked first and unconditionally,
4707
- * before config is even read. Isolate DVMs have no Postgres of their own;
4708
- * their only DVM-side persistence is the last-write-wins callback KV, which
4709
- * the durable-ledger requirement prohibits for credit state. Until isolate
4710
- * runtimes have durable credit storage, they run implicit N=1 only and their quote never offers
4711
- * credit so nothing is misadvertised.
4712
- * 2. **Not opted in** — no `credit` block on `configureDVM`.
4713
- * 3. **No descriptor auth** — a credit belongs to a verified secp256k1 pubkey.
4714
- * Without auth the ledger's funder identity degrades to the requester id or
4715
- * `"anonymous"` (see `resolveLedgerContext`), which would pool every
4716
- * anonymous caller's money into one balance. Advertising a per-caller
4717
- * balance on such a DVM would be a lie at best and a disclosure at worst.
4718
- * 4. **Non-durable ledger outside devMode** — a `MemoryCreditLedger` is
4719
- * per-process, so a caller funding on machine A and drawing on machine B
4720
- * gets `credit_not_found`. Advertise only what survives the fleet.
4721
- * 5. **Bounds not expressible in `currency`** — an fx outage, or a currency the
4722
- * snapshot doesn't carry. Omit rather than quote a number we can't state.
4723
- *
4724
- * The balance echo is added only when a verified `callerPubkey` holds a live,
4725
- * same-currency credit.
4381
+ * Return no menu for static ineligibility or unresolvable denomination bounds. Isolates
4382
+ * currently lack durable credit storage; anonymous balances must not be advertised.
4726
4383
  *
4727
- * Rungs 1–4 live in {@link creditMenuConfigured}, which the capability refresh
4728
- * reads too.
4384
+ * Select the caller echo only from live, same-currency credits with spendable value.
4729
4385
  */
4730
4386
  declare function buildCreditMenu(args: BuildCreditMenuArgs): Promise<CreditMenu | undefined>;
4731
4387
  /**
4732
- * The one credit a caller's quote echoes, from the several they may hold —
4733
- * every implicit N=1 payment mints its own `imp:<rail>:<paymentId>` credit, so
4734
- * this list grows with each paid job.
4388
+ * Choose the largest live, active, same-currency spendable balance; newest creation breaks
4389
+ * a tie. Released implicit payments can hold reclaimable value and are eligible too.
4735
4390
  *
4736
- * Live, same-currency credits with something left in them; largest spendable
4737
- * balance wins, newest breaks a tie. That is the credit a caller would in fact
4738
- * draw against next. A failed job's released hold leaves a positive implicit
4739
- * balance, which is real caller money (the credit lifecycle contract, no debit on failure) and is
4740
- * echoed like any other.
4741
- *
4742
- * **Requires a verified pubkey.** Never call this with a requester id or
4743
- * `"anonymous"`: on an auth-less DVM the ledger pools every anonymous caller
4744
- * under one `caller_pubkey`, so echoing it would show one caller another's
4745
- * balance.
4391
+ * The caller supplies a verified pubkey. Anonymous/missing identity returns no credit; the
4392
+ * ledger’s anonymous pool must not be exposed to an individual caller.
4746
4393
  */
4747
4394
  declare function selectPrimaryCredit(args: {
4748
4395
  ledger: CreditLedgerLike;
@@ -4750,21 +4397,16 @@ declare function selectPrimaryCredit(args: {
4750
4397
  currency: string;
4751
4398
  nowMs?: number;
4752
4399
  }): Promise<CreditSnapshot | undefined>;
4753
- /** Narrow a ledger snapshot to the read-only shape a quote handler receives. */
4754
4400
  declare function toCreditView(snapshot: CreditSnapshot): CreditView;
4755
4401
  /**
4756
- * Attach a menu to a response body when there is one. Keeps the "omit the key
4757
- * entirely rather than emit `credit: null`" rule in one place — every consumer
4758
- * checks presence, and the isolate tier depends on the key never appearing.
4402
+ * Omit the credit key entirely when there is no menu; consumers use presence to determine
4403
+ * whether credit is offered.
4759
4404
  */
4760
4405
  declare function attachCreditMenu(body: Record<string, unknown>, menu: CreditMenu | undefined): Record<string, unknown>;
4761
4406
  /**
4762
- * Project a quote/402 menu onto the public, cache-safe `/v1/info` terms.
4763
- *
4764
- * This is an explicit whitelist rather than object rest syntax: a later
4765
- * caller-specific field added to {@link CreditMenu} cannot cross this boundary
4766
- * until someone deliberately adds it to {@link CreditTerms} and this copy.
4407
+ * Explicitly whitelist public /v1/info terms. A future caller-specific menu field cannot
4408
+ * cross this cacheable boundary merely by being added to CreditMenu.
4767
4409
  */
4768
4410
  declare function toCreditTerms(menu: CreditMenu): CreditTerms;
4769
4411
 
4770
- export { isTerminal as $, type AccumulatorPool as A, buildPaymentErrorResponse as B, type ConsumedCredentialStore as C, clearAccumulatorForDvm as D, createDVMServer as E, type FiatDenomination as F, creditDepositPayload as G, derivedFundCreditId as H, type IncomingPaymentOpts as I, JobCancelledError as J, devModeSkipsPaymentVerification as K, fromJobRecord as L, MintHealthTracker as M, fundedMicroFor as N, hasPaymentProof as O, PAYMENT_PROOF_KEYS as P, hashLockKey as Q, type ReporterBannerOpts as R, type SDKServerOpts as S, type TempoChannelReport as T, type UpfrontPaymentOpts as U, type VerifiedIncomingPayment as V, implicitCreditId as W, type X402BatchChannelObservation as X, initWalletAccumulatorTable as Y, insertAccumulatorRows as Z, isDerivedCreditId as _, type AccumulatorQuerier as a, type X402ExactSettlementAttempt as a$, isYieldMessage as a0, issueUpfrontChallenges as a1, msatsToFiatMicro as a2, paymentErrorBody as a3, pinAskFiat as a4, priceFiatMicro as a5, processIncomingPayment as a6, providerMessage as a7, repairX402ExactSettlementEffect as a8, resolveFxSnapshot as a9, JobManager as aA, type JobManagerOpts as aB, type LightningReceiveConfig as aC, MIN_INVOICE_TTL_SECONDS as aD, MemoryConsumedCredentialStore as aE, type MemoryConsumedCredentialStoreOpts as aF, MemoryProcessedPaymentStore as aG, MemoryX402ExactSettlementStore as aH, type MountOpts as aI, type OwnerDisplay as aJ, type PaidJobCompletion as aK, type PaymentMode as aL, type PlatformReporterOpts as aM, PostgresProcessedPaymentStore as aN, PostgresX402ExactSettlementStore as aO, type PriceFiat as aP, type ProcessedPaymentQuerier as aQ, type ProcessedPaymentRail as aR, type ProcessedPaymentRecord as aS, ProcessedPaymentReplayError as aT, type ProcessedPaymentStore as aU, type X402BatchAcceptance as aV, type X402BatchFunding as aW, type X402BatchRefusal as aX, type X402BatchSettlementServer as aY, type X402ExactAcceptance as aZ, X402ExactIntentConflictError as a_, resolvePriceFiat as aa, revenueReporterBannerState as ab, toCreditTerms as ac, toJobRecord as ad, unknownRouteNotFound as ae, verifyIncomingPayment as af, verifyTempoSessionManagementCredential as ag, verifyUpfrontPayment as ah, x402RequiredUsdcMicro as ai, x402SettledShare as aj, type CreditMenu as ak, ReceiptIssuer as al, LightningReceive as am, TempoSettlementReadiness as an, type DVMHostOpts as ao, type DVMServeResult as ap, type BuildCreditMenuArgs as aq, type BuilderIdentity as ar, CREDIT_ENVELOPE_KEYS as as, type CreateX402BatchSettlementServerOpts as at, type CreditEnvelope as au, CreditEnvelopeError as av, type CreditFundCommitment as aw, type CreditTerms as ax, DEFAULT_INVOICE_TTL_SECONDS as ay, type DVMHost as az, type AppEnv as b, type X402ExactSettlementChainEvidence as b0, type X402ExactSettlementEffect as b1, X402ExactSettlementEvidenceMissingError as b2, type X402ExactSettlementEvidenceReader as b3, type X402ExactSettlementIntent as b4, X402ExactSettlementNotReadyError as b5, X402ExactSettlementServer as b6, type X402ExactSettlementServerOpts as b7, type X402ExactSettlementStatus as b8, type X402ExactSettlementStore as b9, type X402SettlementChainEvidence as ba, type X402SettlementEvidenceReader as bb, X402SettlementSubmissionError as bc, X402_BATCH_AUTO_SETTLEMENT as bd, X402_BATCH_MIN_WITHDRAW_DELAY_SECONDS as be, X402_BATCH_SETTLEMENT_NETWORK as bf, attachCreditMenu as bg, buildCreditMenu as bh, createDVMHost as bi, createX402BatchSettlementServer as bj, creditEnvelopeIgnoreFields as bk, drawSettlementRef as bl, extractCreditEnvelope as bm, fundingCommitment as bn, selectPrimaryCredit as bo, stripCreditEnvelope as bp, toCreditView as bq, type CreditFundingReport as c, type FiatDenominationFailure as d, type FundOnlyRequest as e, type PaymentErrorCode as f, type PaymentErrorDetail as g, type PaymentInfo as h, type ResolvedFx as i, type RevenueBootCheckOpts as j, type ServerJob as k, type ShortPayForfeit as l, type TempoObserverHealth as m, TempoSessionChannelMismatchError as n, type VerifyIncomingSnapshot as o, X402FacilitatorHealth as p, type X402SettlementEvidenceOutcome as q, type X402SettlementRepair as r, type X402SettlementRepairRefusal as s, type X402SettlementRepaired as t, type X402WedgedSettlement as u, type X402WedgedSettlementPage as v, X402_BATCH_SETTLEMENT_MAINNET_NETWORK as w, abortJob as x, applyPaymentInfoToJob as y, assertRevenueReporterReady as z };
4412
+ export { isTerminal as $, type AccumulatorPool as A, buildPaymentErrorResponse as B, type ConsumedCredentialStore as C, clearAccumulatorForDvm as D, createDVMServer as E, type FiatDenomination as F, creditDepositPayload as G, derivedFundCreditId as H, type IncomingPaymentOpts as I, JobCancelledError as J, devModeSkipsPaymentVerification as K, fromJobRecord as L, MintHealthTracker as M, fundedMicroFor as N, hasPaymentProof as O, PAYMENT_PROOF_KEYS as P, hashLockKey as Q, type ReporterBannerOpts as R, type SDKServerOpts as S, type TempoChannelReport as T, type UpfrontPaymentOpts as U, type VerifiedIncomingPayment as V, implicitCreditId as W, type X402BatchChannelObservation as X, initWalletAccumulatorTable as Y, insertAccumulatorRows as Z, isDerivedCreditId as _, type AccumulatorQuerier as a, type X402BatchSettlementServer as a$, isYieldMessage as a0, issueUpfrontChallenges as a1, msatsToFiatMicro as a2, paymentErrorBody as a3, pinAskFiat as a4, priceFiatMicro as a5, processIncomingPayment as a6, providerMessage as a7, repairX402ExactSettlementEffect as a8, resolveFxSnapshot as a9, type HostingControlCommand as aA, type HostingControlConfig as aB, type HostingControlStatus as aC, JobManager as aD, type JobManagerOpts as aE, type LightningReceiveConfig as aF, MIN_INVOICE_TTL_SECONDS as aG, MemoryConsumedCredentialStore as aH, type MemoryConsumedCredentialStoreOpts as aI, MemoryProcessedPaymentStore as aJ, MemoryX402ExactSettlementStore as aK, type MountOpts as aL, type OwnerDisplay as aM, type PaidJobCompletion as aN, type PaymentMode as aO, type PlatformReporterOpts as aP, PostgresProcessedPaymentStore as aQ, PostgresX402ExactSettlementStore as aR, type PriceFiat as aS, type ProcessedPaymentQuerier as aT, type ProcessedPaymentRail as aU, type ProcessedPaymentRecord as aV, ProcessedPaymentReplayError as aW, type ProcessedPaymentStore as aX, type X402BatchAcceptance as aY, type X402BatchFunding as aZ, type X402BatchRefusal as a_, resolvePriceFiat as aa, revenueReporterBannerState as ab, toCreditTerms as ac, toJobRecord as ad, unknownRouteNotFound as ae, verifyIncomingPayment as af, verifyTempoSessionManagementCredential as ag, verifyUpfrontPayment as ah, x402RequiredUsdcMicro as ai, x402SettledShare as aj, type CreditMenu as ak, ReceiptIssuer as al, LightningReceive as am, TempoSettlementReadiness as an, type DVMHostOpts as ao, type DVMServeResult as ap, type BuildCreditMenuArgs as aq, type BuilderIdentity as ar, CREDIT_ENVELOPE_KEYS as as, type CreateX402BatchSettlementServerOpts as at, type CreditEnvelope as au, CreditEnvelopeError as av, type CreditFundCommitment as aw, type CreditTerms as ax, DEFAULT_INVOICE_TTL_SECONDS as ay, type DVMHost as az, type AppEnv as b, type X402ExactAcceptance as b0, X402ExactIntentConflictError as b1, type X402ExactSettlementAttempt as b2, type X402ExactSettlementChainEvidence as b3, type X402ExactSettlementEffect as b4, X402ExactSettlementEvidenceMissingError as b5, type X402ExactSettlementEvidenceReader as b6, type X402ExactSettlementIntent as b7, X402ExactSettlementNotReadyError as b8, X402ExactSettlementServer as b9, type X402ExactSettlementServerOpts as ba, type X402ExactSettlementStatus as bb, type X402ExactSettlementStore as bc, type X402SettlementChainEvidence as bd, type X402SettlementEvidenceReader as be, X402SettlementSubmissionError as bf, X402_BATCH_AUTO_SETTLEMENT as bg, X402_BATCH_MIN_WITHDRAW_DELAY_SECONDS as bh, X402_BATCH_SETTLEMENT_NETWORK as bi, attachCreditMenu as bj, buildCreditMenu as bk, createDVMHost as bl, createX402BatchSettlementServer as bm, creditEnvelopeIgnoreFields as bn, drawSettlementRef as bo, extractCreditEnvelope as bp, fundingCommitment as bq, selectPrimaryCredit as br, signHostingControl as bs, stripCreditEnvelope as bt, toCreditView as bu, type CreditFundingReport as c, type FiatDenominationFailure as d, type FundOnlyRequest as e, type PaymentErrorCode as f, type PaymentErrorDetail as g, type PaymentInfo as h, type ResolvedFx as i, type RevenueBootCheckOpts as j, type ServerJob as k, type ShortPayForfeit as l, type TempoObserverHealth as m, TempoSessionChannelMismatchError as n, type VerifyIncomingSnapshot as o, X402FacilitatorHealth as p, type X402SettlementEvidenceOutcome as q, type X402SettlementRepair as r, type X402SettlementRepairRefusal as s, type X402SettlementRepaired as t, type X402WedgedSettlement as u, type X402WedgedSettlementPage as v, X402_BATCH_SETTLEMENT_MAINNET_NETWORK as w, abortJob as x, applyPaymentInfoToJob as y, assertRevenueReporterReady as z };