@workflow/core 5.0.0-beta.4 → 5.0.0-beta.41

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 (322) hide show
  1. package/dist/attribute-changes.d.ts +7 -0
  2. package/dist/attribute-changes.d.ts.map +1 -0
  3. package/dist/attribute-changes.js +25 -0
  4. package/dist/capabilities.d.ts +33 -1
  5. package/dist/capabilities.d.ts.map +1 -1
  6. package/dist/capabilities.js +71 -4
  7. package/dist/capture-stack.d.ts +16 -0
  8. package/dist/capture-stack.d.ts.map +1 -0
  9. package/dist/capture-stack.js +21 -0
  10. package/dist/class-serialization.d.ts +32 -0
  11. package/dist/class-serialization.d.ts.map +1 -1
  12. package/dist/class-serialization.js +37 -1
  13. package/dist/classify-error.d.ts +26 -3
  14. package/dist/classify-error.d.ts.map +1 -1
  15. package/dist/classify-error.js +109 -6
  16. package/dist/context-errors.d.ts +27 -0
  17. package/dist/context-errors.d.ts.map +1 -0
  18. package/dist/context-errors.js +101 -0
  19. package/dist/context-violation-error.d.ts +97 -0
  20. package/dist/context-violation-error.d.ts.map +1 -0
  21. package/dist/context-violation-error.js +149 -0
  22. package/dist/create-hook.d.ts +62 -4
  23. package/dist/create-hook.d.ts.map +1 -1
  24. package/dist/create-hook.js +4 -3
  25. package/dist/define-hook.d.ts.map +1 -1
  26. package/dist/define-hook.js +20 -5
  27. package/dist/describe-error.d.ts +70 -0
  28. package/dist/describe-error.d.ts.map +1 -0
  29. package/dist/describe-error.js +189 -0
  30. package/dist/encryption.d.ts +37 -3
  31. package/dist/encryption.d.ts.map +1 -1
  32. package/dist/encryption.js +97 -31
  33. package/dist/events-consumer.d.ts +147 -1
  34. package/dist/events-consumer.d.ts.map +1 -1
  35. package/dist/events-consumer.js +444 -43
  36. package/dist/flushable-stream.d.ts +65 -10
  37. package/dist/flushable-stream.d.ts.map +1 -1
  38. package/dist/flushable-stream.js +131 -18
  39. package/dist/global.d.ts +37 -1
  40. package/dist/global.d.ts.map +1 -1
  41. package/dist/global.js +21 -3
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +2 -1
  45. package/dist/log-format.d.ts +25 -0
  46. package/dist/log-format.d.ts.map +1 -0
  47. package/dist/log-format.js +250 -0
  48. package/dist/logger.d.ts +29 -30
  49. package/dist/logger.d.ts.map +1 -1
  50. package/dist/logger.js +82 -32
  51. package/dist/private.d.ts +246 -8
  52. package/dist/private.d.ts.map +1 -1
  53. package/dist/private.js +345 -9
  54. package/dist/replay-payload-cache.d.ts +68 -0
  55. package/dist/replay-payload-cache.d.ts.map +1 -0
  56. package/dist/replay-payload-cache.js +160 -0
  57. package/dist/runtime/compute-instance.d.ts +12 -0
  58. package/dist/runtime/compute-instance.d.ts.map +1 -0
  59. package/dist/runtime/compute-instance.js +13 -0
  60. package/dist/runtime/constants.d.ts +251 -0
  61. package/dist/runtime/constants.d.ts.map +1 -1
  62. package/dist/runtime/constants.js +425 -16
  63. package/dist/runtime/count-step-started-events.d.ts +52 -0
  64. package/dist/runtime/count-step-started-events.d.ts.map +1 -0
  65. package/dist/runtime/count-step-started-events.js +72 -0
  66. package/dist/runtime/deployment-guard.d.ts +99 -0
  67. package/dist/runtime/deployment-guard.d.ts.map +1 -0
  68. package/dist/runtime/deployment-guard.js +154 -0
  69. package/dist/runtime/get-port-lazy.d.ts +25 -0
  70. package/dist/runtime/get-port-lazy.d.ts.map +1 -0
  71. package/dist/runtime/get-port-lazy.js +92 -0
  72. package/dist/runtime/get-world-lazy.d.ts +23 -0
  73. package/dist/runtime/get-world-lazy.d.ts.map +1 -0
  74. package/dist/runtime/get-world-lazy.js +46 -0
  75. package/dist/runtime/helpers.d.ts +327 -10
  76. package/dist/runtime/helpers.d.ts.map +1 -1
  77. package/dist/runtime/helpers.js +586 -40
  78. package/dist/runtime/quickjs-assets.generated.d.ts +14 -0
  79. package/dist/runtime/quickjs-assets.generated.d.ts.map +1 -0
  80. package/dist/runtime/quickjs-assets.generated.js +30 -0
  81. package/dist/runtime/quickjs-entrypoint.d.ts +124 -0
  82. package/dist/runtime/quickjs-entrypoint.d.ts.map +1 -0
  83. package/dist/runtime/quickjs-entrypoint.js +1437 -0
  84. package/dist/runtime/quickjs-runtime.d.ts +228 -0
  85. package/dist/runtime/quickjs-runtime.d.ts.map +1 -0
  86. package/dist/runtime/quickjs-runtime.js +2372 -0
  87. package/dist/runtime/quickjs-serde.d.ts +107 -0
  88. package/dist/runtime/quickjs-serde.d.ts.map +1 -0
  89. package/dist/runtime/quickjs-serde.js +2098 -0
  90. package/dist/runtime/replay-budget.d.ts +89 -0
  91. package/dist/runtime/replay-budget.d.ts.map +1 -0
  92. package/dist/runtime/replay-budget.js +139 -0
  93. package/dist/runtime/replay-recovery-reporter.d.ts +36 -0
  94. package/dist/runtime/replay-recovery-reporter.d.ts.map +1 -0
  95. package/dist/runtime/replay-recovery-reporter.js +64 -0
  96. package/dist/runtime/resume-hook.d.ts +27 -4
  97. package/dist/runtime/resume-hook.d.ts.map +1 -1
  98. package/dist/runtime/resume-hook.js +452 -76
  99. package/dist/runtime/run-id-time.d.ts +19 -0
  100. package/dist/runtime/run-id-time.d.ts.map +1 -0
  101. package/dist/runtime/run-id-time.js +42 -0
  102. package/dist/runtime/run.d.ts +8 -2
  103. package/dist/runtime/run.d.ts.map +1 -1
  104. package/dist/runtime/run.js +62 -15
  105. package/dist/runtime/runs.d.ts +54 -3
  106. package/dist/runtime/runs.d.ts.map +1 -1
  107. package/dist/runtime/runs.js +119 -13
  108. package/dist/runtime/start.d.ts +70 -1
  109. package/dist/runtime/start.d.ts.map +1 -1
  110. package/dist/runtime/start.js +313 -60
  111. package/dist/runtime/step-executor.d.ts +177 -0
  112. package/dist/runtime/step-executor.d.ts.map +1 -0
  113. package/dist/runtime/step-executor.js +946 -0
  114. package/dist/runtime/step-latency.d.ts +197 -0
  115. package/dist/runtime/step-latency.d.ts.map +1 -0
  116. package/dist/runtime/step-latency.js +207 -0
  117. package/dist/runtime/step-ownership.d.ts +72 -0
  118. package/dist/runtime/step-ownership.d.ts.map +1 -0
  119. package/dist/runtime/step-ownership.js +114 -0
  120. package/dist/runtime/step-single-flight.d.ts +12 -0
  121. package/dist/runtime/step-single-flight.d.ts.map +1 -0
  122. package/dist/runtime/step-single-flight.js +69 -0
  123. package/dist/runtime/suspension-handler.d.ts +109 -7
  124. package/dist/runtime/suspension-handler.d.ts.map +1 -1
  125. package/dist/runtime/suspension-handler.js +486 -140
  126. package/dist/runtime/vm-mode.d.ts +44 -0
  127. package/dist/runtime/vm-mode.d.ts.map +1 -0
  128. package/dist/runtime/vm-mode.js +62 -0
  129. package/dist/runtime/vm-serde-bundle.generated.d.ts +14 -0
  130. package/dist/runtime/vm-serde-bundle.generated.d.ts.map +1 -0
  131. package/dist/runtime/vm-serde-bundle.generated.js +16 -0
  132. package/dist/runtime/wait-continuation.d.ts +84 -0
  133. package/dist/runtime/wait-continuation.d.ts.map +1 -0
  134. package/dist/runtime/wait-continuation.js +105 -0
  135. package/dist/runtime/wait-until.d.ts +18 -0
  136. package/dist/runtime/wait-until.d.ts.map +1 -0
  137. package/dist/runtime/wait-until.js +42 -0
  138. package/dist/runtime/world-compatibility.d.ts +20 -0
  139. package/dist/runtime/world-compatibility.d.ts.map +1 -0
  140. package/dist/runtime/world-compatibility.js +32 -0
  141. package/dist/runtime/world-init.d.ts +50 -0
  142. package/dist/runtime/world-init.d.ts.map +1 -0
  143. package/dist/runtime/world-init.js +50 -0
  144. package/dist/runtime/world.d.ts +14 -2
  145. package/dist/runtime/world.d.ts.map +1 -1
  146. package/dist/runtime/world.js +101 -26
  147. package/dist/runtime.d.ts +17 -12
  148. package/dist/runtime.d.ts.map +1 -1
  149. package/dist/runtime.js +3135 -328
  150. package/dist/schemas.d.ts +1 -1
  151. package/dist/schemas.d.ts.map +1 -1
  152. package/dist/schemas.js +1 -1
  153. package/dist/sealed-box.d.ts +167 -0
  154. package/dist/sealed-box.d.ts.map +1 -0
  155. package/dist/sealed-box.js +571 -0
  156. package/dist/serialization/client.d.ts +17 -0
  157. package/dist/serialization/client.d.ts.map +1 -0
  158. package/dist/serialization/client.js +48 -0
  159. package/dist/serialization/codec-devalue-vm.d.ts +16 -0
  160. package/dist/serialization/codec-devalue-vm.d.ts.map +1 -0
  161. package/dist/serialization/codec-devalue-vm.js +148 -0
  162. package/dist/serialization/codec-devalue.d.ts +14 -0
  163. package/dist/serialization/codec-devalue.d.ts.map +1 -0
  164. package/dist/serialization/codec-devalue.js +105 -0
  165. package/dist/serialization/codec.d.ts +125 -0
  166. package/dist/serialization/codec.d.ts.map +1 -0
  167. package/dist/serialization/codec.js +17 -0
  168. package/dist/serialization/compression.d.ts +104 -0
  169. package/dist/serialization/compression.d.ts.map +1 -0
  170. package/dist/serialization/compression.js +260 -0
  171. package/dist/serialization/encryption.d.ts +134 -0
  172. package/dist/serialization/encryption.d.ts.map +1 -0
  173. package/dist/serialization/encryption.js +186 -0
  174. package/dist/serialization/errors.d.ts +34 -0
  175. package/dist/serialization/errors.d.ts.map +1 -0
  176. package/dist/serialization/errors.js +59 -0
  177. package/dist/serialization/format.d.ts +60 -0
  178. package/dist/serialization/format.d.ts.map +1 -0
  179. package/dist/serialization/format.js +97 -0
  180. package/dist/serialization/hardened.d.ts +155 -0
  181. package/dist/serialization/hardened.d.ts.map +1 -0
  182. package/dist/serialization/hardened.js +523 -0
  183. package/dist/serialization/index.d.ts +20 -0
  184. package/dist/serialization/index.d.ts.map +1 -0
  185. package/dist/serialization/index.js +22 -0
  186. package/dist/serialization/reducers/class-vm.d.ts +20 -0
  187. package/dist/serialization/reducers/class-vm.d.ts.map +1 -0
  188. package/dist/serialization/reducers/class-vm.js +77 -0
  189. package/dist/serialization/reducers/class.d.ts +11 -0
  190. package/dist/serialization/reducers/class.d.ts.map +1 -0
  191. package/dist/serialization/reducers/class.js +73 -0
  192. package/dist/serialization/reducers/common-vm.d.ts +15 -0
  193. package/dist/serialization/reducers/common-vm.d.ts.map +1 -0
  194. package/dist/serialization/reducers/common-vm.js +579 -0
  195. package/dist/serialization/reducers/common.d.ts +16 -0
  196. package/dist/serialization/reducers/common.d.ts.map +1 -0
  197. package/dist/serialization/reducers/common.js +478 -0
  198. package/dist/serialization/reducers/step-function-vm.d.ts +44 -0
  199. package/dist/serialization/reducers/step-function-vm.d.ts.map +1 -0
  200. package/dist/serialization/reducers/step-function-vm.js +97 -0
  201. package/dist/serialization/reducers/step-function.d.ts +35 -0
  202. package/dist/serialization/reducers/step-function.d.ts.map +1 -0
  203. package/dist/serialization/reducers/step-function.js +104 -0
  204. package/dist/serialization/step.d.ts +17 -0
  205. package/dist/serialization/step.d.ts.map +1 -0
  206. package/dist/serialization/step.js +48 -0
  207. package/dist/serialization/types.d.ts +273 -0
  208. package/dist/serialization/types.d.ts.map +1 -0
  209. package/dist/serialization/types.js +35 -0
  210. package/dist/serialization/workflow-vm.d.ts +29 -0
  211. package/dist/serialization/workflow-vm.d.ts.map +1 -0
  212. package/dist/serialization/workflow-vm.js +71 -0
  213. package/dist/serialization/workflow.d.ts +29 -0
  214. package/dist/serialization/workflow.d.ts.map +1 -0
  215. package/dist/serialization/workflow.js +54 -0
  216. package/dist/serialization-format.d.ts +60 -4
  217. package/dist/serialization-format.d.ts.map +1 -1
  218. package/dist/serialization-format.js +276 -56
  219. package/dist/serialization.d.ts +374 -221
  220. package/dist/serialization.d.ts.map +1 -1
  221. package/dist/serialization.js +2300 -783
  222. package/dist/set-attributes.d.ts +13 -0
  223. package/dist/set-attributes.d.ts.map +1 -0
  224. package/dist/set-attributes.js +60 -0
  225. package/dist/sleep.d.ts.map +1 -1
  226. package/dist/sleep.js +3 -2
  227. package/dist/source-map.d.ts +25 -0
  228. package/dist/source-map.d.ts.map +1 -1
  229. package/dist/source-map.js +148 -10
  230. package/dist/step/context-storage.d.ts +61 -2
  231. package/dist/step/context-storage.d.ts.map +1 -1
  232. package/dist/step/context-storage.js +7 -5
  233. package/dist/step/get-closure-vars.d.ts.map +1 -1
  234. package/dist/step/get-closure-vars.js +3 -2
  235. package/dist/step/get-step-metadata.d.ts.map +1 -1
  236. package/dist/step/get-step-metadata.js +3 -2
  237. package/dist/step/get-workflow-metadata.d.ts.map +1 -1
  238. package/dist/step/get-workflow-metadata.js +3 -2
  239. package/dist/step/writable-stream.d.ts.map +1 -1
  240. package/dist/step/writable-stream.js +71 -7
  241. package/dist/step.d.ts.map +1 -1
  242. package/dist/step.js +225 -29
  243. package/dist/symbols.d.ts +54 -0
  244. package/dist/symbols.d.ts.map +1 -1
  245. package/dist/symbols.js +55 -1
  246. package/dist/telemetry/semantic-conventions.d.ts +265 -2
  247. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  248. package/dist/telemetry/semantic-conventions.js +190 -1
  249. package/dist/telemetry.d.ts +73 -0
  250. package/dist/telemetry.d.ts.map +1 -1
  251. package/dist/telemetry.js +153 -16
  252. package/dist/types.d.ts +6 -0
  253. package/dist/types.d.ts.map +1 -1
  254. package/dist/types.js +23 -1
  255. package/dist/util.d.ts +16 -6
  256. package/dist/util.d.ts.map +1 -1
  257. package/dist/util.js +25 -16
  258. package/dist/version.d.ts +1 -1
  259. package/dist/version.d.ts.map +1 -1
  260. package/dist/version.js +2 -2
  261. package/dist/vm/index.d.ts.map +1 -1
  262. package/dist/vm/index.js +85 -14
  263. package/dist/vm/script-cache.d.ts +28 -0
  264. package/dist/vm/script-cache.d.ts.map +1 -0
  265. package/dist/vm/script-cache.js +140 -0
  266. package/dist/workflow/abort-controller.d.ts +65 -0
  267. package/dist/workflow/abort-controller.d.ts.map +1 -0
  268. package/dist/workflow/abort-controller.js +312 -0
  269. package/dist/workflow/attribute-dispatcher.d.ts +6 -0
  270. package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
  271. package/dist/workflow/attribute-dispatcher.js +48 -0
  272. package/dist/workflow/create-hook.d.ts.map +1 -1
  273. package/dist/workflow/create-hook.js +25 -3
  274. package/dist/workflow/define-hook.d.ts +1 -1
  275. package/dist/workflow/define-hook.d.ts.map +1 -1
  276. package/dist/workflow/define-hook.js +8 -4
  277. package/dist/workflow/get-workflow-metadata.d.ts.map +1 -1
  278. package/dist/workflow/get-workflow-metadata.js +14 -3
  279. package/dist/workflow/hook.d.ts.map +1 -1
  280. package/dist/workflow/hook.js +302 -36
  281. package/dist/workflow/index.d.ts +1 -0
  282. package/dist/workflow/index.d.ts.map +1 -1
  283. package/dist/workflow/index.js +5 -3
  284. package/dist/workflow/set-attributes.d.ts +68 -0
  285. package/dist/workflow/set-attributes.d.ts.map +1 -0
  286. package/dist/workflow/set-attributes.js +60 -0
  287. package/dist/workflow/sleep.d.ts.map +1 -1
  288. package/dist/workflow/sleep.js +57 -8
  289. package/dist/workflow/world-init-stub.d.ts +15 -0
  290. package/dist/workflow/world-init-stub.d.ts.map +1 -0
  291. package/dist/workflow/world-init-stub.js +15 -0
  292. package/dist/workflow.d.ts +79 -3
  293. package/dist/workflow.d.ts.map +1 -1
  294. package/dist/workflow.js +831 -553
  295. package/docs/api-reference/create-hook.mdx +79 -0
  296. package/docs/api-reference/create-webhook.mdx +1 -0
  297. package/docs/api-reference/define-hook.mdx +26 -24
  298. package/docs/api-reference/fatal-error.mdx +29 -7
  299. package/docs/api-reference/fetch.mdx +8 -4
  300. package/docs/api-reference/index.mdx +3 -0
  301. package/docs/api-reference/set-attributes.mdx +61 -0
  302. package/docs/api-reference/sleep.mdx +1 -1
  303. package/docs/foundations/cancellation.mdx +459 -0
  304. package/docs/foundations/errors-and-retries.mdx +7 -3
  305. package/docs/foundations/hooks.mdx +29 -0
  306. package/docs/foundations/idempotency.mdx +243 -11
  307. package/docs/foundations/index.mdx +1 -23
  308. package/docs/foundations/meta.json +3 -1
  309. package/docs/foundations/serialization.mdx +77 -41
  310. package/docs/foundations/starting-workflows.mdx +79 -2
  311. package/docs/foundations/streaming.mdx +14 -23
  312. package/docs/foundations/versioning.mdx +263 -0
  313. package/docs/how-it-works/cancellation.mdx +287 -0
  314. package/docs/how-it-works/code-transform.mdx +21 -17
  315. package/docs/how-it-works/encryption.mdx +5 -5
  316. package/docs/how-it-works/event-sourcing.mdx +17 -9
  317. package/docs/how-it-works/framework-integrations.mdx +96 -337
  318. package/docs/how-it-works/meta.json +2 -1
  319. package/package.json +31 -13
  320. package/dist/runtime/step-handler.d.ts +0 -2
  321. package/dist/runtime/step-handler.d.ts.map +0 -1
  322. package/dist/runtime/step-handler.js +0 -678
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Composable encryption layer for serialized data.
3
+ *
4
+ * Wraps/unwraps serialized payloads with either symmetric AES-256-GCM
5
+ * encryption (`encr`) or an asymmetric sealed box (`encp`), using the format
6
+ * prefix system to mark which. See {@link PayloadKey} for how a caller
7
+ * declares which capabilities it holds.
8
+ */
9
+ import { RuntimeDecryptionError } from '@workflow/errors';
10
+ import { decrypt as aesGcmDecrypt, encrypt as aesGcmEncrypt, importKey as importAesKey, } from '../encryption.js';
11
+ import { deriveRunKeyPair, open as openSealed, seal as sealToPublicKey, } from '../sealed-box.js';
12
+ import { decodeFormatPrefix, encodeWithFormatPrefix, peekFormatPrefix, } from './format.js';
13
+ import { SerializationFormat } from './types.js';
14
+ /**
15
+ * Brands distinguishing the structured key variants from a bare `CryptoKey`.
16
+ *
17
+ * `Symbol.for` rather than `Symbol()` because these values cross realm
18
+ * boundaries (host ↔ workflow VM), and the global symbol registry is shared
19
+ * across realms while unique symbols are not.
20
+ */
21
+ const SEAL_TARGET_BRAND = Symbol.for('workflow.serialization.sealTarget');
22
+ const RUN_KEYS_BRAND = Symbol.for('workflow.serialization.runKeys');
23
+ /**
24
+ * Build a write-only seal capability for a recipient run's public key.
25
+ *
26
+ * @param recipientPublicKey - The recipient run's raw 32-byte X25519 public key
27
+ * @param aad - Additional authenticated data, conventionally `runAad(projectId, runId)`
28
+ */
29
+ export function sealTo(recipientPublicKey, aad) {
30
+ return { [SEAL_TARGET_BRAND]: true, recipientPublicKey, aad };
31
+ }
32
+ /**
33
+ * Bundle a run's symmetric key with the keypair that opens payloads sealed
34
+ * to it.
35
+ */
36
+ export function runPayloadKeys(aes, keyPair, aad) {
37
+ return { [RUN_KEYS_BRAND]: true, aes, keyPair, aad };
38
+ }
39
+ /**
40
+ * Build the full key capability for a run from its raw 32-byte key material —
41
+ * the value `World.getEncryptionKeyForRun()` returns.
42
+ *
43
+ * Use this anywhere a run reads its own event log: it yields a key that opens
44
+ * both its own symmetric (`encr`) payloads and sealed (`encp`) payloads other
45
+ * runs wrote to it. Resolving only `importKey(material)` would leave the
46
+ * reader unable to open sealed writes.
47
+ */
48
+ export async function deriveRunPayloadKeys(runKeyMaterial) {
49
+ const [aes, keyPair] = await Promise.all([
50
+ importAesKey(runKeyMaterial),
51
+ deriveRunKeyPair(runKeyMaterial),
52
+ ]);
53
+ return runPayloadKeys(aes, keyPair);
54
+ }
55
+ export function isSealTarget(value) {
56
+ return (typeof value === 'object' &&
57
+ value !== null &&
58
+ value[SEAL_TARGET_BRAND] === true);
59
+ }
60
+ export function isRunPayloadKeys(value) {
61
+ return (typeof value === 'object' &&
62
+ value !== null &&
63
+ value[RUN_KEYS_BRAND] === true);
64
+ }
65
+ /**
66
+ * The symmetric key to use for `encr` operations, or undefined when this key
67
+ * has no symmetric capability (i.e. it is a seal-only target).
68
+ */
69
+ export function aesKeyOf(key) {
70
+ if (!key)
71
+ return undefined;
72
+ if (isRunPayloadKeys(key))
73
+ return key.aes;
74
+ if (isSealTarget(key))
75
+ return undefined;
76
+ return key;
77
+ }
78
+ export async function resolveEncryptionKey(key) {
79
+ return typeof key === 'function' ? key() : key;
80
+ }
81
+ /**
82
+ * Encrypt a format-prefixed payload if a key is provided.
83
+ *
84
+ * Wraps the data with the `encr` prefix for symmetric keys, or the `encp`
85
+ * prefix when handed a {@link SealTarget} — a cross-run writer that holds only
86
+ * the recipient's public key.
87
+ *
88
+ * @param data - The format-prefixed serialized data
89
+ * @param key - Encryption key (undefined to skip encryption)
90
+ * @returns The encrypted data with its format prefix, or the original data if no key
91
+ */
92
+ export async function encrypt(data, key) {
93
+ if (!key || !(data instanceof Uint8Array))
94
+ return data;
95
+ if (isSealTarget(key)) {
96
+ const sealed = await sealToPublicKey(key.recipientPublicKey, data, key.aad);
97
+ return encodeWithFormatPrefix(SerializationFormat.SEALED, sealed);
98
+ }
99
+ // Symmetric path — a run's own payloads, including when the caller holds
100
+ // the full `RunPayloadKeys` bundle and *could* seal. See `PayloadKey`.
101
+ const aesKey = isRunPayloadKeys(key) ? key.aes : key;
102
+ const encrypted = await aesGcmEncrypt(aesKey, data);
103
+ return encodeWithFormatPrefix(SerializationFormat.ENCRYPTED, encrypted);
104
+ }
105
+ /**
106
+ * Decrypt a format-prefixed payload if it's encrypted or sealed.
107
+ *
108
+ * Strips the `encr`/`encp` format prefix and recovers the inner payload.
109
+ * Opening a sealed (`encp`) payload requires the run's X25519 keypair, so the
110
+ * caller must supply {@link RunPayloadKeys} — a bare symmetric key cannot do
111
+ * it, and neither can a {@link SealTarget} (which is write-only by design).
112
+ *
113
+ * @param data - The potentially encrypted data
114
+ * @param key - Encryption key (undefined to skip decryption)
115
+ * @returns The decrypted inner payload, or the original data if not encrypted
116
+ */
117
+ /**
118
+ * Open a sealed (`encp`) envelope. Split out from {@link decrypt} to keep
119
+ * each scheme's error handling readable on its own.
120
+ */
121
+ async function openSealedEnvelope(data, key) {
122
+ // Sealed payloads need the private scalar. Anything else — no key, a bare
123
+ // symmetric key, or a write-only seal target — cannot open them.
124
+ if (!isRunPayloadKeys(key)) {
125
+ throw new RuntimeDecryptionError('Sealed data encountered but no run keypair is available. ' +
126
+ "Opening a sealed payload requires the run's own encryption key " +
127
+ 'material; a symmetric key or a seal-only target cannot decrypt it.', {
128
+ context: {
129
+ operation: 'decrypt',
130
+ byteLength: data.byteLength,
131
+ formatPrefix: 'encp',
132
+ },
133
+ });
134
+ }
135
+ const { payload } = decodeFormatPrefix(data);
136
+ try {
137
+ return await openSealed(key.keyPair, payload, key.aad);
138
+ }
139
+ catch (error) {
140
+ // The sealed-box layer only sees the stripped payload, so it cannot
141
+ // record the outer envelope prefix. Enrich it here before rethrowing.
142
+ if (RuntimeDecryptionError.is(error) && error.context) {
143
+ error.context.formatPrefix = SerializationFormat.SEALED;
144
+ }
145
+ throw error;
146
+ }
147
+ }
148
+ export async function decrypt(data, key) {
149
+ // Non-binary data is returned as-is.
150
+ if (!(data instanceof Uint8Array))
151
+ return data;
152
+ const format = peekFormatPrefix(data);
153
+ if (format === SerializationFormat.SEALED) {
154
+ return openSealedEnvelope(data, key);
155
+ }
156
+ // If the data is not encrypted, return it unchanged.
157
+ if (format !== SerializationFormat.ENCRYPTED)
158
+ return data;
159
+ // If the data is encrypted but no symmetric key is available, fail fast.
160
+ const aesKey = aesKeyOf(key);
161
+ if (!aesKey) {
162
+ throw new RuntimeDecryptionError('Encrypted data encountered but no encryption key is available. ' +
163
+ 'Encryption is not configured or no key was provided for this run.', {
164
+ context: {
165
+ operation: 'decrypt',
166
+ byteLength: data.byteLength,
167
+ formatPrefix: 'encr',
168
+ },
169
+ });
170
+ }
171
+ const { payload } = decodeFormatPrefix(data);
172
+ try {
173
+ return await aesGcmDecrypt(aesKey, payload);
174
+ }
175
+ catch (error) {
176
+ // The low-level AES layer only sees the stripped payload, so it cannot
177
+ // record the outer envelope prefix. This layer peeked it (`encr`), so
178
+ // enrich the diagnostic context with the real format prefix before
179
+ // rethrowing.
180
+ if (RuntimeDecryptionError.is(error) && error.context) {
181
+ error.context.formatPrefix = format;
182
+ }
183
+ throw error;
184
+ }
185
+ }
186
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW5jcnlwdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJpYWxpemF0aW9uL2VuY3J5cHRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUVILE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzFELE9BQU8sRUFDTCxPQUFPLElBQUksYUFBYSxFQUN4QixPQUFPLElBQUksYUFBYSxFQUV4QixTQUFTLElBQUksWUFBWSxHQUMxQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsSUFBSSxJQUFJLFVBQVUsRUFFbEIsSUFBSSxJQUFJLGVBQWUsR0FDeEIsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQixPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLHNCQUFzQixFQUN0QixnQkFBZ0IsR0FDakIsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBSWpEOzs7Ozs7R0FNRztBQUNILE1BQU0saUJBQWlCLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO0FBQzFFLE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztBQXVFcEU7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsTUFBTSxDQUNwQixrQkFBOEIsRUFDOUIsR0FBZ0I7SUFFaEIsT0FBTyxFQUFFLENBQUMsaUJBQWlCLENBQUMsRUFBRSxJQUFJLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFDaEUsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQzVCLEdBQWMsRUFDZCxPQUFtQixFQUNuQixHQUFnQjtJQUVoQixPQUFPLEVBQUUsQ0FBQyxjQUFjLENBQUMsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxHQUFH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LENBQUMsTUFBTSxFQUFFLENBQUM7UUFDWixNQUFNLElBQUksc0JBQXNCLENBQzlCLGlFQUFpRTtZQUMvRCxtRUFBbUUsRUFDckU7WUFDRSxPQUFPLEVBQUU7Z0JBQ1AsU0FBUyxFQUFFLFNBQVM7Z0JBQ3BCLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVTtnQkFDM0IsWUFBWSxFQUFFLE1BQU07YUFDckI7U0FDRixDQUNGLENBQUM7SUFDSixDQUFDO0lBRUQsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdDLElBQUksQ0FBQztRQUNILE9BQU8sTUFBTSxhQUFhLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsdUVBQXVFO1FBQ3ZFLHNFQUFzRTtRQUN0RSxtRUFBbUU7UUFDbkUsY0FBYztRQUNkLElBQUksc0JBQXNCLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN0RCxLQUFLLENBQUMsT0FBTyxDQUFDLFlBQVksR0FBRyxNQUFNLENBQUM7UUFDdEMsQ0FBQztRQUNELE1BQU0sS0FBSyxDQUFDO0lBQ2QsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvbXBvc2FibGUgZW5jcnlwdGlvbiBsYXllciBmb3Igc2VyaWFsaXplZCBkYXRhLlxuICpcbiAqIFdyYXBzL3Vud3JhcHMgc2VyaWFsaXplZCBwYXlsb2FkcyB3aXRoIGVpdGhlciBzeW1tZXRyaWMgQUVTLTI1Ni1HQ01cbiAqIGVuY3J5cHRpb24gKGBlbmNyYCkgb3IgYW4gYXN5bW1ldHJpYyBzZWFsZWQgYm94IChgZW5jcGApLCB1c2luZyB0aGUgZm9ybWF0XG4gKiBwcmVmaXggc3lzdGVtIHRvIG1hcmsgd2hpY2guIFNlZSB7QGxpbmsgUGF5bG9hZEtleX0gZm9yIGhvdyBhIGNhbGxlclxuICogZGVjbGFyZXMgd2hpY2ggY2FwYWJpbGl0aWVzIGl0IGhvbGRzLlxuICovXG5cbmltcG9ydCB7IFJ1bnRpbWVEZWNyeXB0aW9uRXJyb3IgfSBmcm9tICdAd29ya2Zsb3cvZXJyb3JzJztcbmltcG9ydCB7XG4gIGRlY3J5cHQgYXMgYWVzR2NtRGVjcnlwdCxcbiAgZW5jcnlwdCBhcyBhZXNHY21FbmNyeXB0LFxuICB0eXBlIENyeXB0b0tleSxcbiAgaW1wb3J0S2V5IGFzIGltcG9ydEFlc0tleSxcbn0gZnJvbSAnLi4vZW5jcnlwdGlvbi5qcyc7XG5pbXBvcnQge1xuICBkZXJpdmVSdW5LZXlQYWlyLFxuICBvcGVuIGFzIG9wZW5TZWFsZWQsXG4gIHR5cGUgUnVuS2V5UGFpcixcbiAgc2VhbCBhcyBzZWFsVG9QdWJsaWNLZXksXG59IGZyb20gJy4uL3NlYWxlZC1ib3guanMnO1xuaW1wb3J0IHtcbiAgZGVjb2RlRm9ybWF0UHJlZml4LFxuICBlbmNvZGVXaXRoRm9ybWF0UHJlZml4LFxuICBwZWVrRm9ybWF0UHJlZml4LFxufSBmcm9tICcuL2Zvcm1hdC5qcyc7XG5pbXBvcnQgeyBTZXJpYWxpemF0aW9uRm9ybWF0IH0gZnJvbSAnLi90eXBlcy5qcyc7XG5cbmV4cG9ydCB0eXBlIHsgQ3J5cHRvS2V5LCBSdW5LZXlQYWlyIH07XG5cbi8qKlxuICogQnJhbmRzIGRpc3Rpbmd1aXNoaW5nIHRoZSBzdHJ1Y3R1cmVkIGtleSB2YXJpYW50cyBmcm9tIGEgYmFyZSBgQ3J5cHRvS2V5YC5cbiAqXG4gKiBgU3ltYm9sLmZvcmAgcmF0aGVyIHRoYW4gYFN5bWJvbCgpYCBiZWNhdXNlIHRoZXNlIHZhbHVlcyBjcm9zcyByZWFsbVxuICogYm91bmRhcmllcyAoaG9zdCDihpQgd29ya2Zsb3cgVk0pLCBhbmQgdGhlIGdsb2JhbCBzeW1ib2wgcmVnaXN0cnkgaXMgc2hhcmVkXG4gKiBhY3Jvc3MgcmVhbG1zIHdoaWxlIHVuaXF1ZSBzeW1ib2xzIGFyZSBub3QuXG4gKi9cbmNvbnN0IFNFQUxfVEFSR0VUX0JSQU5EID0gU3ltYm9sLmZvcignd29ya2Zsb3cuc2VyaWFsaXphdGlvbi5zZWFsVGFyZ2V0Jyk7XG5jb25zdCBSVU5fS0VZU19CUkFORCA9IFN5bWJvbC5mb3IoJ3dvcmtmbG93LnNlcmlhbGl6YXRpb24ucnVuS2V5cycpO1xuXG4vKipcbiAqIEEgd3JpdGUtb25seSBjYXBhYmlsaXR5OiBzZWFsIHBheWxvYWRzIHRvIGEgcnVuJ3MgWDI1NTE5IHB1YmxpYyBrZXkuXG4gKlxuICogVGhpcyBpcyB3aGF0IGEgKmNyb3NzLXJ1biogd3JpdGVyIGhvbGRzIOKAlCBhIGhvb2sgcmVzdW1wdGlvbiB0YXJnZXRpbmdcbiAqIGFub3RoZXIgcnVuLCBvciBhIGNoaWxkIHdvcmtmbG93IHdyaXRpbmcgaW50byBhIHBhcmVudCdzIGZvcndhcmRlZCBzdHJlYW0uXG4gKiBJdCBjYXJyaWVzIG5vIGFiaWxpdHkgdG8gZGVjcnlwdCBhbnl0aGluZywgYW5kIGJlY2F1c2UgaXQgaXMgYSBkaXN0aW5jdFxuICogbm9taW5hbCB0eXBlIGl0IGNhbm5vdCBiZSBtaXN0YWtlbiBmb3Igc3ltbWV0cmljIGtleSBtYXRlcmlhbC5cbiAqXG4gKiBUaGF0IGxhc3QgcHJvcGVydHkgbWF0dGVycyBtb3JlIHRoYW4gaXQgbG9va3M6IGEgcmF3IDMyLWJ5dGUgWDI1NTE5IHB1YmxpY1xuICoga2V5IGlzIGEgKnN0cnVjdHVyYWxseSB2YWxpZCogQUVTLTI1NiBrZXksIHNvIGhhbmRpbmcgb25lIHRvXG4gKiBgaW1wb3J0S2V5KC4uLiwgJ0FFUy1HQ00nKWAgc3VjY2VlZHMgYW5kIHNpbGVudGx5IHByb2R1Y2VzIGNpcGhlcnRleHQgdGhhdFxuICogbm9ib2R5IGNhbiBldmVyIG9wZW4uIFJvdXRpbmcgcHVibGljIGtleXMgZXhjbHVzaXZlbHkgdGhyb3VnaFxuICoge0BsaW5rIHNlYWxUb30gbWFrZXMgdGhhdCBtaXN0YWtlIHVucmVwcmVzZW50YWJsZSByYXRoZXIgdGhhbiBtZXJlbHlcbiAqIGRpc2NvdXJhZ2VkLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNlYWxUYXJnZXQge1xuICByZWFkb25seSBbU0VBTF9UQVJHRVRfQlJBTkRdOiB0cnVlO1xuICAvKiogVGhlIHJlY2lwaWVudCBydW4ncyByYXcgMzItYnl0ZSBYMjU1MTkgcHVibGljIGtleS4gKi9cbiAgcmVhZG9ubHkgcmVjaXBpZW50UHVibGljS2V5OiBVaW50OEFycmF5O1xuICAvKiogQWRkaXRpb25hbCBhdXRoZW50aWNhdGVkIGRhdGEgYmluZGluZyB0aGUgcGF5bG9hZCB0byB0aGUgcmVjaXBpZW50IHJ1bi4gKi9cbiAgcmVhZG9ubHkgYWFkPzogVWludDhBcnJheTtcbn1cblxuLyoqXG4gKiBUaGUgZnVsbCBrZXkgY2FwYWJpbGl0eSBvZiBhIHJ1bidzICpvd24qIHJ1bnRpbWUgKGFuZCBvZiBvMTF5IHRvb2xpbmdcbiAqIGFjdGluZyBvbiBpdHMgYmVoYWxmKTogdGhlIHN5bW1ldHJpYyBrZXkgZm9yIGl0cyBvd24gcGF5bG9hZHMsIHBsdXMgdGhlXG4gKiBrZXlwYWlyIG5lZWRlZCB0byBvcGVuIHNlYWxlZCBwYXlsb2FkcyB0aGF0IG90aGVyIHJ1bnMgd3JvdGUgdG8gaXQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUnVuUGF5bG9hZEtleXMge1xuICByZWFkb25seSBbUlVOX0tFWVNfQlJBTkRdOiB0cnVlO1xuICAvKiogU3ltbWV0cmljIEFFUy0yNTYtR0NNIGtleSDigJQgdGhlIHJ1bidzIG93biBgZW5jcmAgcGF5bG9hZHMuICovXG4gIHJlYWRvbmx5IGFlczogQ3J5cHRvS2V5O1xuICAvKiogWDI1NTE5IGtleXBhaXIg4oCUIG9wZW5zIGBlbmNwYCBwYXlsb2FkcyBzZWFsZWQgdG8gdGhpcyBydW4uICovXG4gIHJlYWRvbmx5IGtleVBhaXI6IFJ1bktleVBhaXI7XG4gIC8qKiBBZGRpdGlvbmFsIGF1dGhlbnRpY2F0ZWQgZGF0YSBleHBlY3RlZCBvbiBzZWFsZWQgcGF5bG9hZHMuICovXG4gIHJlYWRvbmx5IGFhZD86IFVpbnQ4QXJyYXk7XG59XG5cbi8qKlxuICogQSByZXNvbHZlZCBrZXkgZm9yIHJlYWRpbmcgb3Igd3JpdGluZyBhIHNlcmlhbGl6ZWQgcGF5bG9hZC5cbiAqXG4gKiBUaGUgYmFyZSBgQ3J5cHRvS2V5YCB2YXJpYW50IGlzIHRoZSBoaXN0b3JpY2FsIHNoYXBlIGFuZCByZW1haW5zIHZhbGlkOiBpdFxuICogbWVhbnMgXCJzeW1tZXRyaWMgb25seVwiLCB3aGljaCBpcyBleGFjdGx5IHJpZ2h0IGZvciBhIHJ1biB0aGF0IHByZWRhdGVzXG4gKiBzZWFsZWQgYm94ZXMgb3IgZm9yIGFueSBzYW1lLXJ1biBwYXlsb2FkLiBUaGUgc3RydWN0dXJlZCB2YXJpYW50cyBhcmVcbiAqIGFkZGl0aXZlOlxuICpcbiAqIHwgVmFyaWFudCAgICAgICAgICAgIHwgV3JpdGVzICB8IFJlYWRzICAgICAgICAgIHwgSGVsZCBieSAgICAgICAgICAgICAgICAgIHxcbiAqIHwgLS0tLS0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHxcbiAqIHwgYENyeXB0b0tleWAgICAgICAgIHwgYGVuY3JgICB8IGBlbmNyYCAgICAgICAgIHwgc2FtZS1ydW4gKGxlZ2FjeSBzaGFwZSkgIHxcbiAqIHwge0BsaW5rIFJ1blBheWxvYWRLZXlzfSB8IGBlbmNyYCAgfCBgZW5jcmAsIGBlbmNwYCB8IHRoZSBvd25pbmcgcnVuLCBvMTF5ICAgICB8XG4gKiB8IHtAbGluayBTZWFsVGFyZ2V0fSB8IGBlbmNwYCAgfCDigJQgICAgICAgICAgICAgIHwgY3Jvc3MtcnVuIHdyaXRlcnMgICAgICAgIHxcbiAqXG4gKiBBIHJ1bidzIG93biBwYXlsb2FkcyBkZWxpYmVyYXRlbHkgc3RheSBzeW1tZXRyaWMgZXZlbiB3aGVuIHRoZSB3cml0ZXIgY291bGRcbiAqIHNlYWw6IHNlYWxpbmcgY29zdHMgYSBmcmVzaCBFQ0RIIHBlciBlbnZlbG9wZSBhbmQgMzIgZXh0cmEgYnl0ZXMsIGFuZCBidXlzXG4gKiBub3RoaW5nIHdoZW4gdGhlIHdyaXRlciBhbHJlYWR5IGhvbGRzIHRoZSBkZWNyeXB0aW9uIGtleS5cbiAqL1xuZXhwb3J0IHR5cGUgUGF5bG9hZEtleSA9IENyeXB0b0tleSB8IFNlYWxUYXJnZXQgfCBSdW5QYXlsb2FkS2V5cztcblxuLyoqXG4gKiBUaGUgc3Vic2V0IG9mIHtAbGluayBQYXlsb2FkS2V5fSB0aGF0IGNhbiBhY3R1YWxseSAqcmVhZCogYSBwYXlsb2FkLlxuICpcbiAqIEV4Y2x1ZGVzIHtAbGluayBTZWFsVGFyZ2V0fSwgd2hpY2ggaXMgd3JpdGUtb25seSBieSBjb25zdHJ1Y3Rpb246IGl0IGhvbGRzIGFcbiAqIHB1YmxpYyBrZXksIHNvIGl0IGNhbiBvcGVuIG5laXRoZXIgYGVuY3BgIChuZWVkcyB0aGUgcHJpdmF0ZSBzY2FsYXIpIG5vclxuICogYGVuY3JgIChuZWVkcyB0aGUgc3ltbWV0cmljIGtleSkuIERlY3J5cHQtc2lkZSBzaWduYXR1cmVzIHNob3VsZCB0YWtlIHRoaXNcbiAqIHJhdGhlciB0aGFuIGBQYXlsb2FkS2V5YCwgc28gcGFzc2luZyBhIHNlYWwgdGFyZ2V0IGlzIGEgY29tcGlsZSBlcnJvciBpbnN0ZWFkXG4gKiBvZiBhIGd1YXJhbnRlZWQgcnVudGltZSBmYWlsdXJlLlxuICovXG5leHBvcnQgdHlwZSBEZWNyeXB0aW9uS2V5ID0gQ3J5cHRvS2V5IHwgUnVuUGF5bG9hZEtleXM7XG5cbi8qKlxuICogQnVpbGQgYSB3cml0ZS1vbmx5IHNlYWwgY2FwYWJpbGl0eSBmb3IgYSByZWNpcGllbnQgcnVuJ3MgcHVibGljIGtleS5cbiAqXG4gKiBAcGFyYW0gcmVjaXBpZW50UHVibGljS2V5IC0gVGhlIHJlY2lwaWVudCBydW4ncyByYXcgMzItYnl0ZSBYMjU1MTkgcHVibGljIGtleVxuICogQHBhcmFtIGFhZCAtIEFkZGl0aW9uYWwgYXV0aGVudGljYXRlZCBkYXRhLCBjb252ZW50aW9uYWxseSBgcnVuQWFkKHByb2plY3RJZCwgcnVuSWQpYFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhbFRvKFxuICByZWNpcGllbnRQdWJsaWNLZXk6IFVpbnQ4QXJyYXksXG4gIGFhZD86IFVpbnQ4QXJyYXlcbik6IFNlYWxUYXJnZXQge1xuICByZXR1cm4geyBbU0VBTF9UQVJHRVRfQlJBTkRdOiB0cnVlLCByZWNpcGllbnRQdWJsaWNLZXksIGFhZCB9O1xufVxuXG4vKipcbiAqIEJ1bmRsZSBhIHJ1bidzIHN5bW1ldHJpYyBrZXkgd2l0aCB0aGUga2V5cGFpciB0aGF0IG9wZW5zIHBheWxvYWRzIHNlYWxlZFxuICogdG8gaXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBydW5QYXlsb2FkS2V5cyhcbiAgYWVzOiBDcnlwdG9LZXksXG4gIGtleVBhaXI6IFJ1bktleVBhaXIsXG4gIGFhZD86IFVpbnQ4QXJyYXlcbik6IFJ1blBheWxvYWRLZXlzIHtcbiAgcmV0dXJuIHsgW1JVTl9LRVlTX0JSQU5EXTogdHJ1ZSwgYWVzLCBrZXlQYWlyLCBhYWQgfTtcbn1cblxuLyoqXG4gKiBCdWlsZCB0aGUgZnVsbCBrZXkgY2FwYWJpbGl0eSBmb3IgYSBydW4gZnJvbSBpdHMgcmF3IDMyLWJ5dGUga2V5IG1hdGVyaWFsIOKAlFxuICogdGhlIHZhbHVlIGBXb3JsZC5nZXRFbmNyeXB0aW9uS2V5Rm9yUnVuKClgIHJldHVybnMuXG4gKlxuICogVXNlIHRoaXMgYW55d2hlcmUgYSBydW4gcmVhZHMgaXRzIG93biBldmVudCBsb2c6IGl0IHlpZWxkcyBhIGtleSB0aGF0IG9wZW5zXG4gKiBib3RoIGl0cyBvd24gc3ltbWV0cmljIChgZW5jcmApIHBheWxvYWRzIGFuZCBzZWFsZWQgKGBlbmNwYCkgcGF5bG9hZHMgb3RoZXJcbiAqIHJ1bnMgd3JvdGUgdG8gaXQuIFJlc29sdmluZyBvbmx5IGBpbXBvcnRLZXkobWF0ZXJpYWwpYCB3b3VsZCBsZWF2ZSB0aGVcbiAqIHJlYWRlciB1bmFibGUgdG8gb3BlbiBzZWFsZWQgd3JpdGVzLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVyaXZlUnVuUGF5bG9hZEtleXMoXG4gIHJ1bktleU1hdGVyaWFsOiBVaW50OEFycmF5XG4pOiBQcm9taXNlPFJ1blBheWxvYWRLZXlzPiB7XG4gIGNvbnN0IFthZXMsIGtleVBhaXJdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIGltcG9ydEFlc0tleShydW5LZXlNYXRlcmlhbCksXG4gICAgZGVyaXZlUnVuS2V5UGFpcihydW5LZXlNYXRlcmlhbCksXG4gIF0pO1xuICByZXR1cm4gcnVuUGF5bG9hZEtleXMoYWVzLCBrZXlQYWlyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzU2VhbFRhcmdldCh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIFNlYWxUYXJnZXQge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiZcbiAgICB2YWx1ZSAhPT0gbnVsbCAmJlxuICAgICh2YWx1ZSBhcyBQYXJ0aWFsPFNlYWxUYXJnZXQ+KVtTRUFMX1RBUkdFVF9CUkFORF0gPT09IHRydWVcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzUnVuUGF5bG9hZEtleXModmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBSdW5QYXlsb2FkS2V5cyB7XG4gIHJldHVybiAoXG4gICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxuICAgIHZhbHVlICE9PSBudWxsICYmXG4gICAgKHZhbHVlIGFzIFBhcnRpYWw8UnVuUGF5bG9hZEtleXM+KVtSVU5fS0VZU19CUkFORF0gPT09IHRydWVcbiAgKTtcbn1cblxuLyoqXG4gKiBUaGUgc3ltbWV0cmljIGtleSB0byB1c2UgZm9yIGBlbmNyYCBvcGVyYXRpb25zLCBvciB1bmRlZmluZWQgd2hlbiB0aGlzIGtleVxuICogaGFzIG5vIHN5bW1ldHJpYyBjYXBhYmlsaXR5IChpLmUuIGl0IGlzIGEgc2VhbC1vbmx5IHRhcmdldCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZXNLZXlPZihrZXk6IFBheWxvYWRLZXkgfCB1bmRlZmluZWQpOiBDcnlwdG9LZXkgfCB1bmRlZmluZWQge1xuICBpZiAoIWtleSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgaWYgKGlzUnVuUGF5bG9hZEtleXMoa2V5KSkgcmV0dXJuIGtleS5hZXM7XG4gIGlmIChpc1NlYWxUYXJnZXQoa2V5KSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgcmV0dXJuIGtleTtcbn1cblxuLyoqXG4gKiBFbmNyeXB0aW9uIGtleSBwYXJhbWV0ZXIgdHlwZS4gQWNjZXB0cyBhIHJlc29sdmVkIGtleSwgdW5kZWZpbmVkIChubyBlbmNyeXB0aW9uKSxcbiAqIGEgcHJvbWlzZSwgb3IgYSByZXNvbHZlciB0aGF0IGNhbiBkZWZlciBmZXRjaGluZyB0aGUga2V5IHVudGlsIGRhdGEgbmVlZHMgaXQuXG4gKi9cbmV4cG9ydCB0eXBlIEVuY3J5cHRpb25LZXlQYXJhbSA9XG4gIHwgUGF5bG9hZEtleVxuICB8IHVuZGVmaW5lZFxuICB8IFByb21pc2U8UGF5bG9hZEtleSB8IHVuZGVmaW5lZD5cbiAgfCAoKCkgPT4gUHJvbWlzZTxQYXlsb2FkS2V5IHwgdW5kZWZpbmVkPik7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlRW5jcnlwdGlvbktleShcbiAga2V5OiBFbmNyeXB0aW9uS2V5UGFyYW1cbik6IFByb21pc2U8UGF5bG9hZEtleSB8IHVuZGVmaW5lZD4ge1xuICByZXR1cm4gdHlwZW9mIGtleSA9PT0gJ2Z1bmN0aW9uJyA/IGtleSgpIDoga2V5O1xufVxuXG4vKipcbiAqIEVuY3J5cHQgYSBmb3JtYXQtcHJlZml4ZWQgcGF5bG9hZCBpZiBhIGtleSBpcyBwcm92aWRlZC5cbiAqXG4gKiBXcmFwcyB0aGUgZGF0YSB3aXRoIHRoZSBgZW5jcmAgcHJlZml4IGZvciBzeW1tZXRyaWMga2V5cywgb3IgdGhlIGBlbmNwYFxuICogcHJlZml4IHdoZW4gaGFuZGVkIGEge0BsaW5rIFNlYWxUYXJnZXR9IOKAlCBhIGNyb3NzLXJ1biB3cml0ZXIgdGhhdCBob2xkcyBvbmx5XG4gKiB0aGUgcmVjaXBpZW50J3MgcHVibGljIGtleS5cbiAqXG4gKiBAcGFyYW0gZGF0YSAtIFRoZSBmb3JtYXQtcHJlZml4ZWQgc2VyaWFsaXplZCBkYXRhXG4gKiBAcGFyYW0ga2V5IC0gRW5jcnlwdGlvbiBrZXkgKHVuZGVmaW5lZCB0byBza2lwIGVuY3J5cHRpb24pXG4gKiBAcmV0dXJucyBUaGUgZW5jcnlwdGVkIGRhdGEgd2l0aCBpdHMgZm9ybWF0IHByZWZpeCwgb3IgdGhlIG9yaWdpbmFsIGRhdGEgaWYgbm8ga2V5XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBlbmNyeXB0KFxuICBkYXRhOiBVaW50OEFycmF5IHwgdW5rbm93bixcbiAga2V5OiBQYXlsb2FkS2V5IHwgdW5kZWZpbmVkXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXkgfCB1bmtub3duPiB7XG4gIGlmICgha2V5IHx8ICEoZGF0YSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKSByZXR1cm4gZGF0YTtcblxuICBpZiAoaXNTZWFsVGFyZ2V0KGtleSkpIHtcbiAgICBjb25zdCBzZWFsZWQgPSBhd2FpdCBzZWFsVG9QdWJsaWNLZXkoa2V5LnJlY2lwaWVudFB1YmxpY0tleSwgZGF0YSwga2V5LmFhZCk7XG4gICAgcmV0dXJuIGVuY29kZVdpdGhGb3JtYXRQcmVmaXgoU2VyaWFsaXphdGlvbkZvcm1hdC5TRUFMRUQsIHNlYWxlZCk7XG4gIH1cblxuICAvLyBTeW1tZXRyaWMgcGF0aCDigJQgYSBydW4ncyBvd24gcGF5bG9hZHMsIGluY2x1ZGluZyB3aGVuIHRoZSBjYWxsZXIgaG9sZHNcbiAgLy8gdGhlIGZ1bGwgYFJ1blBheWxvYWRLZXlzYCBidW5kbGUgYW5kICpjb3VsZCogc2VhbC4gU2VlIGBQYXlsb2FkS2V5YC5cbiAgY29uc3QgYWVzS2V5ID0gaXNSdW5QYXlsb2FkS2V5cyhrZXkpID8ga2V5LmFlcyA6IGtleTtcbiAgY29uc3QgZW5jcnlwdGVkID0gYXdhaXQgYWVzR2NtRW5jcnlwdChhZXNLZXksIGRhdGEpO1xuICByZXR1cm4gZW5jb2RlV2l0aEZvcm1hdFByZWZpeChTZXJpYWxpemF0aW9uRm9ybWF0LkVOQ1JZUFRFRCwgZW5jcnlwdGVkKTtcbn1cblxuLyoqXG4gKiBEZWNyeXB0IGEgZm9ybWF0LXByZWZpeGVkIHBheWxvYWQgaWYgaXQncyBlbmNyeXB0ZWQgb3Igc2VhbGVkLlxuICpcbiAqIFN0cmlwcyB0aGUgYGVuY3JgL2BlbmNwYCBmb3JtYXQgcHJlZml4IGFuZCByZWNvdmVycyB0aGUgaW5uZXIgcGF5bG9hZC5cbiAqIE9wZW5pbmcgYSBzZWFsZWQgKGBlbmNwYCkgcGF5bG9hZCByZXF1aXJlcyB0aGUgcnVuJ3MgWDI1NTE5IGtleXBhaXIsIHNvIHRoZVxuICogY2FsbGVyIG11c3Qgc3VwcGx5IHtAbGluayBSdW5QYXlsb2FkS2V5c30g4oCUIGEgYmFyZSBzeW1tZXRyaWMga2V5IGNhbm5vdCBkb1xuICogaXQsIGFuZCBuZWl0aGVyIGNhbiBhIHtAbGluayBTZWFsVGFyZ2V0fSAod2hpY2ggaXMgd3JpdGUtb25seSBieSBkZXNpZ24pLlxuICpcbiAqIEBwYXJhbSBkYXRhIC0gVGhlIHBvdGVudGlhbGx5IGVuY3J5cHRlZCBkYXRhXG4gKiBAcGFyYW0ga2V5IC0gRW5jcnlwdGlvbiBrZXkgKHVuZGVmaW5lZCB0byBza2lwIGRlY3J5cHRpb24pXG4gKiBAcmV0dXJucyBUaGUgZGVjcnlwdGVkIGlubmVyIHBheWxvYWQsIG9yIHRoZSBvcmlnaW5hbCBkYXRhIGlmIG5vdCBlbmNyeXB0ZWRcbiAqL1xuLyoqXG4gKiBPcGVuIGEgc2VhbGVkIChgZW5jcGApIGVudmVsb3BlLiBTcGxpdCBvdXQgZnJvbSB7QGxpbmsgZGVjcnlwdH0gdG8ga2VlcFxuICogZWFjaCBzY2hlbWUncyBlcnJvciBoYW5kbGluZyByZWFkYWJsZSBvbiBpdHMgb3duLlxuICovXG5hc3luYyBmdW5jdGlvbiBvcGVuU2VhbGVkRW52ZWxvcGUoXG4gIGRhdGE6IFVpbnQ4QXJyYXksXG4gIGtleTogUGF5bG9hZEtleSB8IHVuZGVmaW5lZFxuKTogUHJvbWlzZTxVaW50OEFycmF5PiB7XG4gIC8vIFNlYWxlZCBwYXlsb2FkcyBuZWVkIHRoZSBwcml2YXRlIHNjYWxhci4gQW55dGhpbmcgZWxzZSDigJQgbm8ga2V5LCBhIGJhcmVcbiAgLy8gc3ltbWV0cmljIGtleSwgb3IgYSB3cml0ZS1vbmx5IHNlYWwgdGFyZ2V0IOKAlCBjYW5ub3Qgb3BlbiB0aGVtLlxuICBpZiAoIWlzUnVuUGF5bG9hZEtleXMoa2V5KSkge1xuICAgIHRocm93IG5ldyBSdW50aW1lRGVjcnlwdGlvbkVycm9yKFxuICAgICAgJ1NlYWxlZCBkYXRhIGVuY291bnRlcmVkIGJ1dCBubyBydW4ga2V5cGFpciBpcyBhdmFpbGFibGUuICcgK1xuICAgICAgICBcIk9wZW5pbmcgYSBzZWFsZWQgcGF5bG9hZCByZXF1aXJlcyB0aGUgcnVuJ3Mgb3duIGVuY3J5cHRpb24ga2V5IFwiICtcbiAgICAgICAgJ21hdGVyaWFsOyBhIHN5bW1ldHJpYyBrZXkgb3IgYSBzZWFsLW9ubHkgdGFyZ2V0IGNhbm5vdCBkZWNyeXB0IGl0LicsXG4gICAgICB7XG4gICAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgICBvcGVyYXRpb246ICdkZWNyeXB0JyxcbiAgICAgICAgICBieXRlTGVuZ3RoOiBkYXRhLmJ5dGVMZW5ndGgsXG4gICAgICAgICAgZm9ybWF0UHJlZml4OiAnZW5jcCcsXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIGNvbnN0IHsgcGF5bG9hZCB9ID0gZGVjb2RlRm9ybWF0UHJlZml4KGRhdGEpO1xuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCBvcGVuU2VhbGVkKGtleS5rZXlQYWlyLCBwYXlsb2FkLCBrZXkuYWFkKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAvLyBUaGUgc2VhbGVkLWJveCBsYXllciBvbmx5IHNlZXMgdGhlIHN0cmlwcGVkIHBheWxvYWQsIHNvIGl0IGNhbm5vdFxuICAgIC8vIHJlY29yZCB0aGUgb3V0ZXIgZW52ZWxvcGUgcHJlZml4LiBFbnJpY2ggaXQgaGVyZSBiZWZvcmUgcmV0aHJvd2luZy5cbiAgICBpZiAoUnVudGltZURlY3J5cHRpb25FcnJvci5pcyhlcnJvcikgJiYgZXJyb3IuY29udGV4dCkge1xuICAgICAgZXJyb3IuY29udGV4dC5mb3JtYXRQcmVmaXggPSBTZXJpYWxpemF0aW9uRm9ybWF0LlNFQUxFRDtcbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlY3J5cHQoXG4gIGRhdGE6IFVpbnQ4QXJyYXkgfCB1bmtub3duLFxuICBrZXk6IFBheWxvYWRLZXkgfCB1bmRlZmluZWRcbik6IFByb21pc2U8VWludDhBcnJheSB8IHVua25vd24+IHtcbiAgLy8gTm9uLWJpbmFyeSBkYXRhIGlzIHJldHVybmVkIGFzLWlzLlxuICBpZiAoIShkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSkpIHJldHVybiBkYXRhO1xuXG4gIGNvbnN0IGZvcm1hdCA9IHBlZWtGb3JtYXRQcmVmaXgoZGF0YSk7XG5cbiAgaWYgKGZvcm1hdCA9PT0gU2VyaWFsaXphdGlvbkZvcm1hdC5TRUFMRUQpIHtcbiAgICByZXR1cm4gb3BlblNlYWxlZEVudmVsb3BlKGRhdGEsIGtleSk7XG4gIH1cblxuICAvLyBJZiB0aGUgZGF0YSBpcyBub3QgZW5jcnlwdGVkLCByZXR1cm4gaXQgdW5jaGFuZ2VkLlxuICBpZiAoZm9ybWF0ICE9PSBTZXJpYWxpemF0aW9uRm9ybWF0LkVOQ1JZUFRFRCkgcmV0dXJuIGRhdGE7XG5cbiAgLy8gSWYgdGhlIGRhdGEgaXMgZW5jcnlwdGVkIGJ1dCBubyBzeW1tZXRyaWMga2V5IGlzIGF2YWlsYWJsZSwgZmFpbCBmYXN0LlxuICBjb25zdCBhZXNLZXkgPSBhZXNLZXlPZihrZXkpO1xuICBpZiAoIWFlc0tleSkge1xuICAgIHRocm93IG5ldyBSdW50aW1lRGVjcnlwdGlvbkVycm9yKFxuICAgICAgJ0VuY3J5cHRlZCBkYXRhIGVuY291bnRlcmVkIGJ1dCBubyBlbmNyeXB0aW9uIGtleSBpcyBhdmFpbGFibGUuICcgK1xuICAgICAgICAnRW5jcnlwdGlvbiBpcyBub3QgY29uZmlndXJlZCBvciBubyBrZXkgd2FzIHByb3ZpZGVkIGZvciB0aGlzIHJ1bi4nLFxuICAgICAge1xuICAgICAgICBjb250ZXh0OiB7XG4gICAgICAgICAgb3BlcmF0aW9uOiAnZGVjcnlwdCcsXG4gICAgICAgICAgYnl0ZUxlbmd0aDogZGF0YS5ieXRlTGVuZ3RoLFxuICAgICAgICAgIGZvcm1hdFByZWZpeDogJ2VuY3InLFxuICAgICAgICB9LFxuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBjb25zdCB7IHBheWxvYWQgfSA9IGRlY29kZUZvcm1hdFByZWZpeChkYXRhKTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgYWVzR2NtRGVjcnlwdChhZXNLZXksIHBheWxvYWQpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIC8vIFRoZSBsb3ctbGV2ZWwgQUVTIGxheWVyIG9ubHkgc2VlcyB0aGUgc3RyaXBwZWQgcGF5bG9hZCwgc28gaXQgY2Fubm90XG4gICAgLy8gcmVjb3JkIHRoZSBvdXRlciBlbnZlbG9wZSBwcmVmaXguIFRoaXMgbGF5ZXIgcGVla2VkIGl0IChgZW5jcmApLCBzb1xuICAgIC8vIGVucmljaCB0aGUgZGlhZ25vc3RpYyBjb250ZXh0IHdpdGggdGhlIHJlYWwgZm9ybWF0IHByZWZpeCBiZWZvcmVcbiAgICAvLyByZXRocm93aW5nLlxuICAgIGlmIChSdW50aW1lRGVjcnlwdGlvbkVycm9yLmlzKGVycm9yKSAmJiBlcnJvci5jb250ZXh0KSB7XG4gICAgICBlcnJvci5jb250ZXh0LmZvcm1hdFByZWZpeCA9IGZvcm1hdDtcbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Shared error formatting utility for serialization failures.
3
+ *
4
+ * Used by the mode-specific serializers (workflow, step, client) to
5
+ * produce consistent error messages with devalue path information.
6
+ *
7
+ * Returns a `{ message, hint }` pair so callers can throw a
8
+ * `SerializationError(message, { hint, cause })` and have the hint flow
9
+ * through the standard friendly-errors framing instead of being baked
10
+ * into the message string.
11
+ */
12
+ /**
13
+ * Rethrow SDK runtime errors that must not be reframed as
14
+ * `SerializationError`.
15
+ *
16
+ * The serialize/dehydrate wrappers catch every throw and reframe it as a
17
+ * `SerializationError` (which classifies as `USER_ERROR`). That's correct
18
+ * for genuine serialization failures, but a `RuntimeDecryptionError` from
19
+ * the AES-GCM layer is an SDK-internal failure that must keep its identity
20
+ * so the run-failure classifier routes it to `RUNTIME_ERROR`. Call this at
21
+ * the top of each serialize catch block to let those errors propagate
22
+ * unchanged.
23
+ */
24
+ export declare function rethrowIfRuntimeError(error: unknown): void;
25
+ /**
26
+ * Format a serialization error with context about what failed.
27
+ * Extracts path, value, and reason from devalue's DevalueError when available.
28
+ * Logs the problematic value to the console for better debugging.
29
+ */
30
+ export declare function formatSerializationError(context: string, error: unknown): {
31
+ message: string;
32
+ hint: string;
33
+ };
34
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/serialization/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAI1D;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,GACb;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAqBnC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Shared error formatting utility for serialization failures.
3
+ *
4
+ * Used by the mode-specific serializers (workflow, step, client) to
5
+ * produce consistent error messages with devalue path information.
6
+ *
7
+ * Returns a `{ message, hint }` pair so callers can throw a
8
+ * `SerializationError(message, { hint, cause })` and have the hint flow
9
+ * through the standard friendly-errors framing instead of being baked
10
+ * into the message string.
11
+ */
12
+ import { RuntimeDecryptionError } from '@workflow/errors';
13
+ import { DevalueError } from 'devalue';
14
+ import { runtimeLogger } from '../logger.js';
15
+ /**
16
+ * Rethrow SDK runtime errors that must not be reframed as
17
+ * `SerializationError`.
18
+ *
19
+ * The serialize/dehydrate wrappers catch every throw and reframe it as a
20
+ * `SerializationError` (which classifies as `USER_ERROR`). That's correct
21
+ * for genuine serialization failures, but a `RuntimeDecryptionError` from
22
+ * the AES-GCM layer is an SDK-internal failure that must keep its identity
23
+ * so the run-failure classifier routes it to `RUNTIME_ERROR`. Call this at
24
+ * the top of each serialize catch block to let those errors propagate
25
+ * unchanged.
26
+ */
27
+ export function rethrowIfRuntimeError(error) {
28
+ if (RuntimeDecryptionError.is(error)) {
29
+ throw error;
30
+ }
31
+ }
32
+ /**
33
+ * Format a serialization error with context about what failed.
34
+ * Extracts path, value, and reason from devalue's DevalueError when available.
35
+ * Logs the problematic value to the console for better debugging.
36
+ */
37
+ export function formatSerializationError(context, error) {
38
+ // `returning` for outputs, `passing` for everything that crosses the
39
+ // boundary the other way (arguments, stream messages, etc.).
40
+ const verb = context.includes('return value') ? 'returning' : 'passing';
41
+ let message = `Failed to serialize ${context}`;
42
+ if (error instanceof DevalueError && error.path) {
43
+ message += ` at path "${error.path}"`;
44
+ }
45
+ // Workflow can serialize a much richer set than the devalue defaults —
46
+ // classes registered via `WORKFLOW_SERIALIZE`, FatalError / RetryableError
47
+ // subclasses, AbortSignal, etc. Pointing at the foundations doc keeps
48
+ // this hint accurate as the supported set grows, instead of repeating
49
+ // a hardcoded list that drifts out of sync.
50
+ const hint = `Ensure you're ${verb} workflow serializable types. Check the serialization docs to see what's serializable: https://workflow-sdk.dev/docs/foundations/serialization`;
51
+ if (error instanceof DevalueError && error.value !== undefined) {
52
+ runtimeLogger.error('Serialization failed', {
53
+ context,
54
+ problematicValue: error.value,
55
+ });
56
+ }
57
+ return { message, hint };
58
+ }
59
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcmlhbGl6YXRpb24vZXJyb3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7O0dBVUc7QUFFSCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMxRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFN0M7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQUMsS0FBYztJQUNsRCxJQUFJLHNCQUFzQixDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3JDLE1BQU0sS0FBSyxDQUFDO0lBQ2QsQ0FBQztBQUNILENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLHdCQUF3QixDQUN0QyxPQUFlLEVBQ2YsS0FBYztJQUVkLHFFQUFxRTtJQUNyRSw2REFBNkQ7SUFDN0QsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDeEUsSUFBSSxPQUFPLEdBQUcsdUJBQXVCLE9BQU8sRUFBRSxDQUFDO0lBQy9DLElBQUksS0FBSyxZQUFZLFlBQVksSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDaEQsT0FBTyxJQUFJLGFBQWEsS0FBSyxDQUFDLElBQUksR0FBRyxDQUFDO0lBQ3hDLENBQUM7SUFDRCx1RUFBdUU7SUFDdkUsMkVBQTJFO0lBQzNFLHNFQUFzRTtJQUN0RSxzRUFBc0U7SUFDdEUsNENBQTRDO0lBQzVDLE1BQU0sSUFBSSxHQUFHLGlCQUFpQixJQUFJLGdKQUFnSixDQUFDO0lBQ25MLElBQUksS0FBSyxZQUFZLFlBQVksSUFBSSxLQUFLLENBQUMsS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQy9ELGFBQWEsQ0FBQyxLQUFLLENBQUMsc0JBQXNCLEVBQUU7WUFDMUMsT0FBTztZQUNQLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxLQUFLO1NBQzlCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFDRCxPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDO0FBQzNCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNoYXJlZCBlcnJvciBmb3JtYXR0aW5nIHV0aWxpdHkgZm9yIHNlcmlhbGl6YXRpb24gZmFpbHVyZXMuXG4gKlxuICogVXNlZCBieSB0aGUgbW9kZS1zcGVjaWZpYyBzZXJpYWxpemVycyAod29ya2Zsb3csIHN0ZXAsIGNsaWVudCkgdG9cbiAqIHByb2R1Y2UgY29uc2lzdGVudCBlcnJvciBtZXNzYWdlcyB3aXRoIGRldmFsdWUgcGF0aCBpbmZvcm1hdGlvbi5cbiAqXG4gKiBSZXR1cm5zIGEgYHsgbWVzc2FnZSwgaGludCB9YCBwYWlyIHNvIGNhbGxlcnMgY2FuIHRocm93IGFcbiAqIGBTZXJpYWxpemF0aW9uRXJyb3IobWVzc2FnZSwgeyBoaW50LCBjYXVzZSB9KWAgYW5kIGhhdmUgdGhlIGhpbnQgZmxvd1xuICogdGhyb3VnaCB0aGUgc3RhbmRhcmQgZnJpZW5kbHktZXJyb3JzIGZyYW1pbmcgaW5zdGVhZCBvZiBiZWluZyBiYWtlZFxuICogaW50byB0aGUgbWVzc2FnZSBzdHJpbmcuXG4gKi9cblxuaW1wb3J0IHsgUnVudGltZURlY3J5cHRpb25FcnJvciB9IGZyb20gJ0B3b3JrZmxvdy9lcnJvcnMnO1xuaW1wb3J0IHsgRGV2YWx1ZUVycm9yIH0gZnJvbSAnZGV2YWx1ZSc7XG5pbXBvcnQgeyBydW50aW1lTG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyLmpzJztcblxuLyoqXG4gKiBSZXRocm93IFNESyBydW50aW1lIGVycm9ycyB0aGF0IG11c3Qgbm90IGJlIHJlZnJhbWVkIGFzXG4gKiBgU2VyaWFsaXphdGlvbkVycm9yYC5cbiAqXG4gKiBUaGUgc2VyaWFsaXplL2RlaHlkcmF0ZSB3cmFwcGVycyBjYXRjaCBldmVyeSB0aHJvdyBhbmQgcmVmcmFtZSBpdCBhcyBhXG4gKiBgU2VyaWFsaXphdGlvbkVycm9yYCAod2hpY2ggY2xhc3NpZmllcyBhcyBgVVNFUl9FUlJPUmApLiBUaGF0J3MgY29ycmVjdFxuICogZm9yIGdlbnVpbmUgc2VyaWFsaXphdGlvbiBmYWlsdXJlcywgYnV0IGEgYFJ1bnRpbWVEZWNyeXB0aW9uRXJyb3JgIGZyb21cbiAqIHRoZSBBRVMtR0NNIGxheWVyIGlzIGFuIFNESy1pbnRlcm5hbCBmYWlsdXJlIHRoYXQgbXVzdCBrZWVwIGl0cyBpZGVudGl0eVxuICogc28gdGhlIHJ1bi1mYWlsdXJlIGNsYXNzaWZpZXIgcm91dGVzIGl0IHRvIGBSVU5USU1FX0VSUk9SYC4gQ2FsbCB0aGlzIGF0XG4gKiB0aGUgdG9wIG9mIGVhY2ggc2VyaWFsaXplIGNhdGNoIGJsb2NrIHRvIGxldCB0aG9zZSBlcnJvcnMgcHJvcGFnYXRlXG4gKiB1bmNoYW5nZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXRocm93SWZSdW50aW1lRXJyb3IoZXJyb3I6IHVua25vd24pOiB2b2lkIHtcbiAgaWYgKFJ1bnRpbWVEZWNyeXB0aW9uRXJyb3IuaXMoZXJyb3IpKSB7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuLyoqXG4gKiBGb3JtYXQgYSBzZXJpYWxpemF0aW9uIGVycm9yIHdpdGggY29udGV4dCBhYm91dCB3aGF0IGZhaWxlZC5cbiAqIEV4dHJhY3RzIHBhdGgsIHZhbHVlLCBhbmQgcmVhc29uIGZyb20gZGV2YWx1ZSdzIERldmFsdWVFcnJvciB3aGVuIGF2YWlsYWJsZS5cbiAqIExvZ3MgdGhlIHByb2JsZW1hdGljIHZhbHVlIHRvIHRoZSBjb25zb2xlIGZvciBiZXR0ZXIgZGVidWdnaW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0U2VyaWFsaXphdGlvbkVycm9yKFxuICBjb250ZXh0OiBzdHJpbmcsXG4gIGVycm9yOiB1bmtub3duXG4pOiB7IG1lc3NhZ2U6IHN0cmluZzsgaGludDogc3RyaW5nIH0ge1xuICAvLyBgcmV0dXJuaW5nYCBmb3Igb3V0cHV0cywgYHBhc3NpbmdgIGZvciBldmVyeXRoaW5nIHRoYXQgY3Jvc3NlcyB0aGVcbiAgLy8gYm91bmRhcnkgdGhlIG90aGVyIHdheSAoYXJndW1lbnRzLCBzdHJlYW0gbWVzc2FnZXMsIGV0Yy4pLlxuICBjb25zdCB2ZXJiID0gY29udGV4dC5pbmNsdWRlcygncmV0dXJuIHZhbHVlJykgPyAncmV0dXJuaW5nJyA6ICdwYXNzaW5nJztcbiAgbGV0IG1lc3NhZ2UgPSBgRmFpbGVkIHRvIHNlcmlhbGl6ZSAke2NvbnRleHR9YDtcbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgRGV2YWx1ZUVycm9yICYmIGVycm9yLnBhdGgpIHtcbiAgICBtZXNzYWdlICs9IGAgYXQgcGF0aCBcIiR7ZXJyb3IucGF0aH1cImA7XG4gIH1cbiAgLy8gV29ya2Zsb3cgY2FuIHNlcmlhbGl6ZSBhIG11Y2ggcmljaGVyIHNldCB0aGFuIHRoZSBkZXZhbHVlIGRlZmF1bHRzIOKAlFxuICAvLyBjbGFzc2VzIHJlZ2lzdGVyZWQgdmlhIGBXT1JLRkxPV19TRVJJQUxJWkVgLCBGYXRhbEVycm9yIC8gUmV0cnlhYmxlRXJyb3JcbiAgLy8gc3ViY2xhc3NlcywgQWJvcnRTaWduYWwsIGV0Yy4gUG9pbnRpbmcgYXQgdGhlIGZvdW5kYXRpb25zIGRvYyBrZWVwc1xuICAvLyB0aGlzIGhpbnQgYWNjdXJhdGUgYXMgdGhlIHN1cHBvcnRlZCBzZXQgZ3Jvd3MsIGluc3RlYWQgb2YgcmVwZWF0aW5nXG4gIC8vIGEgaGFyZGNvZGVkIGxpc3QgdGhhdCBkcmlmdHMgb3V0IG9mIHN5bmMuXG4gIGNvbnN0IGhpbnQgPSBgRW5zdXJlIHlvdSdyZSAke3ZlcmJ9IHdvcmtmbG93IHNlcmlhbGl6YWJsZSB0eXBlcy4gQ2hlY2sgdGhlIHNlcmlhbGl6YXRpb24gZG9jcyB0byBzZWUgd2hhdCdzIHNlcmlhbGl6YWJsZTogaHR0cHM6Ly93b3JrZmxvdy1zZGsuZGV2L2RvY3MvZm91bmRhdGlvbnMvc2VyaWFsaXphdGlvbmA7XG4gIGlmIChlcnJvciBpbnN0YW5jZW9mIERldmFsdWVFcnJvciAmJiBlcnJvci52YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcnVudGltZUxvZ2dlci5lcnJvcignU2VyaWFsaXphdGlvbiBmYWlsZWQnLCB7XG4gICAgICBjb250ZXh0LFxuICAgICAgcHJvYmxlbWF0aWNWYWx1ZTogZXJyb3IudmFsdWUsXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIHsgbWVzc2FnZSwgaGludCB9O1xufVxuIl19
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Format prefix system for serialized payloads.
3
+ *
4
+ * All serialized payloads are prefixed with a 4-byte format identifier that
5
+ * allows the deserializer to determine how to decode the payload. This enables:
6
+ *
7
+ * 1. Self-describing payloads — the World layer is agnostic to serialization format
8
+ * 2. Gradual migration — old runs keep working, new runs can use new formats
9
+ * 3. Composability — encryption can wrap any format ("encr" wrapping "devl")
10
+ * 4. Debugging — raw data inspection immediately reveals the format
11
+ *
12
+ * Format: [4 bytes: format identifier][payload]
13
+ *
14
+ * The format prefix is open-ended — any 4-character [a-z0-9] string is valid.
15
+ * This allows new codecs to be added without modifying this module.
16
+ */
17
+ import { type FormatPrefix } from './types.js';
18
+ /**
19
+ * Encode a payload with a format prefix.
20
+ *
21
+ * @param format - The format identifier (4 chars, [a-z0-9])
22
+ * @param payload - The serialized payload bytes
23
+ * @returns A new Uint8Array with format prefix prepended
24
+ */
25
+ export declare function encodeWithFormatPrefix(format: FormatPrefix, payload: Uint8Array | unknown): Uint8Array | unknown;
26
+ /**
27
+ * Peek at the format prefix without consuming it.
28
+ *
29
+ * Returns the prefix if it's a valid format prefix ([a-z0-9]{4}),
30
+ * or null if the data is legacy/non-binary or doesn't start with a
31
+ * valid prefix.
32
+ *
33
+ * @param data - The format-prefixed data
34
+ * @returns The format prefix, or null
35
+ */
36
+ export declare function peekFormatPrefix(data: Uint8Array | unknown): FormatPrefix | null;
37
+ /**
38
+ * Check if data is encrypted (has 'encr' format prefix).
39
+ */
40
+ export declare function isEncrypted(data: Uint8Array | unknown): boolean;
41
+ /**
42
+ * Decode a format-prefixed payload.
43
+ *
44
+ * Unlike the legacy implementation which only accepted known formats
45
+ * (`devl`, `encr`), this function accepts any valid format prefix
46
+ * (`[a-z0-9]{4}`). This is intentional for forward compatibility —
47
+ * new codecs (e.g. `cbor`) can be added without modifying this module.
48
+ * Callers are responsible for checking whether they support the returned
49
+ * format and throwing an appropriate error if not (e.g. "Unsupported
50
+ * serialization format").
51
+ *
52
+ * @param data - The format-prefixed data
53
+ * @returns An object with the format prefix and payload
54
+ * @throws Error if the data is too short or has an invalid prefix
55
+ */
56
+ export declare function decodeFormatPrefix(data: Uint8Array | unknown): {
57
+ format: FormatPrefix;
58
+ payload: Uint8Array;
59
+ };
60
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/serialization/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,YAAY,CAAC;AAQpB;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,UAAU,GAAG,OAAO,GAC5B,UAAU,GAAG,OAAO,CAUtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,GAAG,OAAO,GACzB,YAAY,GAAG,IAAI,CAOrB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,CAE/D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG;IAC9D,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,UAAU,CAAC;CACrB,CA0BA"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Format prefix system for serialized payloads.
3
+ *
4
+ * All serialized payloads are prefixed with a 4-byte format identifier that
5
+ * allows the deserializer to determine how to decode the payload. This enables:
6
+ *
7
+ * 1. Self-describing payloads — the World layer is agnostic to serialization format
8
+ * 2. Gradual migration — old runs keep working, new runs can use new formats
9
+ * 3. Composability — encryption can wrap any format ("encr" wrapping "devl")
10
+ * 4. Debugging — raw data inspection immediately reveals the format
11
+ *
12
+ * Format: [4 bytes: format identifier][payload]
13
+ *
14
+ * The format prefix is open-ended — any 4-character [a-z0-9] string is valid.
15
+ * This allows new codecs to be added without modifying this module.
16
+ */
17
+ import { isFormatPrefix, SerializationFormat, } from './types.js';
18
+ /** Length of the format prefix in bytes */
19
+ const FORMAT_PREFIX_LENGTH = 4;
20
+ const formatEncoder = new TextEncoder();
21
+ const formatDecoder = new TextDecoder();
22
+ /**
23
+ * Encode a payload with a format prefix.
24
+ *
25
+ * @param format - The format identifier (4 chars, [a-z0-9])
26
+ * @param payload - The serialized payload bytes
27
+ * @returns A new Uint8Array with format prefix prepended
28
+ */
29
+ export function encodeWithFormatPrefix(format, payload) {
30
+ if (!(payload instanceof Uint8Array)) {
31
+ return payload;
32
+ }
33
+ const prefixBytes = formatEncoder.encode(format);
34
+ const result = new Uint8Array(FORMAT_PREFIX_LENGTH + payload.length);
35
+ result.set(prefixBytes, 0);
36
+ result.set(payload, FORMAT_PREFIX_LENGTH);
37
+ return result;
38
+ }
39
+ /**
40
+ * Peek at the format prefix without consuming it.
41
+ *
42
+ * Returns the prefix if it's a valid format prefix ([a-z0-9]{4}),
43
+ * or null if the data is legacy/non-binary or doesn't start with a
44
+ * valid prefix.
45
+ *
46
+ * @param data - The format-prefixed data
47
+ * @returns The format prefix, or null
48
+ */
49
+ export function peekFormatPrefix(data) {
50
+ if (!(data instanceof Uint8Array) || data.length < FORMAT_PREFIX_LENGTH) {
51
+ return null;
52
+ }
53
+ const prefixBytes = data.subarray(0, FORMAT_PREFIX_LENGTH);
54
+ const str = formatDecoder.decode(prefixBytes);
55
+ return isFormatPrefix(str) ? str : null;
56
+ }
57
+ /**
58
+ * Check if data is encrypted (has 'encr' format prefix).
59
+ */
60
+ export function isEncrypted(data) {
61
+ return peekFormatPrefix(data) === SerializationFormat.ENCRYPTED;
62
+ }
63
+ /**
64
+ * Decode a format-prefixed payload.
65
+ *
66
+ * Unlike the legacy implementation which only accepted known formats
67
+ * (`devl`, `encr`), this function accepts any valid format prefix
68
+ * (`[a-z0-9]{4}`). This is intentional for forward compatibility —
69
+ * new codecs (e.g. `cbor`) can be added without modifying this module.
70
+ * Callers are responsible for checking whether they support the returned
71
+ * format and throwing an appropriate error if not (e.g. "Unsupported
72
+ * serialization format").
73
+ *
74
+ * @param data - The format-prefixed data
75
+ * @returns An object with the format prefix and payload
76
+ * @throws Error if the data is too short or has an invalid prefix
77
+ */
78
+ export function decodeFormatPrefix(data) {
79
+ // Compat for legacy specVersion 1 runs that don't have a format prefix
80
+ if (!(data instanceof Uint8Array)) {
81
+ return {
82
+ format: SerializationFormat.DEVALUE_V1,
83
+ payload: new TextEncoder().encode(JSON.stringify(data)),
84
+ };
85
+ }
86
+ if (data.length < FORMAT_PREFIX_LENGTH) {
87
+ throw new Error(`Data too short to contain format prefix: expected at least ${FORMAT_PREFIX_LENGTH} bytes, got ${data.length}`);
88
+ }
89
+ const prefixBytes = data.subarray(0, FORMAT_PREFIX_LENGTH);
90
+ const str = formatDecoder.decode(prefixBytes);
91
+ if (!isFormatPrefix(str)) {
92
+ throw new Error(`Invalid format prefix: "${str}". Must be 4 characters of [a-z0-9].`);
93
+ }
94
+ const payload = data.subarray(FORMAT_PREFIX_LENGTH);
95
+ return { format: str, payload };
96
+ }
97
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWF0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcmlhbGl6YXRpb24vZm9ybWF0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sRUFFTCxjQUFjLEVBQ2QsbUJBQW1CLEdBQ3BCLE1BQU0sWUFBWSxDQUFDO0FBRXBCLDJDQUEyQztBQUMzQyxNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQztBQUUvQixNQUFNLGFBQWEsR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO0FBQ3hDLE1BQU0sYUFBYSxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7QUFFeEM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLHNCQUFzQixDQUNwQyxNQUFvQixFQUNwQixPQUE2QjtJQUU3QixJQUFJLENBQUMsQ0FBQyxPQUFPLFlBQVksVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUNyQyxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRUQsTUFBTSxXQUFXLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNqRCxNQUFNLE1BQU0sR0FBRyxJQUFJLFVBQVUsQ0FBQyxvQkFBb0IsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDckUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDM0IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztJQUMxQyxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBRUQ7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUM5QixJQUEwQjtJQUUxQixJQUFJLENBQUMsQ0FBQyxJQUFJLFlBQVksVUFBVSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sR0FBRyxvQkFBb0IsRUFBRSxDQUFDO1FBQ3hFLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLG9CQUFvQixDQUFDLENBQUM7SUFDM0QsTUFBTSxHQUFHLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUM5QyxPQUFPLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDMUMsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLFdBQVcsQ0FBQyxJQUEwQjtJQUNwRCxPQUFPLGdCQUFnQixDQUFDLElBQUksQ0FBQyxLQUFLLG1CQUFtQixDQUFDLFNBQVMsQ0FBQztBQUNsRSxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsSUFBMEI7SUFJM0QsdUVBQXVFO0lBQ3ZFLElBQUksQ0FBQyxDQUFDLElBQUksWUFBWSxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQ2xDLE9BQU87WUFDTCxNQUFNLEVBQUUsbUJBQW1CLENBQUMsVUFBVTtZQUN0QyxPQUFPLEVBQUUsSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUN4RCxDQUFDO0lBQ0osQ0FBQztJQUVELElBQUksSUFBSSxDQUFDLE1BQU0sR0FBRyxvQkFBb0IsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sSUFBSSxLQUFLLENBQ2IsOERBQThELG9CQUFvQixlQUFlLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FDL0csQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO0lBQzNELE1BQU0sR0FBRyxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7SUFFOUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sSUFBSSxLQUFLLENBQ2IsMkJBQTJCLEdBQUcsc0NBQXNDLENBQ3JFLENBQUM7SUFDSixDQUFDO0lBRUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBQ3BELE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxDQUFDO0FBQ2xDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEZvcm1hdCBwcmVmaXggc3lzdGVtIGZvciBzZXJpYWxpemVkIHBheWxvYWRzLlxuICpcbiAqIEFsbCBzZXJpYWxpemVkIHBheWxvYWRzIGFyZSBwcmVmaXhlZCB3aXRoIGEgNC1ieXRlIGZvcm1hdCBpZGVudGlmaWVyIHRoYXRcbiAqIGFsbG93cyB0aGUgZGVzZXJpYWxpemVyIHRvIGRldGVybWluZSBob3cgdG8gZGVjb2RlIHRoZSBwYXlsb2FkLiBUaGlzIGVuYWJsZXM6XG4gKlxuICogMS4gU2VsZi1kZXNjcmliaW5nIHBheWxvYWRzIOKAlCB0aGUgV29ybGQgbGF5ZXIgaXMgYWdub3N0aWMgdG8gc2VyaWFsaXphdGlvbiBmb3JtYXRcbiAqIDIuIEdyYWR1YWwgbWlncmF0aW9uIOKAlCBvbGQgcnVucyBrZWVwIHdvcmtpbmcsIG5ldyBydW5zIGNhbiB1c2UgbmV3IGZvcm1hdHNcbiAqIDMuIENvbXBvc2FiaWxpdHkg4oCUIGVuY3J5cHRpb24gY2FuIHdyYXAgYW55IGZvcm1hdCAoXCJlbmNyXCIgd3JhcHBpbmcgXCJkZXZsXCIpXG4gKiA0LiBEZWJ1Z2dpbmcg4oCUIHJhdyBkYXRhIGluc3BlY3Rpb24gaW1tZWRpYXRlbHkgcmV2ZWFscyB0aGUgZm9ybWF0XG4gKlxuICogRm9ybWF0OiBbNCBieXRlczogZm9ybWF0IGlkZW50aWZpZXJdW3BheWxvYWRdXG4gKlxuICogVGhlIGZvcm1hdCBwcmVmaXggaXMgb3Blbi1lbmRlZCDigJQgYW55IDQtY2hhcmFjdGVyIFthLXowLTldIHN0cmluZyBpcyB2YWxpZC5cbiAqIFRoaXMgYWxsb3dzIG5ldyBjb2RlY3MgdG8gYmUgYWRkZWQgd2l0aG91dCBtb2RpZnlpbmcgdGhpcyBtb2R1bGUuXG4gKi9cblxuaW1wb3J0IHtcbiAgdHlwZSBGb3JtYXRQcmVmaXgsXG4gIGlzRm9ybWF0UHJlZml4LFxuICBTZXJpYWxpemF0aW9uRm9ybWF0LFxufSBmcm9tICcuL3R5cGVzLmpzJztcblxuLyoqIExlbmd0aCBvZiB0aGUgZm9ybWF0IHByZWZpeCBpbiBieXRlcyAqL1xuY29uc3QgRk9STUFUX1BSRUZJWF9MRU5HVEggPSA0O1xuXG5jb25zdCBmb3JtYXRFbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKCk7XG5jb25zdCBmb3JtYXREZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCk7XG5cbi8qKlxuICogRW5jb2RlIGEgcGF5bG9hZCB3aXRoIGEgZm9ybWF0IHByZWZpeC5cbiAqXG4gKiBAcGFyYW0gZm9ybWF0IC0gVGhlIGZvcm1hdCBpZGVudGlmaWVyICg0IGNoYXJzLCBbYS16MC05XSlcbiAqIEBwYXJhbSBwYXlsb2FkIC0gVGhlIHNlcmlhbGl6ZWQgcGF5bG9hZCBieXRlc1xuICogQHJldHVybnMgQSBuZXcgVWludDhBcnJheSB3aXRoIGZvcm1hdCBwcmVmaXggcHJlcGVuZGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVXaXRoRm9ybWF0UHJlZml4KFxuICBmb3JtYXQ6IEZvcm1hdFByZWZpeCxcbiAgcGF5bG9hZDogVWludDhBcnJheSB8IHVua25vd25cbik6IFVpbnQ4QXJyYXkgfCB1bmtub3duIHtcbiAgaWYgKCEocGF5bG9hZCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKSB7XG4gICAgcmV0dXJuIHBheWxvYWQ7XG4gIH1cblxuICBjb25zdCBwcmVmaXhCeXRlcyA9IGZvcm1hdEVuY29kZXIuZW5jb2RlKGZvcm1hdCk7XG4gIGNvbnN0IHJlc3VsdCA9IG5ldyBVaW50OEFycmF5KEZPUk1BVF9QUkVGSVhfTEVOR1RIICsgcGF5bG9hZC5sZW5ndGgpO1xuICByZXN1bHQuc2V0KHByZWZpeEJ5dGVzLCAwKTtcbiAgcmVzdWx0LnNldChwYXlsb2FkLCBGT1JNQVRfUFJFRklYX0xFTkdUSCk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogUGVlayBhdCB0aGUgZm9ybWF0IHByZWZpeCB3aXRob3V0IGNvbnN1bWluZyBpdC5cbiAqXG4gKiBSZXR1cm5zIHRoZSBwcmVmaXggaWYgaXQncyBhIHZhbGlkIGZvcm1hdCBwcmVmaXggKFthLXowLTldezR9KSxcbiAqIG9yIG51bGwgaWYgdGhlIGRhdGEgaXMgbGVnYWN5L25vbi1iaW5hcnkgb3IgZG9lc24ndCBzdGFydCB3aXRoIGFcbiAqIHZhbGlkIHByZWZpeC5cbiAqXG4gKiBAcGFyYW0gZGF0YSAtIFRoZSBmb3JtYXQtcHJlZml4ZWQgZGF0YVxuICogQHJldHVybnMgVGhlIGZvcm1hdCBwcmVmaXgsIG9yIG51bGxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBlZWtGb3JtYXRQcmVmaXgoXG4gIGRhdGE6IFVpbnQ4QXJyYXkgfCB1bmtub3duXG4pOiBGb3JtYXRQcmVmaXggfCBudWxsIHtcbiAgaWYgKCEoZGF0YSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHx8IGRhdGEubGVuZ3RoIDwgRk9STUFUX1BSRUZJWF9MRU5HVEgpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBjb25zdCBwcmVmaXhCeXRlcyA9IGRhdGEuc3ViYXJyYXkoMCwgRk9STUFUX1BSRUZJWF9MRU5HVEgpO1xuICBjb25zdCBzdHIgPSBmb3JtYXREZWNvZGVyLmRlY29kZShwcmVmaXhCeXRlcyk7XG4gIHJldHVybiBpc0Zvcm1hdFByZWZpeChzdHIpID8gc3RyIDogbnVsbDtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBkYXRhIGlzIGVuY3J5cHRlZCAoaGFzICdlbmNyJyBmb3JtYXQgcHJlZml4KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRW5jcnlwdGVkKGRhdGE6IFVpbnQ4QXJyYXkgfCB1bmtub3duKTogYm9vbGVhbiB7XG4gIHJldHVybiBwZWVrRm9ybWF0UHJlZml4KGRhdGEpID09PSBTZXJpYWxpemF0aW9uRm9ybWF0LkVOQ1JZUFRFRDtcbn1cblxuLyoqXG4gKiBEZWNvZGUgYSBmb3JtYXQtcHJlZml4ZWQgcGF5bG9hZC5cbiAqXG4gKiBVbmxpa2UgdGhlIGxlZ2FjeSBpbXBsZW1lbnRhdGlvbiB3aGljaCBvbmx5IGFjY2VwdGVkIGtub3duIGZvcm1hdHNcbiAqIChgZGV2bGAsIGBlbmNyYCksIHRoaXMgZnVuY3Rpb24gYWNjZXB0cyBhbnkgdmFsaWQgZm9ybWF0IHByZWZpeFxuICogKGBbYS16MC05XXs0fWApLiBUaGlzIGlzIGludGVudGlvbmFsIGZvciBmb3J3YXJkIGNvbXBhdGliaWxpdHkg4oCUXG4gKiBuZXcgY29kZWNzIChlLmcuIGBjYm9yYCkgY2FuIGJlIGFkZGVkIHdpdGhvdXQgbW9kaWZ5aW5nIHRoaXMgbW9kdWxlLlxuICogQ2FsbGVycyBhcmUgcmVzcG9uc2libGUgZm9yIGNoZWNraW5nIHdoZXRoZXIgdGhleSBzdXBwb3J0IHRoZSByZXR1cm5lZFxuICogZm9ybWF0IGFuZCB0aHJvd2luZyBhbiBhcHByb3ByaWF0ZSBlcnJvciBpZiBub3QgKGUuZy4gXCJVbnN1cHBvcnRlZFxuICogc2VyaWFsaXphdGlvbiBmb3JtYXRcIikuXG4gKlxuICogQHBhcmFtIGRhdGEgLSBUaGUgZm9ybWF0LXByZWZpeGVkIGRhdGFcbiAqIEByZXR1cm5zIEFuIG9iamVjdCB3aXRoIHRoZSBmb3JtYXQgcHJlZml4IGFuZCBwYXlsb2FkXG4gKiBAdGhyb3dzIEVycm9yIGlmIHRoZSBkYXRhIGlzIHRvbyBzaG9ydCBvciBoYXMgYW4gaW52YWxpZCBwcmVmaXhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZUZvcm1hdFByZWZpeChkYXRhOiBVaW50OEFycmF5IHwgdW5rbm93bik6IHtcbiAgZm9ybWF0OiBGb3JtYXRQcmVmaXg7XG4gIHBheWxvYWQ6IFVpbnQ4QXJyYXk7XG59IHtcbiAgLy8gQ29tcGF0IGZvciBsZWdhY3kgc3BlY1ZlcnNpb24gMSBydW5zIHRoYXQgZG9uJ3QgaGF2ZSBhIGZvcm1hdCBwcmVmaXhcbiAgaWYgKCEoZGF0YSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGZvcm1hdDogU2VyaWFsaXphdGlvbkZvcm1hdC5ERVZBTFVFX1YxLFxuICAgICAgcGF5bG9hZDogbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKEpTT04uc3RyaW5naWZ5KGRhdGEpKSxcbiAgICB9O1xuICB9XG5cbiAgaWYgKGRhdGEubGVuZ3RoIDwgRk9STUFUX1BSRUZJWF9MRU5HVEgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgRGF0YSB0b28gc2hvcnQgdG8gY29udGFpbiBmb3JtYXQgcHJlZml4OiBleHBlY3RlZCBhdCBsZWFzdCAke0ZPUk1BVF9QUkVGSVhfTEVOR1RIfSBieXRlcywgZ290ICR7ZGF0YS5sZW5ndGh9YFxuICAgICk7XG4gIH1cblxuICBjb25zdCBwcmVmaXhCeXRlcyA9IGRhdGEuc3ViYXJyYXkoMCwgRk9STUFUX1BSRUZJWF9MRU5HVEgpO1xuICBjb25zdCBzdHIgPSBmb3JtYXREZWNvZGVyLmRlY29kZShwcmVmaXhCeXRlcyk7XG5cbiAgaWYgKCFpc0Zvcm1hdFByZWZpeChzdHIpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEludmFsaWQgZm9ybWF0IHByZWZpeDogXCIke3N0cn1cIi4gTXVzdCBiZSA0IGNoYXJhY3RlcnMgb2YgW2EtejAtOV0uYFxuICAgICk7XG4gIH1cblxuICBjb25zdCBwYXlsb2FkID0gZGF0YS5zdWJhcnJheShGT1JNQVRfUFJFRklYX0xFTkdUSCk7XG4gIHJldHVybiB7IGZvcm1hdDogc3RyLCBwYXlsb2FkIH07XG59XG4iXX0=