@dvmkit/sdk 0.7.0-rc.7 → 0.7.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 (45) hide show
  1. package/README.md +6 -2
  2. package/dist/{chunk-YK54BJ2L.js → chunk-2DE32RAW.js} +1 -1
  3. package/dist/{chunk-NUPEAWRM.js → chunk-2GTLF74N.js} +1 -1
  4. package/dist/{chunk-MYJOV4R4.js → chunk-2HAFZ5GC.js} +1 -1
  5. package/dist/{chunk-LQQ6H4UB.js → chunk-5CSR33B5.js} +1 -1
  6. package/dist/{chunk-FXDQMJQ2.js → chunk-5PLQOC4B.js} +29 -3
  7. package/dist/{chunk-QTH7CIA3.js → chunk-5TIFEMHJ.js} +83 -1
  8. package/dist/{chunk-JUEEUV5X.js → chunk-6JZDFYQL.js} +15 -4
  9. package/dist/{chunk-BDHJVTWA.js → chunk-7RZEJJTN.js} +1 -1
  10. package/dist/{chunk-XEOTTFLH.js → chunk-FYETJDBB.js} +1 -1
  11. package/dist/{chunk-HGMS3LR7.js → chunk-G7IXOVKV.js} +27 -21
  12. package/dist/{chunk-GDCIHJAR.js → chunk-HU6ZMQDN.js} +1 -1
  13. package/dist/{chunk-WP7UX6RF.js → chunk-IOKEKMIU.js} +2 -2
  14. package/dist/{chunk-6RYCZLCK.js → chunk-QM2OS3NJ.js} +1 -1
  15. package/dist/{chunk-KYCLHWKO.js → chunk-QN3CQOE2.js} +1 -1
  16. package/dist/{chunk-SX4WCPW7.js → chunk-RGSWVNQG.js} +1 -1
  17. package/dist/{chunk-HG2CZPRJ.js → chunk-RJFBBEWQ.js} +1 -1
  18. package/dist/{chunk-BIZR5ORK.js → chunk-WGK5KZ6S.js} +2 -2
  19. package/dist/{chunk-FOJKZ4E7.js → chunk-YE53E4BT.js} +1 -1
  20. package/dist/{chunk-3VFEX2Y3.js → chunk-YNHXOONR.js} +1 -1
  21. package/dist/{chunk-X5RY2G3C.js → chunk-YS6PWVCZ.js} +1 -1
  22. package/dist/{chunk-BQP3LU2O.js → chunk-ZLWPEIE2.js} +1 -1
  23. package/dist/{credit-ledger-SW4BGMNH.js → credit-ledger-F2LWQU6N.js} +3 -3
  24. package/dist/{credit-menu-Bm8opjYy.d.ts → credit-menu-CUJdCfpt.d.ts} +2 -0
  25. package/dist/index.js +4 -4
  26. package/dist/internal/caller.d.ts +64 -1
  27. package/dist/internal/caller.js +14 -6
  28. package/dist/internal/index.js +1 -1
  29. package/dist/internal/server.d.ts +2 -2
  30. package/dist/internal/server.js +19 -19
  31. package/dist/{memory-credit-ledger-E4C3VQE4.js → memory-credit-ledger-XOOWJTBZ.js} +4 -4
  32. package/dist/{mpp-setup-BYKGEYFA.js → mpp-setup-KGX6PLAF.js} +2 -2
  33. package/dist/{payout-reporter-3UVWPGMO.js → payout-reporter-W3CCLYCN.js} +2 -2
  34. package/dist/{postgres-consumed-credential-store-EZ4KETWH.js → postgres-consumed-credential-store-LUJ5CUJS.js} +1 -1
  35. package/dist/{postgres-job-store-E6AUHNKB.js → postgres-job-store-IX7IUXF4.js} +2 -2
  36. package/dist/{postgres-replay-store-GIYZS4LJ.js → postgres-replay-store-Q6MEQDWZ.js} +2 -2
  37. package/dist/{pricing-DG5IJ5QF.js → pricing-ZUEFO3CM.js} +3 -3
  38. package/dist/{revenue-reporter-E56J3NZK.js → revenue-reporter-NRS2FANA.js} +2 -2
  39. package/dist/server/index.d.ts +4 -3
  40. package/dist/server/index.js +26 -26
  41. package/dist/{tempo-charge-store-WTBIX2JX.js → tempo-charge-store-NZJTJCUO.js} +2 -2
  42. package/dist/{tempo-session-store-AWIFUAA6.js → tempo-session-store-ENFDLDKC.js} +3 -3
  43. package/dist/testing/index.js +5 -5
  44. package/dist/{x402-BN26TQZ6.js → x402-T7WVKDD4.js} +3 -3
  45. package/package.json +1 -1
package/README.md CHANGED
@@ -110,7 +110,7 @@ This metadata describes the retention schedule. The SDK does not automatically d
110
110
 
111
111
  Use the Node.js release in `.nvmrc` (Node 22). Install with `npm ci`, then run the same gate CI runs with `npm run verify`. The gate checks repository metadata in the checkout, copies only tracked and unignored source into an isolated directory, installs its locked dependencies, and runs lint, build, typecheck (including the release scripts under `checkJs`), unit and database tests, API, package, consumer, packed-artifact safety, and release checks there. The clean source tree owns the complete build and test pass, so verification never depends on the checkout's `node_modules` or pre-existing `dist` and does not repeat the full suite; after every check passes, its verified `dist` replaces the checkout's build output for release packaging.
112
112
 
113
- `DATABASE_URL` is optional locally. Without it the database suite is skipped rather than passed, and `verify` says so in its summary, because a skipped suite verified nothing and must not be reported as green. Point `DATABASE_URL` at a scratch Postgres to run it, and pass `npm run verify -- --require-database` to make a missing one a failure, which is what CI does.
113
+ `DATABASE_URL` is optional locally. Without it the database suite is skipped rather than passed, and `verify` says so in its summary, because a skipped suite verified nothing and must not be reported as green. Point `DATABASE_URL` at a scratch Postgres to run it, and pass `npm run verify -- --require-database` to make a missing one a failure, which is what CI does. That mode also requires the local test mint started by `node scripts/start-cashu-mint.mjs`.
114
114
 
115
115
  The public surface is exactly `@dvmkit/sdk`, `@dvmkit/sdk/server`, and `@dvmkit/sdk/testing`.
116
116
 
@@ -150,6 +150,10 @@ The same values are accepted as `--endpoint <url>` and `--job-token <hex>`. Thes
150
150
 
151
151
  If an upgrade broke something for you, an [API compatibility report](https://github.com/dvmkit/sdk/issues/new/choose) is the most useful thing you can send us. It tells us which parts of the published surface people actually build on, which no test of ours can.
152
152
 
153
+ ## Job identity field
154
+
155
+ Every 200 or 202 response to `POST /v1/job`, `POST /v1/request-resume/:id` and `POST /v1/request-result/:id` carries a `DVM-Job-Identity-V1` response-head field whose value is the body's `job_id`, byte for byte, so a router or caller can learn which job a response names without reading a body of any size. No other status carries it. The value grammar is `^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$`; a server whose job ID falls outside it sends no field. A reader takes the value from `Headers.get`, trims nothing and never folds case: a repeated field (joined with `", "`), an empty value or any other character is invalid, and a trailer of the same name is never identity. The portable contract and its classification vectors are in `protocol-fixtures/job-identity-v1.json`. Hosting control's status reports `jobIdentityHeader: "v1"` when the deployment emits the field.
156
+
153
157
  ## Per-job costs
154
158
 
155
159
  A handler can declare what a job cost **you**, the builder, to serve — a vendor API call, a GPU minute, a per-request licence fee — and the SDK reports it to the platform alongside what the caller paid, so your dashboard can state a margin instead of guessing at one.
@@ -171,7 +175,7 @@ Three things worth knowing:
171
175
  - **Declare the cost where you incur it, including inside `ctx.step`.** The step cache carries those declarations with the result and applies them once when a replay skips the body.
172
176
  - **Every terminal job reports its declared cost.** A paid completion carries the cost on its revenue report. A free completion, failure, or cancellation sends a separate cost-only report and does not create revenue.
173
177
 
174
- The cost is yours, never the caller's: it is recorded separately from what the caller paid and is never netted against it. Both report shapes use the same durable outbox. Cost-only reports are keyed on the job id and revisioned, so retries and cross-machine updates converge on the latest cumulative value. With the Postgres job store, boot-time and periodic reconciliation enqueue any terminal cost revision that a process exited before reporting.
178
+ The cost is yours, never the caller's: it is recorded separately from what the caller paid and is never netted against it. Both report shapes use the same durable outbox. Cost-only reports are keyed on the job id and revisioned, so retries and cross-machine updates converge on the latest cumulative value. With the Postgres job store, boot-time and periodic reconciliation enqueue any terminal cost revision that a process exited before reporting. Other job stores get no reconciliation: their cost-only report is durable only once the outbox insert commits, so an exit between the terminal save and that insert loses it.
175
179
 
176
180
  ## Rate cards
177
181
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  diagnosticConsole
3
- } from "./chunk-FXDQMJQ2.js";
3
+ } from "./chunk-5PLQOC4B.js";
4
4
  import {
5
5
  withSdkInitLock
6
6
  } from "./chunk-COYKJRMM.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  validateCurrency
3
- } from "./chunk-LQQ6H4UB.js";
3
+ } from "./chunk-5CSR33B5.js";
4
4
 
5
5
  // src/sdk/pricing/upfront.ts
6
6
  function buildUpfront(input) {
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-AFV77S4C.js";
6
6
  import {
7
7
  loggers
8
- } from "./chunk-SX4WCPW7.js";
8
+ } from "./chunk-RGSWVNQG.js";
9
9
  import {
10
10
  redactUrl
11
11
  } from "./chunk-KXWROQGK.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  diagnosticConsole
3
- } from "./chunk-FXDQMJQ2.js";
3
+ } from "./chunk-5PLQOC4B.js";
4
4
 
5
5
  // src/sdk/pricing/currency.ts
6
6
  var InvalidCurrencyError = class extends Error {
@@ -779,6 +779,7 @@ var diagnostic_catalogue_v1_default = {
779
779
  "hardened",
780
780
  "head_status",
781
781
  "hint",
782
+ "hosting_identity_revoke_failed",
782
783
  "ingest_concurrency",
783
784
  "ingest_global_concurrency",
784
785
  "ingest_ip_concurrency",
@@ -1067,6 +1068,25 @@ var diagnostic_catalogue_v1_default = {
1067
1068
  "UA-14",
1068
1069
  "UA-40",
1069
1070
  "UA-43"
1071
+ ],
1072
+ submitIdentitySources: [
1073
+ "header",
1074
+ "header_absent",
1075
+ "header_invalid",
1076
+ "not_extracted"
1077
+ ],
1078
+ fundedRuntimeReclaims: [
1079
+ "closed"
1080
+ ],
1081
+ suspensionReasons: [
1082
+ "request_limit",
1083
+ "dvm_limit",
1084
+ "behaviour",
1085
+ "free_tier_idle",
1086
+ "admin_org_suspend",
1087
+ "builder_pause",
1088
+ "withdrawn",
1089
+ "operator"
1070
1090
  ]
1071
1091
  };
1072
1092
 
@@ -1080,6 +1100,12 @@ var PAYMENT_ENUMS = {
1080
1100
  failure_stage: new Set(diagnostic_catalogue_v1_default.paymentFailureStages),
1081
1101
  phase: new Set(diagnostic_catalogue_v1_default.paymentPhases)
1082
1102
  };
1103
+ var ROUTER_ENUMS = {
1104
+ submit_identity_source: new Set(diagnostic_catalogue_v1_default.submitIdentitySources),
1105
+ funded_runtime_reclaim: new Set(diagnostic_catalogue_v1_default.fundedRuntimeReclaims),
1106
+ suspended_reclaim: new Set(diagnostic_catalogue_v1_default.suspensionReasons),
1107
+ suspended_admin: new Set(diagnostic_catalogue_v1_default.suspensionReasons)
1108
+ };
1083
1109
  var EVENTS = new Set(diagnostic_catalogue_v1_default.events);
1084
1110
  var ROUTE_TEMPLATES = [...diagnostic_catalogue_v1_default.routeTemplates].sort(
1085
1111
  compareRouteTemplates
@@ -1280,9 +1306,9 @@ function projectFields(input, dataset, authority, identityAuthority) {
1280
1306
  return output;
1281
1307
  }
1282
1308
  function projectField(key, value, dataset, authority, identityAuthority) {
1283
- const paymentEnum = Object.hasOwn(PAYMENT_ENUMS, key) ? PAYMENT_ENUMS[key] : void 0;
1284
- if (paymentEnum)
1285
- return typeof value === "string" && paymentEnum.has(value) ? value : void 0;
1309
+ const closedEnum = Object.hasOwn(PAYMENT_ENUMS, key) ? PAYMENT_ENUMS[key] : Object.hasOwn(ROUTER_ENUMS, key) ? ROUTER_ENUMS[key] : void 0;
1310
+ if (closedEnum)
1311
+ return typeof value === "string" && closedEnum.has(value) ? value : void 0;
1286
1312
  if (BOOLEAN_FIELDS.has(key))
1287
1313
  return typeof value === "boolean" ? value : void 0;
1288
1314
  if (INTEGER_FIELDS.has(key))
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-BPYMEMQX.js";
10
10
  import {
11
11
  diagnosticConsole
12
- } from "./chunk-FXDQMJQ2.js";
12
+ } from "./chunk-5PLQOC4B.js";
13
13
 
14
14
  // src/lib/cashu/lock-pubkey.ts
15
15
  function toLockPubkey(raw) {
@@ -397,10 +397,20 @@ var DEFAULT_LOCK_RETRY_INTERVAL_MS = 1e3;
397
397
  var WALLET_VERSION = 9;
398
398
  var RECENT_SPENDS_CAP = 10;
399
399
  var DEFAULT_AGENT_MINT_URL = "https://mint.coinos.io";
400
+ var MAX_STORABLE_JOB_ID_LENGTH = 512;
401
+ function isStorableJobId(value) {
402
+ return typeof value === "string" && value.length > 0 && value.length <= MAX_STORABLE_JOB_ID_LENGTH && // eslint-disable-next-line no-control-regex -- control characters are what this rejects
403
+ !/[\u0000-\u001f\u007f-\u009f]/u.test(value);
404
+ }
400
405
  function loadWalletConfiguredMints() {
401
406
  return loadAgentWallet()?.mints ?? [];
402
407
  }
403
408
  function loadAgentWallet() {
409
+ const wallet = parseAgentWallet();
410
+ if (wallet) normalizeAcceptedUnresolved(wallet);
411
+ return wallet;
412
+ }
413
+ function parseAgentWallet() {
404
414
  if (!existsSync4(WALLET_FILE)) return null;
405
415
  const raw = readFileSync4(WALLET_FILE, "utf-8");
406
416
  let parsed;
@@ -481,6 +491,7 @@ function loadAgentWallet() {
481
491
  return parsed;
482
492
  }
483
493
  function saveAgentWallet(wallet) {
494
+ assertAcceptedUnresolvedStorable(wallet);
484
495
  ensureConfigDir();
485
496
  const tmp = `${WALLET_FILE}.tmp`;
486
497
  const data = JSON.stringify(wallet, null, 2) + "\n";
@@ -649,6 +660,62 @@ function migrateV8ToV9(parsed) {
649
660
  created_at: typeof parsed.created_at === "string" ? parsed.created_at : (/* @__PURE__ */ new Date()).toISOString()
650
661
  };
651
662
  }
663
+ var ACCEPTED_UNRESOLVED_KINDS = /* @__PURE__ */ new Set([
664
+ "identity_mismatch",
665
+ "body_unreadable",
666
+ "router_identity_conflict"
667
+ ]);
668
+ var OBSERVED_JOB_ID_FIELDS = ["header_job_id", "body_job_id", "accepted_job_id"];
669
+ var PLACEHOLDER_KIND = "body_unreadable";
670
+ var PLACEHOLDER_OBSERVED_AT = (/* @__PURE__ */ new Date(0)).toISOString();
671
+ function assertAcceptedUnresolvedStorable(wallet) {
672
+ const entries = wallet.pending_submissions;
673
+ if (!Array.isArray(entries)) return;
674
+ for (const entry of entries) {
675
+ const record = entry?.accepted_unresolved;
676
+ if (record === void 0 || isStorableAcceptedUnresolved(record)) continue;
677
+ throw new DvmError(
678
+ "accepted_unresolved_invalid",
679
+ `Refusing to save pending submission ${String(entry?.request_id)}: its accepted_unresolved record is outside the stored contract.`,
680
+ "Use one of the three kinds, an ISO-8601 observed_at, and job IDs and ambiguity_id that pass isStorableJobId; omit an observed ID that does not. The wallet file was not changed."
681
+ );
682
+ }
683
+ }
684
+ function isStorableAcceptedUnresolved(value) {
685
+ if (!isPlainRecord(value)) return false;
686
+ return ACCEPTED_UNRESOLVED_KINDS.has(value.kind) && isIsoTimestamp(value.observed_at) && isStorableJobId(value.ambiguity_id) && OBSERVED_JOB_ID_FIELDS.every((field) => value[field] === void 0 || isStorableJobId(value[field]));
687
+ }
688
+ function normalizeAcceptedUnresolved(wallet) {
689
+ const entries = wallet.pending_submissions;
690
+ if (!Array.isArray(entries)) return;
691
+ for (const entry of entries) {
692
+ if (!entry || entry.accepted_unresolved === void 0) continue;
693
+ const stored = entry.accepted_unresolved;
694
+ if (isStorableAcceptedUnresolved(stored)) continue;
695
+ const record = isPlainRecord(stored) ? { ...stored } : {};
696
+ if (!ACCEPTED_UNRESOLVED_KINDS.has(record.kind)) record.kind = PLACEHOLDER_KIND;
697
+ if (!isIsoTimestamp(record.observed_at)) record.observed_at = PLACEHOLDER_OBSERVED_AT;
698
+ if (!isStorableJobId(record.ambiguity_id)) {
699
+ record.ambiguity_id = isStorableJobId(entry.request_id) ? entry.request_id : "missing-ambiguity";
700
+ }
701
+ for (const field of OBSERVED_JOB_ID_FIELDS) {
702
+ if (record[field] !== void 0 && !isStorableJobId(record[field])) delete record[field];
703
+ }
704
+ entry.accepted_unresolved = record;
705
+ }
706
+ }
707
+ function isPlainRecord(value) {
708
+ return typeof value === "object" && value !== null && !Array.isArray(value);
709
+ }
710
+ var ISO_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d{1,9})?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/;
711
+ function isIsoTimestamp(value) {
712
+ if (typeof value !== "string") return false;
713
+ const match = ISO_TIMESTAMP.exec(value);
714
+ if (!match) return false;
715
+ const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])];
716
+ const date = new Date(Date.UTC(year, month - 1, day));
717
+ return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
718
+ }
652
719
  function isCounterMap(value) {
653
720
  if (typeof value !== "object" || value === null) return false;
654
721
  for (const inner of Object.values(value)) {
@@ -1255,6 +1322,17 @@ function buildAdminAuthHeader(args) {
1255
1322
  };
1256
1323
  }
1257
1324
 
1325
+ // src/lib/job-identity-header.ts
1326
+ var JOB_IDENTITY_HEADER = "dvm-job-identity-v1";
1327
+ var JOB_IDENTITY_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
1328
+ function isJobIdentityValue(value) {
1329
+ return typeof value === "string" && JOB_IDENTITY_PATTERN.test(value);
1330
+ }
1331
+ function parseJobIdentityHeader(value) {
1332
+ if (value === null) return { kind: "absent" };
1333
+ return isJobIdentityValue(value) ? { kind: "valid", jobId: value } : { kind: "invalid" };
1334
+ }
1335
+
1258
1336
  // src/lib/builder-identity.ts
1259
1337
  import {
1260
1338
  chmodSync as chmodSync4,
@@ -1808,6 +1886,7 @@ export {
1808
1886
  WALLET_VERSION,
1809
1887
  RECENT_SPENDS_CAP,
1810
1888
  DEFAULT_AGENT_MINT_URL,
1889
+ isStorableJobId,
1811
1890
  loadWalletConfiguredMints,
1812
1891
  loadAgentWallet,
1813
1892
  saveAgentWallet,
@@ -1835,6 +1914,9 @@ export {
1835
1914
  ADMIN_STATE_UNAVAILABLE,
1836
1915
  buildAdminChallenge,
1837
1916
  buildAdminAuthHeader,
1917
+ JOB_IDENTITY_HEADER,
1918
+ isJobIdentityValue,
1919
+ parseJobIdentityHeader,
1838
1920
  generateIdentity,
1839
1921
  loadIdentitySecret,
1840
1922
  writeIdentity,
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-AFV77S4C.js";
5
5
  import {
6
6
  diagnosticConsole
7
- } from "./chunk-FXDQMJQ2.js";
7
+ } from "./chunk-5PLQOC4B.js";
8
8
  import {
9
9
  withSdkInitLock
10
10
  } from "./chunk-COYKJRMM.js";
@@ -286,10 +286,20 @@ var PostgresJobStore = class {
286
286
  CREATE INDEX IF NOT EXISTS idx_jobs_retention
287
287
  ON jobs (last_activity_at, id)
288
288
  WHERE redacted_at IS NULL AND status IN ('completed', 'failed', 'cancelled');
289
- CREATE INDEX IF NOT EXISTS idx_jobs_pending_cost_report
289
+ -- Terminal cost recovery runs at boot and every 30s on each machine.
290
+ -- Indexing only rows whose latest revision is not yet enqueued keeps each
291
+ -- pass proportional to that backlog; marking a row drops it from the
292
+ -- index. listUnreportedTerminalCosts' WHERE clause must imply this
293
+ -- predicate or the planner falls back to scanning terminal history.
294
+ DROP INDEX IF EXISTS idx_jobs_pending_cost_report;
295
+ CREATE INDEX IF NOT EXISTS idx_jobs_unreported_terminal_cost
290
296
  ON jobs (dvm_id, id)
291
297
  WHERE cost_revision IS NOT NULL
292
- AND status IN ('completed', 'failed', 'cancelled');
298
+ AND (cost_reported_revision IS NULL OR cost_reported_revision < cost_revision)
299
+ AND (
300
+ status IN ('failed', 'cancelled')
301
+ OR (status = 'completed' AND paid_msats = 0)
302
+ );
293
303
  -- the idempotent-replay lookup. payment_tx_hash carries the
294
304
  -- caller's X-Cashu-Request-Id on the accumulator path, so a retried paid
295
305
  -- submit finds the job its payment already created.
@@ -689,7 +699,8 @@ var PostgresJobStore = class {
689
699
  }
690
700
  /**
691
701
  * Read terminal zero-revenue jobs whose latest declared-cost revision has
692
- * not yet reached the durable reporter outbox.
702
+ * not yet reached the durable reporter outbox. Keep the filter in step with
703
+ * `idx_jobs_unreported_terminal_cost`, which bounds each pass to the backlog.
693
704
  */
694
705
  async listUnreportedTerminalCosts(args) {
695
706
  const { rows } = await this.pool.query(
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  diagnosticConsole,
6
6
  projectSpanRow
7
- } from "./chunk-FXDQMJQ2.js";
7
+ } from "./chunk-5PLQOC4B.js";
8
8
 
9
9
  // src/lib/x402/env.ts
10
10
  import { isAddress } from "viem";
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-KXWROQGK.js";
7
7
  import {
8
8
  diagnosticConsole
9
- } from "./chunk-FXDQMJQ2.js";
9
+ } from "./chunk-5PLQOC4B.js";
10
10
 
11
11
  // src/observability/payment-diagnostics.ts
12
12
  import { AsyncLocalStorage } from "async_hooks";
@@ -7,10 +7,10 @@ import {
7
7
  installHostedTempoCloseGuard,
8
8
  isTempoInsufficientFundsError,
9
9
  resolveTempoNetwork
10
- } from "./chunk-KYCLHWKO.js";
10
+ } from "./chunk-QN3CQOE2.js";
11
11
  import {
12
12
  x402EarnedCeiling
13
- } from "./chunk-3VFEX2Y3.js";
13
+ } from "./chunk-YNHXOONR.js";
14
14
  import {
15
15
  createX402FacilitatorAuthHeaders,
16
16
  createX402FacilitatorClient,
@@ -19,13 +19,13 @@ import {
19
19
  verifyWithFacilitator,
20
20
  withPaymentDiagnostics,
21
21
  withPaymentStage
22
- } from "./chunk-XEOTTFLH.js";
22
+ } from "./chunk-FYETJDBB.js";
23
23
  import {
24
24
  MemoryCreditLedger
25
- } from "./chunk-FOJKZ4E7.js";
25
+ } from "./chunk-YE53E4BT.js";
26
26
  import {
27
27
  PostgresJobStore
28
- } from "./chunk-JUEEUV5X.js";
28
+ } from "./chunk-6JZDFYQL.js";
29
29
  import {
30
30
  parseStoreValue
31
31
  } from "./chunk-YG7G4DPZ.js";
@@ -36,7 +36,7 @@ import {
36
36
  humanizeZodIssues,
37
37
  signedRequestInput,
38
38
  zodIssuesOf
39
- } from "./chunk-X5RY2G3C.js";
39
+ } from "./chunk-YS6PWVCZ.js";
40
40
  import {
41
41
  MemoryJobStore,
42
42
  UNCAPPABLE_ASK_TOTAL,
@@ -45,7 +45,7 @@ import {
45
45
  isJobRetentionStore,
46
46
  isReceiptIssuingStore,
47
47
  isStreamableJobStore
48
- } from "./chunk-MYJOV4R4.js";
48
+ } from "./chunk-2HAFZ5GC.js";
49
49
  import {
50
50
  ContentHoldError,
51
51
  JobCancelledError,
@@ -65,6 +65,7 @@ import {
65
65
  ADMIN_AUTH_NONCE_TTL_SECONDS,
66
66
  ADMIN_STATE_UNAVAILABLE,
67
67
  IMPLICIT_CREDIT_TTL_MS,
68
+ JOB_IDENTITY_HEADER,
68
69
  TEMPO_SESSION_UPDATED_REASON,
69
70
  X402_BATCH_CHANNEL_ABI,
70
71
  attestedDvmIdentity,
@@ -74,6 +75,7 @@ import {
74
75
  createMonotonicClock,
75
76
  formatStaleness,
76
77
  getWallet,
78
+ isJobIdentityValue,
77
79
  isPublicRequestId,
78
80
  isX402SettlementReconciliationReason,
79
81
  parseTraceparent,
@@ -83,7 +85,7 @@ import {
83
85
  signReceipt,
84
86
  toLockPubkey,
85
87
  verifyChallenge
86
- } from "./chunk-QTH7CIA3.js";
88
+ } from "./chunk-5TIFEMHJ.js";
87
89
  import {
88
90
  X402_BATCH_SETTLEMENT_SCHEME,
89
91
  X402_DEFAULT_FACILITATOR,
@@ -115,7 +117,7 @@ import {
115
117
  pinDimension,
116
118
  withSpan,
117
119
  withTraceContext
118
- } from "./chunk-SX4WCPW7.js";
120
+ } from "./chunk-RGSWVNQG.js";
119
121
  import {
120
122
  StepCache
121
123
  } from "./chunk-BQJIFRAZ.js";
@@ -132,7 +134,7 @@ import {
132
134
  roundUsd,
133
135
  satsToFiat,
134
136
  validateCurrency
135
- } from "./chunk-LQQ6H4UB.js";
137
+ } from "./chunk-5CSR33B5.js";
136
138
  import {
137
139
  CreditLedger,
138
140
  CreditLedgerError,
@@ -148,10 +150,10 @@ import {
148
150
  isNonChannelBitcoinRail,
149
151
  netOwedSats,
150
152
  x402SettlementPending
151
- } from "./chunk-WP7UX6RF.js";
153
+ } from "./chunk-IOKEKMIU.js";
152
154
  import {
153
155
  withPostgresRecoveryContext
154
- } from "./chunk-6RYCZLCK.js";
156
+ } from "./chunk-QM2OS3NJ.js";
155
157
  import {
156
158
  DvmError,
157
159
  x402NetworkByCaip2
@@ -159,7 +161,7 @@ import {
159
161
  import {
160
162
  createDiagnosticCapabilityAuthority,
161
163
  diagnosticConsole
162
- } from "./chunk-FXDQMJQ2.js";
164
+ } from "./chunk-5PLQOC4B.js";
163
165
  import {
164
166
  MemoryProcessedPaymentStore,
165
167
  PostgresProcessedPaymentStore,
@@ -3875,7 +3877,7 @@ async function verifyUpfrontPaymentInScope(opts) {
3875
3877
  x402Requirements
3876
3878
  });
3877
3879
  }
3878
- const { verifyX402Payment } = await import("./x402-BN26TQZ6.js");
3880
+ const { verifyX402Payment } = await import("./x402-T7WVKDD4.js");
3879
3881
  const receipt = await withPaymentStage("verifier_broadcast", () => verifyX402Payment(
3880
3882
  x402Payment,
3881
3883
  x402Config,
@@ -4863,7 +4865,7 @@ async function verifyIncomingPaymentInScope(body, opts, snapshot) {
4863
4865
  snapshot
4864
4866
  });
4865
4867
  }
4866
- const { verifyX402Payment } = await import("./x402-BN26TQZ6.js");
4868
+ const { verifyX402Payment } = await import("./x402-T7WVKDD4.js");
4867
4869
  const receipt = await withPaymentStage("verifier_broadcast", () => verifyX402Payment(
4868
4870
  body.content.x402_payment,
4869
4871
  opts.x402Config,
@@ -5294,7 +5296,7 @@ async function processIncomingPaymentInScope(job, body, opts) {
5294
5296
  try {
5295
5297
  const requiredMsats = job.pendingPaymentMsats ?? 0;
5296
5298
  const requiredUsdcMicro = job.pendingX402AmountUsdcMicro !== void 0 ? BigInt(job.pendingX402AmountUsdcMicro) : BigInt(msatsToUsdc(requiredMsats, rate));
5297
- const { verifyX402Payment } = await import("./x402-BN26TQZ6.js");
5299
+ const { verifyX402Payment } = await import("./x402-T7WVKDD4.js");
5298
5300
  const receipt = await withPaymentStage("verifier_broadcast", () => verifyX402Payment(
5299
5301
  body.content.x402_payment,
5300
5302
  opts.x402Config,
@@ -11769,7 +11771,8 @@ var HostingControl = class {
11769
11771
  pendingAdmissionCount: Number(pending.rows[0].pending),
11770
11772
  pendingAdmissions: inFlight.rows.map((row) => ({ admissionId: row.id, workId: row.job_id })),
11771
11773
  unresolvedAdmissionCount: Number(pending.rows[0].unresolved),
11772
- unresolvedAdmissions: unresolved.rows.map((row) => ({ admissionId: row.id, jobId: row.job_id }))
11774
+ unresolvedAdmissions: unresolved.rows.map((row) => ({ admissionId: row.id, jobId: row.job_id })),
11775
+ jobIdentityHeader: "v1"
11773
11776
  };
11774
11777
  }
11775
11778
  };
@@ -19534,7 +19537,7 @@ async function createDVMServer(descriptor, opts) {
19534
19537
  }
19535
19538
  }
19536
19539
  if (!opts.onJobCompleted && platformToken && platformUrl && dvmId && opts.db) {
19537
- const { RevenueReporter } = await import("./revenue-reporter-E56J3NZK.js");
19540
+ const { RevenueReporter } = await import("./revenue-reporter-NRS2FANA.js");
19538
19541
  const reporter = new RevenueReporter(
19539
19542
  opts.db,
19540
19543
  platformUrl,
@@ -19544,7 +19547,7 @@ async function createDVMServer(descriptor, opts) {
19544
19547
  revenueReporter = reporter;
19545
19548
  await reporter.init();
19546
19549
  reporter.startRetryLoop();
19547
- const { MemoryX402BatchStore, PayoutReporter } = await import("./payout-reporter-3UVWPGMO.js");
19550
+ const { MemoryX402BatchStore, PayoutReporter } = await import("./payout-reporter-W3CCLYCN.js");
19548
19551
  payoutReporter = new PayoutReporter({
19549
19552
  dvmId,
19550
19553
  db: opts.db,
@@ -22495,7 +22498,7 @@ function buildSubmitResponse(c, job, jobToken, contentFields) {
22495
22498
  else if (job.status === "completed") res.status = "completed";
22496
22499
  Object.assign(res, terminalResponseFields(job), contentFields);
22497
22500
  removeUnavailableContent(res);
22498
- return c.json(res, job.status === "completed" ? 200 : 202);
22501
+ return c.json(res, job.status === "completed" ? 200 : 202, jobIdentityHeaders(job.id));
22499
22502
  }
22500
22503
  function requestRecoveryStore(store) {
22501
22504
  return store.findJobByRequestId && store.claimRequestId && store.resumeRequestId && store.releaseRequestIdClaim ? store : void 0;
@@ -22561,7 +22564,10 @@ function buildRequestResultResponse(c, requestId, job, contentFields) {
22561
22564
  if (job.paymentTransactionHash) res.transaction_hash = job.paymentTransactionHash;
22562
22565
  Object.assign(res, terminalResponseFields(job), contentFields);
22563
22566
  removeUnavailableContent(res);
22564
- return c.json(res, isTerminal(job.status) ? 200 : 202);
22567
+ return c.json(res, isTerminal(job.status) ? 200 : 202, jobIdentityHeaders(job.id));
22568
+ }
22569
+ function jobIdentityHeaders(jobId) {
22570
+ return isJobIdentityValue(jobId) ? { [JOB_IDENTITY_HEADER]: jobId } : {};
22565
22571
  }
22566
22572
  function requestResultNotFound(c, requestId) {
22567
22573
  return c.json(
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-YG7G4DPZ.js";
5
5
  import {
6
6
  withPostgresTransactionRecovery
7
- } from "./chunk-6RYCZLCK.js";
7
+ } from "./chunk-QM2OS3NJ.js";
8
8
  import {
9
9
  withSdkInitLock
10
10
  } from "./chunk-COYKJRMM.js";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  applyRetryToPool
3
- } from "./chunk-6RYCZLCK.js";
3
+ } from "./chunk-QM2OS3NJ.js";
4
4
  import {
5
5
  x402NetworkByCaip2
6
6
  } from "./chunk-BPYMEMQX.js";
7
7
  import {
8
8
  diagnosticConsole
9
- } from "./chunk-FXDQMJQ2.js";
9
+ } from "./chunk-5PLQOC4B.js";
10
10
  import {
11
11
  withSdkInitLock
12
12
  } from "./chunk-COYKJRMM.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  diagnosticConsole
3
- } from "./chunk-FXDQMJQ2.js";
3
+ } from "./chunk-5PLQOC4B.js";
4
4
 
5
5
  // src/lib/pg-retry.ts
6
6
  import { AsyncLocalStorage } from "async_hooks";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  diagnosticConsole
3
- } from "./chunk-FXDQMJQ2.js";
3
+ } from "./chunk-5PLQOC4B.js";
4
4
 
5
5
  // src/sdk/server/mpp-setup.ts
6
6
  import { createHash, randomUUID } from "crypto";
@@ -8,7 +8,7 @@ import {
8
8
  extendDiagnosticIdentityAuthority,
9
9
  projectDiagnosticFields,
10
10
  projectSpanRow
11
- } from "./chunk-FXDQMJQ2.js";
11
+ } from "./chunk-5PLQOC4B.js";
12
12
 
13
13
  // src/sdk/logger.ts
14
14
  function createConsoleLogger(_jobId) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  diagnosticConsole
3
- } from "./chunk-FXDQMJQ2.js";
3
+ } from "./chunk-5PLQOC4B.js";
4
4
  import {
5
5
  withSdkInitLock
6
6
  } from "./chunk-COYKJRMM.js";
@@ -2,7 +2,7 @@ import {
2
2
  createX402FacilitatorAuthHeaders,
3
3
  settleWithFacilitator,
4
4
  verifyWithFacilitator
5
- } from "./chunk-XEOTTFLH.js";
5
+ } from "./chunk-FYETJDBB.js";
6
6
  import {
7
7
  buildPaymentRequirements,
8
8
  decodePayment,
@@ -15,7 +15,7 @@ import {
15
15
  } from "./chunk-KXWROQGK.js";
16
16
  import {
17
17
  diagnosticConsole
18
- } from "./chunk-FXDQMJQ2.js";
18
+ } from "./chunk-5PLQOC4B.js";
19
19
 
20
20
  // src/lib/x402/verify.ts
21
21
  async function verifyX402Payment(paymentHeader, config, requiredUsdcMicro, resource, btcUsdRate, exactVersions = { v1: true, v2: true }) {
@@ -15,7 +15,7 @@ import {
15
15
  lotOwedSats,
16
16
  netOwedSats,
17
17
  x402SettlementPending
18
- } from "./chunk-WP7UX6RF.js";
18
+ } from "./chunk-IOKEKMIU.js";
19
19
 
20
20
  // src/sdk/server/memory-credit-ledger.ts
21
21
  import { randomUUID } from "crypto";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  diagnosticConsole
3
- } from "./chunk-FXDQMJQ2.js";
3
+ } from "./chunk-5PLQOC4B.js";
4
4
  import {
5
5
  withSdkInitLock
6
6
  } from "./chunk-COYKJRMM.js";
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-UKD3R2KU.js";
8
8
  import {
9
9
  diagnosticConsole
10
- } from "./chunk-FXDQMJQ2.js";
10
+ } from "./chunk-5PLQOC4B.js";
11
11
 
12
12
  // src/sdk/server/zod-error.ts
13
13
  function humanizeZodError(err, opts) {
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-YG7G4DPZ.js";
5
5
  import {
6
6
  diagnosticConsole
7
- } from "./chunk-FXDQMJQ2.js";
7
+ } from "./chunk-5PLQOC4B.js";
8
8
  import {
9
9
  withSdkInitLock
10
10
  } from "./chunk-COYKJRMM.js";
@@ -10,10 +10,10 @@ import {
10
10
  isDrainMethod,
11
11
  isFundingRail,
12
12
  x402SettlementPending
13
- } from "./chunk-WP7UX6RF.js";
14
- import "./chunk-6RYCZLCK.js";
13
+ } from "./chunk-IOKEKMIU.js";
14
+ import "./chunk-QM2OS3NJ.js";
15
15
  import "./chunk-BPYMEMQX.js";
16
- import "./chunk-FXDQMJQ2.js";
16
+ import "./chunk-5PLQOC4B.js";
17
17
  import "./chunk-COYKJRMM.js";
18
18
  export {
19
19
  CreditLedger,
@@ -417,6 +417,8 @@ interface HostingControlStatus {
417
417
  admissionId: string;
418
418
  jobId: string;
419
419
  }[];
420
+ /** Version of the job-identity response-head field this deployment emits. */
421
+ jobIdentityHeader: "v1";
420
422
  }
421
423
 
422
424
  interface PromptResolver {