@mysten-incubation/devstack 0.0.1 → 0.1.1

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 (838) hide show
  1. package/README.md +8 -4
  2. package/dashboard-ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  3. package/dashboard-ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  4. package/dashboard-ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  5. package/dashboard-ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  6. package/dashboard-ui/assets/geist-mono-cyrillic-ext-wght-normal-I4S5GZfc.woff2 +0 -0
  7. package/dashboard-ui/assets/geist-mono-cyrillic-wght-normal-BmXc_FBt.woff2 +0 -0
  8. package/dashboard-ui/assets/geist-mono-latin-ext-wght-normal-DrnZ1wKl.woff2 +0 -0
  9. package/dashboard-ui/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2 +0 -0
  10. package/dashboard-ui/assets/geist-mono-symbols2-wght-normal-GZpp1pK2.woff2 +0 -0
  11. package/dashboard-ui/assets/geist-mono-vietnamese-wght-normal-D8KDMBhC.woff2 +0 -0
  12. package/dashboard-ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  13. package/dashboard-ui/assets/index-Bmi1UtAg.js +1356 -0
  14. package/dashboard-ui/assets/index-D5EShVt4.js +3 -0
  15. package/dashboard-ui/assets/index-Deml9drg.css +1 -0
  16. package/dashboard-ui/index.html +13 -0
  17. package/dist/api/define-capabilities.d.mts +14 -3
  18. package/dist/api/define-capabilities.mjs +18 -1
  19. package/dist/api/define-capabilities.mjs.map +1 -1
  20. package/dist/api/define-devstack.d.mts +1 -1
  21. package/dist/api/define-devstack.mjs +6 -26
  22. package/dist/api/define-devstack.mjs.map +1 -1
  23. package/dist/api/define-plugin.d.mts +1 -0
  24. package/dist/api/define-plugin.mjs +2 -0
  25. package/dist/api/inference-network.d.mts +132 -0
  26. package/dist/api/inference-network.mjs +105 -16
  27. package/dist/api/inference-network.mjs.map +1 -1
  28. package/dist/api/plugin-errors.d.mts +7 -0
  29. package/dist/api/run-stack.d.mts +20 -9
  30. package/dist/api/run-stack.mjs +56 -29
  31. package/dist/api/run-stack.mjs.map +1 -1
  32. package/dist/build-integrations/playwright/config.d.mts +6 -4
  33. package/dist/build-integrations/playwright/config.mjs +5 -3
  34. package/dist/build-integrations/playwright/config.mjs.map +1 -1
  35. package/dist/build-integrations/playwright/errors.d.mts +1 -1
  36. package/dist/build-integrations/playwright/global-setup.d.mts +43 -17
  37. package/dist/build-integrations/playwright/global-setup.mjs +250 -13
  38. package/dist/build-integrations/playwright/global-setup.mjs.map +1 -1
  39. package/dist/build-integrations/playwright/index.d.mts +5 -3
  40. package/dist/build-integrations/playwright/index.mjs +4 -2
  41. package/dist/build-integrations/playwright/stack-context.d.mts +0 -1
  42. package/dist/build-integrations/playwright/stack-context.mjs +24 -63
  43. package/dist/build-integrations/playwright/stack-context.mjs.map +1 -1
  44. package/dist/build-integrations/playwright/wallet-context.d.mts +7 -10
  45. package/dist/build-integrations/playwright/wallet-context.mjs +8 -13
  46. package/dist/build-integrations/playwright/wallet-context.mjs.map +1 -1
  47. package/dist/build-integrations/runtime/cold-start-url.d.mts +5 -0
  48. package/dist/build-integrations/runtime/cold-start-url.mjs +4 -3
  49. package/dist/build-integrations/runtime/cold-start-url.mjs.map +1 -1
  50. package/dist/build-integrations/runtime/conventional-routes.d.mts +51 -0
  51. package/dist/build-integrations/runtime/conventional-routes.mjs +92 -0
  52. package/dist/build-integrations/runtime/conventional-routes.mjs.map +1 -0
  53. package/dist/build-integrations/runtime/discover.d.mts +38 -30
  54. package/dist/build-integrations/runtime/discover.mjs +73 -70
  55. package/dist/build-integrations/runtime/discover.mjs.map +1 -1
  56. package/dist/build-integrations/runtime/endpoint-registry.d.mts +3 -1
  57. package/dist/build-integrations/runtime/endpoint-registry.mjs +3 -1
  58. package/dist/build-integrations/runtime/endpoint-registry.mjs.map +1 -1
  59. package/dist/build-integrations/runtime/index.d.mts +7 -2
  60. package/dist/build-integrations/runtime/index.mjs +9 -2
  61. package/dist/build-integrations/runtime/manifest-types.d.mts +2 -0
  62. package/dist/build-integrations/runtime/manifest-types.mjs +3 -0
  63. package/dist/build-integrations/runtime/playwright-stack-context-slot.d.mts +29 -0
  64. package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs +10 -0
  65. package/dist/build-integrations/runtime/playwright-stack-context-slot.mjs.map +1 -0
  66. package/dist/build-integrations/runtime/read-stack-context.d.mts +1 -1
  67. package/dist/build-integrations/runtime/read-stack-context.mjs +10 -4
  68. package/dist/build-integrations/runtime/read-stack-context.mjs.map +1 -1
  69. package/dist/build-integrations/runtime/resolve-discovery-env.d.mts +48 -0
  70. package/dist/build-integrations/runtime/resolve-discovery-env.mjs +42 -0
  71. package/dist/build-integrations/runtime/resolve-discovery-env.mjs.map +1 -0
  72. package/dist/build-integrations/runtime/stack-context.d.mts +1 -1
  73. package/dist/build-integrations/runtime/wallet-paths.mjs +2 -0
  74. package/dist/build-integrations/vite/index.d.mts +51 -0
  75. package/dist/build-integrations/vite/index.mjs +73 -0
  76. package/dist/build-integrations/vite/index.mjs.map +1 -0
  77. package/dist/build-integrations/vitest/env.d.mts +4 -3
  78. package/dist/build-integrations/vitest/env.mjs +6 -4
  79. package/dist/build-integrations/vitest/env.mjs.map +1 -1
  80. package/dist/build-integrations/vitest/errors.d.mts +25 -4
  81. package/dist/build-integrations/vitest/errors.mjs +15 -2
  82. package/dist/build-integrations/vitest/errors.mjs.map +1 -1
  83. package/dist/build-integrations/vitest/index.d.mts +2 -2
  84. package/dist/build-integrations/vitest/index.mjs +3 -3
  85. package/dist/build-integrations/vitest/setup.d.mts +4 -2
  86. package/dist/build-integrations/vitest/setup.mjs +2 -2
  87. package/dist/build-integrations/vitest/setup.mjs.map +1 -1
  88. package/dist/build-integrations/vitest/stack-context.d.mts +0 -1
  89. package/dist/build-integrations/vitest/stack-context.mjs +33 -13
  90. package/dist/build-integrations/vitest/stack-context.mjs.map +1 -1
  91. package/dist/cli/bail.mjs +23 -0
  92. package/dist/cli/bail.mjs.map +1 -0
  93. package/dist/{surfaces/cli/commands → cli}/doctor-probes.mjs +26 -16
  94. package/dist/cli/doctor-probes.mjs.map +1 -0
  95. package/dist/cli/main.d.mts +15 -1
  96. package/dist/cli/main.mjs +166 -482
  97. package/dist/cli/main.mjs.map +1 -1
  98. package/dist/cli/prune-direct.mjs +31 -201
  99. package/dist/cli/prune-direct.mjs.map +1 -1
  100. package/dist/cli/snapshot-reader.mjs +14 -11
  101. package/dist/cli/snapshot-reader.mjs.map +1 -1
  102. package/dist/cli/up-lifecycle.mjs +4 -1
  103. package/dist/cli/up-lifecycle.mjs.map +1 -1
  104. package/dist/cli/wirings/apply.mjs +95 -0
  105. package/dist/cli/wirings/apply.mjs.map +1 -0
  106. package/dist/cli/wirings/build-verb-layers.mjs +42 -0
  107. package/dist/cli/wirings/build-verb-layers.mjs.map +1 -0
  108. package/dist/cli/wirings/config-loader.mjs +69 -0
  109. package/dist/cli/wirings/config-loader.mjs.map +1 -0
  110. package/dist/cli/wirings/engine-command.mjs +30 -0
  111. package/dist/cli/wirings/engine-command.mjs.map +1 -0
  112. package/dist/cli/wirings/identity.mjs +72 -0
  113. package/dist/cli/wirings/identity.mjs.map +1 -0
  114. package/dist/cli/wirings/provide-file-system.mjs +7 -0
  115. package/dist/cli/wirings/provide-file-system.mjs.map +1 -0
  116. package/dist/cli/wirings/snapshot.mjs +177 -0
  117. package/dist/cli/wirings/snapshot.mjs.map +1 -0
  118. package/dist/cli/wirings/up.mjs +287 -0
  119. package/dist/cli/wirings/up.mjs.map +1 -0
  120. package/dist/cli/wirings/wipe.mjs +40 -0
  121. package/dist/cli/wirings/wipe.mjs.map +1 -0
  122. package/dist/contracts/capability-decl.d.mts +0 -2
  123. package/dist/contracts/codegenable.d.mts +43 -0
  124. package/dist/contracts/container-runtime.d.mts +26 -1
  125. package/dist/contracts/faucet-strategy.d.mts +25 -0
  126. package/dist/contracts/funding-strategy.d.mts +42 -0
  127. package/dist/contracts/plugin-expander.mjs +60 -0
  128. package/dist/contracts/plugin-expander.mjs.map +1 -0
  129. package/dist/contracts/projection.d.mts +5 -3
  130. package/dist/contracts/renderer.d.mts +23 -0
  131. package/dist/contracts/routable.d.mts +14 -1
  132. package/dist/contracts/snapshotable.d.mts +25 -3
  133. package/dist/contracts/wallet-protocol.d.mts +52 -0
  134. package/dist/contracts/wallet-protocol.mjs +52 -0
  135. package/dist/contracts/wallet-protocol.mjs.map +1 -0
  136. package/dist/index.d.mts +26 -25
  137. package/dist/index.mjs +20 -13
  138. package/dist/{runtime → orchestrators}/built-in-plugin-layers.mjs +10 -5
  139. package/dist/orchestrators/built-in-plugin-layers.mjs.map +1 -0
  140. package/dist/orchestrators/codegen/bindings.d.mts +1 -2
  141. package/dist/orchestrators/codegen/bindings.mjs +52 -186
  142. package/dist/orchestrators/codegen/bindings.mjs.map +1 -1
  143. package/dist/orchestrators/codegen/emit.mjs +19 -1
  144. package/dist/orchestrators/codegen/emit.mjs.map +1 -1
  145. package/dist/orchestrators/codegen/errors.mjs +8 -3
  146. package/dist/orchestrators/codegen/errors.mjs.map +1 -1
  147. package/dist/orchestrators/codegen/format.mjs +47 -39
  148. package/dist/orchestrators/codegen/format.mjs.map +1 -1
  149. package/dist/orchestrators/codegen/gitignore.mjs +3 -1
  150. package/dist/orchestrators/codegen/gitignore.mjs.map +1 -1
  151. package/dist/orchestrators/codegen/output-location.mjs +41 -0
  152. package/dist/orchestrators/codegen/output-location.mjs.map +1 -0
  153. package/dist/orchestrators/codegen/paths.d.mts +1 -1
  154. package/dist/orchestrators/codegen/paths.mjs +40 -14
  155. package/dist/orchestrators/codegen/paths.mjs.map +1 -1
  156. package/dist/orchestrators/codegen/permissions.mjs +3 -1
  157. package/dist/orchestrators/codegen/permissions.mjs.map +1 -1
  158. package/dist/orchestrators/codegen/service.mjs +157 -105
  159. package/dist/orchestrators/codegen/service.mjs.map +1 -1
  160. package/dist/orchestrators/lifecycle-prune/errors.mjs +31 -0
  161. package/dist/orchestrators/lifecycle-prune/errors.mjs.map +1 -0
  162. package/dist/orchestrators/lifecycle-prune/index.mjs +350 -0
  163. package/dist/orchestrators/lifecycle-prune/index.mjs.map +1 -0
  164. package/dist/orchestrators/router/cleanup.mjs +26 -27
  165. package/dist/orchestrators/router/cleanup.mjs.map +1 -1
  166. package/dist/orchestrators/router/entrypoints.mjs +2 -2
  167. package/dist/orchestrators/router/entrypoints.mjs.map +1 -1
  168. package/dist/orchestrators/router/file-provider.mjs +14 -5
  169. package/dist/orchestrators/router/file-provider.mjs.map +1 -1
  170. package/dist/orchestrators/router/hostname.mjs +19 -55
  171. package/dist/orchestrators/router/hostname.mjs.map +1 -1
  172. package/dist/orchestrators/router/index.mjs +11 -0
  173. package/dist/orchestrators/router/profile.mjs +2 -2
  174. package/dist/orchestrators/router/sentinels.mjs +26 -0
  175. package/dist/orchestrators/router/sentinels.mjs.map +1 -0
  176. package/dist/orchestrators/router/service.mjs +40 -37
  177. package/dist/orchestrators/router/service.mjs.map +1 -1
  178. package/dist/orchestrators/router/traefik-container.mjs +27 -16
  179. package/dist/orchestrators/router/traefik-container.mjs.map +1 -1
  180. package/dist/{substrate/runtime → orchestrators}/run.mjs +26 -21
  181. package/dist/orchestrators/run.mjs.map +1 -0
  182. package/dist/orchestrators/runtime-composition.d.mts +1 -1
  183. package/dist/orchestrators/runtime-composition.mjs +123 -39
  184. package/dist/orchestrators/runtime-composition.mjs.map +1 -1
  185. package/dist/orchestrators/snapshot/capture-command.d.mts +1 -0
  186. package/dist/orchestrators/snapshot/capture-command.mjs +25 -0
  187. package/dist/orchestrators/snapshot/capture-command.mjs.map +1 -0
  188. package/dist/orchestrators/snapshot/capture.mjs +42 -28
  189. package/dist/orchestrators/snapshot/capture.mjs.map +1 -1
  190. package/dist/orchestrators/snapshot/descriptor.mjs +35 -10
  191. package/dist/orchestrators/snapshot/descriptor.mjs.map +1 -1
  192. package/dist/orchestrators/snapshot/identity-guard.mjs +1 -1
  193. package/dist/orchestrators/snapshot/index.mjs +13 -0
  194. package/dist/orchestrators/snapshot/integrity.d.mts +1 -1
  195. package/dist/orchestrators/snapshot/integrity.mjs +73 -17
  196. package/dist/orchestrators/snapshot/integrity.mjs.map +1 -1
  197. package/dist/orchestrators/snapshot/pending-marker.d.mts +1 -0
  198. package/dist/orchestrators/snapshot/pending-marker.mjs +99 -0
  199. package/dist/orchestrators/snapshot/pending-marker.mjs.map +1 -0
  200. package/dist/orchestrators/snapshot/phase-error.mjs +23 -0
  201. package/dist/orchestrators/snapshot/phase-error.mjs.map +1 -0
  202. package/dist/orchestrators/snapshot/prune.mjs +20 -55
  203. package/dist/orchestrators/snapshot/prune.mjs.map +1 -1
  204. package/dist/orchestrators/snapshot/recover-pending.d.mts +1 -0
  205. package/dist/orchestrators/snapshot/recover-pending.mjs +223 -0
  206. package/dist/orchestrators/snapshot/recover-pending.mjs.map +1 -0
  207. package/dist/orchestrators/snapshot/restore.mjs +118 -84
  208. package/dist/orchestrators/snapshot/restore.mjs.map +1 -1
  209. package/dist/orchestrators/snapshot/service.mjs +53 -56
  210. package/dist/orchestrators/snapshot/service.mjs.map +1 -1
  211. package/dist/orchestrators/snapshot/state-document.d.mts +1 -0
  212. package/dist/orchestrators/snapshot/state-document.mjs +47 -7
  213. package/dist/orchestrators/snapshot/state-document.mjs.map +1 -1
  214. package/dist/orchestrators/snapshot/wipe.mjs +67 -10
  215. package/dist/orchestrators/snapshot/wipe.mjs.map +1 -1
  216. package/dist/plugins/account/codegen.mjs +9 -8
  217. package/dist/plugins/account/codegen.mjs.map +1 -1
  218. package/dist/plugins/account/errors.d.mts +33 -6
  219. package/dist/plugins/account/errors.mjs.map +1 -1
  220. package/dist/plugins/account/funding.d.mts +29 -19
  221. package/dist/plugins/account/funding.mjs +84 -66
  222. package/dist/plugins/account/funding.mjs.map +1 -1
  223. package/dist/plugins/account/index.d.mts +2 -4
  224. package/dist/plugins/account/index.mjs +64 -31
  225. package/dist/plugins/account/index.mjs.map +1 -1
  226. package/dist/plugins/account/keypair.mjs +6 -9
  227. package/dist/plugins/account/keypair.mjs.map +1 -1
  228. package/dist/plugins/account/lease.mjs +1 -0
  229. package/dist/plugins/account/lease.mjs.map +1 -1
  230. package/dist/plugins/account/registry.d.mts +14 -1
  231. package/dist/plugins/account/registry.mjs +18 -18
  232. package/dist/plugins/account/registry.mjs.map +1 -1
  233. package/dist/plugins/account/service.d.mts +23 -4
  234. package/dist/plugins/account/service.mjs +83 -45
  235. package/dist/plugins/account/service.mjs.map +1 -1
  236. package/dist/plugins/account/snapshot.mjs +2 -5
  237. package/dist/plugins/account/snapshot.mjs.map +1 -1
  238. package/dist/plugins/account/spans.mjs +16 -0
  239. package/dist/plugins/account/spans.mjs.map +1 -0
  240. package/dist/plugins/account/variants/keystore.mjs +6 -8
  241. package/dist/plugins/account/variants/keystore.mjs.map +1 -1
  242. package/dist/plugins/action/build-context.d.mts +3 -2
  243. package/dist/plugins/action/errors.d.mts +16 -12
  244. package/dist/plugins/action/errors.mjs.map +1 -1
  245. package/dist/plugins/action/execute.mjs +65 -103
  246. package/dist/plugins/action/execute.mjs.map +1 -1
  247. package/dist/plugins/action/index.d.mts +0 -2
  248. package/dist/plugins/action/index.mjs +17 -13
  249. package/dist/plugins/action/index.mjs.map +1 -1
  250. package/dist/plugins/action/service.mjs +38 -35
  251. package/dist/plugins/action/service.mjs.map +1 -1
  252. package/dist/plugins/action/spans.mjs +11 -0
  253. package/dist/plugins/action/spans.mjs.map +1 -0
  254. package/dist/plugins/coin/codegen.mjs +9 -8
  255. package/dist/plugins/coin/codegen.mjs.map +1 -1
  256. package/dist/plugins/coin/discovery.mjs +8 -4
  257. package/dist/plugins/coin/discovery.mjs.map +1 -1
  258. package/dist/plugins/coin/index.d.mts +11 -29
  259. package/dist/plugins/coin/index.mjs +56 -27
  260. package/dist/plugins/coin/index.mjs.map +1 -1
  261. package/dist/plugins/coin/metadata.mjs +8 -15
  262. package/dist/plugins/coin/metadata.mjs.map +1 -1
  263. package/dist/plugins/coin/mint.d.mts +30 -11
  264. package/dist/plugins/coin/mint.mjs +78 -74
  265. package/dist/plugins/coin/mint.mjs.map +1 -1
  266. package/dist/plugins/coin/registry.mjs +4 -7
  267. package/dist/plugins/coin/registry.mjs.map +1 -1
  268. package/dist/plugins/coin/service.d.mts +39 -1
  269. package/dist/plugins/coin/service.mjs +11 -4
  270. package/dist/plugins/coin/service.mjs.map +1 -1
  271. package/dist/plugins/coin/spans.mjs +20 -0
  272. package/dist/plugins/coin/spans.mjs.map +1 -0
  273. package/dist/plugins/dashboard/domain.mjs +402 -0
  274. package/dist/plugins/dashboard/domain.mjs.map +1 -0
  275. package/dist/plugins/dashboard/index.d.mts +29 -0
  276. package/dist/plugins/dashboard/index.mjs +91 -0
  277. package/dist/plugins/dashboard/index.mjs.map +1 -0
  278. package/dist/plugins/dashboard/origin-policy.mjs +36 -0
  279. package/dist/plugins/dashboard/origin-policy.mjs.map +1 -0
  280. package/dist/plugins/dashboard/routable.mjs +27 -0
  281. package/dist/plugins/dashboard/routable.mjs.map +1 -0
  282. package/dist/plugins/dashboard/schema/builder.mjs +21 -0
  283. package/dist/plugins/dashboard/schema/builder.mjs.map +1 -0
  284. package/dist/plugins/dashboard/schema/enums.mjs +72 -0
  285. package/dist/plugins/dashboard/schema/enums.mjs.map +1 -0
  286. package/dist/plugins/dashboard/schema/root.mjs +351 -0
  287. package/dist/plugins/dashboard/schema/root.mjs.map +1 -0
  288. package/dist/plugins/dashboard/schema/types.mjs +508 -0
  289. package/dist/plugins/dashboard/schema/types.mjs.map +1 -0
  290. package/dist/plugins/dashboard/schema.mjs +11 -0
  291. package/dist/plugins/dashboard/schema.mjs.map +1 -0
  292. package/dist/plugins/dashboard/server.mjs +166 -0
  293. package/dist/plugins/dashboard/server.mjs.map +1 -0
  294. package/dist/plugins/deepbook/deploy.mjs +53 -115
  295. package/dist/plugins/deepbook/deploy.mjs.map +1 -1
  296. package/dist/plugins/deepbook/errors.mjs +1 -0
  297. package/dist/plugins/deepbook/errors.mjs.map +1 -1
  298. package/dist/plugins/deepbook/faucet-strategy.mjs +47 -34
  299. package/dist/plugins/deepbook/faucet-strategy.mjs.map +1 -1
  300. package/dist/plugins/deepbook/hash.mjs +9 -0
  301. package/dist/plugins/deepbook/hash.mjs.map +1 -0
  302. package/dist/plugins/deepbook/index.d.mts +1 -10
  303. package/dist/plugins/deepbook/index.mjs +25 -22
  304. package/dist/plugins/deepbook/index.mjs.map +1 -1
  305. package/dist/plugins/deepbook/pyth/index.mjs +26 -55
  306. package/dist/plugins/deepbook/pyth/index.mjs.map +1 -1
  307. package/dist/plugins/deepbook/snapshot.mjs +17 -29
  308. package/dist/plugins/deepbook/snapshot.mjs.map +1 -1
  309. package/dist/plugins/deepbook/spans.mjs +18 -0
  310. package/dist/plugins/deepbook/spans.mjs.map +1 -0
  311. package/dist/plugins/deepbook/type-strings.mjs +65 -0
  312. package/dist/plugins/deepbook/type-strings.mjs.map +1 -0
  313. package/dist/plugins/deepbook/types.d.mts +2 -3
  314. package/dist/plugins/deepbook/types.mjs.map +1 -1
  315. package/dist/plugins/faucet/dispatcher.d.mts +21 -2
  316. package/dist/plugins/faucet/dispatcher.mjs +1 -2
  317. package/dist/plugins/faucet/dispatcher.mjs.map +1 -1
  318. package/dist/plugins/faucet/errors.d.mts +11 -24
  319. package/dist/plugins/faucet/errors.mjs.map +1 -1
  320. package/dist/plugins/faucet/http.mjs +33 -14
  321. package/dist/plugins/faucet/http.mjs.map +1 -1
  322. package/dist/plugins/faucet/index.d.mts +15 -5
  323. package/dist/plugins/faucet/index.mjs +3 -0
  324. package/dist/plugins/faucet/index.mjs.map +1 -1
  325. package/dist/plugins/faucet/spans.mjs +12 -0
  326. package/dist/plugins/faucet/spans.mjs.map +1 -0
  327. package/dist/plugins/host-service/errors.d.mts +1 -1
  328. package/dist/plugins/host-service/index.mjs +34 -8
  329. package/dist/plugins/host-service/index.mjs.map +1 -1
  330. package/dist/plugins/host-service/routable.mjs +2 -1
  331. package/dist/plugins/host-service/routable.mjs.map +1 -1
  332. package/dist/plugins/host-service/service.d.mts +21 -0
  333. package/dist/plugins/host-service/service.mjs +136 -81
  334. package/dist/plugins/host-service/service.mjs.map +1 -1
  335. package/dist/plugins/internal/acquire-on-chain-artifact.mjs +23 -0
  336. package/dist/plugins/internal/acquire-on-chain-artifact.mjs.map +1 -0
  337. package/dist/plugins/internal/codegen-helpers.mjs +18 -0
  338. package/dist/plugins/internal/codegen-helpers.mjs.map +1 -0
  339. package/dist/plugins/internal/funding-failure-error.mjs +32 -0
  340. package/dist/plugins/internal/funding-failure-error.mjs.map +1 -0
  341. package/dist/plugins/package/build.mjs +1 -1
  342. package/dist/plugins/package/build.mjs.map +1 -1
  343. package/dist/plugins/package/codegen.mjs +26 -0
  344. package/dist/plugins/package/codegen.mjs.map +1 -1
  345. package/dist/plugins/package/errors.d.mts +16 -6
  346. package/dist/plugins/package/errors.mjs.map +1 -1
  347. package/dist/plugins/package/index.d.mts +0 -4
  348. package/dist/plugins/package/index.mjs +27 -21
  349. package/dist/plugins/package/index.mjs.map +1 -1
  350. package/dist/plugins/package/mode-known.mjs +26 -12
  351. package/dist/plugins/package/mode-known.mjs.map +1 -1
  352. package/dist/plugins/package/mode-local.mjs +47 -41
  353. package/dist/plugins/package/mode-local.mjs.map +1 -1
  354. package/dist/plugins/package/publish-executor.mjs +55 -114
  355. package/dist/plugins/package/publish-executor.mjs.map +1 -1
  356. package/dist/plugins/package/registry.mjs +2 -1
  357. package/dist/plugins/package/registry.mjs.map +1 -1
  358. package/dist/plugins/package/service.mjs.map +1 -1
  359. package/dist/plugins/package/spans.mjs +14 -0
  360. package/dist/plugins/package/spans.mjs.map +1 -0
  361. package/dist/plugins/postgres/db-ensure.mjs +19 -12
  362. package/dist/plugins/postgres/db-ensure.mjs.map +1 -1
  363. package/dist/plugins/postgres/errors.d.mts +5 -0
  364. package/dist/plugins/postgres/errors.mjs.map +1 -1
  365. package/dist/plugins/postgres/index.mjs +10 -17
  366. package/dist/plugins/postgres/index.mjs.map +1 -1
  367. package/dist/plugins/postgres/service.mjs +58 -24
  368. package/dist/plugins/postgres/service.mjs.map +1 -1
  369. package/dist/plugins/postgres/snapshot.mjs.map +1 -1
  370. package/dist/plugins/postgres/spans.mjs +11 -0
  371. package/dist/plugins/postgres/spans.mjs.map +1 -0
  372. package/dist/plugins/router-entrypoints.mjs +4 -4
  373. package/dist/plugins/router-entrypoints.mjs.map +1 -1
  374. package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs +15 -13
  375. package/dist/plugins/seal/bootstrap-assets/cargo-image.mjs.map +1 -1
  376. package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs +15 -19
  377. package/dist/plugins/seal/bootstrap-assets/source-fetch.mjs.map +1 -1
  378. package/dist/plugins/seal/codegen.d.mts +2 -3
  379. package/dist/plugins/seal/codegen.mjs.map +1 -1
  380. package/dist/plugins/seal/config-render.mjs +35 -8
  381. package/dist/plugins/seal/config-render.mjs.map +1 -1
  382. package/dist/plugins/seal/deploy.mjs +31 -39
  383. package/dist/plugins/seal/deploy.mjs.map +1 -1
  384. package/dist/plugins/seal/errors.d.mts +1 -3
  385. package/dist/plugins/seal/errors.mjs +7 -1
  386. package/dist/plugins/seal/errors.mjs.map +1 -1
  387. package/dist/plugins/seal/index.d.mts +1 -6
  388. package/dist/plugins/seal/index.mjs +40 -14
  389. package/dist/plugins/seal/index.mjs.map +1 -1
  390. package/dist/plugins/seal/key-manager.d.mts +1 -9
  391. package/dist/plugins/seal/key-manager.mjs +2 -18
  392. package/dist/plugins/seal/key-manager.mjs.map +1 -1
  393. package/dist/plugins/seal/key-server.mjs +37 -36
  394. package/dist/plugins/seal/key-server.mjs.map +1 -1
  395. package/dist/plugins/seal/keygen.mjs +16 -17
  396. package/dist/plugins/seal/keygen.mjs.map +1 -1
  397. package/dist/plugins/seal/mode/fork-known.mjs +36 -14
  398. package/dist/plugins/seal/mode/fork-known.mjs.map +1 -1
  399. package/dist/plugins/seal/mode/live.d.mts +6 -4
  400. package/dist/plugins/seal/mode/live.mjs +14 -21
  401. package/dist/plugins/seal/mode/live.mjs.map +1 -1
  402. package/dist/plugins/seal/mode/local-keygen.mjs +57 -21
  403. package/dist/plugins/seal/mode/local-keygen.mjs.map +1 -1
  404. package/dist/plugins/seal/registry-publish.mjs +1 -0
  405. package/dist/plugins/seal/registry-publish.mjs.map +1 -1
  406. package/dist/plugins/seal/routable.mjs.map +1 -1
  407. package/dist/plugins/seal/service.mjs.map +1 -1
  408. package/dist/plugins/seal/spans.mjs +18 -0
  409. package/dist/plugins/seal/spans.mjs.map +1 -0
  410. package/dist/plugins/sui/auto-tick.mjs +17 -23
  411. package/dist/plugins/sui/auto-tick.mjs.map +1 -1
  412. package/dist/plugins/sui/chain-build-container.mjs +18 -0
  413. package/dist/plugins/sui/chain-build-container.mjs.map +1 -0
  414. package/dist/plugins/sui/chain-probe.d.mts +5 -5
  415. package/dist/plugins/sui/chain-probe.mjs +28 -58
  416. package/dist/plugins/sui/chain-probe.mjs.map +1 -1
  417. package/dist/plugins/sui/codegen.mjs +26 -0
  418. package/dist/plugins/sui/codegen.mjs.map +1 -1
  419. package/dist/plugins/sui/errors.d.mts +2 -29
  420. package/dist/plugins/sui/errors.mjs +1 -3
  421. package/dist/plugins/sui/errors.mjs.map +1 -1
  422. package/dist/plugins/sui/fork-faucet-strategy.d.mts +1 -0
  423. package/dist/plugins/sui/fork-faucet-strategy.mjs +55 -0
  424. package/dist/plugins/sui/fork-faucet-strategy.mjs.map +1 -0
  425. package/dist/plugins/sui/fork-orchestration.d.mts +1 -0
  426. package/dist/plugins/sui/fork-orchestration.mjs +170 -2
  427. package/dist/plugins/sui/fork-orchestration.mjs.map +1 -1
  428. package/dist/plugins/sui/fork-transaction.d.mts +2 -0
  429. package/dist/plugins/sui/fork-transaction.mjs +92 -28
  430. package/dist/plugins/sui/fork-transaction.mjs.map +1 -1
  431. package/dist/plugins/sui/index.d.mts +33 -70
  432. package/dist/plugins/sui/index.mjs +58 -35
  433. package/dist/plugins/sui/index.mjs.map +1 -1
  434. package/dist/plugins/{faucet/strategies/sui-local.mjs → sui/local-faucet-strategy.mjs} +10 -7
  435. package/dist/plugins/sui/local-faucet-strategy.mjs.map +1 -0
  436. package/dist/plugins/sui/mode/external.mjs +7 -13
  437. package/dist/plugins/sui/mode/external.mjs.map +1 -1
  438. package/dist/plugins/sui/mode/fork.mjs +136 -59
  439. package/dist/plugins/sui/mode/fork.mjs.map +1 -1
  440. package/dist/plugins/sui/mode/live.mjs +10 -16
  441. package/dist/plugins/sui/mode/live.mjs.map +1 -1
  442. package/dist/plugins/sui/mode/local.mjs +37 -36
  443. package/dist/plugins/sui/mode/local.mjs.map +1 -1
  444. package/dist/plugins/sui/mode/shared-boot.mjs +38 -115
  445. package/dist/plugins/sui/mode/shared-boot.mjs.map +1 -1
  446. package/dist/plugins/sui/mode/shared.d.mts +1 -5
  447. package/dist/plugins/sui/mode/shared.mjs.map +1 -1
  448. package/dist/plugins/sui/mode/spec.d.mts +18 -0
  449. package/dist/plugins/sui/move-summary-runner.mjs +207 -0
  450. package/dist/plugins/sui/move-summary-runner.mjs.map +1 -0
  451. package/dist/plugins/sui/network-resolver.d.mts +4 -3
  452. package/dist/plugins/sui/service.mjs.map +1 -1
  453. package/dist/plugins/sui/snapshot.mjs +3 -0
  454. package/dist/plugins/sui/snapshot.mjs.map +1 -1
  455. package/dist/plugins/sui/spans.mjs +17 -0
  456. package/dist/plugins/sui/spans.mjs.map +1 -0
  457. package/dist/plugins/wallet/codegen.d.mts +0 -1
  458. package/dist/plugins/wallet/codegen.mjs +8 -9
  459. package/dist/plugins/wallet/codegen.mjs.map +1 -1
  460. package/dist/plugins/wallet/index.d.mts +6 -8
  461. package/dist/plugins/wallet/index.mjs +46 -35
  462. package/dist/plugins/wallet/index.mjs.map +1 -1
  463. package/dist/plugins/wallet/origin-policy.mjs +12 -28
  464. package/dist/plugins/wallet/origin-policy.mjs.map +1 -1
  465. package/dist/plugins/wallet/pairing.mjs +6 -4
  466. package/dist/plugins/wallet/pairing.mjs.map +1 -1
  467. package/dist/plugins/wallet/protocol.d.mts +1 -0
  468. package/dist/plugins/wallet/protocol.mjs +5 -44
  469. package/dist/plugins/wallet/protocol.mjs.map +1 -1
  470. package/dist/plugins/wallet/routable.mjs +2 -8
  471. package/dist/plugins/wallet/routable.mjs.map +1 -1
  472. package/dist/plugins/wallet/server.mjs +36 -44
  473. package/dist/plugins/wallet/server.mjs.map +1 -1
  474. package/dist/plugins/wallet/service.d.mts +1 -5
  475. package/dist/plugins/wallet/service.mjs +22 -18
  476. package/dist/plugins/wallet/service.mjs.map +1 -1
  477. package/dist/plugins/wallet/spans.mjs +22 -0
  478. package/dist/plugins/wallet/spans.mjs.map +1 -0
  479. package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs +33 -8
  480. package/dist/plugins/walrus/bootstrap-assets/cargo-image.mjs.map +1 -1
  481. package/dist/plugins/walrus/codegen.d.mts +3 -3
  482. package/dist/plugins/walrus/codegen.mjs.map +1 -1
  483. package/dist/plugins/walrus/deploy-paths.mjs +21 -5
  484. package/dist/plugins/walrus/deploy-paths.mjs.map +1 -1
  485. package/dist/plugins/walrus/deploy.mjs +67 -69
  486. package/dist/plugins/walrus/deploy.mjs.map +1 -1
  487. package/dist/plugins/walrus/errors.mjs +1 -0
  488. package/dist/plugins/walrus/errors.mjs.map +1 -1
  489. package/dist/plugins/walrus/faucet-strategy.mjs +12 -7
  490. package/dist/plugins/walrus/faucet-strategy.mjs.map +1 -1
  491. package/dist/plugins/walrus/index.d.mts +2 -13
  492. package/dist/plugins/walrus/index.mjs +18 -23
  493. package/dist/plugins/walrus/index.mjs.map +1 -1
  494. package/dist/plugins/walrus/mode/known-deploy.mjs +7 -5
  495. package/dist/plugins/walrus/mode/known-deploy.mjs.map +1 -1
  496. package/dist/plugins/walrus/mode/local-cluster.mjs +26 -7
  497. package/dist/plugins/walrus/mode/local-cluster.mjs.map +1 -1
  498. package/dist/plugins/walrus/registry-publish.mjs.map +1 -1
  499. package/dist/plugins/walrus/routable.mjs +7 -23
  500. package/dist/plugins/walrus/routable.mjs.map +1 -1
  501. package/dist/plugins/walrus/service.mjs.map +1 -1
  502. package/dist/plugins/walrus/spans.mjs +18 -0
  503. package/dist/plugins/walrus/spans.mjs.map +1 -0
  504. package/dist/plugins/walrus/storage-nodes.d.mts +6 -2
  505. package/dist/plugins/walrus/storage-nodes.mjs +15 -8
  506. package/dist/plugins/walrus/storage-nodes.mjs.map +1 -1
  507. package/dist/plugins/walrus/wal-swap.mjs +58 -15
  508. package/dist/plugins/walrus/wal-swap.mjs.map +1 -1
  509. package/dist/primitives/artifact-publisher.d.mts +1 -1
  510. package/dist/primitives/artifact-publisher.mjs +15 -0
  511. package/dist/primitives/artifact-publisher.mjs.map +1 -0
  512. package/dist/runtime/docker/client.mjs +17 -4
  513. package/dist/runtime/docker/client.mjs.map +1 -1
  514. package/dist/runtime/docker/container.mjs +219 -132
  515. package/dist/runtime/docker/container.mjs.map +1 -1
  516. package/dist/runtime/docker/errors.mjs +0 -6
  517. package/dist/runtime/docker/errors.mjs.map +1 -1
  518. package/dist/runtime/docker/exec.mjs +21 -18
  519. package/dist/runtime/docker/exec.mjs.map +1 -1
  520. package/dist/runtime/docker/image.mjs +36 -13
  521. package/dist/runtime/docker/image.mjs.map +1 -1
  522. package/dist/runtime/docker/index.mjs +14 -0
  523. package/dist/runtime/docker/inspect-and-decode.mjs +51 -0
  524. package/dist/runtime/docker/inspect-and-decode.mjs.map +1 -0
  525. package/dist/runtime/docker/inventory.mjs +14 -11
  526. package/dist/runtime/docker/inventory.mjs.map +1 -1
  527. package/dist/runtime/docker/labels.mjs +38 -5
  528. package/dist/runtime/docker/labels.mjs.map +1 -1
  529. package/dist/runtime/docker/logs.d.mts +1 -1
  530. package/dist/runtime/docker/logs.mjs.map +1 -1
  531. package/dist/runtime/docker/network.mjs +83 -47
  532. package/dist/runtime/docker/network.mjs.map +1 -1
  533. package/dist/runtime/docker/render-run-args.mjs +82 -0
  534. package/dist/runtime/docker/render-run-args.mjs.map +1 -0
  535. package/dist/runtime/docker/service.d.mts +1 -1
  536. package/dist/runtime/docker/service.mjs +12 -7
  537. package/dist/runtime/docker/service.mjs.map +1 -1
  538. package/dist/runtime/docker/sweep.mjs +118 -43
  539. package/dist/runtime/docker/sweep.mjs.map +1 -1
  540. package/dist/runtime/docker/volume.mjs +2 -0
  541. package/dist/runtime/docker/volume.mjs.map +1 -1
  542. package/dist/runtime/docker/wrap.mjs +30 -1
  543. package/dist/runtime/docker/wrap.mjs.map +1 -1
  544. package/dist/substrate/cross-process.mjs +14 -8
  545. package/dist/substrate/cross-process.mjs.map +1 -1
  546. package/dist/substrate/event-time.mjs +33 -0
  547. package/dist/substrate/event-time.mjs.map +1 -0
  548. package/dist/substrate/events.d.mts +28 -8
  549. package/dist/substrate/identity.d.mts +2 -1
  550. package/dist/substrate/manifest.d.mts +68 -5
  551. package/dist/substrate/manifest.mjs +34 -5
  552. package/dist/substrate/manifest.mjs.map +1 -1
  553. package/dist/substrate/network.d.mts +3 -5
  554. package/dist/substrate/options.d.mts +0 -2
  555. package/dist/substrate/plugin.d.mts +13 -0
  556. package/dist/substrate/plugin.mjs +4 -2
  557. package/dist/substrate/plugin.mjs.map +1 -1
  558. package/dist/substrate/projection.d.mts +35 -3
  559. package/dist/substrate/runtime/artifact-publisher/index.mjs +19 -9
  560. package/dist/substrate/runtime/artifact-publisher/index.mjs.map +1 -1
  561. package/dist/substrate/runtime/atomic-write.mjs +97 -32
  562. package/dist/substrate/runtime/atomic-write.mjs.map +1 -1
  563. package/dist/substrate/runtime/cache/index.mjs +3 -0
  564. package/dist/substrate/runtime/cache/schema.mjs +2 -2
  565. package/dist/substrate/runtime/cache/schema.mjs.map +1 -1
  566. package/dist/substrate/runtime/cache/service.mjs +9 -7
  567. package/dist/substrate/runtime/cache/service.mjs.map +1 -1
  568. package/dist/substrate/runtime/capability-sinks/index.d.mts +1 -1
  569. package/dist/substrate/runtime/capability-sinks/index.mjs +3 -0
  570. package/dist/substrate/runtime/capability-sinks/layer.mjs +1 -1
  571. package/dist/substrate/runtime/capability-sinks/service.d.mts +61 -2
  572. package/dist/substrate/runtime/capability-sinks/service.mjs +21 -26
  573. package/dist/substrate/runtime/capability-sinks/service.mjs.map +1 -1
  574. package/dist/substrate/runtime/config-validation.d.mts +1 -13
  575. package/dist/substrate/runtime/config-validation.mjs +2 -91
  576. package/dist/substrate/runtime/config-validation.mjs.map +1 -1
  577. package/dist/substrate/runtime/container-runtime.d.mts +1 -0
  578. package/dist/substrate/runtime/container-runtime.mjs +2 -0
  579. package/dist/substrate/runtime/control-plane/domain.mjs +101 -0
  580. package/dist/substrate/runtime/control-plane/domain.mjs.map +1 -0
  581. package/dist/substrate/runtime/control-plane/service.mjs +7 -0
  582. package/dist/substrate/runtime/control-plane/service.mjs.map +1 -0
  583. package/dist/substrate/runtime/cross-process/command-channel/channel.mjs +46 -19
  584. package/dist/substrate/runtime/cross-process/command-channel/channel.mjs.map +1 -1
  585. package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs +30 -12
  586. package/dist/substrate/runtime/cross-process/command-channel/file-channel.mjs.map +1 -1
  587. package/dist/substrate/runtime/cross-process/command-channel/index.mjs +5 -0
  588. package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs +11 -2
  589. package/dist/substrate/runtime/cross-process/command-channel/protocol.mjs.map +1 -1
  590. package/dist/substrate/runtime/cross-process/command-channel/runtime-control-lock.mjs +1 -1
  591. package/dist/substrate/runtime/cross-process/index.mjs +11 -0
  592. package/dist/substrate/runtime/cross-process/live-clock.mjs +34 -0
  593. package/dist/substrate/runtime/cross-process/live-clock.mjs.map +1 -0
  594. package/dist/substrate/runtime/cross-process/liveness.mjs +52 -10
  595. package/dist/substrate/runtime/cross-process/liveness.mjs.map +1 -1
  596. package/dist/substrate/runtime/cross-process/lock.d.mts +1 -0
  597. package/dist/substrate/runtime/cross-process/lock.mjs +23 -0
  598. package/dist/substrate/runtime/cross-process/lock.mjs.map +1 -0
  599. package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs +64 -0
  600. package/dist/substrate/runtime/cross-process/reclaim-stale-file.mjs.map +1 -0
  601. package/dist/substrate/runtime/cross-process/roster.mjs +97 -83
  602. package/dist/substrate/runtime/cross-process/roster.mjs.map +1 -1
  603. package/dist/substrate/runtime/cross-process/self-pid.mjs +8 -0
  604. package/dist/substrate/runtime/cross-process/self-pid.mjs.map +1 -0
  605. package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs +24 -28
  606. package/dist/substrate/runtime/cross-process/snapshot-reservation.mjs.map +1 -1
  607. package/dist/substrate/runtime/cross-process/stack-lock.mjs +41 -20
  608. package/dist/substrate/runtime/cross-process/stack-lock.mjs.map +1 -1
  609. package/dist/substrate/runtime/current-plugin.mjs +2 -2
  610. package/dist/substrate/runtime/current-plugin.mjs.map +1 -1
  611. package/dist/substrate/runtime/errors.mjs +12 -6
  612. package/dist/substrate/runtime/errors.mjs.map +1 -1
  613. package/dist/substrate/runtime/format-unknown-error.mjs +30 -0
  614. package/dist/substrate/runtime/format-unknown-error.mjs.map +1 -0
  615. package/dist/substrate/runtime/host-bind-mount-owner.mjs +10 -0
  616. package/dist/substrate/runtime/host-bind-mount-owner.mjs.map +1 -0
  617. package/dist/substrate/runtime/host-gateway.mjs +20 -0
  618. package/dist/substrate/runtime/host-gateway.mjs.map +1 -0
  619. package/dist/substrate/runtime/host-tree-tar/index.mjs +61 -50
  620. package/dist/substrate/runtime/host-tree-tar/index.mjs.map +1 -1
  621. package/dist/substrate/runtime/http-probe.d.mts +1 -1
  622. package/dist/substrate/runtime/index.mjs +14 -0
  623. package/dist/substrate/runtime/lease-broker/index.d.mts +1 -1
  624. package/dist/substrate/runtime/lease-broker/index.mjs +2 -0
  625. package/dist/substrate/runtime/lease-broker/service.d.mts +1 -64
  626. package/dist/substrate/runtime/lease-broker/service.mjs +1 -1
  627. package/dist/substrate/runtime/lease-broker/service.mjs.map +1 -1
  628. package/dist/substrate/runtime/lifecycle/dep-graph.mjs +22 -3
  629. package/dist/substrate/runtime/lifecycle/dep-graph.mjs.map +1 -1
  630. package/dist/substrate/runtime/lifecycle/index.mjs +9 -0
  631. package/dist/substrate/runtime/lifecycle/lifecycle-fact.mjs.map +1 -1
  632. package/dist/substrate/runtime/lifecycle/plugin-registry.mjs +20 -3
  633. package/dist/substrate/runtime/lifecycle/plugin-registry.mjs.map +1 -1
  634. package/dist/substrate/runtime/lifecycle/selective-restart.mjs +1 -1
  635. package/dist/substrate/runtime/lifecycle/signals.mjs +5 -5
  636. package/dist/substrate/runtime/lifecycle/signals.mjs.map +1 -1
  637. package/dist/substrate/runtime/lifecycle/state-machine.mjs +1 -1
  638. package/dist/substrate/runtime/managed-container.d.mts +19 -1
  639. package/dist/substrate/runtime/managed-container.mjs +20 -1
  640. package/dist/substrate/runtime/managed-container.mjs.map +1 -1
  641. package/dist/substrate/runtime/manifest/index.mjs +3 -0
  642. package/dist/substrate/runtime/manifest/manifest.mjs +15 -11
  643. package/dist/substrate/runtime/manifest/manifest.mjs.map +1 -1
  644. package/dist/substrate/runtime/mode-errors.mjs +20 -0
  645. package/dist/substrate/runtime/mode-errors.mjs.map +1 -0
  646. package/dist/substrate/runtime/observability/cascade-formatter.mjs +9 -13
  647. package/dist/substrate/runtime/observability/cascade-formatter.mjs.map +1 -1
  648. package/dist/substrate/runtime/observability/formatter-registry.mjs +19 -36
  649. package/dist/substrate/runtime/observability/formatter-registry.mjs.map +1 -1
  650. package/dist/substrate/runtime/observability/ignore-with-log.d.mts +1 -0
  651. package/dist/substrate/runtime/observability/ignore-with-log.mjs +17 -0
  652. package/dist/substrate/runtime/observability/ignore-with-log.mjs.map +1 -0
  653. package/dist/substrate/runtime/observability/index.d.mts +1 -1
  654. package/dist/substrate/runtime/observability/index.mjs +13 -0
  655. package/dist/substrate/runtime/observability/log-store.d.mts +1 -0
  656. package/dist/substrate/runtime/observability/log-store.mjs +175 -0
  657. package/dist/substrate/runtime/observability/log-store.mjs.map +1 -0
  658. package/dist/substrate/runtime/observability/logger.d.mts +2 -1
  659. package/dist/substrate/runtime/observability/logger.mjs +5 -9
  660. package/dist/substrate/runtime/observability/logger.mjs.map +1 -1
  661. package/dist/substrate/runtime/observability/output-truncate.mjs +35 -0
  662. package/dist/substrate/runtime/observability/output-truncate.mjs.map +1 -0
  663. package/dist/substrate/runtime/observability/pretty-error.mjs +9 -12
  664. package/dist/substrate/runtime/observability/pretty-error.mjs.map +1 -1
  665. package/dist/substrate/runtime/observability/redaction.d.mts +2 -13
  666. package/dist/substrate/runtime/observability/redaction.mjs +8 -14
  667. package/dist/substrate/runtime/observability/redaction.mjs.map +1 -1
  668. package/dist/substrate/runtime/observability/span-store.d.mts +1 -0
  669. package/dist/substrate/runtime/observability/span-store.mjs +110 -0
  670. package/dist/substrate/runtime/observability/span-store.mjs.map +1 -0
  671. package/dist/substrate/runtime/observability/spans.mjs +14 -14
  672. package/dist/substrate/runtime/observability/spans.mjs.map +1 -1
  673. package/dist/substrate/runtime/observability/subprocess-capture.mjs +1 -1
  674. package/dist/substrate/runtime/passthrough-or-wrap.mjs +33 -0
  675. package/dist/substrate/runtime/passthrough-or-wrap.mjs.map +1 -0
  676. package/dist/substrate/runtime/paths.d.mts +1 -1
  677. package/dist/substrate/runtime/paths.mjs +4 -3
  678. package/dist/substrate/runtime/paths.mjs.map +1 -1
  679. package/dist/substrate/runtime/phase-preserving-produce.mjs +40 -0
  680. package/dist/substrate/runtime/phase-preserving-produce.mjs.map +1 -0
  681. package/dist/substrate/runtime/port-broker/index.mjs +3 -0
  682. package/dist/substrate/runtime/port-broker/service.mjs +170 -126
  683. package/dist/substrate/runtime/port-broker/service.mjs.map +1 -1
  684. package/dist/substrate/runtime/post-acquire-tasks.mjs +1 -1
  685. package/dist/substrate/runtime/post-acquire-tasks.mjs.map +1 -1
  686. package/dist/substrate/runtime/probes.d.mts +7 -5
  687. package/dist/substrate/runtime/probes.mjs +3 -1
  688. package/dist/substrate/runtime/probes.mjs.map +1 -1
  689. package/dist/substrate/runtime/projection/index.mjs +4 -0
  690. package/dist/substrate/runtime/projection/operational-endpoints.mjs +1 -2
  691. package/dist/substrate/runtime/projection/operational-endpoints.mjs.map +1 -1
  692. package/dist/substrate/runtime/projection/persisted.mjs +33 -15
  693. package/dist/substrate/runtime/projection/persisted.mjs.map +1 -1
  694. package/dist/substrate/runtime/projection/state-ref.mjs +26 -2
  695. package/dist/substrate/runtime/projection/state-ref.mjs.map +1 -1
  696. package/dist/substrate/runtime/projection/update.mjs +88 -24
  697. package/dist/substrate/runtime/projection/update.mjs.map +1 -1
  698. package/dist/substrate/runtime/random-suffix.mjs +11 -0
  699. package/dist/substrate/runtime/random-suffix.mjs.map +1 -0
  700. package/dist/substrate/runtime/retry-policy.d.mts +59 -1
  701. package/dist/substrate/runtime/retry-policy.mjs +66 -1
  702. package/dist/substrate/runtime/retry-policy.mjs.map +1 -1
  703. package/dist/substrate/runtime/routed-url.d.mts +1 -0
  704. package/dist/substrate/runtime/routed-url.mjs +79 -0
  705. package/dist/substrate/runtime/routed-url.mjs.map +1 -0
  706. package/dist/substrate/runtime/runtime-decode.d.mts +1 -1
  707. package/dist/substrate/runtime/runtime-decode.mjs.map +1 -1
  708. package/dist/substrate/runtime/scoped-http-server.mjs +2 -3
  709. package/dist/substrate/runtime/scoped-http-server.mjs.map +1 -1
  710. package/dist/substrate/runtime/scoped-multimap/index.mjs +2 -0
  711. package/dist/substrate/runtime/scoped-multimap/service.mjs +52 -0
  712. package/dist/substrate/runtime/scoped-multimap/service.mjs.map +1 -0
  713. package/dist/substrate/runtime/scoped-ref-map/index.mjs +2 -0
  714. package/dist/substrate/runtime/scoped-ref-map/service.mjs +2 -2
  715. package/dist/substrate/runtime/scoped-ref-map/service.mjs.map +1 -1
  716. package/dist/substrate/runtime/stage-and-swap/index.mjs +72 -4
  717. package/dist/substrate/runtime/stage-and-swap/index.mjs.map +1 -1
  718. package/dist/substrate/runtime/state-store/index.d.mts +1 -0
  719. package/dist/substrate/runtime/state-store/index.mjs +3 -0
  720. package/dist/substrate/runtime/state-store/schema.d.mts +1 -0
  721. package/dist/substrate/runtime/state-store/schema.mjs +19 -14
  722. package/dist/substrate/runtime/state-store/schema.mjs.map +1 -1
  723. package/dist/substrate/runtime/state-store/service.d.mts +1 -0
  724. package/dist/substrate/runtime/state-store/service.mjs +145 -0
  725. package/dist/substrate/runtime/state-store/service.mjs.map +1 -0
  726. package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.d.mts +1 -0
  727. package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs +33 -0
  728. package/dist/substrate/runtime/strategy-registry/chain-keyed-strategy-for.mjs.map +1 -0
  729. package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs +1 -1
  730. package/dist/substrate/runtime/strategy-registry/chain-probe-for.mjs.map +1 -1
  731. package/dist/substrate/runtime/strategy-registry/index.mjs +4 -0
  732. package/dist/substrate/runtime/strategy-registry/service.mjs +19 -33
  733. package/dist/substrate/runtime/strategy-registry/service.mjs.map +1 -1
  734. package/dist/substrate/runtime/subnet-broker.mjs +60 -0
  735. package/dist/substrate/runtime/subnet-broker.mjs.map +1 -0
  736. package/dist/substrate/runtime/sui-execute/index.d.mts +21 -1
  737. package/dist/substrate/runtime/sui-execute/index.mjs +84 -20
  738. package/dist/substrate/runtime/sui-execute/index.mjs.map +1 -1
  739. package/dist/substrate/runtime/sui-execute/sign-and-dispatch.d.mts +1 -0
  740. package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs +32 -0
  741. package/dist/substrate/runtime/sui-execute/sign-and-dispatch.mjs.map +1 -0
  742. package/dist/substrate/runtime/sui-ledger/object-ref.mjs +32 -0
  743. package/dist/substrate/runtime/sui-ledger/object-ref.mjs.map +1 -0
  744. package/dist/substrate/runtime/sui-move-build/index.mjs +93 -19
  745. package/dist/substrate/runtime/sui-move-build/index.mjs.map +1 -1
  746. package/dist/substrate/runtime/supervisor/acquire-node.mjs +181 -0
  747. package/dist/substrate/runtime/supervisor/acquire-node.mjs.map +1 -0
  748. package/dist/substrate/runtime/supervisor/background-tasks.mjs +144 -0
  749. package/dist/substrate/runtime/supervisor/background-tasks.mjs.map +1 -0
  750. package/dist/substrate/runtime/supervisor/command-loop.mjs +68 -0
  751. package/dist/substrate/runtime/supervisor/command-loop.mjs.map +1 -0
  752. package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs +151 -0
  753. package/dist/substrate/runtime/supervisor/dispatch-contributions.mjs.map +1 -0
  754. package/dist/substrate/runtime/supervisor/errors.d.mts +1 -0
  755. package/dist/substrate/runtime/supervisor/errors.mjs +9 -0
  756. package/dist/substrate/runtime/supervisor/errors.mjs.map +1 -0
  757. package/dist/substrate/runtime/supervisor/index.d.mts +1 -0
  758. package/dist/substrate/runtime/supervisor/index.mjs +3 -0
  759. package/dist/substrate/runtime/supervisor/shutdown.mjs +51 -0
  760. package/dist/substrate/runtime/supervisor/shutdown.mjs.map +1 -0
  761. package/dist/substrate/runtime/supervisor/start-supervisor.d.mts +1 -0
  762. package/dist/substrate/runtime/supervisor/start-supervisor.mjs +250 -0
  763. package/dist/substrate/runtime/supervisor/start-supervisor.mjs.map +1 -0
  764. package/dist/substrate/runtime/supervisor/state.d.mts +1 -0
  765. package/dist/substrate/runtime/supervisor/state.mjs +22 -0
  766. package/dist/substrate/runtime/supervisor/state.mjs.map +1 -0
  767. package/dist/substrate/runtime/supervisor/teardown.mjs +57 -0
  768. package/dist/substrate/runtime/supervisor/teardown.mjs.map +1 -0
  769. package/dist/substrate/runtime/supervisor/types.d.mts +1 -0
  770. package/dist/substrate/runtime/supervisor/wiring.mjs +133 -0
  771. package/dist/substrate/runtime/supervisor/wiring.mjs.map +1 -0
  772. package/dist/substrate/runtime/typed-env.mjs +8 -0
  773. package/dist/substrate/runtime/typed-env.mjs.map +1 -0
  774. package/dist/substrate/state-store.d.mts +1 -0
  775. package/dist/substrate/versioned-doc-schema.mjs +17 -0
  776. package/dist/substrate/versioned-doc-schema.mjs.map +1 -0
  777. package/dist/substrate/versioned-doc-sync.mjs +94 -0
  778. package/dist/substrate/versioned-doc-sync.mjs.map +1 -0
  779. package/dist/surfaces/cli/command-tree.mjs.map +1 -1
  780. package/dist/surfaces/cli/commands/index.mjs +9 -0
  781. package/dist/surfaces/cli/commands/prune-picker-entry.mjs +13 -0
  782. package/dist/surfaces/cli/commands/prune-picker-entry.mjs.map +1 -0
  783. package/dist/surfaces/cli/commands/prune-picker.mjs +3 -2
  784. package/dist/surfaces/cli/commands/prune-picker.mjs.map +1 -1
  785. package/dist/surfaces/cli/commands/prune.mjs +34 -17
  786. package/dist/surfaces/cli/commands/prune.mjs.map +1 -1
  787. package/dist/surfaces/cli/commands/status.mjs +2 -2
  788. package/dist/surfaces/cli/commands/status.mjs.map +1 -1
  789. package/dist/surfaces/cli/commands/supervisor-presence.mjs +5 -3
  790. package/dist/surfaces/cli/commands/supervisor-presence.mjs.map +1 -1
  791. package/dist/surfaces/cli/commands/wipe.mjs +38 -4
  792. package/dist/surfaces/cli/commands/wipe.mjs.map +1 -1
  793. package/dist/surfaces/cli/errors.mjs +1 -1
  794. package/dist/surfaces/cli/errors.mjs.map +1 -1
  795. package/dist/surfaces/cli/flags.mjs +0 -1
  796. package/dist/surfaces/cli/flags.mjs.map +1 -1
  797. package/dist/surfaces/cli/index.mjs +98 -18
  798. package/dist/surfaces/cli/index.mjs.map +1 -1
  799. package/dist/surfaces/cli/output.mjs +1 -0
  800. package/dist/surfaces/cli/output.mjs.map +1 -1
  801. package/dist/surfaces/cli/sysexits.mjs +2 -1
  802. package/dist/surfaces/cli/sysexits.mjs.map +1 -1
  803. package/dist/surfaces/tui/app.mjs +25 -3
  804. package/dist/surfaces/tui/app.mjs.map +1 -1
  805. package/dist/surfaces/tui/display-derivation.mjs +23 -74
  806. package/dist/surfaces/tui/display-derivation.mjs.map +1 -1
  807. package/dist/surfaces/tui/event-log.mjs +35 -23
  808. package/dist/surfaces/tui/event-log.mjs.map +1 -1
  809. package/dist/surfaces/tui/input.mjs +5 -1
  810. package/dist/surfaces/tui/input.mjs.map +1 -1
  811. package/dist/surfaces/tui/plain-renderer.mjs +70 -34
  812. package/dist/surfaces/tui/plain-renderer.mjs.map +1 -1
  813. package/package.json +24 -4
  814. package/dist/contracts/liveness-classifier.d.mts +0 -19
  815. package/dist/contracts/network-resolver.d.mts +0 -15
  816. package/dist/contracts/network-resolver.mjs +0 -7
  817. package/dist/contracts/network-resolver.mjs.map +0 -1
  818. package/dist/orchestrators/codegen/extras.mjs +0 -16
  819. package/dist/orchestrators/codegen/extras.mjs.map +0 -1
  820. package/dist/plugins/deepbook/routable.mjs +0 -21
  821. package/dist/plugins/deepbook/routable.mjs.map +0 -1
  822. package/dist/plugins/faucet/service.d.mts +0 -20
  823. package/dist/plugins/faucet/strategies/sui-local.d.mts +0 -23
  824. package/dist/plugins/faucet/strategies/sui-local.mjs.map +0 -1
  825. package/dist/plugins/sui/seed-objects.d.mts +0 -18
  826. package/dist/plugins/sui/seed-objects.mjs +0 -25
  827. package/dist/plugins/sui/seed-objects.mjs.map +0 -1
  828. package/dist/runtime/built-in-plugin-layers.mjs.map +0 -1
  829. package/dist/substrate/runtime/context-helpers.mjs +0 -32
  830. package/dist/substrate/runtime/context-helpers.mjs.map +0 -1
  831. package/dist/substrate/runtime/run.mjs.map +0 -1
  832. package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs +0 -30
  833. package/dist/substrate/runtime/strategy-registry/faucet-capability-for.mjs.map +0 -1
  834. package/dist/substrate/runtime/supervisor.d.mts +0 -1
  835. package/dist/substrate/runtime/supervisor.mjs +0 -831
  836. package/dist/substrate/runtime/supervisor.mjs.map +0 -1
  837. package/dist/surfaces/cli/commands/doctor-probes.mjs.map +0 -1
  838. /package/dist/{substrate/runtime/strategy-registry/faucet-capability-for.d.mts → plugins/faucet/http.d.mts} +0 -0
@@ -1,8 +1,11 @@
1
+ import { SpanAttr } from "../../substrate/runtime/observability/spans.mjs";
1
2
  import { ProbeTimeoutError, exitCodeProbeResult, waitForProbe } from "../../substrate/runtime/probes.mjs";
2
- import { ensureManagedContainer } from "../../substrate/runtime/managed-container.mjs";
3
3
  import { setCurrentPluginPhase } from "../../substrate/runtime/current-plugin.mjs";
4
+ import { HOST_GATEWAY_EXTRA_HOSTS } from "../../substrate/runtime/host-gateway.mjs";
5
+ import { ensureManagedContainer } from "../../substrate/runtime/managed-container.mjs";
4
6
  import { walrusDeployMountPaths } from "./deploy-paths.mjs";
5
7
  import { walrusPluginError } from "./errors.mjs";
8
+ import { WalrusSpans } from "./spans.mjs";
6
9
  import { Duration, Effect, Scope } from "effect";
7
10
  /** Default per-node ready-probe timeout. */
8
11
  const DEFAULT_NODE_READY_TIMEOUT_MS = 6e4;
@@ -72,11 +75,16 @@ const NODE_READY_PROBE_INTERVAL_MS = 500;
72
75
  */
73
76
  const startStorageNodes = (runtime, spec) => Effect.gen(function* () {
74
77
  if (spec.nodeCount < 1) return yield* Effect.fail(walrusPluginError("storage-node", `storage-nodes: nodeCount must be >= 1 (got ${spec.nodeCount})`));
78
+ if (spec.images.length !== spec.nodeCount) return yield* Effect.fail(walrusPluginError("storage-node", `storage-nodes: images length (${spec.images.length}) must equal nodeCount (${spec.nodeCount}) — one distinct per-node image tag is required for restore-safe commits`));
75
79
  const outerScope = yield* Effect.scope;
76
80
  const nodeStopScope = yield* Scope.fork(outerScope, "parallel");
77
81
  const stopGraceSeconds = spec.stopGraceSeconds ?? 20;
78
82
  const readyTimeout = Duration.millis(spec.readyTimeoutMs ?? 6e4);
79
- const deployMount = walrusDeployMountPaths(spec.deployHostMountPath, "/opt/walrus/runtime");
83
+ const deployMount = walrusDeployMountPaths({
84
+ stackRoot: spec.stackRoot,
85
+ deployOutputDirHostPath: spec.deployHostMountPath,
86
+ mountTarget: "/opt/walrus/runtime"
87
+ });
80
88
  const indices = Array.from({ length: spec.nodeCount }, (_, i) => i);
81
89
  const bootOne = (i) => Effect.gen(function* () {
82
90
  const containerIp = `${spec.subnetPrefix}.${10 + i}`;
@@ -94,7 +102,7 @@ const startStorageNodes = (runtime, spec) => Effect.gen(function* () {
94
102
  role: `storage-node-${i}`,
95
103
  spec: {
96
104
  name: containerName,
97
- image: spec.image,
105
+ image: spec.images[i],
98
106
  recreate: "on-config-change",
99
107
  configHash: storageNodeConfigHash({
100
108
  deployConfigHash: spec.deployConfigHash,
@@ -111,7 +119,7 @@ const startStorageNodes = (runtime, spec) => Effect.gen(function* () {
111
119
  },
112
120
  stopGraceSeconds,
113
121
  networkAttach: [spec.walrusNetworkName, spec.suiNetworkName],
114
- extraHosts: { "host.docker.internal": "host-gateway" },
122
+ extraHosts: HOST_GATEWAY_EXTRA_HOSTS,
115
123
  mounts: [{
116
124
  source: deployMount.sourceHostPath,
117
125
  target: deployMount.mountTarget,
@@ -138,16 +146,15 @@ const startStorageNodes = (runtime, spec) => Effect.gen(function* () {
138
146
  return {
139
147
  nodeIndex: i,
140
148
  nodeId: `walrus-node-${i}`,
141
- publicKey: `<bls-pubkey-storage-node-${i}>`,
142
149
  publicHostname,
143
150
  rpcUrl: `http://${publicHostname}:${WALRUS_ROUTER_PORT}`
144
151
  };
145
152
  }).pipe(Effect.withSpan(`devstack.plugin.walrus.storage-node-${i}.boot`, { attributes: {
146
- "devstack.plugin": "walrus",
147
- "walrus.node": i
153
+ [SpanAttr.plugin]: "walrus",
154
+ [WalrusSpans.node]: i
148
155
  } }));
149
156
  return { nodes: yield* Effect.all(indices.map(bootOne), { concurrency: "unbounded" }) };
150
- }).pipe(Effect.withSpan("devstack.plugin.walrus.storage-nodes.boot", { attributes: { "devstack.plugin": "walrus" } }));
157
+ }).pipe(Effect.withSpan("devstack.plugin.walrus.storage-nodes.boot", { attributes: { [SpanAttr.plugin]: "walrus" } }));
151
158
  //#endregion
152
159
  export { DEFAULT_CONTAINER_API_PORT, DEFAULT_NODE_READY_TIMEOUT_MS, WALRUS_ROUTER_PORT, buildWalrusNetworkName, computePublicHostname, startStorageNodes };
153
160
 
@@ -1 +1 @@
1
- {"version":3,"file":"storage-nodes.mjs","names":[],"sources":["../../../src/plugins/walrus/storage-nodes.ts"],"sourcesContent":["// Walrus storage-node committee lifecycle.\n//\n// Distilled-doc reference (06-walrus.md §\"Capabilities CONSUMED\" +\n// §\"Lifecycle phase 4\"): N storage-node containers, pinned IPs on a\n// per-stack /24 docker network. Each node carries one Traefik route\n// via the `Routable` capability; the router binds host port 9185 once\n// globally and dispatches by `Host:` header.\n//\n// Substrate-side responsibilities:\n// - `ContainerRuntime.ensureContainer` per node — content-addressed\n// image, label tuple, recreate policy.\n// - Parallel `Effect.all({concurrency: 'unbounded'})` over [0..N) —\n// concurrent boot.\n// - Per-node stop finalizer fires in a *forked parallel scope* so\n// teardown collapses to ~max(grace) instead of summing graces\n// (distilled-doc invariant 21 — \"StopFinalizerScope MUST be a\n// forked parallel scope\").\n//\n// What we DON'T own here:\n// - Plugin row narration.\n// - The faucet-strategy registration — `faucet-strategy.ts`.\n// - The deploy one-shot — `deploy.ts`.\n\nimport { Duration, Effect, Scope } from 'effect';\n\nimport type {\n\tContainerHandle,\n\tContainerRuntime,\n\tImageRef,\n} from '../../contracts/container-runtime.ts';\nimport {\n\tProbeTimeoutError,\n\texitCodeProbeResult,\n\twaitForProbe,\n} from '../../substrate/runtime/probes.ts';\nimport { setCurrentPluginPhase } from '../../substrate/runtime/current-plugin.ts';\nimport { ensureManagedContainer } from '../../substrate/runtime/managed-container.ts';\nimport { walrusDeployMountPaths } from './deploy-paths.ts';\nimport { walrusPluginError, type WalrusPluginError } from './errors.ts';\n\n/** Default per-node grace window. Storage nodes maintain RocksDB-\n * backed state; need >10s to flush and checkpoint on `docker stop`.\n * Distilled-doc invariant 22. */\nexport const DEFAULT_NODE_STOP_GRACE_SECONDS = 20;\n\n/** Default per-node ready-probe timeout. */\nexport const DEFAULT_NODE_READY_TIMEOUT_MS = 60_000;\n\n/** Distilled-doc invariant 9: the on-chain `public_port` value\n * matches the global router entrypoint port. One canonical\n * constant — opportunity #14 in the distilled doc was to deduplicate\n * this across three files. */\nexport const WALRUS_ROUTER_PORT = 9185;\n\n/** Default container API port — each storage node binds this inside\n * the container. Same value as the router port (the storage node's\n * in-container bind matches the on-chain public_port). */\nexport const DEFAULT_CONTAINER_API_PORT = WALRUS_ROUTER_PORT;\n\n/** Per-node descriptor — what the plugin resolved value surfaces\n * for downstream consumers (the `@mysten/walrus` SDK reads this). */\nexport interface WalrusStorageNode {\n\treadonly nodeIndex: number;\n\treadonly nodeId: string;\n\treadonly publicKey: string;\n\treadonly publicHostname: string;\n\treadonly rpcUrl: string;\n}\n\n/** Storage-node startup config — the plugin's local-cluster mode\n * passes this in once per cluster boot. */\nexport interface StorageNodesSpec {\n\treadonly app: string;\n\treadonly stack: string;\n\treadonly walrusName: string;\n\treadonly image: ImageRef;\n\treadonly nodeCount: number;\n\t/** Pre-allocated /24 prefix from `subnetForStack`. Example:\n\t * `'10.42.7'` (the third octet is hashed per stack). */\n\treadonly subnetPrefix: string;\n\treadonly containerApiPort: number;\n\treadonly walrusNetworkName: string;\n\treadonly suiNetworkName: string;\n\treadonly deployHostMountPath: string;\n\t/** Fingerprint of the deploy outputs mounted into each node. */\n\treadonly deployConfigHash: string;\n\treadonly stopGraceSeconds?: number;\n\treadonly readyTimeoutMs?: number;\n}\n\n/** Result of starting the committee — descriptors used by the\n * plugin's resolved value. */\nexport interface StorageNodesAcquired {\n\treadonly nodes: ReadonlyArray<WalrusStorageNode>;\n}\n\n/** Distilled-doc invariant 1: pinned IPs start at `<prefix>.10`.\n * Centralized so the deploy one-shot's `WALRUS_LISTENING_IPS` env\n * var and the per-node `--ip` pin compute from one source. */\nexport const WALRUS_NODE_IP_BASE = 10;\n\n/** Compute the public hostname for one storage node. Mirrors\n * v3's `routerHostname(identity, 'walrus-node-' + i)` shape\n * (06-walrus.md §\"Routes registered\"). Main stack omits the stack\n * segment; non-main inserts it after the service label. */\nexport const computePublicHostname = (app: string, stack: string, nodeIndex: number): string => {\n\tconst base = `walrus-node-${nodeIndex}.${app}.localhost`;\n\treturn stack === 'main' ? base : `walrus-node-${nodeIndex}.${stack}.${app}.localhost`;\n};\n\nexport const storageNodeConfigHash = (parts: {\n\treadonly deployConfigHash: string;\n\treadonly nodeIndex: number;\n\treadonly deploySourceHostPath: string;\n\treadonly deployMountTarget: string;\n\treadonly containerApiPort: number;\n\treadonly walrusNetworkName: string;\n\treadonly suiNetworkName: string;\n}): string =>\n\t[\n\t\tparts.deployConfigHash,\n\t\t`node=${parts.nodeIndex}`,\n\t\t`mount=${parts.deploySourceHostPath}->${parts.deployMountTarget}`,\n\t\t`api=${parts.containerApiPort}`,\n\t\t`net=${parts.walrusNetworkName},${parts.suiNetworkName}`,\n\t].join('|');\n\nexport const buildWalrusNetworkName = (app: string, stack: string, walrusName: string): string =>\n\t`devstack-${app}-${stack}-walrus-${walrusName}-net`;\n\n/** Per-node TCP ready-probe interval. */\nconst NODE_READY_PROBE_INTERVAL_MS = 500;\n\n/** Start the N-node committee.\n *\n * Wiring (this body is the load-bearing path):\n *\n * 1. Defense-in-depth nodeCount guard.\n * 2. Fork a parallel-strategy child scope off the caller's scope so\n * every node's `docker stop` finalizer fires concurrently on\n * outer teardown — collapses shutdown wall-time from `N×grace` to\n * `~max(grace)` (distilled-doc invariant 21).\n * 3. For each `i ∈ [0..N)`:\n * a. `ensureContainer` on the wrapper image with pinned IP,\n * label tuple, primary network attach (walrus net), recreate\n * on config-change.\n * b. TCP ready probe against `<publicHostname>:<routerPort>`\n * with bounded retries until the outer `readyTimeoutMs`.\n * 4. Run [3] under `Effect.all({concurrency: 'unbounded'})` — boot\n * parallelism collapses to ~max(perNode).\n *\n * WHAT THE SUBSTRATE STILL OWES:\n * - Secondary network attach (`Docker.networkConnect(suiNet)`).\n * `EnsureContainerSpec.networkAttach` accepts an array, so passing\n * `[walrusNet, suiNet]` would dual-home in one shot, but the\n * runtime adapter currently treats the first entry as the primary\n * and post-attaches the rest; the per-node pinned IP only attaches\n * to the primary. The dual-home is documented inline below and\n * relies on that adapter behavior. Storage nodes do not request\n * faucet funds during boot; the secondary network is retained for\n * future Sui-side in-network calls.\n * - Per-node `networkAlias` (`walrus-node-<i>.localhost`). The\n * contract doesn't expose alias plumbing yet; peer containers dial by\n * container name, which docker DNS publishes. The architecture\n * revision is tracked in `index.ts`.\n * - Stop-grace duration propagation. The contract's `stop` takes a\n * Duration but `ensureContainer` doesn't yet accept a default\n * grace; the runtime adapter defaults to 10s. RocksDB needs 20s\n * (distilled-doc invariant 22) — see opportunity below.\n */\nexport const startStorageNodes = (\n\truntime: ContainerRuntime,\n\tspec: StorageNodesSpec,\n): Effect.Effect<StorageNodesAcquired, WalrusPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tif (spec.nodeCount < 1) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\twalrusPluginError(\n\t\t\t\t\t'storage-node',\n\t\t\t\t\t`storage-nodes: nodeCount must be >= 1 (got ${spec.nodeCount})`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Fork a parallel stop-scope. Per-node `ensureContainer` finalizers\n\t\t// fire here on outer teardown; closing the parallel scope races\n\t\t// the per-container `docker stop`s instead of summing them.\n\t\tconst outerScope = yield* Effect.scope;\n\t\tconst nodeStopScope = yield* Scope.fork(outerScope, 'parallel');\n\n\t\tconst stopGraceSeconds = spec.stopGraceSeconds ?? DEFAULT_NODE_STOP_GRACE_SECONDS;\n\t\tconst readyTimeout = Duration.millis(spec.readyTimeoutMs ?? DEFAULT_NODE_READY_TIMEOUT_MS);\n\t\tconst deployMount = walrusDeployMountPaths(spec.deployHostMountPath, '/opt/walrus/runtime');\n\n\t\tconst indices = Array.from({ length: spec.nodeCount }, (_, i) => i);\n\n\t\tconst bootOne = (i: number): Effect.Effect<WalrusStorageNode, WalrusPluginError, Scope.Scope> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst containerIp = `${spec.subnetPrefix}.${WALRUS_NODE_IP_BASE + i}`;\n\t\t\t\tconst containerName = `devstack-${spec.app}-${spec.stack}-walrus-${spec.walrusName}-node-${i}`;\n\t\t\t\tconst nodeHostname = `dryrun-node-${i}`;\n\t\t\t\tconst publicHostname = computePublicHostname(spec.app, spec.stack, i);\n\n\t\t\t\tyield* setCurrentPluginPhase(`creating storage-node-${i} container ${containerName}`);\n\t\t\t\t// Acquire under the forked parallel stop scope so the\n\t\t\t\t// finalizer (docker stop) joins the per-node fan-out race.\n\t\t\t\tconst ensureNode: Effect.Effect<ContainerHandle, WalrusPluginError, Scope.Scope> =\n\t\t\t\t\tensureManagedContainer<WalrusPluginError>({\n\t\t\t\t\t\truntime,\n\t\t\t\t\t\tidentity: { app: spec.app, stack: spec.stack },\n\t\t\t\t\t\tplugin: 'walrus',\n\t\t\t\t\t\trole: `storage-node-${i}`,\n\t\t\t\t\t\tspec: {\n\t\t\t\t\t\t\tname: containerName,\n\t\t\t\t\t\t\timage: spec.image,\n\t\t\t\t\t\t\trecreate: 'on-config-change',\n\t\t\t\t\t\t\tconfigHash: storageNodeConfigHash({\n\t\t\t\t\t\t\t\tdeployConfigHash: spec.deployConfigHash,\n\t\t\t\t\t\t\t\tnodeIndex: i,\n\t\t\t\t\t\t\t\tdeploySourceHostPath: deployMount.sourceHostPath,\n\t\t\t\t\t\t\t\tdeployMountTarget: deployMount.mountTarget,\n\t\t\t\t\t\t\t\tcontainerApiPort: spec.containerApiPort,\n\t\t\t\t\t\t\t\twalrusNetworkName: spec.walrusNetworkName,\n\t\t\t\t\t\t\t\tsuiNetworkName: spec.suiNetworkName,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tenv: {\n\t\t\t\t\t\t\t\tHOSTNAME: nodeHostname,\n\t\t\t\t\t\t\t\tDEPLOY_OUTPUT_DIR: deployMount.outputDirInContainer,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tstopGraceSeconds,\n\t\t\t\t\t\t\t// Primary network owns the pinned `--ip`; the\n\t\t\t\t\t\t\t// secondary attach gives docker DNS for the sui\n\t\t\t\t\t\t\t// network. The adapter treats [0] as primary.\n\t\t\t\t\t\t\tnetworkAttach: [spec.walrusNetworkName, spec.suiNetworkName],\n\t\t\t\t\t\t\t// `host-gateway` resolves `host.docker.internal` to\n\t\t\t\t\t\t\t// the host's loopback inside the container — Docker\n\t\t\t\t\t\t\t// Desktop wires this automatically on macOS/Windows\n\t\t\t\t\t\t\t// but native Linux Docker requires the explicit\n\t\t\t\t\t\t\t// `--add-host` flag. Storage nodes dial sui's\n\t\t\t\t\t\t\t// host-bound RPC + faucet via this hostname.\n\t\t\t\t\t\t\textraHosts: { 'host.docker.internal': 'host-gateway' },\n\t\t\t\t\t\t\tmounts: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// Mount the stack root and point the entrypoint at\n\t\t\t\t\t\t\t\t\t// the deploy child. Docker Desktop can reject\n\t\t\t\t\t\t\t\t\t// freshly-created nested bind sources immediately\n\t\t\t\t\t\t\t\t\t// after a wiped stack recreates them.\n\t\t\t\t\t\t\t\t\tsource: deployMount.sourceHostPath,\n\t\t\t\t\t\t\t\t\ttarget: deployMount.mountTarget,\n\t\t\t\t\t\t\t\t\treadonly: true,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmapError: (cause) =>\n\t\t\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t\t\t'storage-node',\n\t\t\t\t\t\t\t\t`walrus storage-node-${i} (ip=${containerIp}) ensureContainer failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\t\t\t{ cause },\n\t\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\tconst handle: ContainerHandle = yield* Scope.provide(ensureNode, nodeStopScope);\n\n\t\t\t\t// TCP ready probe. We exec a tiny `nc`-style probe inside\n\t\t\t\t// the container against its own listener — proves the\n\t\t\t\t// in-container HTTP server bound and is accepting before\n\t\t\t\t// declaring ready. `exec` only fails on daemon-level\n\t\t\t\t// errors; a non-zero exit code is treated as \"retry\"\n\t\t\t\t// (the same policy postgres uses for `pg_isready`).\n\t\t\t\tyield* setCurrentPluginPhase(\n\t\t\t\t\t`waiting for storage-node-${i} on 127.0.0.1:${spec.containerApiPort}`,\n\t\t\t\t);\n\t\t\t\tyield* waitForProbe({\n\t\t\t\t\tlabel: `walrus.storage-node.${i}`,\n\t\t\t\t\ttimeoutMs: Duration.toMillis(readyTimeout),\n\t\t\t\t\tintervalMs: NODE_READY_PROBE_INTERVAL_MS,\n\t\t\t\t\tprobe: () =>\n\t\t\t\t\t\truntime\n\t\t\t\t\t\t\t.exec(handle, [\n\t\t\t\t\t\t\t\t'sh',\n\t\t\t\t\t\t\t\t'-c',\n\t\t\t\t\t\t\t\t// busybox-style portable probe: open TCP, write\n\t\t\t\t\t\t\t\t// nothing, exit. `nc -z` is the common form.\n\t\t\t\t\t\t\t\t`nc -z 127.0.0.1 ${spec.containerApiPort} || exit 1`,\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t.pipe(Effect.map(exitCodeProbeResult)),\n\t\t\t\t}).pipe(\n\t\t\t\t\tEffect.mapError((cause) => {\n\t\t\t\t\t\tif (cause instanceof ProbeTimeoutError) {\n\t\t\t\t\t\t\treturn walrusPluginError(\n\t\t\t\t\t\t\t\t'storage-node',\n\t\t\t\t\t\t\t\t`storage-node-${i} never became ready within ${Duration.toMillis(readyTimeout)}ms ` +\n\t\t\t\t\t\t\t\t\t`(container=${containerName}, probe=127.0.0.1:${spec.containerApiPort}, ` +\n\t\t\t\t\t\t\t\t\t`publicUrl=http://${publicHostname}:${WALRUS_ROUTER_PORT}). ` +\n\t\t\t\t\t\t\t\t\t`The container was created, but walrus-node did not bind its API port. ` +\n\t\t\t\t\t\t\t\t\t`Check the storage-node container logs for the faucet, WAL exchange, or ` +\n\t\t\t\t\t\t\t\t\t`walrus-node run step that stalled.`,\n\t\t\t\t\t\t\t\t{ cause: cause.lastError ?? cause.lastNotReady ?? cause },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn walrusPluginError(\n\t\t\t\t\t\t\t'storage-node',\n\t\t\t\t\t\t\t`storage-node-${i} ready-probe exec failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\t\t{ cause },\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\treturn {\n\t\t\t\t\tnodeIndex: i,\n\t\t\t\t\t// Stable node-id derived from name. The on-chain\n\t\t\t\t\t// public_key + bls12-381 keypair lives inside the\n\t\t\t\t\t// per-node keystore the deploy one-shot emitted;\n\t\t\t\t\t// this descriptor is the routing handle, not the\n\t\t\t\t\t// crypto identity. The SDK consumer reads the\n\t\t\t\t\t// public key off `packageConfig` rather than this\n\t\t\t\t\t// per-node descriptor.\n\t\t\t\t\tnodeId: `walrus-node-${i}`,\n\t\t\t\t\tpublicKey: `<bls-pubkey-storage-node-${i}>`,\n\t\t\t\t\tpublicHostname,\n\t\t\t\t\t// Router-fronted URL on the well-known walrus\n\t\t\t\t\t// entrypoint port — Traefik routes by Host: header.\n\t\t\t\t\trpcUrl: `http://${publicHostname}:${WALRUS_ROUTER_PORT}`,\n\t\t\t\t} satisfies WalrusStorageNode;\n\t\t\t}).pipe(\n\t\t\t\tEffect.withSpan(`devstack.plugin.walrus.storage-node-${i}.boot`, {\n\t\t\t\t\tattributes: { 'devstack.plugin': 'walrus', 'walrus.node': i },\n\t\t\t\t}),\n\t\t\t);\n\n\t\tconst nodes = yield* Effect.all(indices.map(bootOne), {\n\t\t\tconcurrency: 'unbounded',\n\t\t});\n\n\t\treturn { nodes };\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.walrus.storage-nodes.boot', {\n\t\t\tattributes: { 'devstack.plugin': 'walrus' },\n\t\t}),\n\t);\n"],"mappings":"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"}
1
+ {"version":3,"file":"storage-nodes.mjs","names":[],"sources":["../../../src/plugins/walrus/storage-nodes.ts"],"sourcesContent":["// Walrus storage-node committee lifecycle.\n//\n// Distilled-doc reference (06-walrus.md §\"Capabilities CONSUMED\" +\n// §\"Lifecycle phase 4\"): N storage-node containers, pinned IPs on a\n// per-stack /24 docker network. Each node carries one Traefik route\n// via the `Routable` capability; the router binds host port 9185 once\n// globally and dispatches by `Host:` header.\n//\n// Substrate-side responsibilities:\n// - `ContainerRuntime.ensureContainer` per node — content-addressed\n// image, label tuple, recreate policy.\n// - Parallel `Effect.all({concurrency: 'unbounded'})` over [0..N) —\n// concurrent boot.\n// - Per-node stop finalizer fires in a *forked parallel scope* so\n// teardown collapses to ~max(grace) instead of summing graces\n// (distilled-doc invariant 21 — \"StopFinalizerScope MUST be a\n// forked parallel scope\").\n//\n// What we DON'T own here:\n// - Plugin row narration.\n// - The faucet-strategy registration — `faucet-strategy.ts`.\n// - The deploy one-shot — `deploy.ts`.\n\nimport { Duration, Effect, Scope } from 'effect';\n\nimport type {\n\tContainerHandle,\n\tContainerRuntime,\n\tImageRef,\n} from '../../contracts/container-runtime.ts';\nimport {\n\tProbeTimeoutError,\n\texitCodeProbeResult,\n\twaitForProbe,\n} from '../../substrate/runtime/probes.ts';\nimport { setCurrentPluginPhase } from '../../substrate/runtime/current-plugin.ts';\nimport { ensureManagedContainer } from '../../substrate/runtime/managed-container.ts';\nimport { HOST_GATEWAY_EXTRA_HOSTS } from '../../substrate/runtime/host-gateway.ts';\nimport { SpanAttr } from '../../substrate/runtime/observability/spans.ts';\nimport { walrusDeployMountPaths } from './deploy-paths.ts';\nimport { walrusPluginError, type WalrusPluginError } from './errors.ts';\nimport { WalrusSpans } from './spans.ts';\n\n/** Default per-node grace window. Storage nodes maintain RocksDB-\n * backed state; need >10s to flush and checkpoint on `docker stop`.\n * Distilled-doc invariant 22. */\nexport const DEFAULT_NODE_STOP_GRACE_SECONDS = 20;\n\n/** Default per-node ready-probe timeout. */\nexport const DEFAULT_NODE_READY_TIMEOUT_MS = 60_000;\n\n/** Distilled-doc invariant 9: the on-chain `public_port` value\n * matches the global router entrypoint port. One canonical\n * constant — opportunity #14 in the distilled doc was to deduplicate\n * this across three files. */\nexport const WALRUS_ROUTER_PORT = 9185;\n\n/** Default container API port — each storage node binds this inside\n * the container. Same value as the router port (the storage node's\n * in-container bind matches the on-chain public_port). */\nexport const DEFAULT_CONTAINER_API_PORT = WALRUS_ROUTER_PORT;\n\n/** Per-node descriptor — what the plugin resolved value surfaces\n * for downstream consumers (the `@mysten/walrus` SDK reads this).\n *\n * Note: no `publicKey` field. The per-node BLS12-381 keypair lives\n * inside the per-node keystore the deploy one-shot emitted; the SDK\n * consumer reads the public key off `packageConfig` rather than this\n * routing-handle descriptor. */\nexport interface WalrusStorageNode {\n\treadonly nodeIndex: number;\n\treadonly nodeId: string;\n\treadonly publicHostname: string;\n\treadonly rpcUrl: string;\n}\n\n/** Storage-node startup config — the plugin's local-cluster mode\n * passes this in once per cluster boot. */\nexport interface StorageNodesSpec {\n\treadonly app: string;\n\treadonly stack: string;\n\treadonly walrusName: string;\n\t/** One image ref PER node (`images[i]` for node `i`; length MUST equal\n\t * `nodeCount`). Each node runs under its own tag so its committed writable\n\t * layer (RocksDB slivers) promotes to a DISTINCT image on snapshot restore;\n\t * a single shared tag collapses N committed layers -> 1 on the restore\n\t * image-promote, orphaning N-1 nodes' blobs. */\n\treadonly images: ReadonlyArray<ImageRef>;\n\treadonly nodeCount: number;\n\t/** Pre-allocated /24 prefix from `subnetForStack`. Example:\n\t * `'10.42.7'` (the third octet is hashed per stack). */\n\treadonly subnetPrefix: string;\n\treadonly containerApiPort: number;\n\treadonly walrusNetworkName: string;\n\treadonly suiNetworkName: string;\n\treadonly deployHostMountPath: string;\n\t/** On-disk per-stack root from `StackPathsService.stackRoot`. The\n\t * walrus bind-mount is computed by `walrusDeployMountPaths` as\n\t * `<stackRoot> -> <mountTarget>`; the deploy output dir MUST be a\n\t * descendant. Threaded explicitly to remove the previous\n\t * `dirname(dirname(dirname(...)))` walk-up footgun. */\n\treadonly stackRoot: string;\n\t/** Fingerprint of the deploy outputs mounted into each node. */\n\treadonly deployConfigHash: string;\n\treadonly stopGraceSeconds?: number;\n\treadonly readyTimeoutMs?: number;\n}\n\n/** Result of starting the committee — descriptors used by the\n * plugin's resolved value. */\nexport interface StorageNodesAcquired {\n\treadonly nodes: ReadonlyArray<WalrusStorageNode>;\n}\n\n/** Distilled-doc invariant 1: pinned IPs start at `<prefix>.10`.\n * Centralized so the deploy one-shot's `WALRUS_LISTENING_IPS` env\n * var and the per-node `--ip` pin compute from one source. */\nexport const WALRUS_NODE_IP_BASE = 10;\n\n/** Compute the public hostname for one storage node. Mirrors\n * v3's `routerHostname(identity, 'walrus-node-' + i)` shape\n * (06-walrus.md §\"Routes registered\"). Main stack omits the stack\n * segment; non-main inserts it after the service label. */\nexport const computePublicHostname = (app: string, stack: string, nodeIndex: number): string => {\n\tconst base = `walrus-node-${nodeIndex}.${app}.localhost`;\n\treturn stack === 'main' ? base : `walrus-node-${nodeIndex}.${stack}.${app}.localhost`;\n};\n\nexport const storageNodeConfigHash = (parts: {\n\treadonly deployConfigHash: string;\n\treadonly nodeIndex: number;\n\treadonly deploySourceHostPath: string;\n\treadonly deployMountTarget: string;\n\treadonly containerApiPort: number;\n\treadonly walrusNetworkName: string;\n\treadonly suiNetworkName: string;\n}): string =>\n\t[\n\t\tparts.deployConfigHash,\n\t\t`node=${parts.nodeIndex}`,\n\t\t`mount=${parts.deploySourceHostPath}->${parts.deployMountTarget}`,\n\t\t`api=${parts.containerApiPort}`,\n\t\t`net=${parts.walrusNetworkName},${parts.suiNetworkName}`,\n\t].join('|');\n\nexport const buildWalrusNetworkName = (app: string, stack: string, walrusName: string): string =>\n\t`devstack-${app}-${stack}-walrus-${walrusName}-net`;\n\n/** Per-node TCP ready-probe interval. */\nconst NODE_READY_PROBE_INTERVAL_MS = 500;\n\n/** Start the N-node committee.\n *\n * Wiring (this body is the load-bearing path):\n *\n * 1. Defense-in-depth nodeCount guard.\n * 2. Fork a parallel-strategy child scope off the caller's scope so\n * every node's `docker stop` finalizer fires concurrently on\n * outer teardown — collapses shutdown wall-time from `N×grace` to\n * `~max(grace)` (distilled-doc invariant 21).\n * 3. For each `i ∈ [0..N)`:\n * a. `ensureContainer` on the wrapper image with pinned IP,\n * label tuple, primary network attach (walrus net), recreate\n * on config-change.\n * b. TCP ready probe against `<publicHostname>:<routerPort>`\n * with bounded retries until the outer `readyTimeoutMs`.\n * 4. Run [3] under `Effect.all({concurrency: 'unbounded'})` — boot\n * parallelism collapses to ~max(perNode).\n *\n * WHAT THE SUBSTRATE STILL OWES:\n * - Secondary network attach (`Docker.networkConnect(suiNet)`).\n * `EnsureContainerSpec.networkAttach` accepts an array, so passing\n * `[walrusNet, suiNet]` would dual-home in one shot, but the\n * runtime adapter currently treats the first entry as the primary\n * and post-attaches the rest; the per-node pinned IP only attaches\n * to the primary. The dual-home is documented inline below and\n * relies on that adapter behavior. Storage nodes do not request\n * faucet funds during boot; the secondary network is retained for\n * future Sui-side in-network calls.\n * - Per-node `networkAlias` (`walrus-node-<i>.localhost`). The\n * contract doesn't expose alias plumbing yet; peer containers dial by\n * container name, which docker DNS publishes. The architecture\n * revision is tracked in `index.ts`.\n * - Stop-grace duration propagation. The contract's `stop` takes a\n * Duration but `ensureContainer` doesn't yet accept a default\n * grace; the runtime adapter defaults to 10s. RocksDB needs 20s\n * (distilled-doc invariant 22) — see opportunity below.\n */\nexport const startStorageNodes = (\n\truntime: ContainerRuntime,\n\tspec: StorageNodesSpec,\n): Effect.Effect<StorageNodesAcquired, WalrusPluginError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tif (spec.nodeCount < 1) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\twalrusPluginError(\n\t\t\t\t\t'storage-node',\n\t\t\t\t\t`storage-nodes: nodeCount must be >= 1 (got ${spec.nodeCount})`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (spec.images.length !== spec.nodeCount) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\twalrusPluginError(\n\t\t\t\t\t'storage-node',\n\t\t\t\t\t`storage-nodes: images length (${spec.images.length}) must equal nodeCount (${spec.nodeCount}) — one distinct per-node image tag is required for restore-safe commits`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Fork a parallel stop-scope. Per-node `ensureContainer` finalizers\n\t\t// fire here on outer teardown; closing the parallel scope races\n\t\t// the per-container `docker stop`s instead of summing them.\n\t\t//\n\t\t// Cascade semantics (verified against effect-v4 `Scope.ts`\n\t\t// `fork` docs — \"Closing the parent closes the child with the\n\t\t// same exit value\"): when ANY `bootOne` fails (e.g. a ready-\n\t\t// probe times out on node i), `Effect.all` interrupts the rest;\n\t\t// the failure propagates up through the encompassing\n\t\t// `Effect.scoped` boundary which closes `outerScope`; that\n\t\t// cascade-closes `nodeStopScope`, running EVERY already-acquired\n\t\t// per-node `docker stop` finalizer in parallel. The probe is\n\t\t// intentionally OUTSIDE `Scope.provide(nodeStopScope)` — its\n\t\t// failures do NOT need their own finalizer attached to the\n\t\t// stop scope; the just-started container's finalizer is already\n\t\t// there from the `ensureNode` acquire that preceded the probe.\n\t\tconst outerScope = yield* Effect.scope;\n\t\tconst nodeStopScope = yield* Scope.fork(outerScope, 'parallel');\n\n\t\tconst stopGraceSeconds = spec.stopGraceSeconds ?? DEFAULT_NODE_STOP_GRACE_SECONDS;\n\t\tconst readyTimeout = Duration.millis(spec.readyTimeoutMs ?? DEFAULT_NODE_READY_TIMEOUT_MS);\n\t\tconst deployMount = walrusDeployMountPaths({\n\t\t\tstackRoot: spec.stackRoot,\n\t\t\tdeployOutputDirHostPath: spec.deployHostMountPath,\n\t\t\tmountTarget: '/opt/walrus/runtime',\n\t\t});\n\n\t\tconst indices = Array.from({ length: spec.nodeCount }, (_, i) => i);\n\n\t\tconst bootOne = (i: number): Effect.Effect<WalrusStorageNode, WalrusPluginError, Scope.Scope> =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst containerIp = `${spec.subnetPrefix}.${WALRUS_NODE_IP_BASE + i}`;\n\t\t\t\tconst containerName = `devstack-${spec.app}-${spec.stack}-walrus-${spec.walrusName}-node-${i}`;\n\t\t\t\tconst nodeHostname = `dryrun-node-${i}`;\n\t\t\t\tconst publicHostname = computePublicHostname(spec.app, spec.stack, i);\n\n\t\t\t\tyield* setCurrentPluginPhase(`creating storage-node-${i} container ${containerName}`);\n\t\t\t\t// Acquire under the forked parallel stop scope so the\n\t\t\t\t// finalizer (docker stop) joins the per-node fan-out race.\n\t\t\t\tconst ensureNode: Effect.Effect<ContainerHandle, WalrusPluginError, Scope.Scope> =\n\t\t\t\t\tensureManagedContainer<WalrusPluginError>({\n\t\t\t\t\t\truntime,\n\t\t\t\t\t\tidentity: { app: spec.app, stack: spec.stack },\n\t\t\t\t\t\tplugin: 'walrus',\n\t\t\t\t\t\trole: `storage-node-${i}`,\n\t\t\t\t\t\tspec: {\n\t\t\t\t\t\t\tname: containerName,\n\t\t\t\t\t\t\t// Node `i`'s own image tag — distinct per node so its\n\t\t\t\t\t\t\t// committed RocksDB layer survives snapshot restore.\n\t\t\t\t\t\t\timage: spec.images[i]!,\n\t\t\t\t\t\t\trecreate: 'on-config-change',\n\t\t\t\t\t\t\tconfigHash: storageNodeConfigHash({\n\t\t\t\t\t\t\t\tdeployConfigHash: spec.deployConfigHash,\n\t\t\t\t\t\t\t\tnodeIndex: i,\n\t\t\t\t\t\t\t\tdeploySourceHostPath: deployMount.sourceHostPath,\n\t\t\t\t\t\t\t\tdeployMountTarget: deployMount.mountTarget,\n\t\t\t\t\t\t\t\tcontainerApiPort: spec.containerApiPort,\n\t\t\t\t\t\t\t\twalrusNetworkName: spec.walrusNetworkName,\n\t\t\t\t\t\t\t\tsuiNetworkName: spec.suiNetworkName,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tenv: {\n\t\t\t\t\t\t\t\tHOSTNAME: nodeHostname,\n\t\t\t\t\t\t\t\tDEPLOY_OUTPUT_DIR: deployMount.outputDirInContainer,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tstopGraceSeconds,\n\t\t\t\t\t\t\t// Primary network owns the pinned `--ip`; the\n\t\t\t\t\t\t\t// secondary attach gives docker DNS for the sui\n\t\t\t\t\t\t\t// network. The adapter treats [0] as primary.\n\t\t\t\t\t\t\tnetworkAttach: [spec.walrusNetworkName, spec.suiNetworkName],\n\t\t\t\t\t\t\t// Storage nodes dial sui's host-bound RPC + faucet via\n\t\t\t\t\t\t\t// `host.docker.internal`. See\n\t\t\t\t\t\t\t// substrate/runtime/host-gateway.ts for the platform\n\t\t\t\t\t\t\t// rationale (Docker Desktop auto-wires; native Linux\n\t\t\t\t\t\t\t// Docker requires the explicit `--add-host`).\n\t\t\t\t\t\t\textraHosts: HOST_GATEWAY_EXTRA_HOSTS,\n\t\t\t\t\t\t\tmounts: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// Mount the stack root and point the entrypoint at\n\t\t\t\t\t\t\t\t\t// the deploy child. Docker Desktop can reject\n\t\t\t\t\t\t\t\t\t// freshly-created nested bind sources immediately\n\t\t\t\t\t\t\t\t\t// after a wiped stack recreates them.\n\t\t\t\t\t\t\t\t\tsource: deployMount.sourceHostPath,\n\t\t\t\t\t\t\t\t\ttarget: deployMount.mountTarget,\n\t\t\t\t\t\t\t\t\treadonly: true,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmapError: (cause) =>\n\t\t\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t\t\t'storage-node',\n\t\t\t\t\t\t\t\t`walrus storage-node-${i} (ip=${containerIp}) ensureContainer failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\t\t\t{ cause },\n\t\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\tconst handle: ContainerHandle = yield* Scope.provide(ensureNode, nodeStopScope);\n\n\t\t\t\t// TCP ready probe. We exec a tiny `nc`-style probe inside\n\t\t\t\t// the container against its own listener — proves the\n\t\t\t\t// in-container HTTP server bound and is accepting before\n\t\t\t\t// declaring ready. `exec` only fails on daemon-level\n\t\t\t\t// errors; a non-zero exit code is treated as \"retry\"\n\t\t\t\t// (the same policy postgres uses for `pg_isready`).\n\t\t\t\tyield* setCurrentPluginPhase(\n\t\t\t\t\t`waiting for storage-node-${i} on 127.0.0.1:${spec.containerApiPort}`,\n\t\t\t\t);\n\t\t\t\tyield* waitForProbe({\n\t\t\t\t\tlabel: `walrus.storage-node.${i}`,\n\t\t\t\t\ttimeoutMs: Duration.toMillis(readyTimeout),\n\t\t\t\t\tintervalMs: NODE_READY_PROBE_INTERVAL_MS,\n\t\t\t\t\tprobe: () =>\n\t\t\t\t\t\truntime\n\t\t\t\t\t\t\t.exec(handle, [\n\t\t\t\t\t\t\t\t'sh',\n\t\t\t\t\t\t\t\t'-c',\n\t\t\t\t\t\t\t\t// busybox-style portable probe: open TCP, write\n\t\t\t\t\t\t\t\t// nothing, exit. `nc -z` is the common form.\n\t\t\t\t\t\t\t\t`nc -z 127.0.0.1 ${spec.containerApiPort} || exit 1`,\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t.pipe(Effect.map(exitCodeProbeResult)),\n\t\t\t\t}).pipe(\n\t\t\t\t\tEffect.mapError((cause) => {\n\t\t\t\t\t\tif (cause instanceof ProbeTimeoutError) {\n\t\t\t\t\t\t\treturn walrusPluginError(\n\t\t\t\t\t\t\t\t'storage-node',\n\t\t\t\t\t\t\t\t`storage-node-${i} never became ready within ${Duration.toMillis(readyTimeout)}ms ` +\n\t\t\t\t\t\t\t\t\t`(container=${containerName}, probe=127.0.0.1:${spec.containerApiPort}, ` +\n\t\t\t\t\t\t\t\t\t`publicUrl=http://${publicHostname}:${WALRUS_ROUTER_PORT}). ` +\n\t\t\t\t\t\t\t\t\t`The container was created, but walrus-node did not bind its API port. ` +\n\t\t\t\t\t\t\t\t\t`Check the storage-node container logs for the faucet, WAL exchange, or ` +\n\t\t\t\t\t\t\t\t\t`walrus-node run step that stalled.`,\n\t\t\t\t\t\t\t\t{ cause: cause.lastError ?? cause.lastNotReady ?? cause },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn walrusPluginError(\n\t\t\t\t\t\t\t'storage-node',\n\t\t\t\t\t\t\t`storage-node-${i} ready-probe exec failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\t\t{ cause },\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\treturn {\n\t\t\t\t\tnodeIndex: i,\n\t\t\t\t\t// Stable node-id derived from name. The on-chain\n\t\t\t\t\t// public_key + bls12-381 keypair lives inside the\n\t\t\t\t\t// per-node keystore the deploy one-shot emitted;\n\t\t\t\t\t// this descriptor is the routing handle, not the\n\t\t\t\t\t// crypto identity. The SDK consumer reads the\n\t\t\t\t\t// public key off `packageConfig` rather than this\n\t\t\t\t\t// per-node descriptor.\n\t\t\t\t\tnodeId: `walrus-node-${i}`,\n\t\t\t\t\tpublicHostname,\n\t\t\t\t\t// Router-fronted URL on the well-known walrus\n\t\t\t\t\t// entrypoint port — Traefik routes by Host: header.\n\t\t\t\t\trpcUrl: `http://${publicHostname}:${WALRUS_ROUTER_PORT}`,\n\t\t\t\t} satisfies WalrusStorageNode;\n\t\t\t}).pipe(\n\t\t\t\tEffect.withSpan(`devstack.plugin.walrus.storage-node-${i}.boot`, {\n\t\t\t\t\tattributes: { [SpanAttr.plugin]: 'walrus', [WalrusSpans.node]: i },\n\t\t\t\t}),\n\t\t\t);\n\n\t\tconst nodes = yield* Effect.all(indices.map(bootOne), {\n\t\t\tconcurrency: 'unbounded',\n\t\t});\n\n\t\treturn { nodes };\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.walrus.storage-nodes.boot', {\n\t\t\tattributes: { [SpanAttr.plugin]: 'walrus' },\n\t\t}),\n\t);\n"],"mappings":"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"}
@@ -1,7 +1,40 @@
1
1
  import { walrusPluginError } from "./errors.mjs";
2
+ import { WalrusSpans } from "./spans.mjs";
3
+ import { signAndDispatch } from "../../substrate/runtime/sui-execute/sign-and-dispatch.mjs";
4
+ import { formatExecutedFailure } from "../../substrate/runtime/sui-execute/index.mjs";
5
+ import { SUI_FULL_COIN_TYPE } from "../account/funding.mjs";
6
+ import "../account/index.mjs";
2
7
  import { Effect, Schema } from "effect";
3
8
  import { Transaction } from "@mysten/sui/transactions";
4
9
  //#region src/plugins/walrus/wal-swap.ts
10
+ /** Conservative reserve held back from the gas coin for transaction
11
+ * gas itself. The swap call splits `paymentMist` off the gas coin
12
+ * via `tx.coin({ useGasCoin: true })`, so the on-chain balance must
13
+ * cover BOTH the payment AND a gas budget reserve. The exact gas
14
+ * budget is set by the SDK at build time; this reserve is a coarse
15
+ * upper bound used only by the pre-flight refusal — if the wire
16
+ * call proves the reserve is too small the SDK still surfaces the
17
+ * native `InsufficientGas` cause with the real numbers. */
18
+ const WAL_SWAP_GAS_RESERVE_MIST = 50000000n;
19
+ /** Read the account's SUI balance (best-effort). Returns `null` if the
20
+ * RPC throws or the response shape is unexpected — the pre-flight is
21
+ * a hint, not a hard gate. */
22
+ const readSuiBalance = (sdk, owner) => Effect.promise(async () => {
23
+ try {
24
+ const response = await sdk.core.getBalance({
25
+ owner,
26
+ coinType: SUI_FULL_COIN_TYPE
27
+ });
28
+ const outer = typeof response === "object" && response !== null && "balance" in response ? response.balance : response;
29
+ const value = typeof outer === "object" && outer !== null && "balance" in outer ? outer.balance : outer;
30
+ if (typeof value === "bigint") return value;
31
+ if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) return BigInt(value);
32
+ if (typeof value === "string" && /^\d+$/.test(value)) return BigInt(value);
33
+ return null;
34
+ } catch {
35
+ return null;
36
+ }
37
+ });
5
38
  const WalExchangeObjectShape = Schema.Struct({
6
39
  objectId: Schema.String,
7
40
  type: Schema.String
@@ -35,22 +68,32 @@ const buildWalSwapTransaction = (args) => {
35
68
  tx.transferObjects([walCoin], tx.pure.address(args.recipientAddress));
36
69
  return tx;
37
70
  };
38
- const swapAccountSuiForWal = (args) => args.account.withTransactionSigner((lockedSigner) => Effect.gen(function* () {
39
- const tx = buildWalSwapTransaction({
40
- signerAddress: args.account.address,
41
- recipientAddress: args.recipientAddress,
42
- exchange: args.exchange,
43
- paymentMist: args.paymentMist
44
- });
45
- const txBytes = yield* Effect.tryPromise({
46
- try: () => tx.build({ client: args.sdk.client }),
47
- catch: (cause) => walrusPluginError("fund-wal", `walrus.fundWal: transaction serialization failed for account '${args.account.name}'.`, { cause })
71
+ const swapAccountSuiForWal = (args) => Effect.gen(function* () {
72
+ const suiBalance = yield* readSuiBalance(args.sdk, args.account.address);
73
+ const required = args.paymentMist + WAL_SWAP_GAS_RESERVE_MIST;
74
+ if (suiBalance !== null && suiBalance < required) return yield* Effect.fail(walrusPluginError("fund-wal", `walrus.fundWal: account '${args.account.name}' (address=${args.account.address}) has insufficient SUI to swap ${args.paymentMist} for WAL — balance=${suiBalance} mist, required≥${required} mist (payment=${args.paymentMist} + gas reserve=${WAL_SWAP_GAS_RESERVE_MIST}). Top up the account's SUI funding before declaring the WAL funding entry.`));
75
+ return yield* signAndDispatch({
76
+ signerSource: args.account,
77
+ buildTxBytes: () => Effect.gen(function* () {
78
+ const tx = buildWalSwapTransaction({
79
+ signerAddress: args.account.address,
80
+ recipientAddress: args.recipientAddress,
81
+ exchange: args.exchange,
82
+ paymentMist: args.paymentMist
83
+ });
84
+ return yield* Effect.tryPromise({
85
+ try: () => tx.build({ client: args.sdk.client }),
86
+ catch: (cause) => walrusPluginError("fund-wal", `walrus.fundWal: transaction serialization failed for account '${args.account.name}'.`, { cause })
87
+ });
88
+ }),
89
+ mapSignError: (cause) => walrusPluginError("fund-wal", `walrus.fundWal: SUI -> WAL swap failed for ${args.recipientAddress} using account '${args.account.name}' (address=${args.account.address}) against exchange ${args.exchange.objectId}.`, { cause }),
90
+ onFailed: (failure) => Effect.fail(walrusPluginError("fund-wal", `walrus.fundWal: SUI -> WAL swap failed on-chain (exchange=${args.exchange.objectId}) ` + formatExecutedFailure(failure))),
91
+ onSuccess: (ok) => Effect.succeed({ digest: ok.digest })
48
92
  });
49
- return { digest: (yield* lockedSigner.signAndExecute(txBytes).pipe(Effect.mapError((cause) => walrusPluginError("fund-wal", `walrus.fundWal: SUI -> WAL swap failed for ${args.recipientAddress} using account '${args.account.name}' (address=${args.account.address}) against exchange ${args.exchange.objectId}.`, { cause })))).digest };
50
- })).pipe(Effect.withSpan("devstack.plugin.walrus.fundWal", { attributes: {
51
- "walrus.fund.account": args.account.name,
52
- "walrus.fund.address": args.recipientAddress,
53
- "walrus.fund.exchange": args.exchange.objectId
93
+ }).pipe(Effect.withSpan("devstack.plugin.walrus.fundWal", { attributes: {
94
+ [WalrusSpans.fundAccount]: args.account.name,
95
+ [WalrusSpans.fundAddress]: args.recipientAddress,
96
+ [WalrusSpans.fundExchange]: args.exchange.objectId
54
97
  } }));
55
98
  //#endregion
56
99
  export { resolveWalExchange, swapAccountSuiForWal };
@@ -1 +1 @@
1
- {"version":3,"file":"wal-swap.mjs","names":[],"sources":["../../../src/plugins/walrus/wal-swap.ts"],"sourcesContent":["import { Effect, Schema } from 'effect';\nimport { Transaction } from '@mysten/sui/transactions';\n\nimport type { ChainProbe } from '../../contracts/chain-probe.ts';\nimport type { AccountValue } from '../account/index.ts';\nimport { walrusPluginError, type WalrusPluginError } from './errors.ts';\n\nexport interface WalExchangeHandle {\n\treadonly objectId: string;\n\treadonly packageId: string;\n}\n\nexport type WalExchangeProbeKey = { readonly kind: 'object'; readonly objectId: string };\n\nexport interface WalSwapSdk {\n\treadonly client: unknown;\n}\n\nexport interface WalAccountSwapRequest {\n\treadonly account: AccountValue;\n\treadonly sdk: WalSwapSdk;\n\treadonly exchange: WalExchangeHandle;\n\treadonly recipientAddress: string;\n\treadonly paymentMist: bigint;\n}\n\nconst WalExchangeObjectShape = Schema.Struct({\n\tobjectId: Schema.String,\n\ttype: Schema.String,\n});\n\nexport const resolveWalExchange = (\n\tprobe: ChainProbe<WalExchangeProbeKey>,\n\texchangeObjectId: string | undefined,\n): Effect.Effect<WalExchangeHandle | null, WalrusPluginError> =>\n\tEffect.gen(function* () {\n\t\tif (exchangeObjectId === undefined) return null;\n\t\tconst found = yield* probe\n\t\t\t.get({ kind: 'object', objectId: exchangeObjectId }, WalExchangeObjectShape, 'lenient')\n\t\t\t.pipe(\n\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t'exchange',\n\t\t\t\t\t\t`walrus.exchange: failed to resolve exchange object ${exchangeObjectId}: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\t{ cause },\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\tif (found === null) return null;\n\t\tconst packageId = found.type.split('::')[0];\n\t\tif (packageId === undefined || !packageId.startsWith('0x')) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\twalrusPluginError(\n\t\t\t\t\t'exchange',\n\t\t\t\t\t`walrus.exchange: unexpected exchange object type \"${found.type}\" — expected \"<pkg>::wal_exchange::Exchange\"`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn { objectId: exchangeObjectId, packageId };\n\t});\n\nexport const buildWalSwapTransaction = (args: {\n\treadonly signerAddress: string;\n\treadonly recipientAddress: string;\n\treadonly exchange: WalExchangeHandle;\n\treadonly paymentMist: bigint;\n}): Transaction => {\n\tconst tx = new Transaction();\n\ttx.setSender(args.signerAddress);\n\tconst paymentCoin = tx.coin({\n\t\tbalance: args.paymentMist,\n\t\ttype: '0x2::sui::SUI',\n\t\tuseGasCoin: true,\n\t});\n\tconst walCoin = tx.moveCall({\n\t\ttarget: `${args.exchange.packageId}::wal_exchange::exchange_all_for_wal`,\n\t\targuments: [tx.object(args.exchange.objectId), paymentCoin],\n\t});\n\ttx.transferObjects([walCoin], tx.pure.address(args.recipientAddress));\n\treturn tx;\n};\n\ntype TransactionBuildClient = Parameters<Transaction['build']>[0] extends\n\t| { readonly client?: infer Client }\n\t| undefined\n\t? Client\n\t: never;\n\nexport const swapAccountSuiForWal = (\n\targs: WalAccountSwapRequest,\n): Effect.Effect<{ readonly digest: string }, WalrusPluginError> =>\n\targs.account\n\t\t.withTransactionSigner((lockedSigner) =>\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst tx = buildWalSwapTransaction({\n\t\t\t\t\tsignerAddress: args.account.address,\n\t\t\t\t\trecipientAddress: args.recipientAddress,\n\t\t\t\t\texchange: args.exchange,\n\t\t\t\t\tpaymentMist: args.paymentMist,\n\t\t\t\t});\n\t\t\t\tconst txBytes = yield* Effect.tryPromise({\n\t\t\t\t\ttry: () =>\n\t\t\t\t\t\ttx.build({\n\t\t\t\t\t\t\tclient: args.sdk.client as TransactionBuildClient,\n\t\t\t\t\t\t}),\n\t\t\t\t\tcatch: (cause): WalrusPluginError =>\n\t\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t\t'fund-wal',\n\t\t\t\t\t\t\t`walrus.fundWal: transaction serialization failed for account '${args.account.name}'.`,\n\t\t\t\t\t\t\t{ cause },\n\t\t\t\t\t\t),\n\t\t\t\t});\n\t\t\t\tconst receipt = yield* lockedSigner\n\t\t\t\t\t.signAndExecute(txBytes)\n\t\t\t\t\t.pipe(\n\t\t\t\t\t\tEffect.mapError(\n\t\t\t\t\t\t\t(cause): WalrusPluginError =>\n\t\t\t\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t\t\t\t'fund-wal',\n\t\t\t\t\t\t\t\t\t`walrus.fundWal: SUI -> WAL swap failed for ${args.recipientAddress} ` +\n\t\t\t\t\t\t\t\t\t\t`using account '${args.account.name}' (address=${args.account.address}) ` +\n\t\t\t\t\t\t\t\t\t\t`against exchange ${args.exchange.objectId}.`,\n\t\t\t\t\t\t\t\t\t{ cause },\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\treturn { digest: receipt.digest };\n\t\t\t}),\n\t\t)\n\t\t.pipe(\n\t\t\tEffect.withSpan('devstack.plugin.walrus.fundWal', {\n\t\t\t\tattributes: {\n\t\t\t\t\t'walrus.fund.account': args.account.name,\n\t\t\t\t\t'walrus.fund.address': args.recipientAddress,\n\t\t\t\t\t'walrus.fund.exchange': args.exchange.objectId,\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n"],"mappings":";;;;AA0BA,MAAM,yBAAyB,OAAO,OAAO;CAC5C,UAAU,OAAO;CACjB,MAAM,OAAO;CACb,CAAC;AAEF,MAAa,sBACZ,OACA,qBAEA,OAAO,IAAI,aAAa;AACvB,KAAI,qBAAqB,KAAA,EAAW,QAAO;CAC3C,MAAM,QAAQ,OAAO,MACnB,IAAI;EAAE,MAAM;EAAU,UAAU;EAAkB,EAAE,wBAAwB,UAAU,CACtF,KACA,OAAO,UAAU,UAChB,kBACC,YACA,sDAAsD,iBAAiB,IAAI,MAAM,OAAO,IAAI,MAAM,UAClG,EAAE,OAAO,CACT,CACD,CACD;AACF,KAAI,UAAU,KAAM,QAAO;CAC3B,MAAM,YAAY,MAAM,KAAK,MAAM,KAAK,CAAC;AACzC,KAAI,cAAc,KAAA,KAAa,CAAC,UAAU,WAAW,KAAK,CACzD,QAAO,OAAO,OAAO,KACpB,kBACC,YACA,qDAAqD,MAAM,KAAK,8CAChE,CACD;AAEF,QAAO;EAAE,UAAU;EAAkB;EAAW;EAC/C;AAEH,MAAa,2BAA2B,SAKrB;CAClB,MAAM,KAAK,IAAI,aAAa;AAC5B,IAAG,UAAU,KAAK,cAAc;CAChC,MAAM,cAAc,GAAG,KAAK;EAC3B,SAAS,KAAK;EACd,MAAM;EACN,YAAY;EACZ,CAAC;CACF,MAAM,UAAU,GAAG,SAAS;EAC3B,QAAQ,GAAG,KAAK,SAAS,UAAU;EACnC,WAAW,CAAC,GAAG,OAAO,KAAK,SAAS,SAAS,EAAE,YAAY;EAC3D,CAAC;AACF,IAAG,gBAAgB,CAAC,QAAQ,EAAE,GAAG,KAAK,QAAQ,KAAK,iBAAiB,CAAC;AACrE,QAAO;;AASR,MAAa,wBACZ,SAEA,KAAK,QACH,uBAAuB,iBACvB,OAAO,IAAI,aAAa;CACvB,MAAM,KAAK,wBAAwB;EAClC,eAAe,KAAK,QAAQ;EAC5B,kBAAkB,KAAK;EACvB,UAAU,KAAK;EACf,aAAa,KAAK;EAClB,CAAC;CACF,MAAM,UAAU,OAAO,OAAO,WAAW;EACxC,WACC,GAAG,MAAM,EACR,QAAQ,KAAK,IAAI,QACjB,CAAC;EACH,QAAQ,UACP,kBACC,YACA,iEAAiE,KAAK,QAAQ,KAAK,KACnF,EAAE,OAAO,CACT;EACF,CAAC;AAeF,QAAO,EAAE,SAAQ,OAdM,aACrB,eAAe,QAAQ,CACvB,KACA,OAAO,UACL,UACA,kBACC,YACA,8CAA8C,KAAK,iBAAiB,kBACjD,KAAK,QAAQ,KAAK,aAAa,KAAK,QAAQ,QAAQ,qBAClD,KAAK,SAAS,SAAS,IAC5C,EAAE,OAAO,CACT,CACF,CACD,EACuB,QAAQ;EAChC,CACF,CACA,KACA,OAAO,SAAS,kCAAkC,EACjD,YAAY;CACX,uBAAuB,KAAK,QAAQ;CACpC,uBAAuB,KAAK;CAC5B,wBAAwB,KAAK,SAAS;CACtC,EACD,CAAC,CACF"}
1
+ {"version":3,"file":"wal-swap.mjs","names":[],"sources":["../../../src/plugins/walrus/wal-swap.ts"],"sourcesContent":["import { Effect, Schema } from 'effect';\nimport { Transaction } from '@mysten/sui/transactions';\n\nimport type { ChainProbe } from '../../contracts/chain-probe.ts';\nimport { formatExecutedFailure } from '../../substrate/runtime/sui-execute/index.ts';\nimport { signAndDispatch } from '../../substrate/runtime/sui-execute/sign-and-dispatch.ts';\nimport type { AccountValue } from '../account/index.ts';\nimport type { SuiSdkShim } from '../sui/index.ts';\nimport { SUI_FULL_COIN_TYPE } from '../account/index.ts';\nimport { walrusPluginError, type WalrusPluginError } from './errors.ts';\nimport { WalrusSpans } from './spans.ts';\n\n/** Conservative reserve held back from the gas coin for transaction\n * gas itself. The swap call splits `paymentMist` off the gas coin\n * via `tx.coin({ useGasCoin: true })`, so the on-chain balance must\n * cover BOTH the payment AND a gas budget reserve. The exact gas\n * budget is set by the SDK at build time; this reserve is a coarse\n * upper bound used only by the pre-flight refusal — if the wire\n * call proves the reserve is too small the SDK still surfaces the\n * native `InsufficientGas` cause with the real numbers. */\nconst WAL_SWAP_GAS_RESERVE_MIST = 50_000_000n;\n\nexport interface WalExchangeHandle {\n\treadonly objectId: string;\n\treadonly packageId: string;\n}\n\nexport type WalExchangeProbeKey = { readonly kind: 'object'; readonly objectId: string };\n\nexport type WalSwapSdk = Pick<SuiSdkShim, 'client'> & {\n\treadonly core: Pick<SuiSdkShim['core'], 'getBalance'>;\n};\n\n/** Read the account's SUI balance (best-effort). Returns `null` if the\n * RPC throws or the response shape is unexpected — the pre-flight is\n * a hint, not a hard gate. */\nconst readSuiBalance = (\n\tsdk: WalSwapSdk,\n\towner: string,\n): Effect.Effect<bigint | null, never> =>\n\tEffect.promise(async () => {\n\t\ttry {\n\t\t\tconst response = await sdk.core.getBalance({ owner, coinType: SUI_FULL_COIN_TYPE });\n\t\t\tconst outer =\n\t\t\t\ttypeof response === 'object' && response !== null && 'balance' in response\n\t\t\t\t\t? (response as { readonly balance?: unknown }).balance\n\t\t\t\t\t: response;\n\t\t\tconst value =\n\t\t\t\ttypeof outer === 'object' && outer !== null && 'balance' in outer\n\t\t\t\t\t? (outer as { readonly balance?: unknown }).balance\n\t\t\t\t\t: outer;\n\t\t\tif (typeof value === 'bigint') return value;\n\t\t\tif (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0)\n\t\t\t\treturn BigInt(value);\n\t\t\tif (typeof value === 'string' && /^\\d+$/.test(value)) return BigInt(value);\n\t\t\treturn null;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t});\n\nexport interface WalAccountSwapRequest {\n\treadonly account: AccountValue;\n\treadonly sdk: WalSwapSdk;\n\treadonly exchange: WalExchangeHandle;\n\treadonly recipientAddress: string;\n\treadonly paymentMist: bigint;\n}\n\nconst WalExchangeObjectShape = Schema.Struct({\n\tobjectId: Schema.String,\n\ttype: Schema.String,\n});\n\nexport const resolveWalExchange = (\n\tprobe: ChainProbe<WalExchangeProbeKey>,\n\texchangeObjectId: string | undefined,\n): Effect.Effect<WalExchangeHandle | null, WalrusPluginError> =>\n\tEffect.gen(function* () {\n\t\tif (exchangeObjectId === undefined) return null;\n\t\tconst found = yield* probe\n\t\t\t.get({ kind: 'object', objectId: exchangeObjectId }, WalExchangeObjectShape, 'lenient')\n\t\t\t.pipe(\n\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t'exchange',\n\t\t\t\t\t\t`walrus.exchange: failed to resolve exchange object ${exchangeObjectId}: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\t{ cause },\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\tif (found === null) return null;\n\t\tconst packageId = found.type.split('::')[0];\n\t\tif (packageId === undefined || !packageId.startsWith('0x')) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\twalrusPluginError(\n\t\t\t\t\t'exchange',\n\t\t\t\t\t`walrus.exchange: unexpected exchange object type \"${found.type}\" — expected \"<pkg>::wal_exchange::Exchange\"`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn { objectId: exchangeObjectId, packageId };\n\t});\n\nexport const buildWalSwapTransaction = (args: {\n\treadonly signerAddress: string;\n\treadonly recipientAddress: string;\n\treadonly exchange: WalExchangeHandle;\n\treadonly paymentMist: bigint;\n}): Transaction => {\n\tconst tx = new Transaction();\n\ttx.setSender(args.signerAddress);\n\tconst paymentCoin = tx.coin({\n\t\tbalance: args.paymentMist,\n\t\ttype: '0x2::sui::SUI',\n\t\tuseGasCoin: true,\n\t});\n\tconst walCoin = tx.moveCall({\n\t\ttarget: `${args.exchange.packageId}::wal_exchange::exchange_all_for_wal`,\n\t\targuments: [tx.object(args.exchange.objectId), paymentCoin],\n\t});\n\ttx.transferObjects([walCoin], tx.pure.address(args.recipientAddress));\n\treturn tx;\n};\n\nexport const swapAccountSuiForWal = (\n\targs: WalAccountSwapRequest,\n): Effect.Effect<{ readonly digest: string }, WalrusPluginError> =>\n\tEffect.gen(function* () {\n\t\t// Pre-flight gas-budget refusal — the swap splits `paymentMist`\n\t\t// off the gas coin via `tx.coin({ useGasCoin: true })`, so the\n\t\t// on-chain SUI balance must cover BOTH the payment AND a gas\n\t\t// reserve. Without this check the failure surfaces as an opaque\n\t\t// `Transaction.build` / chain-side `InsufficientGas` after the\n\t\t// wire call has already been attempted; the typed refusal here\n\t\t// names the numbers so the caller sees the real cause. The\n\t\t// balance read is best-effort — a `null` from the SDK falls\n\t\t// through to the wire call (the existing `mapSignError` /\n\t\t// `onFailed` paths still catch the chain-side failure).\n\t\tconst suiBalance = yield* readSuiBalance(args.sdk, args.account.address);\n\t\tconst required = args.paymentMist + WAL_SWAP_GAS_RESERVE_MIST;\n\t\tif (suiBalance !== null && suiBalance < required) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\twalrusPluginError(\n\t\t\t\t\t'fund-wal',\n\t\t\t\t\t`walrus.fundWal: account '${args.account.name}' (address=${args.account.address}) ` +\n\t\t\t\t\t\t`has insufficient SUI to swap ${args.paymentMist} for WAL — ` +\n\t\t\t\t\t\t`balance=${suiBalance} mist, required≥${required} mist ` +\n\t\t\t\t\t\t`(payment=${args.paymentMist} + gas reserve=${WAL_SWAP_GAS_RESERVE_MIST}). ` +\n\t\t\t\t\t\t`Top up the account's SUI funding before declaring the WAL funding entry.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn yield* signAndDispatch({\n\t\t\tsignerSource: args.account,\n\t\t\tbuildTxBytes: () =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst tx = buildWalSwapTransaction({\n\t\t\t\t\t\tsignerAddress: args.account.address,\n\t\t\t\t\t\trecipientAddress: args.recipientAddress,\n\t\t\t\t\t\texchange: args.exchange,\n\t\t\t\t\t\tpaymentMist: args.paymentMist,\n\t\t\t\t\t});\n\t\t\t\t\treturn yield* Effect.tryPromise({\n\t\t\t\t\t\ttry: () => tx.build({ client: args.sdk.client }),\n\t\t\t\t\t\tcatch: (cause): WalrusPluginError =>\n\t\t\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t\t\t'fund-wal',\n\t\t\t\t\t\t\t\t`walrus.fundWal: transaction serialization failed for account '${args.account.name}'.`,\n\t\t\t\t\t\t\t\t{ cause },\n\t\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\t}),\n\t\t\tmapSignError: (cause): WalrusPluginError =>\n\t\t\t\twalrusPluginError(\n\t\t\t\t\t'fund-wal',\n\t\t\t\t\t`walrus.fundWal: SUI -> WAL swap failed for ${args.recipientAddress} ` +\n\t\t\t\t\t\t`using account '${args.account.name}' (address=${args.account.address}) ` +\n\t\t\t\t\t\t`against exchange ${args.exchange.objectId}.`,\n\t\t\t\t\t{ cause },\n\t\t\t\t),\n\t\t\tonFailed: (failure) =>\n\t\t\t\tEffect.fail(\n\t\t\t\t\twalrusPluginError(\n\t\t\t\t\t\t'fund-wal',\n\t\t\t\t\t\t`walrus.fundWal: SUI -> WAL swap failed on-chain ` +\n\t\t\t\t\t\t\t`(exchange=${args.exchange.objectId}) ` +\n\t\t\t\t\t\t\tformatExecutedFailure(failure),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\tonSuccess: (ok) => Effect.succeed({ digest: ok.digest }),\n\t\t});\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.walrus.fundWal', {\n\t\t\tattributes: {\n\t\t\t\t[WalrusSpans.fundAccount]: args.account.name,\n\t\t\t\t[WalrusSpans.fundAddress]: args.recipientAddress,\n\t\t\t\t[WalrusSpans.fundExchange]: args.exchange.objectId,\n\t\t\t},\n\t\t}),\n\t);\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Effect, Schema, Scope } from "effect";
1
+ import { Effect, Scope } from "effect";
2
2
 
3
3
  //#region src/primitives/artifact-publisher.d.ts
4
4
  /** Tagged error from a publish round. */
@@ -0,0 +1,15 @@
1
+ //#region src/primitives/artifact-publisher.ts
2
+ /** Constructor for `ArtifactPublishError`. Centralising the literal
3
+ * shape (single `_tag` site, no `as const` ceremony at call sites)
4
+ * per STYLE_GUIDE §2: tagged errors expose a factory at every
5
+ * plugin/public boundary. Every plugin's `produce` /
6
+ * `Effect.mapError` path goes through this. */
7
+ const artifactPublishError = (reason, detail) => ({
8
+ _tag: "ArtifactPublishError",
9
+ reason,
10
+ detail
11
+ });
12
+ //#endregion
13
+ export { artifactPublishError };
14
+
15
+ //# sourceMappingURL=artifact-publisher.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-publisher.mjs","names":[],"sources":["../../src/primitives/artifact-publisher.ts"],"sourcesContent":["// ArtifactPublisher — L0 substrate primitive (architecture §10).\n//\n// Unifies the discipline that recurs across many on-chain\n// produce/verify plugins (substrate must remain service-name-blind;\n// the plugin index is the authoritative list). cache → verify →\n// produce → register on EVERY cycle.\n//\n// This is callable from any plugin; there is NO plugin-side contract\n// to implement. Plugins pass in:\n//\n// - a namespace + cache-key derivation,\n// - a verify procedure (calls ChainProbe with a typed Schema,\n// lenient mode),\n// - a produce procedure (run on miss / verify-fail),\n// - a register procedure (fires on EVERY cycle — hit AND miss).\n\nimport type { Effect, Scope } from 'effect';\n\nimport type { ChainId, ContentHash } from '../substrate/brand.ts';\n\n/** Lenient retry profile constants — shared with ChainProbe.\n * Architecture: 15 attempts, 90s budget, 500ms initial, 1.5×\n * backoff, [0.8, 1.2) jitter. */\nexport const LENIENT_RETRY_PROFILE = {\n\tattempts: 15,\n\ttotalBudgetMillis: 90_000,\n\tinitialMillis: 500,\n\tbackoffMultiplier: 1.5,\n\tjitterRange: [0.8, 1.2] as const,\n} as const;\n\n/** Input contract for ArtifactPublisher.publish. */\nexport interface ArtifactSpec<Produced, Verified> {\n\t/** Cache namespace — plugin-chosen, e.g. `package`. */\n\treadonly namespace: string;\n\t/** Chain identity — substrate folds into the cache key. */\n\treadonly chain: ChainId;\n\t/** Content-hash of canonical input bytes. */\n\treadonly contentHash: ContentHash;\n\t/** Verify probe — typed Schema; lenient mode. Returns null on\n\t * not-found OR transient failure.\n\t *\n\t * The substrate decodes the cached payload (if any) and passes it\n\t * in as `cached`. Plugins that key their on-chain probe off a\n\t * field of the cached payload (e.g. action's `digest`, package's\n\t * `packageId`) read it from here directly — no in-process\n\t * registry-hop required. Plugins that don't care about the\n\t * cached payload ignore the parameter.\n\t *\n\t * When the cache is empty (cold boot) OR decode failed\n\t * (corruption) the substrate short-circuits to \"miss\" before\n\t * invoking this; callers can therefore assume `cached` is\n\t * defined on every call. */\n\treadonly verify: (cached: Produced) => Effect.Effect<Verified | null, never>;\n\t/** Produce procedure — runs on cache miss OR verify-fail. */\n\treadonly produce: Effect.Effect<Produced, ArtifactPublishError, Scope.Scope>;\n\t/** Register procedure — fires on EVERY cycle (hit AND miss). The\n\t * substrate always hands back the decoded `Produced` payload (on\n\t * cache hit) or the freshly produced one (on miss); the verify\n\t * shape is a probe-only signal, never surfaced to callers. */\n\treadonly register: (artifact: Produced) => Effect.Effect<void, never>;\n}\n\n/** Tagged error from a publish round. */\nexport interface ArtifactPublishError {\n\treadonly _tag: 'ArtifactPublishError';\n\treadonly reason: 'produce-failed' | 'verify-exhausted' | 'cache-corrupt';\n\treadonly detail: string;\n}\n\n/** Constructor for `ArtifactPublishError`. Centralising the literal\n * shape (single `_tag` site, no `as const` ceremony at call sites)\n * per STYLE_GUIDE §2: tagged errors expose a factory at every\n * plugin/public boundary. Every plugin's `produce` /\n * `Effect.mapError` path goes through this. */\nexport const artifactPublishError = (\n\treason: ArtifactPublishError['reason'],\n\tdetail: string,\n): ArtifactPublishError => ({\n\t_tag: 'ArtifactPublishError',\n\treason,\n\tdetail,\n});\n\n/** The publisher service. Plugins call `publish`; substrate handles\n * cache lookup, verify, produce-on-miss, idempotent register.\n *\n * Returns the `Produced` payload on EVERY path:\n * - cache hit + verify succeeds → the decoded cached `Produced`,\n * - cache miss or verify-fail → the freshly produced `Produced`.\n *\n * The `Verified` shape is a probe-only signal (drives the lenient\n * null/non-null decision inside the substrate); it is never returned\n * to plugin callers. Callers therefore type-narrow trivially against\n * `Produced` and avoid the `'<sentinel>'` projection dance. */\nexport interface ArtifactPublisher {\n\treadonly publish: <Produced, Verified>(\n\t\tspec: ArtifactSpec<Produced, Verified>,\n\t) => Effect.Effect<Produced, ArtifactPublishError, Scope.Scope>;\n}\n"],"mappings":";;;;;;AA2EA,MAAa,wBACZ,QACA,YAC2B;CAC3B,MAAM;CACN;CACA;CACA"}
@@ -2,20 +2,32 @@ import { capture } from "../../substrate/runtime/observability/subprocess-captur
2
2
  import { Context, Effect, Layer } from "effect";
3
3
  import { ChildProcess } from "effect/unstable/process";
4
4
  //#region src/runtime/docker/client.ts
5
- var DockerHost = class extends Context.Service()("@devstack-rewrite/runtime-docker/DockerHost") {};
5
+ var DockerHost = class extends Context.Service()("@devstack/runtime-docker/DockerHost") {};
6
6
  const layerDockerHostDefault = Layer.succeed(DockerHost)({});
7
7
  /** A spawner service exposing `spawn`. Held as a service so tests can
8
8
  * inject a stub. In production this is `ChildProcessSpawner.make()`
9
9
  * from `effect/unstable/process` (provided via `@effect/platform-node`). */
10
- var DockerSpawner = class extends Context.Service()("@devstack-rewrite/runtime-docker/DockerSpawner") {};
10
+ var DockerSpawner = class extends Context.Service()("@devstack/runtime-docker/DockerSpawner") {};
11
11
  const buildEnv = (host) => {
12
12
  const env = {};
13
13
  if (host.dockerHost !== void 0) env.DOCKER_HOST = host.dockerHost;
14
14
  return env;
15
15
  };
16
+ /** Grace period between the scope-close SIGTERM and the escalation
17
+ * SIGKILL. Without `forceKillAfter` the Node spawner sends ONE SIGTERM
18
+ * on scope close and then waits indefinitely for the child to die — so
19
+ * a timeout-interrupt (see `exec.ts` / `dockerRunOneShot` `Effect.timeout`)
20
+ * blocks on scope-close if the docker CLI ignores SIGTERM. A few
21
+ * seconds lets a well-behaved CLI flush and exit cleanly before we
22
+ * force-kill the wedged case. */
23
+ const KILL_GRACE = "5 seconds";
16
24
  /** Build a `ChildProcess.Command` from `(verb, ...args)`. The verb is
17
25
  * separate so observability span attributes can pin the
18
- * high-cardinality `args` separately from the `devstack.op` tag. */
26
+ * high-cardinality `args` separately from the `devstack.op` tag.
27
+ *
28
+ * `forceKillAfter` makes scope-close termination escalate
29
+ * SIGTERM→SIGKILL so an interrupt (timeout) can't wedge on a docker CLI
30
+ * that ignores SIGTERM. */
19
31
  const dockerCommand = (host, verb, args, overrideEnv = {}) => {
20
32
  const bin = host.bin ?? "docker";
21
33
  const env = {
@@ -24,7 +36,8 @@ const dockerCommand = (host, verb, args, overrideEnv = {}) => {
24
36
  };
25
37
  return ChildProcess.make(bin, [verb, ...args], {
26
38
  env,
27
- extendEnv: true
39
+ extendEnv: true,
40
+ forceKillAfter: KILL_GRACE
28
41
  });
29
42
  };
30
43
  /** Capture a docker invocation, fail on non-zero exit. Use when any
@@ -1 +1 @@
1
- {"version":3,"file":"client.mjs","names":[],"sources":["../../../src/runtime/docker/client.ts"],"sourcesContent":["// Thin `docker` CLI wrapper.\n//\n// Every subprocess invocation flows through the L0 subprocess-capture\n// primitive (one capture function, one error class). This module owns:\n//\n// - The argv constructor (`dockerArgv`).\n// - The `DOCKER_HOST` env passthrough (architecture §7: one-daemon\n// assumption, env override supported).\n// - Two convenience verbs: `run` (capture-with-success-or-fail-by-exit)\n// and `runOk` (capture, return CaptureResult regardless of exit so\n// the caller can classify stderr). NO docker compose anywhere.\n//\n// No service names appear here. No stderr-pattern classification —\n// that's in `wrap.ts`. This file is mechanical argv + spawn.\n\nimport { Context, Effect, Layer } from 'effect';\nimport { ChildProcess } from 'effect/unstable/process';\nimport { ChildProcessSpawner } from 'effect/unstable/process';\n\nimport {\n\tcapture,\n\ttype CaptureError,\n\ttype CaptureOptions,\n\ttype CaptureResult,\n} from '../../substrate/runtime/observability/subprocess-capture.ts';\n\n// -----------------------------------------------------------------------------\n// Daemon-host configuration\n// -----------------------------------------------------------------------------\n\n/** Optional `DOCKER_HOST` override. When absent we let the docker CLI\n * resolve its default socket (Unix: `/var/run/docker.sock`; macOS\n * Desktop: `unix:///var/run/docker.sock`; remote daemon if the user\n * set `DOCKER_HOST` in their own env). */\nexport interface DockerHostShape {\n\treadonly dockerHost?: string;\n\t/** Optional explicit binary path (default `docker`). Tests use\n\t * this to point at a stub; otherwise we resolve via PATH. */\n\treadonly bin?: string;\n}\n\nexport class DockerHost extends Context.Service<DockerHost, DockerHostShape>()(\n\t'@devstack-rewrite/runtime-docker/DockerHost',\n) {}\n\nexport const layerDockerHostDefault: Layer.Layer<DockerHost> = Layer.succeed(DockerHost)({});\n\nexport const layerDockerHost = (shape: DockerHostShape): Layer.Layer<DockerHost> =>\n\tLayer.succeed(DockerHost)(shape);\n\n// -----------------------------------------------------------------------------\n// Spawner injection\n// -----------------------------------------------------------------------------\n\n/** A spawner service exposing `spawn`. Held as a service so tests can\n * inject a stub. In production this is `ChildProcessSpawner.make()`\n * from `effect/unstable/process` (provided via `@effect/platform-node`). */\nexport class DockerSpawner extends Context.Service<\n\tDockerSpawner,\n\tReturnType<typeof ChildProcessSpawner.make>\n>()('@devstack-rewrite/runtime-docker/DockerSpawner') {}\n\n// -----------------------------------------------------------------------------\n// Argv construction\n// -----------------------------------------------------------------------------\n\nconst buildEnv = (host: DockerHostShape): Record<string, string> => {\n\tconst env: Record<string, string> = {};\n\tif (host.dockerHost !== undefined) env.DOCKER_HOST = host.dockerHost;\n\treturn env;\n};\n\n/** Build a `ChildProcess.Command` from `(verb, ...args)`. The verb is\n * separate so observability span attributes can pin the\n * high-cardinality `args` separately from the `devstack.op` tag. */\nexport const dockerCommand = (\n\thost: DockerHostShape,\n\tverb: string,\n\targs: ReadonlyArray<string>,\n\toverrideEnv: Readonly<Record<string, string>> = {},\n): ChildProcess.Command => {\n\tconst bin = host.bin ?? 'docker';\n\tconst env = { ...buildEnv(host), ...overrideEnv };\n\treturn ChildProcess.make(bin, [verb, ...args], { env, extendEnv: true });\n};\n\n// -----------------------------------------------------------------------------\n// Capture verbs\n// -----------------------------------------------------------------------------\n\n/** Capture a docker invocation, fail on non-zero exit. Use when any\n * non-zero exit is a failure case (most write operations). */\nexport const dockerRun = (\n\tverb: string,\n\targs: ReadonlyArray<string>,\n\topts?: Omit<CaptureOptions, 'op' | 'nonZeroIsFailure'>,\n): Effect.Effect<CaptureResult, CaptureError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst host = yield* DockerHost;\n\t\tconst spawner = yield* DockerSpawner;\n\t\treturn yield* capture(spawner, dockerCommand(host, verb, args), {\n\t\t\t...opts,\n\t\t\top: `docker.${verb}`,\n\t\t\tnonZeroIsFailure: true,\n\t\t});\n\t});\n\n/** Capture a docker invocation, return the `CaptureResult` regardless\n * of exit. Use when the caller classifies stderr or wants the exit\n * code (lifecycle state machine, inventory). */\nexport const dockerRunOk = (\n\tverb: string,\n\targs: ReadonlyArray<string>,\n\topts?: Omit<CaptureOptions, 'op' | 'nonZeroIsFailure'>,\n): Effect.Effect<CaptureResult, CaptureError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst host = yield* DockerHost;\n\t\tconst spawner = yield* DockerSpawner;\n\t\treturn yield* capture(spawner, dockerCommand(host, verb, args), {\n\t\t\t...opts,\n\t\t\top: `docker.${verb}`,\n\t\t\tnonZeroIsFailure: false,\n\t\t});\n\t});\n"],"mappings":";;;;AAyCA,IAAa,aAAb,cAAgC,QAAQ,SAAsC,CAC7E,8CACA,CAAC;AAEF,MAAa,yBAAkD,MAAM,QAAQ,WAAW,CAAC,EAAE,CAAC;;;;AAY5F,IAAa,gBAAb,cAAmC,QAAQ,SAGxC,CAAC,iDAAiD,CAAC;AAMtD,MAAM,YAAY,SAAkD;CACnE,MAAM,MAA8B,EAAE;AACtC,KAAI,KAAK,eAAe,KAAA,EAAW,KAAI,cAAc,KAAK;AAC1D,QAAO;;;;;AAMR,MAAa,iBACZ,MACA,MACA,MACA,cAAgD,EAAE,KACxB;CAC1B,MAAM,MAAM,KAAK,OAAO;CACxB,MAAM,MAAM;EAAE,GAAG,SAAS,KAAK;EAAE,GAAG;EAAa;AACjD,QAAO,aAAa,KAAK,KAAK,CAAC,MAAM,GAAG,KAAK,EAAE;EAAE;EAAK,WAAW;EAAM,CAAC;;;;AASzE,MAAa,aACZ,MACA,MACA,SAEA,OAAO,IAAI,aAAa;CACvB,MAAM,OAAO,OAAO;AAEpB,QAAO,OAAO,QAAQ,OADC,eACQ,cAAc,MAAM,MAAM,KAAK,EAAE;EAC/D,GAAG;EACH,IAAI,UAAU;EACd,kBAAkB;EAClB,CAAC;EACD;;;;AAKH,MAAa,eACZ,MACA,MACA,SAEA,OAAO,IAAI,aAAa;CACvB,MAAM,OAAO,OAAO;AAEpB,QAAO,OAAO,QAAQ,OADC,eACQ,cAAc,MAAM,MAAM,KAAK,EAAE;EAC/D,GAAG;EACH,IAAI,UAAU;EACd,kBAAkB;EAClB,CAAC;EACD"}
1
+ {"version":3,"file":"client.mjs","names":[],"sources":["../../../src/runtime/docker/client.ts"],"sourcesContent":["// Thin `docker` CLI wrapper.\n//\n// Every subprocess invocation flows through the L0 subprocess-capture\n// primitive (one capture function, one error class). This module owns:\n//\n// - The argv constructor (`dockerArgv`).\n// - The `DOCKER_HOST` env passthrough (architecture §7: one-daemon\n// assumption, env override supported).\n// - Two convenience verbs: `run` (capture-with-success-or-fail-by-exit)\n// and `runOk` (capture, return CaptureResult regardless of exit so\n// the caller can classify stderr). NO docker compose anywhere.\n//\n// No service names appear here. No stderr-pattern classification —\n// that's in `wrap.ts`. This file is mechanical argv + spawn.\n\nimport { Context, Effect, Layer } from 'effect';\nimport { ChildProcess } from 'effect/unstable/process';\nimport { ChildProcessSpawner } from 'effect/unstable/process';\n\nimport {\n\tcapture,\n\ttype CaptureError,\n\ttype CaptureOptions,\n\ttype CaptureResult,\n} from '../../substrate/runtime/observability/subprocess-capture.ts';\n\n// -----------------------------------------------------------------------------\n// Daemon-host configuration\n// -----------------------------------------------------------------------------\n\n/** Optional `DOCKER_HOST` override. When absent we let the docker CLI\n * resolve its default socket (Unix: `/var/run/docker.sock`; macOS\n * Desktop: `unix:///var/run/docker.sock`; remote daemon if the user\n * set `DOCKER_HOST` in their own env). */\nexport interface DockerHostShape {\n\treadonly dockerHost?: string;\n\t/** Optional explicit binary path (default `docker`). Tests use\n\t * this to point at a stub; otherwise we resolve via PATH. */\n\treadonly bin?: string;\n}\n\nexport class DockerHost extends Context.Service<DockerHost, DockerHostShape>()(\n\t'@devstack/runtime-docker/DockerHost',\n) {}\n\nexport const layerDockerHostDefault: Layer.Layer<DockerHost> = Layer.succeed(DockerHost)({});\n\nexport const layerDockerHost = (shape: DockerHostShape): Layer.Layer<DockerHost> =>\n\tLayer.succeed(DockerHost)(shape);\n\n// -----------------------------------------------------------------------------\n// Spawner injection\n// -----------------------------------------------------------------------------\n\n/** A spawner service exposing `spawn`. Held as a service so tests can\n * inject a stub. In production this is `ChildProcessSpawner.make()`\n * from `effect/unstable/process` (provided via `@effect/platform-node`). */\nexport class DockerSpawner extends Context.Service<\n\tDockerSpawner,\n\tReturnType<typeof ChildProcessSpawner.make>\n>()('@devstack/runtime-docker/DockerSpawner') {}\n\n// -----------------------------------------------------------------------------\n// Argv construction\n// -----------------------------------------------------------------------------\n\nconst buildEnv = (host: DockerHostShape): Record<string, string> => {\n\tconst env: Record<string, string> = {};\n\tif (host.dockerHost !== undefined) env.DOCKER_HOST = host.dockerHost;\n\treturn env;\n};\n\n/** Grace period between the scope-close SIGTERM and the escalation\n * SIGKILL. Without `forceKillAfter` the Node spawner sends ONE SIGTERM\n * on scope close and then waits indefinitely for the child to die — so\n * a timeout-interrupt (see `exec.ts` / `dockerRunOneShot` `Effect.timeout`)\n * blocks on scope-close if the docker CLI ignores SIGTERM. A few\n * seconds lets a well-behaved CLI flush and exit cleanly before we\n * force-kill the wedged case. */\nconst KILL_GRACE = '5 seconds';\n\n/** Build a `ChildProcess.Command` from `(verb, ...args)`. The verb is\n * separate so observability span attributes can pin the\n * high-cardinality `args` separately from the `devstack.op` tag.\n *\n * `forceKillAfter` makes scope-close termination escalate\n * SIGTERM→SIGKILL so an interrupt (timeout) can't wedge on a docker CLI\n * that ignores SIGTERM. */\nexport const dockerCommand = (\n\thost: DockerHostShape,\n\tverb: string,\n\targs: ReadonlyArray<string>,\n\toverrideEnv: Readonly<Record<string, string>> = {},\n): ChildProcess.Command => {\n\tconst bin = host.bin ?? 'docker';\n\tconst env = { ...buildEnv(host), ...overrideEnv };\n\treturn ChildProcess.make(bin, [verb, ...args], {\n\t\tenv,\n\t\textendEnv: true,\n\t\tforceKillAfter: KILL_GRACE,\n\t});\n};\n\n// -----------------------------------------------------------------------------\n// Capture verbs\n// -----------------------------------------------------------------------------\n\n/** Capture a docker invocation, fail on non-zero exit. Use when any\n * non-zero exit is a failure case (most write operations). */\nexport const dockerRun = (\n\tverb: string,\n\targs: ReadonlyArray<string>,\n\topts?: Omit<CaptureOptions, 'op' | 'nonZeroIsFailure'>,\n): Effect.Effect<CaptureResult, CaptureError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst host = yield* DockerHost;\n\t\tconst spawner = yield* DockerSpawner;\n\t\treturn yield* capture(spawner, dockerCommand(host, verb, args), {\n\t\t\t...opts,\n\t\t\top: `docker.${verb}`,\n\t\t\tnonZeroIsFailure: true,\n\t\t});\n\t});\n\n/** Capture a docker invocation, return the `CaptureResult` regardless\n * of exit. Use when the caller classifies stderr or wants the exit\n * code (lifecycle state machine, inventory). */\nexport const dockerRunOk = (\n\tverb: string,\n\targs: ReadonlyArray<string>,\n\topts?: Omit<CaptureOptions, 'op' | 'nonZeroIsFailure'>,\n): Effect.Effect<CaptureResult, CaptureError, DockerHost | DockerSpawner> =>\n\tEffect.gen(function* () {\n\t\tconst host = yield* DockerHost;\n\t\tconst spawner = yield* DockerSpawner;\n\t\treturn yield* capture(spawner, dockerCommand(host, verb, args), {\n\t\t\t...opts,\n\t\t\top: `docker.${verb}`,\n\t\t\tnonZeroIsFailure: false,\n\t\t});\n\t});\n"],"mappings":";;;;AAyCA,IAAa,aAAb,cAAgC,QAAQ,SAAsC,CAC7E,sCACA,CAAC;AAEF,MAAa,yBAAkD,MAAM,QAAQ,WAAW,CAAC,EAAE,CAAC;;;;AAY5F,IAAa,gBAAb,cAAmC,QAAQ,SAGxC,CAAC,yCAAyC,CAAC;AAM9C,MAAM,YAAY,SAAkD;CACnE,MAAM,MAA8B,EAAE;AACtC,KAAI,KAAK,eAAe,KAAA,EAAW,KAAI,cAAc,KAAK;AAC1D,QAAO;;;;;;;;;AAUR,MAAM,aAAa;;;;;;;;AASnB,MAAa,iBACZ,MACA,MACA,MACA,cAAgD,EAAE,KACxB;CAC1B,MAAM,MAAM,KAAK,OAAO;CACxB,MAAM,MAAM;EAAE,GAAG,SAAS,KAAK;EAAE,GAAG;EAAa;AACjD,QAAO,aAAa,KAAK,KAAK,CAAC,MAAM,GAAG,KAAK,EAAE;EAC9C;EACA,WAAW;EACX,gBAAgB;EAChB,CAAC;;;;AASH,MAAa,aACZ,MACA,MACA,SAEA,OAAO,IAAI,aAAa;CACvB,MAAM,OAAO,OAAO;AAEpB,QAAO,OAAO,QAAQ,OADC,eACQ,cAAc,MAAM,MAAM,KAAK,EAAE;EAC/D,GAAG;EACH,IAAI,UAAU;EACd,kBAAkB;EAClB,CAAC;EACD;;;;AAKH,MAAa,eACZ,MACA,MACA,SAEA,OAAO,IAAI,aAAa;CACvB,MAAM,OAAO,OAAO;AAEpB,QAAO,OAAO,QAAQ,OADC,eACQ,cAAc,MAAM,MAAM,KAAK,EAAE;EAC/D,GAAG;EACH,IAAI,UAAU;EACd,kBAAkB;EAClB,CAAC;EACD"}