@lostgradient/weft 0.23.1 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. package/README.md +72 -4
  2. package/dist/cli/codegen-emit-dedup.d.ts +81 -0
  3. package/dist/cli/codegen-emit-dedup.js +45 -0
  4. package/dist/cli/codegen-emit-registry.d.ts +90 -0
  5. package/dist/cli/codegen-emit-registry.js +50 -0
  6. package/dist/cli/codegen-emit.d.ts +26 -39
  7. package/dist/cli/codegen-emit.js +4 -27
  8. package/dist/cli/codegen-validate.d.ts +49 -0
  9. package/dist/cli/codegen-validate.js +186 -0
  10. package/dist/cli/codegen.js +6 -87
  11. package/dist/cli/generated/operation-catalog.snapshot.json +287 -3
  12. package/dist/cli/generated/operation-client.generated.d.ts +324 -10
  13. package/dist/cli/generated/operation-client.generated.js +12 -0
  14. package/dist/cli/output.js +1 -1
  15. package/dist/cli/storage-factory.js +2 -0
  16. package/dist/cli/workflow-commands.js +2 -0
  17. package/dist/cli-main.js +1 -1
  18. package/dist/core/application-payload-digest.d.ts +42 -0
  19. package/dist/core/application-payload-digest.js +76 -0
  20. package/dist/core/application-primitive-abort.d.ts +50 -0
  21. package/dist/core/application-primitive-abort.js +40 -0
  22. package/dist/core/application-primitive-attempt-registry.d.ts +74 -0
  23. package/dist/core/application-primitive-attempt-registry.js +73 -0
  24. package/dist/core/application-primitive-codec.d.ts +36 -0
  25. package/dist/core/application-primitive-codec.js +56 -0
  26. package/dist/core/application-primitive-commit.d.ts +67 -0
  27. package/dist/core/application-primitive-commit.js +66 -0
  28. package/dist/core/application-primitive-guards.d.ts +62 -0
  29. package/dist/core/application-primitive-guards.js +89 -0
  30. package/dist/core/application-primitive-payload.d.ts +29 -0
  31. package/dist/core/application-primitive-payload.js +65 -0
  32. package/dist/core/application-primitive-timing.d.ts +18 -0
  33. package/dist/core/application-primitive-timing.js +22 -0
  34. package/dist/core/atomic-state.js +2 -0
  35. package/dist/core/catalog/codec.d.ts +40 -0
  36. package/dist/core/catalog/codec.js +45 -0
  37. package/dist/core/catalog/errors.d.ts +104 -0
  38. package/dist/core/catalog/errors.js +41 -0
  39. package/dist/core/catalog/index.d.ts +25 -0
  40. package/dist/core/catalog/index.js +15 -0
  41. package/dist/core/catalog/reference-counts.d.ts +105 -0
  42. package/dist/core/catalog/reference-counts.js +28 -0
  43. package/dist/core/catalog/removal.d.ts +52 -0
  44. package/dist/core/catalog/removal.js +14 -0
  45. package/dist/core/catalog/storage-io.d.ts +78 -0
  46. package/dist/core/catalog/storage-io.js +106 -0
  47. package/dist/core/catalog/types.d.ts +108 -0
  48. package/dist/core/catalog/types.js +0 -0
  49. package/dist/core/catalog/workflow-catalog.d.ts +165 -0
  50. package/dist/core/catalog/workflow-catalog.js +198 -0
  51. package/dist/core/compare-codepoint.d.ts +13 -0
  52. package/dist/core/compare-codepoint.js +7 -0
  53. package/dist/core/compression.js +2 -0
  54. package/dist/core/context/attributes.d.ts +1 -1
  55. package/dist/core/context/durable-operations.d.ts +2 -2
  56. package/dist/core/context/index.js +5 -3
  57. package/dist/core/context/state-namespace.d.ts +1 -1
  58. package/dist/core/contract/build.d.ts +64 -0
  59. package/dist/core/contract/build.js +99 -0
  60. package/dist/core/contract/compatibility.d.ts +187 -0
  61. package/dist/core/contract/compatibility.js +37 -0
  62. package/dist/core/contract/failure.d.ts +64 -0
  63. package/dist/core/contract/failure.js +4 -0
  64. package/dist/core/contract/hash.d.ts +92 -0
  65. package/dist/core/contract/hash.js +34 -0
  66. package/dist/core/contract/index.d.ts +21 -0
  67. package/dist/core/contract/index.js +22 -0
  68. package/dist/core/contract/limits.d.ts +74 -0
  69. package/dist/core/contract/limits.js +1 -0
  70. package/dist/core/contract/manifest-parse-schema.d.ts +37 -0
  71. package/dist/core/contract/manifest-parse-schema.js +106 -0
  72. package/dist/core/contract/manifest-parse.d.ts +76 -0
  73. package/dist/core/contract/manifest-parse.js +189 -0
  74. package/dist/core/contract/manifest.d.ts +56 -0
  75. package/dist/core/contract/manifest.js +31 -0
  76. package/dist/core/contract/normalize.d.ts +97 -0
  77. package/dist/core/contract/normalize.js +127 -0
  78. package/dist/core/contract/revision.d.ts +29 -0
  79. package/dist/core/contract/revision.js +5 -0
  80. package/dist/core/contract/types.d.ts +274 -0
  81. package/dist/core/contract/types.js +1 -0
  82. package/dist/core/engine/catalog-activation.d.ts +40 -0
  83. package/dist/core/engine/catalog-activation.js +17 -0
  84. package/dist/core/engine/catalog-events.d.ts +36 -0
  85. package/dist/core/engine/catalog-events.js +15 -0
  86. package/dist/core/engine/catalog-readiness.d.ts +49 -0
  87. package/dist/core/engine/catalog-readiness.js +59 -0
  88. package/dist/core/engine/catalog-removal.d.ts +132 -0
  89. package/dist/core/engine/catalog-removal.js +70 -0
  90. package/dist/core/engine/construction.d.ts +1 -1
  91. package/dist/core/engine/construction.js +4 -2
  92. package/dist/core/engine/disposal.js +9 -0
  93. package/dist/core/engine/engine-workflows-namespace.d.ts +130 -0
  94. package/dist/core/engine/engine-workflows-namespace.js +49 -0
  95. package/dist/core/engine/finalizer-metadata.d.ts +22 -0
  96. package/dist/core/engine/finalizer-metadata.js +12 -0
  97. package/dist/core/engine/handle-result.js +2 -0
  98. package/dist/core/engine/index.d.ts +83 -0
  99. package/dist/core/engine/index.js +61 -0
  100. package/dist/core/engine/internals.d.ts +44 -1
  101. package/dist/core/engine/internals.js +6 -0
  102. package/dist/core/engine/lifecycle/start.js +3 -0
  103. package/dist/core/engine/registration.d.ts +76 -0
  104. package/dist/core/engine/registration.js +12 -6
  105. package/dist/core/engine/source-registration.d.ts +42 -0
  106. package/dist/core/engine/source-registration.js +36 -0
  107. package/dist/core/engine/source-resolution.d.ts +85 -0
  108. package/dist/core/engine/source-resolution.js +119 -0
  109. package/dist/core/engine/validation.js +2 -2
  110. package/dist/core/events/catalog-events.d.ts +117 -0
  111. package/dist/core/events/catalog-events.js +62 -0
  112. package/dist/core/events/event-map.d.ts +6 -0
  113. package/dist/core/events/index.d.ts +1 -0
  114. package/dist/core/events/index.js +1 -0
  115. package/dist/core/mailbox-admission.d.ts +26 -0
  116. package/dist/core/mailbox-admission.js +130 -0
  117. package/dist/core/mailbox-claims.d.ts +251 -0
  118. package/dist/core/mailbox-claims.js +0 -0
  119. package/dist/core/mailbox-codec.d.ts +32 -0
  120. package/dist/core/mailbox-codec.js +221 -0
  121. package/dist/core/mailbox-contract.d.ts +290 -0
  122. package/dist/core/mailbox-contract.js +0 -0
  123. package/dist/core/mailbox-delivery.d.ts +37 -0
  124. package/dist/core/mailbox-delivery.js +193 -0
  125. package/dist/core/mailbox-guards.d.ts +78 -0
  126. package/dist/core/mailbox-guards.js +58 -0
  127. package/dist/core/mailbox-index-codec.d.ts +41 -0
  128. package/dist/core/mailbox-index-codec.js +71 -0
  129. package/dist/core/mailbox-internals.d.ts +156 -0
  130. package/dist/core/mailbox-internals.js +154 -0
  131. package/dist/core/mailbox-maintenance.d.ts +29 -0
  132. package/dist/core/mailbox-maintenance.js +196 -0
  133. package/dist/core/mailbox-settlement.d.ts +69 -0
  134. package/dist/core/mailbox-settlement.js +206 -0
  135. package/dist/core/mailbox-storage.d.ts +117 -0
  136. package/dist/core/mailbox-storage.js +115 -0
  137. package/dist/core/mailbox-transition-helpers.d.ts +70 -0
  138. package/dist/core/mailbox-transition-helpers.js +43 -0
  139. package/dist/core/mailbox-transitions-recovery.d.ts +28 -0
  140. package/dist/core/mailbox-transitions-recovery.js +64 -0
  141. package/dist/core/mailbox-transitions.d.ts +138 -0
  142. package/dist/core/mailbox-transitions.js +180 -0
  143. package/dist/core/mailbox-types.d.ts +406 -0
  144. package/dist/core/mailbox-types.js +16 -0
  145. package/dist/core/mailbox-validation.d.ts +65 -0
  146. package/dist/core/mailbox-validation.js +73 -0
  147. package/dist/core/mailbox-waits.d.ts +50 -0
  148. package/dist/core/mailbox-waits.js +97 -0
  149. package/dist/core/mailbox.d.ts +163 -0
  150. package/dist/core/mailbox.js +211 -0
  151. package/dist/core/outbox-claims.d.ts +307 -0
  152. package/dist/core/outbox-claims.js +0 -0
  153. package/dist/core/outbox-codec.d.ts +24 -0
  154. package/dist/core/outbox-codec.js +257 -0
  155. package/dist/core/outbox-contract.d.ts +346 -0
  156. package/dist/core/outbox-contract.js +0 -0
  157. package/dist/core/outbox-delivery.d.ts +34 -0
  158. package/dist/core/outbox-delivery.js +149 -0
  159. package/dist/core/outbox-drain.d.ts +29 -0
  160. package/dist/core/outbox-drain.js +158 -0
  161. package/dist/core/outbox-enqueue.d.ts +24 -0
  162. package/dist/core/outbox-enqueue.js +115 -0
  163. package/dist/core/outbox-guards.d.ts +76 -0
  164. package/dist/core/outbox-guards.js +60 -0
  165. package/dist/core/outbox-index-codec.d.ts +33 -0
  166. package/dist/core/outbox-index-codec.js +71 -0
  167. package/dist/core/outbox-internals.d.ts +99 -0
  168. package/dist/core/outbox-internals.js +159 -0
  169. package/dist/core/outbox-listing.d.ts +12 -0
  170. package/dist/core/outbox-listing.js +38 -0
  171. package/dist/core/outbox-maintenance.d.ts +28 -0
  172. package/dist/core/outbox-maintenance.js +191 -0
  173. package/dist/core/outbox-operations.d.ts +18 -0
  174. package/dist/core/outbox-operations.js +46 -0
  175. package/dist/core/outbox-runner.d.ts +30 -0
  176. package/dist/core/outbox-runner.js +217 -0
  177. package/dist/core/outbox-settlement.d.ts +57 -0
  178. package/dist/core/outbox-settlement.js +183 -0
  179. package/dist/core/outbox-storage.d.ts +107 -0
  180. package/dist/core/outbox-storage.js +127 -0
  181. package/dist/core/outbox-transition-helpers.d.ts +83 -0
  182. package/dist/core/outbox-transition-helpers.js +63 -0
  183. package/dist/core/outbox-transitions-recovery.d.ts +30 -0
  184. package/dist/core/outbox-transitions-recovery.js +42 -0
  185. package/dist/core/outbox-transitions.d.ts +145 -0
  186. package/dist/core/outbox-transitions.js +236 -0
  187. package/dist/core/outbox-types.d.ts +400 -0
  188. package/dist/core/outbox-types.js +20 -0
  189. package/dist/core/outbox-validation.d.ts +101 -0
  190. package/dist/core/outbox-validation.js +127 -0
  191. package/dist/core/outbox-waits.d.ts +39 -0
  192. package/dist/core/outbox-waits.js +88 -0
  193. package/dist/core/outbox.d.ts +156 -0
  194. package/dist/core/outbox.js +234 -0
  195. package/dist/core/registry-limits.d.ts +49 -0
  196. package/dist/core/registry-limits.js +10 -0
  197. package/dist/core/registry-schema-conversion.d.ts +20 -0
  198. package/dist/core/registry-schema-conversion.js +22 -0
  199. package/dist/core/registry-snapshot.d.ts +91 -42
  200. package/dist/core/registry-snapshot.js +39 -77
  201. package/dist/core/registry-workflow-contract-draft.d.ts +32 -0
  202. package/dist/core/registry-workflow-contract-draft.js +28 -0
  203. package/dist/core/registry-workflow-manifest.d.ts +122 -0
  204. package/dist/core/registry-workflow-manifest.js +92 -0
  205. package/dist/core/source/errors.d.ts +55 -0
  206. package/dist/core/source/errors.js +13 -0
  207. package/dist/core/source/index.d.ts +19 -0
  208. package/dist/core/source/index.js +4 -0
  209. package/dist/core/source/resolvers.d.ts +45 -0
  210. package/dist/core/source/resolvers.js +9 -0
  211. package/dist/core/source/types.d.ts +211 -0
  212. package/dist/core/source/types.js +0 -0
  213. package/dist/core/source/validate.d.ts +91 -0
  214. package/dist/core/source/validate.js +62 -0
  215. package/dist/core/source/workflow-source.d.ts +43 -0
  216. package/dist/core/source/workflow-source.js +16 -0
  217. package/dist/core/types/workflow-registries.d.ts +7 -0
  218. package/dist/core/types/workflow-registry.d.ts +12 -0
  219. package/dist/core/versioning.js +2 -0
  220. package/dist/core/weft-error.d.ts +1 -1
  221. package/dist/core/weft-error.js +9 -1
  222. package/dist/http.js +2 -2
  223. package/dist/index.d.ts +23 -2
  224. package/dist/index.js +50 -0
  225. package/dist/indexeddb.js +1 -1
  226. package/dist/json-schema.js +3 -3
  227. package/dist/mcp/resources.js +2 -0
  228. package/dist/runtime/portable.d.ts +9 -1
  229. package/dist/server/fault-to-json-rpc.js +3 -1
  230. package/dist/server/handler/auth-context-principal.js +4 -0
  231. package/dist/server/json-rpc-http.js +2 -0
  232. package/dist/server/json-rpc-websocket.js +6 -4
  233. package/dist/server/operation-catalog/index.d.ts +1 -1
  234. package/dist/server/operation-catalog/pipeline-helpers.js +2 -0
  235. package/dist/server/operation-catalog/types.d.ts +17 -0
  236. package/dist/server/operation-fault.d.ts +3 -0
  237. package/dist/server/operation-fault.js +3 -1
  238. package/dist/server/operations/activate-workflow-revision.d.ts +30 -0
  239. package/dist/server/operations/activate-workflow-revision.js +69 -0
  240. package/dist/server/operations/fleet-events-subscription.js +1 -1
  241. package/dist/server/operations/fork-workflow.js +1 -1
  242. package/dist/server/operations/get-active-workflow-revision.d.ts +32 -0
  243. package/dist/server/operations/get-active-workflow-revision.js +46 -0
  244. package/dist/server/operations/get-catalog-diagnostics.d.ts +85 -0
  245. package/dist/server/operations/get-catalog-diagnostics.js +57 -0
  246. package/dist/server/operations/get-registry.js +17 -4
  247. package/dist/server/operations/get-workflow-revision.d.ts +25 -0
  248. package/dist/server/operations/get-workflow-revision.js +50 -0
  249. package/dist/server/operations/install-workflow-revision.d.ts +27 -0
  250. package/dist/server/operations/install-workflow-revision.js +46 -0
  251. package/dist/server/operations/list-workflow-revisions.d.ts +20 -0
  252. package/dist/server/operations/list-workflow-revisions.js +40 -0
  253. package/dist/server/operations/start-or-signal-workflow.js +1 -1
  254. package/dist/server/operations/start-workflow.js +1 -1
  255. package/dist/server/operations/static-registrations.js +36 -0
  256. package/dist/server/operations/storage.js +2 -2
  257. package/dist/server/operations/submit-review-decision.js +1 -1
  258. package/dist/server/operations/workflow-catalog-operation-helpers.d.ts +59 -0
  259. package/dist/server/operations/workflow-catalog-operation-helpers.js +135 -0
  260. package/dist/server/runtime/websocket-upgrade.js +2 -0
  261. package/dist/storage/bun-sql.js +49 -6
  262. package/dist/storage/catalog-keys.d.ts +45 -0
  263. package/dist/storage/catalog-keys.js +6 -0
  264. package/dist/storage/compressed-storage.js +1 -1
  265. package/dist/storage/derived-operations.js +1 -1
  266. package/dist/storage/index.d.ts +26 -1
  267. package/dist/storage/interface.d.ts +26 -1
  268. package/dist/storage/interface.js +1 -1
  269. package/dist/storage/key-encoding.d.ts +15 -0
  270. package/dist/storage/key-encoding.js +3 -0
  271. package/dist/storage/key-prefixes.d.ts +1 -1
  272. package/dist/storage/key-prefixes.js +15 -0
  273. package/dist/storage/lmdb.d.ts +26 -1
  274. package/dist/storage/lmdb.js +1 -1
  275. package/dist/storage/mailbox-keys.d.ts +80 -0
  276. package/dist/storage/mailbox-keys.js +14 -0
  277. package/dist/storage/memory.js +1 -1
  278. package/dist/storage/neon.js +2 -2
  279. package/dist/storage/node-sqlite-loader.d.ts +1 -1
  280. package/dist/storage/node-sqlite.js +49 -6
  281. package/dist/storage/outbox-keys.d.ts +77 -0
  282. package/dist/storage/outbox-keys.js +14 -0
  283. package/dist/storage/postgres.js +2 -2
  284. package/dist/storage/resolve.js +1 -1
  285. package/dist/storage/scoped-storage.js +1 -1
  286. package/dist/storage/storage-configuration.d.ts +6 -0
  287. package/dist/storage/testing.js +1 -1
  288. package/dist/storage/turso.js +2 -2
  289. package/dist/version.d.ts +1 -1
  290. package/dist/version.js +1 -1
  291. package/dist/web-extension.js +1 -1
  292. package/dist/worker/manifest/registry-contract-builder.d.ts +21 -3
  293. package/dist/worker/manifest/registry-contract-builder.js +40 -31
  294. package/package.json +1 -1
@@ -0,0 +1,158 @@
1
+ import {
2
+ raceAbort,
3
+ raceAbortWithin,
4
+ WaitBudgetElapsedError
5
+ } from "./application-primitive-abort.js";
6
+ import { delayUnlessAborted } from "./application-primitive-timing.js";
7
+ import { requireWaitBudget } from "./outbox-guards.js";
8
+ import { runOutboxMaintenance } from "./outbox-maintenance.js";
9
+ import { deliverNext, requireAdapter } from "./outbox-runner.js";
10
+ import { loadOutboxHeader } from "./outbox-storage.js";
11
+ function count(counters, receipt) {
12
+ switch (receipt.state) {
13
+ case "acknowledged":
14
+ counters.acknowledged += 1;
15
+ return !0;
16
+ case "rejected":
17
+ counters.rejected += 1;
18
+ return !0;
19
+ case "retry-scheduled":
20
+ counters.retryScheduled += 1;
21
+ return !1;
22
+ case "dead-lettered":
23
+ counters.deadLettered += 1;
24
+ return !0;
25
+ case "cancelled":
26
+ counters.cancelled += 1;
27
+ return !0;
28
+ case "unknown-outcome":
29
+ counters.unknown += 1;
30
+ return !0;
31
+ default:
32
+ return !1;
33
+ }
34
+ }
35
+ export async function drainOutbox(runtime, options) {
36
+ requireAdapter(runtime);
37
+ const { timeoutMs, pollIntervalMs } = requireWaitBudget(options), deadline = runtime.now() + timeoutMs, counters = {
38
+ acknowledged: 0,
39
+ rejected: 0,
40
+ retryScheduled: 0,
41
+ deadLettered: 0,
42
+ cancelled: 0,
43
+ unknown: 0
44
+ }, stop = drainStopSignal(options.signal, timeoutMs);
45
+ let drained = !1;
46
+ try {
47
+ let lastKnownPending = await readOpenCount(runtime, stop.signal);
48
+ lastKnownPending = subtract(lastKnownPending, await maintainOutbox(runtime, counters, stop.signal));
49
+ while (drainActive(runtime, stop.signal) && !budgetSpent(timeoutMs, deadline, runtime.now())) {
50
+ const result = await deliverUnlessStopped(runtime, stop.signal);
51
+ if (result === null)
52
+ break;
53
+ if (result.status === "settled") {
54
+ lastKnownPending = absorbDelivery(counters, result, lastKnownPending);
55
+ continue;
56
+ }
57
+ const round = await pauseBeforeNextRound(runtime, result, {
58
+ counters,
59
+ deadline,
60
+ pending: lastKnownPending,
61
+ pollIntervalMs,
62
+ stop: stop.signal
63
+ });
64
+ lastKnownPending = round.pending;
65
+ drained = round.status === "drained";
66
+ if (round.status !== "again")
67
+ break;
68
+ }
69
+ const pending = runtime.disposal.aborted ? lastKnownPending : await readOpenCount(runtime, stop.signal) ?? lastKnownPending;
70
+ return Object.freeze({ ...counters, pending, drained });
71
+ } finally {
72
+ stop.release();
73
+ }
74
+ }
75
+ function drainStopSignal(callerSignal, timeoutMs) {
76
+ const controller = new AbortController, onCallerAbort = () => {
77
+ controller.abort(callerSignal?.reason);
78
+ };
79
+ if (callerSignal?.aborted === !0)
80
+ onCallerAbort();
81
+ else
82
+ callerSignal?.addEventListener("abort", onCallerAbort, { once: !0 });
83
+ const timer = timeoutMs > 0 ? setTimeout(() => {
84
+ controller.abort(new WaitBudgetElapsedError);
85
+ }, timeoutMs) : null;
86
+ timer?.unref?.();
87
+ return {
88
+ signal: controller.signal,
89
+ release: () => {
90
+ callerSignal?.removeEventListener("abort", onCallerAbort);
91
+ if (timer !== null)
92
+ clearTimeout(timer);
93
+ }
94
+ };
95
+ }
96
+ async function deliverUnlessStopped(runtime, stop) {
97
+ const delivery = deliverNext(runtime, { signal: stop }), raced = await raceAbort(() => delivery, stop);
98
+ if (raced.aborted) {
99
+ delivery.catch(() => {
100
+ return;
101
+ });
102
+ return null;
103
+ }
104
+ return raced.value;
105
+ }
106
+ function absorbDelivery(counters, result, pending) {
107
+ if (!result.committed)
108
+ return pending;
109
+ return count(counters, result.receipt) ? subtract(pending, 1) : pending;
110
+ }
111
+ function subtract(pending, closed) {
112
+ return pending === null ? null : Math.max(0, pending - (closed ?? 0));
113
+ }
114
+ function drainActive(runtime, stop) {
115
+ return !runtime.disposal.aborted && !stop.aborted;
116
+ }
117
+ function budgetSpent(timeoutMs, deadline, now) {
118
+ return timeoutMs > 0 && now >= deadline;
119
+ }
120
+ async function readOpenCount(runtime, stop) {
121
+ const raced = await raceAbortWithin(() => loadOutboxHeader(runtime.storage, runtime.keys, runtime.policy.namespace, runtime.policy.ownerId), null, stop);
122
+ return raced.aborted ? null : raced.value.record.openCount;
123
+ }
124
+ async function maintainOutbox(runtime, counters, stop) {
125
+ const pass = runOutboxMaintenance(runtime, runtime.now(), stop), raced = await raceAbort(() => pass, stop);
126
+ if (raced.aborted) {
127
+ pass.catch(() => {
128
+ return;
129
+ });
130
+ return null;
131
+ }
132
+ const report = raced.value;
133
+ counters.unknown += report.parked;
134
+ counters.deadLettered += report.deadLettered;
135
+ counters.retryScheduled += report.rescheduled;
136
+ return report.parked + report.deadLettered;
137
+ }
138
+ async function pauseBeforeNextRound(runtime, result, context) {
139
+ if (!drainActive(runtime, context.stop))
140
+ return { status: "stop", pending: context.pending };
141
+ const closed = await maintainOutbox(runtime, context.counters, context.stop), cached = subtract(context.pending, closed);
142
+ if (closed === null || runtime.disposal.aborted)
143
+ return { status: "stop", pending: cached };
144
+ const pending = await readOpenCount(runtime, context.stop);
145
+ if (pending === null)
146
+ return { status: "stop", pending: cached };
147
+ if (pending === 0)
148
+ return { status: "drained", pending };
149
+ const remaining = context.deadline - runtime.now();
150
+ if (remaining <= 0)
151
+ return { status: "stop", pending };
152
+ const wait = nextWait(result, remaining, context.pollIntervalMs, runtime.now());
153
+ return { status: await delayUnlessAborted(wait, runtime.disposal, context.stop) ? "again" : "stop", pending };
154
+ }
155
+ function nextWait(result, remaining, pollIntervalMs, now) {
156
+ const untilDue = result.status === "held" ? Math.max(1, result.availableAt - now) : pollIntervalMs;
157
+ return Math.min(remaining, pollIntervalMs, untilDue);
158
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Enqueue for the application delivery outbox (WFT-85): validating an offered
3
+ * delivery, resolving its idempotency identity, enforcing backlog capacity,
4
+ * and committing the record with its indexes and fleet event.
5
+ *
6
+ * Enqueue is the one transition that also allocates: it advances the outbox
7
+ * header's sequence and open count in the same conditional batch as the record
8
+ * itself, so backlog accounting can never drift from the records it describes.
9
+ *
10
+ * @module core/outbox-enqueue
11
+ */
12
+ import type { ApplicationDeliveryAdmission, ApplicationDeliveryInput, OutboxCapacity } from './outbox-contract.ts';
13
+ import { type OutboxRuntime } from './outbox-internals.ts';
14
+ /** Backlog accounting, shared by enqueue rejection and the public `capacity()`. */
15
+ export declare function capacityOf(runtime: OutboxRuntime, open: number, enqueued: number): OutboxCapacity;
16
+ /**
17
+ * Offer a delivery to the outbox.
18
+ *
19
+ * An exact retry of the same idempotency identity returns the original
20
+ * receipt. Reusing the key with a different destination, kind, or payload
21
+ * digest returns a conflict and leaves the original untouched. A full backlog
22
+ * is rejected before anything is persisted.
23
+ */
24
+ export declare function enqueueDelivery(runtime: OutboxRuntime, delivery: ApplicationDeliveryInput): Promise<ApplicationDeliveryAdmission>;
@@ -0,0 +1,115 @@
1
+ import { computeIdentityDigest } from "./application-payload-digest.js";
2
+ import { ApplicationDeliveryValidationError, requireGeneratedIdentifier } from "./outbox-guards.js";
3
+ import {
4
+ encodeApplicationDeliveryEntry,
5
+ encodeApplicationDeliveryIdempotencyRecord
6
+ } from "./outbox-index-codec.js";
7
+ import {
8
+ describeDeliveryTransition,
9
+ MAX_OUTBOX_TRANSITION_ATTEMPTS,
10
+ OutboxContentionError,
11
+ toApplicationDeliveryReceipt
12
+ } from "./outbox-internals.js";
13
+ import {
14
+ commitOutboxTransition,
15
+ headerOperation,
16
+ loadDelivery,
17
+ loadDeliveryIdempotencyBinding,
18
+ loadOutboxHeader,
19
+ planDeliveryTransition
20
+ } from "./outbox-storage.js";
21
+ import { createEnqueuedDeliveryRecord } from "./outbox-transitions.js";
22
+ import { OUTBOX_RECORD_VERSION } from "./outbox-types.js";
23
+ import { validateDeliveryInput } from "./outbox-validation.js";
24
+ import { PersistedDataCorruptError } from "./persisted-data-incompatible-error.js";
25
+ export function capacityOf(runtime, open, enqueued) {
26
+ const limit = runtime.policy.maxBacklog;
27
+ return Object.freeze({ open, limit, remaining: Math.max(0, limit - open), enqueued });
28
+ }
29
+ function identityOf(record) {
30
+ return computeIdentityDigest([record.destinationRef, record.kind, record.payloadDigest]);
31
+ }
32
+ export async function enqueueDelivery(runtime, delivery) {
33
+ const input = await validateDeliveryInput(delivery, runtime.policy), identityDigest = await identityOf(input);
34
+ for (let attempt = 1;attempt <= MAX_OUTBOX_TRANSITION_ATTEMPTS; attempt += 1) {
35
+ let expectedBinding = null;
36
+ if (input.idempotencyKey !== void 0) {
37
+ const resolved = await resolveIdempotency(runtime, input.idempotencyKey, identityDigest);
38
+ if (resolved.admission !== null)
39
+ return resolved.admission;
40
+ expectedBinding = resolved.staleBindingBytes;
41
+ }
42
+ const header = await loadOutboxHeader(runtime.storage, runtime.keys, runtime.policy.namespace, runtime.policy.ownerId);
43
+ if (header.record.openCount >= runtime.policy.maxBacklog)
44
+ return {
45
+ status: "rejected",
46
+ reason: "backlog-full",
47
+ capacity: capacityOf(runtime, header.record.openCount, header.record.enqueuedCount)
48
+ };
49
+ if (header.record.nextSequence >= Number.MAX_SAFE_INTEGER)
50
+ throw new ApplicationDeliveryValidationError("This outbox has exhausted its sequence allocator; no further deliveries can be enqueued under this namespace and owner id.");
51
+ const now = runtime.now(), record = createEnqueuedDeliveryRecord(input, {
52
+ namespace: runtime.policy.namespace,
53
+ ownerId: runtime.policy.ownerId,
54
+ deliveryId: requireGeneratedIdentifier(runtime.generateId(), "deliveryId"),
55
+ sequence: header.record.nextSequence,
56
+ now
57
+ }), idempotencyKey = input.idempotencyKey;
58
+ if (!await commitOutboxTransition(runtime.storage, runtime.events, planDeliveryTransition(runtime.keys, {
59
+ previous: null,
60
+ expectedBytes: null,
61
+ next: record,
62
+ event: describeDeliveryTransition(null, record),
63
+ now,
64
+ extraConditions: [
65
+ { key: runtime.keys.header, expectedValue: header.bytes },
66
+ ...idempotencyKey === void 0 ? [] : [{ key: runtime.keys.idempotency(idempotencyKey), expectedValue: expectedBinding }]
67
+ ],
68
+ extraOperations: [
69
+ {
70
+ type: "put",
71
+ key: runtime.keys.bySequence(record.sequence),
72
+ value: encodeApplicationDeliveryEntry(record.deliveryId)
73
+ },
74
+ headerOperation(runtime.keys, {
75
+ ...header.record,
76
+ nextSequence: header.record.nextSequence + 1,
77
+ openCount: header.record.openCount + 1,
78
+ enqueuedCount: header.record.enqueuedCount + 1
79
+ }),
80
+ ...idempotencyKey === void 0 ? [] : [
81
+ {
82
+ type: "put",
83
+ key: runtime.keys.idempotency(idempotencyKey),
84
+ value: encodeApplicationDeliveryIdempotencyRecord({
85
+ recordVersion: OUTBOX_RECORD_VERSION,
86
+ deliveryId: record.deliveryId,
87
+ identityDigest
88
+ })
89
+ }
90
+ ]
91
+ ]
92
+ })))
93
+ continue;
94
+ return { status: "enqueued", receipt: toApplicationDeliveryReceipt(record) };
95
+ }
96
+ throw new OutboxContentionError("enqueue", null);
97
+ }
98
+ async function resolveIdempotency(runtime, idempotencyKey, identityDigest) {
99
+ const binding = await loadDeliveryIdempotencyBinding(runtime.storage, runtime.keys, idempotencyKey);
100
+ if (binding === null)
101
+ return { admission: null, staleBindingBytes: null };
102
+ const loaded = await loadDelivery(runtime.storage, runtime.keys, binding.record.deliveryId);
103
+ if (loaded === null)
104
+ return { admission: null, staleBindingBytes: binding.bytes };
105
+ const ownDigest = await identityOf(loaded.record);
106
+ if (loaded.record.idempotencyKey !== idempotencyKey || ownDigest !== binding.record.identityDigest)
107
+ throw new PersistedDataCorruptError(runtime.keys.idempotency(idempotencyKey));
108
+ const receipt = toApplicationDeliveryReceipt(loaded.record);
109
+ if (binding.record.identityDigest !== identityDigest)
110
+ return {
111
+ admission: { status: "conflict", receipt, reason: "idempotency-identity-mismatch" },
112
+ staleBindingBytes: null
113
+ };
114
+ return { admission: { status: "duplicate", receipt }, staleBindingBytes: null };
115
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * The delivery outbox's binding of the shared application guards (WFT-85),
3
+ * plus the ceilings and checks only the outbox needs.
4
+ *
5
+ * Every guard throws `ApplicationDeliveryValidationError`, so a caller mistake
6
+ * surfaces as the outbox's own typed diagnostic rather than as the mailbox's.
7
+ *
8
+ * @module core/outbox-guards
9
+ */
10
+ import type { ApplicationDeliveryFailure } from './outbox-types.ts';
11
+ import { WeftError } from './weft-error.ts';
12
+ export { DEFAULT_WAIT_POLL_INTERVAL_MS, MAX_APPLICATION_IDENTITY_BYTES, MAX_DURABLE_METADATA_BYTES, MAX_TIMER_DELAY_MS, } from './application-primitive-guards.ts';
13
+ export { MAX_APPLICATION_PAYLOAD_REFERENCE_BYTES } from './application-primitive-payload.ts';
14
+ /**
15
+ * Maximum bytes in an idempotency key or an external idempotency key. Matches
16
+ * the persisted-identifier ceiling the record decoder enforces, so a key
17
+ * admission accepts can never be one every later read rejects as corrupt.
18
+ */
19
+ export declare const MAX_APPLICATION_DELIVERY_IDEMPOTENCY_KEY_BYTES = 256;
20
+ /** Maximum attempts any one delivery may be configured for. */
21
+ export declare const MAX_APPLICATION_DELIVERY_ATTEMPTS = 100;
22
+ /** Maximum open deliveries any one outbox may be configured for. */
23
+ export declare const MAX_OUTBOX_BACKLOG = 1000000;
24
+ /** Ceiling on a `list()` limit. */
25
+ export declare const MAX_OUTBOX_LIST_LIMIT = 1000;
26
+ /** Maximum bytes in a failure message. */
27
+ export declare const MAX_DELIVERY_FAILURE_MESSAGE_BYTES = 4096;
28
+ /** Maximum bytes in a cancellation reason. */
29
+ export declare const MAX_DELIVERY_CANCELLATION_REASON_BYTES = 1024;
30
+ /**
31
+ * Thrown when a caller supplies an invalid delivery, option, identifier, or
32
+ * outcome, or calls a disposed outbox.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * import { ApplicationDeliveryValidationError } from '@lostgradient/weft';
37
+ *
38
+ * const error = new ApplicationDeliveryValidationError('destinationRef must be a non-empty string.');
39
+ * console.log(error.code); // 'ApplicationDeliveryValidationError'
40
+ * ```
41
+ */
42
+ export declare class ApplicationDeliveryValidationError extends WeftError<'ApplicationDeliveryValidationError'> {
43
+ constructor(message: string, options?: ErrorOptions);
44
+ }
45
+ export declare const requireIdentity: (value: unknown, field: string, maxBytes: number) => string, optionalIdentityOf: (value: unknown, field: string, maxBytes: number) => string | undefined, requirePositiveInteger: (value: unknown, field: string, maximum: number) => number, requireNonNegativeInteger: (value: unknown, field: string, maximum: number) => number, validateDurableJSONValue: (value: unknown, field: string) => import("./json.ts").JSONValue | undefined, requireGeneratedIdentifier: (value: string, field: string) => string, requireClockInstant: (now: number, source?: string) => number, requireDerivedInstant: (instant: number, field: string) => number, requireMaintenanceInstant: (now: number) => number, requireWaitBudget: (options: {
46
+ readonly timeoutMs?: number | undefined;
47
+ readonly pollIntervalMs?: number | undefined;
48
+ }) => {
49
+ readonly timeoutMs: number;
50
+ readonly pollIntervalMs: number;
51
+ };
52
+ /**
53
+ * Validate the message and details a transport attached to an outcome before
54
+ * they become durable evidence. The reason is assigned by the outbox from the
55
+ * outcome's status, never taken from the caller.
56
+ *
57
+ * @throws {ApplicationDeliveryValidationError} When `details` is not JSON-safe
58
+ * or `message` is oversized.
59
+ */
60
+ export declare function validateFailureEvidence(reason: ApplicationDeliveryFailure['reason'], message: unknown, details: unknown): ApplicationDeliveryFailure;
61
+ /**
62
+ * Bound a diagnostic string the outbox composes itself (an adapter's thrown
63
+ * error, say) to the failure-message ceiling, cutting on a character boundary
64
+ * and keeping the result well-formed, so a misbehaving transport cannot grow
65
+ * a delivery record without limit.
66
+ */
67
+ export declare function boundFailureMessage(text: string): string;
68
+ /** Validate a caller-supplied cancellation reason before it becomes durable. */
69
+ export declare function validateCancellationReason(reason: string | undefined): string | undefined;
70
+ /** Clamp a caller-supplied listing limit into the bounded range. */
71
+ export declare function clampListLimit(limit: number | undefined): number;
72
+ /**
73
+ * Validate a caller-supplied delivery id before it reaches key construction,
74
+ * where an unpaired surrogate would escape as a raw `URIError`.
75
+ */
76
+ export declare function validateDeliveryIdentifier(deliveryId: unknown): string;
@@ -0,0 +1,60 @@
1
+ import {
2
+ byteLengthOf,
3
+ createApplicationGuards,
4
+ MAX_APPLICATION_IDENTITY_BYTES
5
+ } from "./application-primitive-guards.js";
6
+ import { WeftError } from "./weft-error.js";
7
+ export {
8
+ DEFAULT_WAIT_POLL_INTERVAL_MS,
9
+ MAX_APPLICATION_IDENTITY_BYTES,
10
+ MAX_DURABLE_METADATA_BYTES,
11
+ MAX_TIMER_DELAY_MS
12
+ } from "./application-primitive-guards.js";
13
+ export { MAX_APPLICATION_PAYLOAD_REFERENCE_BYTES } from "./application-primitive-payload.js";
14
+ export const MAX_APPLICATION_DELIVERY_IDEMPOTENCY_KEY_BYTES = MAX_APPLICATION_IDENTITY_BYTES, MAX_APPLICATION_DELIVERY_ATTEMPTS = 100, MAX_OUTBOX_BACKLOG = 1e6, MAX_OUTBOX_LIST_LIMIT = 1000, MAX_DELIVERY_FAILURE_MESSAGE_BYTES = 4096, MAX_DELIVERY_CANCELLATION_REASON_BYTES = 1024;
15
+
16
+ export class ApplicationDeliveryValidationError extends WeftError {
17
+ constructor(message, options) {
18
+ super("ApplicationDeliveryValidationError", message, options);
19
+ }
20
+ }
21
+ export const {
22
+ requireIdentity,
23
+ optionalIdentityOf,
24
+ requirePositiveInteger,
25
+ requireNonNegativeInteger,
26
+ validateDurableJSONValue,
27
+ requireGeneratedIdentifier,
28
+ requireClockInstant,
29
+ requireDerivedInstant,
30
+ requireMaintenanceInstant,
31
+ requireWaitBudget
32
+ } = createApplicationGuards(ApplicationDeliveryValidationError);
33
+ export function validateFailureEvidence(reason, message, details) {
34
+ return {
35
+ reason,
36
+ message: optionalIdentityOf(message, "message", MAX_DELIVERY_FAILURE_MESSAGE_BYTES),
37
+ details: validateDurableJSONValue(details, "details")
38
+ };
39
+ }
40
+ export function boundFailureMessage(text) {
41
+ let bounded = text.toWellFormed();
42
+ while (byteLengthOf(bounded) > MAX_DELIVERY_FAILURE_MESSAGE_BYTES) {
43
+ const excess = byteLengthOf(bounded) - MAX_DELIVERY_FAILURE_MESSAGE_BYTES;
44
+ bounded = bounded.slice(0, -Math.max(1, Math.ceil(excess / 4))).toWellFormed();
45
+ }
46
+ return bounded;
47
+ }
48
+ export function validateCancellationReason(reason) {
49
+ return optionalIdentityOf(reason, "reason", MAX_DELIVERY_CANCELLATION_REASON_BYTES);
50
+ }
51
+ export function clampListLimit(limit) {
52
+ if (limit === void 0)
53
+ return 100;
54
+ if (!Number.isSafeInteger(limit) || limit < 1)
55
+ throw new ApplicationDeliveryValidationError("limit must be a positive safe integer.");
56
+ return Math.min(limit, MAX_OUTBOX_LIST_LIMIT);
57
+ }
58
+ export function validateDeliveryIdentifier(deliveryId) {
59
+ return requireIdentity(deliveryId, "deliveryId", 256);
60
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Encoding and fail-closed decoding for the application outbox's index
3
+ * records (WFT-85): the per-outbox header, the idempotency binding, and the
4
+ * delivery-id entries the due, listing, and terminal indexes hold.
5
+ *
6
+ * @module core/outbox-index-codec
7
+ */
8
+ import type { ApplicationDeliveryIdempotencyRecord, OutboxRecord } from './outbox-types.ts';
9
+ /**
10
+ * Decode the per-outbox header.
11
+ *
12
+ * @throws {PersistedDataCorruptError} When the stored bytes are malformed or
13
+ * name a different outbox than the key does.
14
+ */
15
+ export declare function decodeOutboxRecord(bytes: Uint8Array, key: string): OutboxRecord;
16
+ /** Encode the per-outbox header. */
17
+ export declare function encodeOutboxRecord(record: OutboxRecord): Uint8Array;
18
+ /**
19
+ * Decode an idempotency binding.
20
+ *
21
+ * @throws {PersistedDataCorruptError} When the stored bytes are malformed.
22
+ */
23
+ export declare function decodeApplicationDeliveryIdempotencyRecord(bytes: Uint8Array, key: string): ApplicationDeliveryIdempotencyRecord;
24
+ /** Encode an idempotency binding. */
25
+ export declare function encodeApplicationDeliveryIdempotencyRecord(record: ApplicationDeliveryIdempotencyRecord): Uint8Array;
26
+ /**
27
+ * Decode a due, listing, or terminal index entry: the delivery id it points at.
28
+ *
29
+ * @throws {PersistedDataCorruptError} When the entry is not a usable identifier.
30
+ */
31
+ export declare function decodeApplicationDeliveryEntry(bytes: Uint8Array, key: string): string;
32
+ /** Encode a due, listing, or terminal index entry. */
33
+ export declare function encodeApplicationDeliveryEntry(deliveryId: string): Uint8Array;
@@ -0,0 +1,71 @@
1
+ import { KEYS } from "../storage/interface.js";
2
+ import {
3
+ fail,
4
+ isRecordObject,
5
+ ownKey,
6
+ readIdentifier,
7
+ readInteger,
8
+ readString,
9
+ readVersion
10
+ } from "./application-primitive-codec.js";
11
+ import { decode, encode } from "./codec.js";
12
+ import { OUTBOX_RECORD_VERSION } from "./outbox-types.js";
13
+ export function decodeOutboxRecord(bytes, key) {
14
+ let decoded;
15
+ try {
16
+ decoded = decode(bytes);
17
+ } catch {
18
+ fail(key);
19
+ }
20
+ if (!isRecordObject(decoded))
21
+ fail(key);
22
+ readVersion(decoded, key, OUTBOX_RECORD_VERSION);
23
+ const namespace = readString(decoded, "namespace", key), ownerId = readString(decoded, "ownerId", key);
24
+ if (ownKey(() => KEYS.applicationOutbox(namespace, ownerId), key) !== key)
25
+ fail(key);
26
+ const nextSequence = readInteger(decoded, "nextSequence", key), openCount = readInteger(decoded, "openCount", key), enqueuedCount = readInteger(decoded, "enqueuedCount", key);
27
+ if (openCount > enqueuedCount || nextSequence < enqueuedCount)
28
+ fail(key);
29
+ return {
30
+ recordVersion: OUTBOX_RECORD_VERSION,
31
+ namespace,
32
+ ownerId,
33
+ nextSequence,
34
+ openCount,
35
+ enqueuedCount
36
+ };
37
+ }
38
+ export function encodeOutboxRecord(record) {
39
+ return encode(record);
40
+ }
41
+ export function decodeApplicationDeliveryIdempotencyRecord(bytes, key) {
42
+ let decoded;
43
+ try {
44
+ decoded = decode(bytes);
45
+ } catch {
46
+ fail(key);
47
+ }
48
+ if (!isRecordObject(decoded))
49
+ fail(key);
50
+ readVersion(decoded, key, OUTBOX_RECORD_VERSION);
51
+ return {
52
+ recordVersion: OUTBOX_RECORD_VERSION,
53
+ deliveryId: readIdentifier(decoded.deliveryId, key),
54
+ identityDigest: readString(decoded, "identityDigest", key)
55
+ };
56
+ }
57
+ export function encodeApplicationDeliveryIdempotencyRecord(record) {
58
+ return encode(record);
59
+ }
60
+ export function decodeApplicationDeliveryEntry(bytes, key) {
61
+ let decoded;
62
+ try {
63
+ decoded = decode(bytes);
64
+ } catch {
65
+ fail(key);
66
+ }
67
+ return readIdentifier(decoded, key);
68
+ }
69
+ export function encodeApplicationDeliveryEntry(deliveryId) {
70
+ return encode(deliveryId);
71
+ }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Shared runtime plumbing for the application delivery outbox (WFT-85): the
3
+ * per-instance runtime, the contention error, receipt projection, fleet event
4
+ * description, process-local attempt release, and the commit that keeps the
5
+ * header's backlog accounting consistent with every transition.
6
+ *
7
+ * @module core/outbox-internals
8
+ */
9
+ import type { BatchOperation, ConditionalBatchCondition, Storage } from '../storage/interface.ts';
10
+ import type { AttemptRegistry } from './application-primitive-attempt-registry.ts';
11
+ import type { ApplicationDeliveryAdapter, ApplicationDeliveryReceipt, OutboxEventSink } from './outbox-contract.ts';
12
+ import { type LoadedOutboxRecord, type OutboxKeys } from './outbox-storage.ts';
13
+ import { type ApplicationDeliveryRecord } from './outbox-types.ts';
14
+ import type { ResolvedOutboxPolicy } from './outbox-validation.ts';
15
+ import { WeftError } from './weft-error.ts';
16
+ /** How many times one operation re-reads and retries a lost compare-and-swap. */
17
+ export declare const MAX_OUTBOX_TRANSITION_ATTEMPTS = 25;
18
+ /** How many scan pages one maintenance pass may walk. */
19
+ export declare const OUTBOX_MAINTENANCE_MAX_PAGES = 200;
20
+ /** The registry-scope tag for the outbox, so it never shares a registry with the mailbox. */
21
+ export declare const OUTBOX_PRIMITIVE = "outbox";
22
+ /** Everything an outbox operation needs that is fixed at construction. */
23
+ export type OutboxRuntime = {
24
+ readonly storage: Storage;
25
+ readonly events: OutboxEventSink | undefined;
26
+ readonly adapter: ApplicationDeliveryAdapter | undefined;
27
+ readonly policy: ResolvedOutboxPolicy;
28
+ readonly keys: OutboxKeys;
29
+ readonly now: () => number;
30
+ readonly generateId: () => string;
31
+ /** The process-local disposal signal every wait and attempt races. */
32
+ readonly disposal: AbortSignal;
33
+ readonly attemptControllers: AttemptRegistry;
34
+ /** Record an attempt this handle now owns, or report that disposal already won. */
35
+ readonly adoptAttempt: (attemptToken: string) => (() => void) | null;
36
+ readonly readMaintenanceCursor: () => string | undefined;
37
+ readonly writeMaintenanceCursor: (cursor: string | undefined) => void;
38
+ };
39
+ /**
40
+ * Thrown when a transition keeps losing its compare-and-swap: durable
41
+ * contention on this outbox is real, and the caller decides whether to back
42
+ * off, shed load, or shard the owner.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * import { OutboxContentionError } from '@lostgradient/weft';
47
+ *
48
+ * const error = new OutboxContentionError('enqueue', null);
49
+ * console.log(error.code); // 'OutboxContentionError'
50
+ * ```
51
+ */
52
+ export declare class OutboxContentionError extends WeftError<'OutboxContentionError'> {
53
+ /** The outbox operation that could not commit. */
54
+ readonly operation: string;
55
+ /** The delivery the operation targeted, or `null` for outbox-wide operations. */
56
+ readonly deliveryId: string | null;
57
+ constructor(operation: string, deliveryId: string | null);
58
+ }
59
+ /**
60
+ * Project a durable record into the immutable public receipt. The attempt
61
+ * token and the credential reference are never projected.
62
+ */
63
+ export declare function toApplicationDeliveryReceipt(record: ApplicationDeliveryRecord): ApplicationDeliveryReceipt;
64
+ /**
65
+ * The durable fleet event that describes a transition. Bounded and free of
66
+ * secrets: no payload, no evidence, no failure details, and neither the
67
+ * destination nor the credential reference.
68
+ */
69
+ export declare function describeDeliveryTransition(previous: ApplicationDeliveryRecord | null, next: ApplicationDeliveryRecord): {
70
+ readonly kind: string;
71
+ readonly payload: unknown;
72
+ };
73
+ /** Abort and forget the process-local controller for one attempt. */
74
+ export declare function releaseAttemptController(runtime: OutboxRuntime, attemptToken: string, reason: string, deliveryId?: string): void;
75
+ /**
76
+ * Release every attempt this process holds for one delivery that is not its
77
+ * current lease, fenced by the lease-commit serial the snapshot was read at.
78
+ */
79
+ export declare function releaseAttemptsForDelivery(runtime: OutboxRuntime, deliveryId: string, reason: string, currentToken?: string, observedAt?: number): void;
80
+ /**
81
+ * Commit one delivery transition together with the index maintenance and
82
+ * backlog accounting it implies.
83
+ *
84
+ * Closing a delivery decrements the header's open count and an operator
85
+ * retry that reopens one increments it, each in the same conditional batch as
86
+ * the record, so `capacity()` can never drift from the records it describes.
87
+ * Enqueue builds its own header operation because it also allocates the
88
+ * sequence.
89
+ */
90
+ export declare function commitDeliveryTransition(runtime: OutboxRuntime, options: {
91
+ readonly previous: ApplicationDeliveryRecord | null;
92
+ readonly expectedBytes: Uint8Array | null;
93
+ readonly next: ApplicationDeliveryRecord;
94
+ readonly now: number;
95
+ readonly extraConditions?: readonly ConditionalBatchCondition[] | undefined;
96
+ readonly extraOperations?: readonly BatchOperation[] | undefined;
97
+ /** A header the caller already read and decided on; the commit fences on these bytes. */
98
+ readonly header?: LoadedOutboxRecord | undefined;
99
+ }): Promise<boolean>;