@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,10 +1,13 @@
1
1
  import { ProbeTimeoutError, exitCodeProbeResult, waitForProbe } from "../../substrate/runtime/probes.mjs";
2
- import { ensureManagedContainer } from "../../substrate/runtime/managed-container.mjs";
2
+ import { HOST_GATEWAY_EXTRA_HOSTS } from "../../substrate/runtime/host-gateway.mjs";
3
3
  import { DEFAULT_KEY_SERVER_PORT, SEAL_KEY_SERVER_ENDPOINT_NAME } from "./routable.mjs";
4
- import { sealError } from "./errors.mjs";
4
+ import { ensureManagedContainer } from "../../substrate/runtime/managed-container.mjs";
5
+ import { deriveSubnetPrefix } from "../../substrate/runtime/subnet-broker.mjs";
6
+ import { isSealError, sealError } from "./errors.mjs";
7
+ import { SealSpans } from "./spans.mjs";
5
8
  import { KEY_SERVER_CONFIG_BASENAME, MASTER_KEY_ENVFILE_BASENAME } from "./keygen.mjs";
6
9
  import { Effect } from "effect";
7
- import { basename, dirname } from "node:path";
10
+ import { basename, dirname, relative } from "node:path";
8
11
  /** Inside-container config path. The binary reads `CONFIG_PATH` to
9
12
  * locate the rendered yaml. */
10
13
  const INSIDE_CONFIG_PATH = "/etc/seal/key-server-config.yaml";
@@ -21,39 +24,35 @@ const CONTAINER_ENV = {
21
24
  MASTER_KEY_ENVFILE: INSIDE_MASTER_KEY_ENVFILE,
22
25
  RUST_LOG: "info"
23
26
  };
24
- const HOST_GATEWAY_EXTRA_HOSTS = { "host.docker.internal": "host-gateway" };
25
27
  const buildSealNetworkName = (app, stack, sealName) => `devstack-${app}-${stack}-seal-${sealName}-net`;
26
28
  /** Seal's key-server network gets a deterministic /24 so repeated
27
- * local runs do not consume Docker's default bridge address pools. */
28
- const deriveSealSubnetPrefix = (identity) => {
29
- const key = `${identity.app}\0${identity.stack}\0${identity.sealName}\0seal`;
30
- let hash = 2166136261;
31
- for (let i = 0; i < key.length; i += 1) {
32
- hash ^= key.charCodeAt(i);
33
- hash = Math.imul(hash, 16777619) >>> 0;
34
- }
35
- const bucket = hash % (64 * 256);
36
- return `10.${128 + Math.floor(bucket / 256)}.${bucket % 256}`;
37
- };
38
- const sealNetworkCreateSpec = (spec, subnetPrefix) => ({
39
- ...spec,
40
- subnet: `${subnetPrefix}.0/24`,
41
- gateway: `${subnetPrefix}.1`
42
- });
29
+ * local runs do not consume Docker's default bridge address pools.
30
+ * Seal claims the `10.128.*` `10.191.*` band; see
31
+ * substrate/runtime/subnet-broker.ts for the algorithm and band
32
+ * coordination with walrus. */
33
+ const deriveSealSubnetPrefix = (identity) => deriveSubnetPrefix(`${identity.app}\0${identity.stack}\0${identity.sealName}\0seal`, 128);
43
34
  /** Per-probe interval inside the bounded retry. */
44
35
  const READY_PROBE_INTERVAL_MS = 500;
45
36
  /** Build the container spec. Distilled-doc invariants #1, #3, #5
46
37
  * encoded here:
47
38
  *
48
39
  * - `routedUrl` is the SAME value the on-chain Move call registers.
49
- * - `env` is `CONTAINER_ENV` (no MASTER_KEY); `masterKeyEnvFileHostPath`
50
- * bind-mount carries the secret.
40
+ * - `env` is `CONTAINER_ENV` (no MASTER_KEY); the bind-mounted env-file
41
+ * at `<servicePath>/master-key.env` (sourced by the entrypoint shell)
42
+ * carries the secret.
51
43
  * - `routing[]` lists the seal-key-server entrypoint; the spec returned has
52
- * NO `ports:` field (it's not modelled). */
44
+ * NO `ports:` field (it's not modelled).
45
+ *
46
+ * Asserts at spec-build time that the substrate-provided `servicePath`
47
+ * lives under the derived `runtimeRootHostPath`. The single host
48
+ * mount publishes the entire `runtimeRootHostPath` subtree; if the
49
+ * caller ever drifts `servicePath` outside that subtree, the
50
+ * rendered config + master-key envfile silently would not reach the
51
+ * container — surface that drift here instead. */
53
52
  const buildKeyServerSpec = (inputs) => {
54
- const masterKeyEnvFileHostPath = `${inputs.servicePath}/${MASTER_KEY_ENVFILE_BASENAME}`;
55
- const configHostPath = `${inputs.servicePath}/${KEY_SERVER_CONFIG_BASENAME}`;
56
53
  const runtimeRootHostPath = dirname(dirname(inputs.servicePath));
54
+ const rel = relative(runtimeRootHostPath, inputs.servicePath);
55
+ if (rel.length === 0 || rel.startsWith("..") || runtimeRootHostPath === "/") throw new Error(`buildKeyServerSpec: servicePath (${inputs.servicePath}) must be a descendant of runtimeRootHostPath (${runtimeRootHostPath}) AND runtimeRootHostPath must not collapse to '/'. The single bind-mount publishes runtimeRootHostPath into the container — if servicePath drifts outside it, the rendered config + master-key envfile would silently not reach the container; if the root collapses to '/', the bind would publish the host root. Cross-check the substrate's seal servicePath layout.`);
57
56
  const serviceDirName = basename(inputs.servicePath);
58
57
  const configContainerPath = `${INSIDE_RUNTIME_ROOT}/seal/${serviceDirName}/${KEY_SERVER_CONFIG_BASENAME}`;
59
58
  const masterKeyEnvFileContainerPath = `${INSIDE_RUNTIME_ROOT}/seal/${serviceDirName}/${MASTER_KEY_ENVFILE_BASENAME}`;
@@ -62,8 +61,6 @@ const buildKeyServerSpec = (inputs) => {
62
61
  image: inputs.image,
63
62
  containerName: inputs.containerName,
64
63
  labels: inputs.labels,
65
- configHostPath,
66
- masterKeyEnvFileHostPath,
67
64
  runtimeRootHostPath,
68
65
  configContainerPath,
69
66
  masterKeyEnvFileContainerPath,
@@ -152,11 +149,15 @@ const startKeyServer = (runtime, spec, name) => Effect.gen(function* () {
152
149
  `(command -v curl >/dev/null 2>&1 && curl -fsS -m 2 ${directProbeUrl} >/dev/null) || nc -z 127.0.0.1 ${spec.containerPort} || exit 1`
153
150
  ]).pipe(Effect.map(exitCodeProbeResult))
154
151
  }).pipe(Effect.mapError((cause) => {
155
- if (cause instanceof ProbeTimeoutError) return sealError("ready", {
156
- name,
157
- message: `seal key-server never became ready within ${spec.readyTimeoutMs}ms (directProbeUrl=${directProbeUrl}, routedUrl=${spec.routedUrl})`,
158
- cause: cause.lastError ?? cause.lastNotReady ?? cause
159
- });
152
+ if (cause instanceof ProbeTimeoutError) {
153
+ const inner = cause.lastError ?? cause.lastNotReady ?? cause;
154
+ if (isSealError(inner)) return inner;
155
+ return sealError("ready", {
156
+ name,
157
+ message: `seal key-server never became ready within ${spec.readyTimeoutMs}ms (directProbeUrl=${directProbeUrl}, routedUrl=${spec.routedUrl})`,
158
+ cause: inner
159
+ });
160
+ }
160
161
  return sealError("ready", {
161
162
  name,
162
163
  message: `seal key-server ready-probe exec failed: ${cause.reason}: ${cause.detail}`,
@@ -165,11 +166,11 @@ const startKeyServer = (runtime, spec, name) => Effect.gen(function* () {
165
166
  }));
166
167
  return { containerName: spec.containerName };
167
168
  }).pipe(Effect.withSpan("devstack.plugin.seal.keyServer.start", { attributes: {
168
- "seal.name": name,
169
- "seal.containerName": spec.containerName,
170
- "seal.routedUrl": spec.routedUrl
169
+ [SealSpans.name]: name,
170
+ [SealSpans.containerName]: spec.containerName,
171
+ [SealSpans.routedUrl]: spec.routedUrl
171
172
  } }));
172
173
  //#endregion
173
- export { buildKeyServerSpec, buildSealNetworkName, deriveSealSubnetPrefix, sealNetworkCreateSpec, startKeyServer };
174
+ export { buildKeyServerSpec, buildSealNetworkName, deriveSealSubnetPrefix, startKeyServer };
174
175
 
175
176
  //# sourceMappingURL=key-server.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"key-server.mjs","names":[],"sources":["../../../src/plugins/seal/key-server.ts"],"sourcesContent":["// Seal plugin — long-running key-server container lifecycle.\n//\n// Distilled-doc invariants pinned by this file:\n//\n// #1 (KeyServer.url == routed hostname): the URL handed to the\n// on-chain Move call MUST equal the routed hostname stamped on\n// the `seal-key-server` route. We resolve the URL ONCE via the\n// router (see `routable.ts`) and pipe the same value into both\n// the Move register pass (`deploy.ts` + `registry-publish.ts`)\n// and this file's container spec.\n//\n// #3 (env-file not -e MASTER_KEY=…): the container is launched\n// with `envFiles: [<masterKeyEnvFile>]` and a `env:` map that\n// does NOT contain `MASTER_KEY`. Distilled doc §Hard\n// requirements #3 — the inline form surfaces the key in host\n// process env + docker inspect output.\n//\n// IMPLEMENTATION CONSTRAINT: the L1 `EnsureContainerSpec`\n// contract today does NOT expose an `envFiles:` slot — only\n// `env:`. We work around this by bind-mounting the env-file\n// into the container under a stack-root bind mount; the cargo\n// image's entrypoint shell (see Hard requirement #7) is\n// responsible for `set -a; . \"$MASTER_KEY_ENVFILE\"; set +a`\n// BEFORE exec'ing the daemon, so the secret never appears in\n// `docker inspect`. ARCHITECTURE REVISION TRACKED: add `envFiles`\n// to `EnsureContainerSpec`.\n//\n// #5 (NO host-port publish): the `ports:` field is INTENTIONALLY\n// absent from the `EnsureContainerSpec` we pass to the runtime.\n// Traefik dispatches by Host: header from the well-known router\n// entrypoint `seal-key-server`.\n//\n// #7 (signal-forwarding entrypoint shell): the cargo-built image\n// embeds the entrypoint shell that traps SIGTERM and forwards\n// SIGTERM to the key-server child. Distilled doc §Hard\n// requirements #21. The image declares the right entrypoint;\n// this file does NOT re-declare it.\n\nimport { Effect, type Scope } from 'effect';\nimport { basename, dirname } from 'node:path';\n\nimport type {\n\tContainerHandle,\n\tContainerRuntime,\n\tEnsureContainerSpec,\n\tEnsureNetworkSpec,\n\tImageRef,\n} from '../../contracts/container-runtime.ts';\nimport type { ContainerLabelTuple } from '../../contracts/snapshotable.ts';\nimport {\n\tProbeTimeoutError,\n\texitCodeProbeResult,\n\twaitForProbe,\n} from '../../substrate/runtime/probes.ts';\nimport { ensureManagedContainer } from '../../substrate/runtime/managed-container.ts';\nimport { sealError, type SealError } from './errors.ts';\nimport { KEY_SERVER_CONFIG_BASENAME, MASTER_KEY_ENVFILE_BASENAME } from './keygen.ts';\nimport { DEFAULT_KEY_SERVER_PORT, SEAL_KEY_SERVER_ENDPOINT_NAME } from './routable.ts';\n\nexport { DEFAULT_KEY_SERVER_PORT } from './routable.ts';\n\n// ---------------------------------------------------------------------------\n// Constants — mirror v3 `seal/internal.ts:102-103`\n// ---------------------------------------------------------------------------\n\n/** Default `/health` probe timeout. */\nexport const DEFAULT_READY_TIMEOUT_MS = 60_000 as const;\n\n/** Inside-container config path. The binary reads `CONFIG_PATH` to\n * locate the rendered yaml. */\nexport const INSIDE_CONFIG_PATH = '/etc/seal/key-server-config.yaml' as const;\n\n/** Inside-container master-key env-file path. The entrypoint shell\n * sources this before exec'ing the daemon (Hard requirement #3 +\n * #7). */\nexport const INSIDE_MASTER_KEY_ENVFILE = '/etc/seal/master-key.env' as const;\n\nconst INSIDE_RUNTIME_ROOT = '/devstack/runtime' as const;\n\n/** Container-side env defaults. NB: `MASTER_KEY` is NOT here — it\n * flows via the bind-mounted env-file sourced by the entrypoint\n * shell. Distilled-doc invariant #3. */\nexport const CONTAINER_ENV: Readonly<Record<string, string>> = {\n\tCONFIG_PATH: INSIDE_CONFIG_PATH,\n\tMASTER_KEY_ENVFILE: INSIDE_MASTER_KEY_ENVFILE,\n\tRUST_LOG: 'info',\n};\n\nexport const HOST_GATEWAY_EXTRA_HOSTS: Readonly<Record<string, string>> = {\n\t'host.docker.internal': 'host-gateway',\n};\n\nexport const buildSealNetworkName = (app: string, stack: string, sealName: string): string =>\n\t`devstack-${app}-${stack}-seal-${sealName}-net`;\n\nexport interface SealNetworkIdentity {\n\treadonly app: string;\n\treadonly stack: string;\n\treadonly sealName: string;\n}\n\n/** Seal's key-server network gets a deterministic /24 so repeated\n * local runs do not consume Docker's default bridge address pools. */\nexport const deriveSealSubnetPrefix = (identity: SealNetworkIdentity): string => {\n\tconst key = `${identity.app}\\0${identity.stack}\\0${identity.sealName}\\0seal`;\n\tlet hash = 0x811c9dc5;\n\tfor (let i = 0; i < key.length; i += 1) {\n\t\thash ^= key.charCodeAt(i);\n\t\thash = Math.imul(hash, 0x01000193) >>> 0;\n\t}\n\tconst bucket = hash % (64 * 256);\n\tconst secondOctet = 128 + Math.floor(bucket / 256);\n\tconst thirdOctet = bucket % 256;\n\treturn `10.${secondOctet}.${thirdOctet}`;\n};\n\nexport const sealNetworkCreateSpec = <Spec extends EnsureNetworkSpec>(\n\tspec: Spec,\n\tsubnetPrefix: string,\n): Spec & Required<Pick<EnsureNetworkSpec, 'subnet' | 'gateway'>> => ({\n\t...spec,\n\tsubnet: `${subnetPrefix}.0/24`,\n\tgateway: `${subnetPrefix}.1`,\n});\n\n/** Per-probe interval inside the bounded retry. */\nconst READY_PROBE_INTERVAL_MS = 500;\n\n// ---------------------------------------------------------------------------\n// Spec shape\n// ---------------------------------------------------------------------------\n\n/** The container spec produced for the long-running key-server. This\n * is the substrate-blind value the ContainerRuntime adapter\n * consumes. */\nexport interface KeyServerContainerSpec {\n\t/** Image ref from the Seal image resolver. */\n\treadonly image: ImageRef;\n\t/** Composed container name (substrate folds `<app>-<stack>-…`). */\n\treadonly containerName: string;\n\t/** Label tuple — drives the snapshot orchestrator's filter +\n\t * `inspectByLabels`. */\n\treadonly labels: ContainerLabelTuple;\n\t/** Mount source on host — the rendered key-server-config.yaml. */\n\treadonly configHostPath: string;\n\t/** Env-file holding `MASTER_KEY=<hex>`. Mode-bit 0o600 inside\n\t * 0o700 parent. Distilled-doc invariant #2. Bind-mounted (see\n\t * file header for the missing-envFiles workaround). */\n\treadonly masterKeyEnvFileHostPath: string;\n\t/** Mount source on host. Docker Desktop can reject freshly-created\n\t * nested file/leaf-directory bind sources even when a parent mount\n\t * can see them, so key-server mounts the stack root and points the\n\t * entrypoint at the config/envfile inside that mount. */\n\treadonly runtimeRootHostPath: string;\n\treadonly configContainerPath: string;\n\treadonly masterKeyEnvFileContainerPath: string;\n\t/** Fingerprint of config contents that affect key-server boot. */\n\treadonly configFingerprint: string;\n\t/** Inner docker network for sui DNS resolution. */\n\treadonly network: string;\n\t/** Router routing spec — Traefik file-provider stamped per\n\t * container. Distilled-doc invariant #5 (no host-port publish). */\n\treadonly routing: ReadonlyArray<{\n\t\treadonly name: string;\n\t\treadonly entrypoint: string;\n\t\treadonly servicePort: number;\n\t}>;\n\t/** Routed URL — `<routedUrl>/health` is what the ready probe\n\t * would hit if/when an HTTP probe contract lands. Today we use\n\t * an exec-based probe (see `startKeyServer`). */\n\treadonly routedUrl: string;\n\t/** Timeout for the ready probe. */\n\treadonly readyTimeoutMs: number;\n\t/** Graceful stop deadline. Distilled-doc invariant #21 — the\n\t * entrypoint shell forwards Docker's SIGTERM to the key-server. */\n\treadonly stopGraceSeconds: number;\n\t/** In-container port the daemon binds. */\n\treadonly containerPort: number;\n}\n\n// ---------------------------------------------------------------------------\n// Spec builder\n// ---------------------------------------------------------------------------\n\n/** Inputs to assemble the container spec. */\nexport interface KeyServerSpecInputs {\n\treadonly name: string;\n\treadonly image: ImageRef;\n\treadonly containerName: string;\n\treadonly labels: ContainerLabelTuple;\n\treadonly suiNetwork: string;\n\treadonly servicePath: string;\n\treadonly configFingerprint: string;\n\treadonly routedHostname: string;\n\treadonly routedUrl: string;\n\treadonly readyTimeoutMs?: number;\n}\n\n/** Build the container spec. Distilled-doc invariants #1, #3, #5\n * encoded here:\n *\n * - `routedUrl` is the SAME value the on-chain Move call registers.\n * - `env` is `CONTAINER_ENV` (no MASTER_KEY); `masterKeyEnvFileHostPath`\n * bind-mount carries the secret.\n * - `routing[]` lists the seal-key-server entrypoint; the spec returned has\n * NO `ports:` field (it's not modelled). */\nexport const buildKeyServerSpec = (inputs: KeyServerSpecInputs): KeyServerContainerSpec => {\n\tconst masterKeyEnvFileHostPath = `${inputs.servicePath}/${MASTER_KEY_ENVFILE_BASENAME}`;\n\tconst configHostPath = `${inputs.servicePath}/${KEY_SERVER_CONFIG_BASENAME}`;\n\tconst runtimeRootHostPath = dirname(dirname(inputs.servicePath));\n\tconst serviceDirName = basename(inputs.servicePath);\n\tconst configContainerPath = `${INSIDE_RUNTIME_ROOT}/seal/${serviceDirName}/${KEY_SERVER_CONFIG_BASENAME}`;\n\tconst masterKeyEnvFileContainerPath = `${INSIDE_RUNTIME_ROOT}/seal/${serviceDirName}/${MASTER_KEY_ENVFILE_BASENAME}`;\n\tvoid inputs.routedHostname; // flows through routedUrl\n\treturn {\n\t\timage: inputs.image,\n\t\tcontainerName: inputs.containerName,\n\t\tlabels: inputs.labels,\n\t\tconfigHostPath,\n\t\tmasterKeyEnvFileHostPath,\n\t\truntimeRootHostPath,\n\t\tconfigContainerPath,\n\t\tmasterKeyEnvFileContainerPath,\n\t\tconfigFingerprint: inputs.configFingerprint,\n\t\tnetwork: inputs.suiNetwork,\n\t\trouting: [\n\t\t\t{\n\t\t\t\tname: SEAL_KEY_SERVER_ENDPOINT_NAME,\n\t\t\t\tentrypoint: SEAL_KEY_SERVER_ENDPOINT_NAME,\n\t\t\t\tservicePort: DEFAULT_KEY_SERVER_PORT,\n\t\t\t},\n\t\t],\n\t\troutedUrl: inputs.routedUrl,\n\t\treadyTimeoutMs: inputs.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS,\n\t\tstopGraceSeconds: 15,\n\t\tcontainerPort: DEFAULT_KEY_SERVER_PORT,\n\t};\n};\n\nexport const buildKeyServerEnsureContainerSpec = (\n\tspec: KeyServerContainerSpec,\n): EnsureContainerSpec => ({\n\tname: spec.containerName,\n\timage: spec.image,\n\tlabels: spec.labels,\n\trecreate: 'on-config-change',\n\tconfigHash: [\n\t\t'seal-key-server',\n\t\t`runtime=${spec.runtimeRootHostPath}`,\n\t\t`config=${spec.configContainerPath}`,\n\t\t`master=${spec.masterKeyEnvFileContainerPath}`,\n\t\t`content=${spec.configFingerprint}`,\n\t\t`network=${spec.network}`,\n\t].join('|'),\n\t// Distilled-doc invariant #3 — MASTER_KEY is NOT here.\n\t// The bind-mounted env-file is sourced by the entrypoint\n\t// shell BEFORE the daemon exec. See file header on the\n\t// L1 `envFiles:` gap.\n\tenv: {\n\t\t...CONTAINER_ENV,\n\t\tCONFIG_PATH: spec.configContainerPath,\n\t\tMASTER_KEY_ENVFILE: spec.masterKeyEnvFileContainerPath,\n\t},\n\tstopGraceSeconds: spec.stopGraceSeconds,\n\tnetworkAttach: [spec.network],\n\t// Distilled-doc invariant #5 — `ports` intentionally absent.\n\textraHosts: HOST_GATEWAY_EXTRA_HOSTS,\n\tmounts: [\n\t\t{\n\t\t\tsource: spec.runtimeRootHostPath,\n\t\t\ttarget: INSIDE_RUNTIME_ROOT,\n\t\t\treadonly: true,\n\t\t},\n\t],\n});\n\n// ---------------------------------------------------------------------------\n// Start procedure — real ContainerRuntime wiring\n// ---------------------------------------------------------------------------\n\n/** Start the long-running key-server container.\n *\n * Wiring:\n *\n * 1. `runtime.ensureContainer` — content-addressed image, label\n * tuple, recreate-on-config-change. Two bind mounts: the\n * rendered yaml (read-only) + the master-key env-file\n * (read-only). NO `ports:` — Traefik dispatches by Host:\n * header on the well-known `seal-key-server` entrypoint port.\n * 2. In-container ready probe via `runtime.exec` — issues an\n * HTTP GET against `http://127.0.0.1:2024/health`. Bounded\n * retries until `readyTimeoutMs`. We shell out to `curl`\n * (present in the vendored `debian:bookworm-slim` base) +\n * fall back to `nc -z` for the stub image which doesn't\n * carry curl. Both probes hit the same socket; curl\n * additionally confirms the binary has parsed CONFIG_PATH\n * and is serving the upstream's `/health` route (returns\n * `{name,version,status:\"up\"}` once boot completes —\n * distilled-doc §\"Container start + ready\").\n *\n * Stop semantics: scope-close runs `ensureContainer`'s finalizer\n * which calls `docker stop` with the Seal-specific grace window. */\nexport const startKeyServer = (\n\truntime: ContainerRuntime,\n\tspec: KeyServerContainerSpec,\n\tname: string,\n): Effect.Effect<{ readonly containerName: string }, SealError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst ensureSpec = buildKeyServerEnsureContainerSpec(spec);\n\t\tconst { labels, ...containerSpec } = ensureSpec;\n\t\tconst handle: ContainerHandle = yield* ensureManagedContainer({\n\t\t\truntime,\n\t\t\tlabels,\n\t\t\tspec: containerSpec,\n\t\t\tmapError: (cause) =>\n\t\t\t\tsealError('container', {\n\t\t\t\t\tname,\n\t\t\t\t\tmessage: `seal key-server (name=${spec.containerName}) ensureContainer failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t}),\n\t\t});\n\n\t\t// Exec-based ready probe — distilled-doc §\"Container start +\n\t\t// ready\". The vendored debian:bookworm-slim base ships\n\t\t// `curl`; the e2e stub image (alpine) ships busybox `nc`. We\n\t\t// probe with curl first (real `/health` round-trip — confirms\n\t\t// the daemon parsed CONFIG_PATH AND bound the listener) and\n\t\t// fall back to `nc -z` (TCP-only — confirms only the socket\n\t\t// is listening). One of the two MUST succeed on a healthy\n\t\t// container.\n\t\t//\n\t\t// `/health` returns `{name, version, status: \"up\"}` once the\n\t\t// binary finishes config + master-key load. Pre-boot we\n\t\t// expect connection-refused → curl returns non-zero, retry.\n\t\tconst directProbeUrl = `http://127.0.0.1:${spec.containerPort}/health`;\n\t\tyield* waitForProbe({\n\t\t\tlabel: `seal.key-server.${name}`,\n\t\t\ttimeoutMs: spec.readyTimeoutMs,\n\t\t\tintervalMs: READY_PROBE_INTERVAL_MS,\n\t\t\tprobe: () =>\n\t\t\t\truntime\n\t\t\t\t\t.exec(handle, [\n\t\t\t\t\t\t'sh',\n\t\t\t\t\t\t'-c',\n\t\t\t\t\t\t`(command -v curl >/dev/null 2>&1 && ` +\n\t\t\t\t\t\t\t`curl -fsS -m 2 ${directProbeUrl} >/dev/null) ` +\n\t\t\t\t\t\t\t`|| nc -z 127.0.0.1 ${spec.containerPort} ` +\n\t\t\t\t\t\t\t`|| exit 1`,\n\t\t\t\t\t])\n\t\t\t\t\t.pipe(Effect.map(exitCodeProbeResult)),\n\t\t}).pipe(\n\t\t\tEffect.mapError((cause) => {\n\t\t\t\tif (cause instanceof ProbeTimeoutError) {\n\t\t\t\t\treturn sealError('ready', {\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t`seal key-server never became ready within ${spec.readyTimeoutMs}ms ` +\n\t\t\t\t\t\t\t`(directProbeUrl=${directProbeUrl}, routedUrl=${spec.routedUrl})`,\n\t\t\t\t\t\tcause: cause.lastError ?? cause.lastNotReady ?? cause,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn sealError('ready', {\n\t\t\t\t\tname,\n\t\t\t\t\tmessage: `seal key-server ready-probe exec failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t});\n\t\t\t}),\n\t\t);\n\n\t\treturn { containerName: spec.containerName };\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.seal.keyServer.start', {\n\t\t\tattributes: {\n\t\t\t\t'seal.name': name,\n\t\t\t\t'seal.containerName': spec.containerName,\n\t\t\t\t'seal.routedUrl': spec.routedUrl,\n\t\t\t},\n\t\t}),\n\t);\n"],"mappings":";;;;;;;;;AAsEA,MAAa,qBAAqB;;;;AAKlC,MAAa,4BAA4B;AAEzC,MAAM,sBAAsB;;;;AAK5B,MAAa,gBAAkD;CAC9D,aAAa;CACb,oBAAoB;CACpB,UAAU;CACV;AAED,MAAa,2BAA6D,EACzE,wBAAwB,gBACxB;AAED,MAAa,wBAAwB,KAAa,OAAe,aAChE,YAAY,IAAI,GAAG,MAAM,QAAQ,SAAS;;;AAU3C,MAAa,0BAA0B,aAA0C;CAChF,MAAM,MAAM,GAAG,SAAS,IAAI,IAAI,SAAS,MAAM,IAAI,SAAS,SAAS;CACrE,IAAI,OAAO;AACX,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK,GAAG;AACvC,UAAQ,IAAI,WAAW,EAAE;AACzB,SAAO,KAAK,KAAK,MAAM,SAAW,KAAK;;CAExC,MAAM,SAAS,QAAQ,KAAK;AAG5B,QAAO,MAFa,MAAM,KAAK,MAAM,SAAS,IAAI,CAEzB,GADN,SAAS;;AAI7B,MAAa,yBACZ,MACA,kBACqE;CACrE,GAAG;CACH,QAAQ,GAAG,aAAa;CACxB,SAAS,GAAG,aAAa;CACzB;;AAGD,MAAM,0BAA0B;;;;;;;;;AAgFhC,MAAa,sBAAsB,WAAwD;CAC1F,MAAM,2BAA2B,GAAG,OAAO,YAAY,GAAG;CAC1D,MAAM,iBAAiB,GAAG,OAAO,YAAY,GAAG;CAChD,MAAM,sBAAsB,QAAQ,QAAQ,OAAO,YAAY,CAAC;CAChE,MAAM,iBAAiB,SAAS,OAAO,YAAY;CACnD,MAAM,sBAAsB,GAAG,oBAAoB,QAAQ,eAAe,GAAG;CAC7E,MAAM,gCAAgC,GAAG,oBAAoB,QAAQ,eAAe,GAAG;AAClF,QAAO;AACZ,QAAO;EACN,OAAO,OAAO;EACd,eAAe,OAAO;EACtB,QAAQ,OAAO;EACf;EACA;EACA;EACA;EACA;EACA,mBAAmB,OAAO;EAC1B,SAAS,OAAO;EAChB,SAAS,CACR;GACC,MAAM;GACN,YAAY;GACZ,aAAa;GACb,CACD;EACD,WAAW,OAAO;EAClB,gBAAgB,OAAO,kBAAA;EACvB,kBAAkB;EAClB,eAAe;EACf;;AAGF,MAAa,qCACZ,UAC0B;CAC1B,MAAM,KAAK;CACX,OAAO,KAAK;CACZ,QAAQ,KAAK;CACb,UAAU;CACV,YAAY;EACX;EACA,WAAW,KAAK;EAChB,UAAU,KAAK;EACf,UAAU,KAAK;EACf,WAAW,KAAK;EAChB,WAAW,KAAK;EAChB,CAAC,KAAK,IAAI;CAKX,KAAK;EACJ,GAAG;EACH,aAAa,KAAK;EAClB,oBAAoB,KAAK;EACzB;CACD,kBAAkB,KAAK;CACvB,eAAe,CAAC,KAAK,QAAQ;CAE7B,YAAY;CACZ,QAAQ,CACP;EACC,QAAQ,KAAK;EACb,QAAQ;EACR,UAAU;EACV,CACD;CACD;;;;;;;;;;;;;;;;;;;;;;;AA4BD,MAAa,kBACZ,SACA,MACA,SAEA,OAAO,IAAI,aAAa;CAEvB,MAAM,EAAE,QAAQ,GAAG,kBADA,kCAAkC,KACN;CAC/C,MAAM,SAA0B,OAAO,uBAAuB;EAC7D;EACA;EACA,MAAM;EACN,WAAW,UACV,UAAU,aAAa;GACtB;GACA,SAAS,yBAAyB,KAAK,cAAc,4BAA4B,MAAM,OAAO,IAAI,MAAM;GACxG;GACA,CAAC;EACH,CAAC;CAcF,MAAM,iBAAiB,oBAAoB,KAAK,cAAc;AAC9D,QAAO,aAAa;EACnB,OAAO,mBAAmB;EAC1B,WAAW,KAAK;EAChB,YAAY;EACZ,aACC,QACE,KAAK,QAAQ;GACb;GACA;GACA,sDACmB,eAAe,kCACX,KAAK,cAAc;GAE1C,CAAC,CACD,KAAK,OAAO,IAAI,oBAAoB,CAAC;EACxC,CAAC,CAAC,KACF,OAAO,UAAU,UAAU;AAC1B,MAAI,iBAAiB,kBACpB,QAAO,UAAU,SAAS;GACzB;GACA,SACC,6CAA6C,KAAK,eAAe,qBAC9C,eAAe,cAAc,KAAK,UAAU;GAChE,OAAO,MAAM,aAAa,MAAM,gBAAgB;GAChD,CAAC;AAEH,SAAO,UAAU,SAAS;GACzB;GACA,SAAS,4CAA4C,MAAM,OAAO,IAAI,MAAM;GAC5E;GACA,CAAC;GACD,CACF;AAED,QAAO,EAAE,eAAe,KAAK,eAAe;EAC3C,CAAC,KACF,OAAO,SAAS,wCAAwC,EACvD,YAAY;CACX,aAAa;CACb,sBAAsB,KAAK;CAC3B,kBAAkB,KAAK;CACvB,EACD,CAAC,CACF"}
1
+ {"version":3,"file":"key-server.mjs","names":[],"sources":["../../../src/plugins/seal/key-server.ts"],"sourcesContent":["// Seal plugin — long-running key-server container lifecycle.\n//\n// Distilled-doc invariants pinned by this file:\n//\n// #1 (KeyServer.url == routed hostname): the URL handed to the\n// on-chain Move call MUST equal the routed hostname stamped on\n// the `seal-key-server` route. We resolve the URL ONCE via the\n// router (see `routable.ts`) and pipe the same value into both\n// the Move register pass (`deploy.ts` + `registry-publish.ts`)\n// and this file's container spec.\n//\n// #3 (env-file not -e MASTER_KEY=…): the container is launched\n// with `envFiles: [<masterKeyEnvFile>]` and a `env:` map that\n// does NOT contain `MASTER_KEY`. Distilled doc §Hard\n// requirements #3 — the inline form surfaces the key in host\n// process env + docker inspect output.\n//\n// IMPLEMENTATION CONSTRAINT: the L1 `EnsureContainerSpec`\n// contract today does NOT expose an `envFiles:` slot — only\n// `env:`. We work around this by bind-mounting the env-file\n// into the container under a stack-root bind mount; the cargo\n// image's entrypoint shell (see Hard requirement #7) is\n// responsible for `set -a; . \"$MASTER_KEY_ENVFILE\"; set +a`\n// BEFORE exec'ing the daemon, so the secret never appears in\n// `docker inspect`. ARCHITECTURE REVISION TRACKED: add `envFiles`\n// to `EnsureContainerSpec`.\n//\n// #5 (NO host-port publish): the `ports:` field is INTENTIONALLY\n// absent from the `EnsureContainerSpec` we pass to the runtime.\n// Traefik dispatches by Host: header from the well-known router\n// entrypoint `seal-key-server`.\n//\n// #7 (signal-forwarding entrypoint shell): the cargo-built image\n// embeds the entrypoint shell that traps SIGTERM and forwards\n// SIGTERM to the key-server child. Distilled doc §Hard\n// requirements #21. The image declares the right entrypoint;\n// this file does NOT re-declare it.\n\nimport { Effect, type Scope } from 'effect';\nimport { basename, dirname, relative } from 'node:path';\n\nimport type {\n\tContainerHandle,\n\tContainerRuntime,\n\tEnsureContainerSpec,\n\tImageRef,\n} from '../../contracts/container-runtime.ts';\nimport type { ContainerLabelTuple } from '../../contracts/snapshotable.ts';\nimport {\n\tProbeTimeoutError,\n\texitCodeProbeResult,\n\twaitForProbe,\n} from '../../substrate/runtime/probes.ts';\nimport { ensureManagedContainer } from '../../substrate/runtime/managed-container.ts';\nimport { HOST_GATEWAY_EXTRA_HOSTS } from '../../substrate/runtime/host-gateway.ts';\nimport { deriveSubnetPrefix } from '../../substrate/runtime/subnet-broker.ts';\nimport { isSealError, sealError, type SealError } from './errors.ts';\nimport { KEY_SERVER_CONFIG_BASENAME, MASTER_KEY_ENVFILE_BASENAME } from './keygen.ts';\nimport { DEFAULT_KEY_SERVER_PORT, SEAL_KEY_SERVER_ENDPOINT_NAME } from './routable.ts';\nimport { SealSpans } from './spans.ts';\n\nexport { DEFAULT_KEY_SERVER_PORT } from './routable.ts';\n\n// ---------------------------------------------------------------------------\n// Constants — mirror v3 `seal/internal.ts:102-103`\n// ---------------------------------------------------------------------------\n\n/** Default `/health` probe timeout. */\nexport const DEFAULT_READY_TIMEOUT_MS = 60_000 as const;\n\n/** Inside-container config path. The binary reads `CONFIG_PATH` to\n * locate the rendered yaml. */\nexport const INSIDE_CONFIG_PATH = '/etc/seal/key-server-config.yaml' as const;\n\n/** Inside-container master-key env-file path. The entrypoint shell\n * sources this before exec'ing the daemon (Hard requirement #3 +\n * #7). */\nexport const INSIDE_MASTER_KEY_ENVFILE = '/etc/seal/master-key.env' as const;\n\nconst INSIDE_RUNTIME_ROOT = '/devstack/runtime' as const;\n\n/** Container-side env defaults. NB: `MASTER_KEY` is NOT here — it\n * flows via the bind-mounted env-file sourced by the entrypoint\n * shell. Distilled-doc invariant #3. */\nexport const CONTAINER_ENV: Readonly<Record<string, string>> = {\n\tCONFIG_PATH: INSIDE_CONFIG_PATH,\n\tMASTER_KEY_ENVFILE: INSIDE_MASTER_KEY_ENVFILE,\n\tRUST_LOG: 'info',\n};\n\nexport { HOST_GATEWAY_EXTRA_HOSTS };\n\nexport const buildSealNetworkName = (app: string, stack: string, sealName: string): string =>\n\t`devstack-${app}-${stack}-seal-${sealName}-net`;\n\nexport interface SealNetworkIdentity {\n\treadonly app: string;\n\treadonly stack: string;\n\treadonly sealName: string;\n}\n\n/** Seal's key-server network gets a deterministic /24 so repeated\n * local runs do not consume Docker's default bridge address pools.\n * Seal claims the `10.128.*` – `10.191.*` band; see\n * substrate/runtime/subnet-broker.ts for the algorithm and band\n * coordination with walrus. */\nexport const deriveSealSubnetPrefix = (identity: SealNetworkIdentity): string =>\n\tderiveSubnetPrefix(`${identity.app}\\0${identity.stack}\\0${identity.sealName}\\0seal`, 128);\n\n/** Per-probe interval inside the bounded retry. */\nconst READY_PROBE_INTERVAL_MS = 500;\n\n// ---------------------------------------------------------------------------\n// Spec shape\n// ---------------------------------------------------------------------------\n\n/** The container spec produced for the long-running key-server. This\n * is the substrate-blind value the ContainerRuntime adapter\n * consumes. */\nexport interface KeyServerContainerSpec {\n\t/** Image ref from the Seal image resolver. */\n\treadonly image: ImageRef;\n\t/** Composed container name (substrate folds `<app>-<stack>-…`). */\n\treadonly containerName: string;\n\t/** Label tuple — drives the snapshot orchestrator's filter +\n\t * `inspectByLabels`. */\n\treadonly labels: ContainerLabelTuple;\n\t/** Mount source on host. Docker Desktop can reject freshly-created\n\t * nested file/leaf-directory bind sources even when a parent mount\n\t * can see them, so key-server mounts the stack root and points the\n\t * entrypoint at the config/envfile inside that mount.\n\t *\n\t * The rendered config + master-key envfile do not appear as their\n\t * own fields on this spec — they live under `servicePath` inside\n\t * `runtimeRootHostPath`. The single host mount publishes both into\n\t * the container; `configContainerPath` /\n\t * `masterKeyEnvFileContainerPath` give the entrypoint shell the\n\t * inside-container locations. The spec-builder asserts the\n\t * relationship between `servicePath` and `runtimeRootHostPath`. */\n\treadonly runtimeRootHostPath: string;\n\treadonly configContainerPath: string;\n\treadonly masterKeyEnvFileContainerPath: string;\n\t/** Fingerprint of config contents that affect key-server boot. */\n\treadonly configFingerprint: string;\n\t/** Inner docker network for sui DNS resolution. */\n\treadonly network: string;\n\t/** Router routing spec — Traefik file-provider stamped per\n\t * container. Distilled-doc invariant #5 (no host-port publish). */\n\treadonly routing: ReadonlyArray<{\n\t\treadonly name: string;\n\t\treadonly entrypoint: string;\n\t\treadonly servicePort: number;\n\t}>;\n\t/** Routed URL — `<routedUrl>/health` is what the ready probe\n\t * would hit if/when an HTTP probe contract lands. Today we use\n\t * an exec-based probe (see `startKeyServer`). */\n\treadonly routedUrl: string;\n\t/** Timeout for the ready probe. */\n\treadonly readyTimeoutMs: number;\n\t/** Graceful stop deadline. Distilled-doc invariant #21 — the\n\t * entrypoint shell forwards Docker's SIGTERM to the key-server. */\n\treadonly stopGraceSeconds: number;\n\t/** In-container port the daemon binds. */\n\treadonly containerPort: number;\n}\n\n// ---------------------------------------------------------------------------\n// Spec builder\n// ---------------------------------------------------------------------------\n\n/** Inputs to assemble the container spec. */\nexport interface KeyServerSpecInputs {\n\treadonly name: string;\n\treadonly image: ImageRef;\n\treadonly containerName: string;\n\treadonly labels: ContainerLabelTuple;\n\treadonly suiNetwork: string;\n\treadonly servicePath: string;\n\treadonly configFingerprint: string;\n\treadonly routedHostname: string;\n\treadonly routedUrl: string;\n\treadonly readyTimeoutMs?: number;\n}\n\n/** Build the container spec. Distilled-doc invariants #1, #3, #5\n * encoded here:\n *\n * - `routedUrl` is the SAME value the on-chain Move call registers.\n * - `env` is `CONTAINER_ENV` (no MASTER_KEY); the bind-mounted env-file\n * at `<servicePath>/master-key.env` (sourced by the entrypoint shell)\n * carries the secret.\n * - `routing[]` lists the seal-key-server entrypoint; the spec returned has\n * NO `ports:` field (it's not modelled).\n *\n * Asserts at spec-build time that the substrate-provided `servicePath`\n * lives under the derived `runtimeRootHostPath`. The single host\n * mount publishes the entire `runtimeRootHostPath` subtree; if the\n * caller ever drifts `servicePath` outside that subtree, the\n * rendered config + master-key envfile silently would not reach the\n * container — surface that drift here instead. */\nexport const buildKeyServerSpec = (inputs: KeyServerSpecInputs): KeyServerContainerSpec => {\n\tconst runtimeRootHostPath = dirname(dirname(inputs.servicePath));\n\tconst rel = relative(runtimeRootHostPath, inputs.servicePath);\n\tif (rel.length === 0 || rel.startsWith('..') || runtimeRootHostPath === '/') {\n\t\t// `runtimeRootHostPath === '/'` catches the degenerate case\n\t\t// where the `dirname(dirname(...))` walk-up collapses to the\n\t\t// host root (e.g. servicePath shorter than 3 segments) — that\n\t\t// would bind-mount the entire host into the container. Same\n\t\t// family of bug as the walrus deploy-paths walk-up.\n\t\tthrow new Error(\n\t\t\t`buildKeyServerSpec: servicePath (${inputs.servicePath}) must be a descendant of ` +\n\t\t\t\t`runtimeRootHostPath (${runtimeRootHostPath}) AND runtimeRootHostPath must not ` +\n\t\t\t\t`collapse to '/'. The single bind-mount publishes runtimeRootHostPath into the ` +\n\t\t\t\t`container — if servicePath drifts outside it, the rendered config + master-key ` +\n\t\t\t\t`envfile would silently not reach the container; if the root collapses to '/', the ` +\n\t\t\t\t`bind would publish the host root. Cross-check the substrate's seal servicePath layout.`,\n\t\t);\n\t}\n\tconst serviceDirName = basename(inputs.servicePath);\n\tconst configContainerPath = `${INSIDE_RUNTIME_ROOT}/seal/${serviceDirName}/${KEY_SERVER_CONFIG_BASENAME}`;\n\tconst masterKeyEnvFileContainerPath = `${INSIDE_RUNTIME_ROOT}/seal/${serviceDirName}/${MASTER_KEY_ENVFILE_BASENAME}`;\n\tvoid inputs.routedHostname; // flows through routedUrl\n\treturn {\n\t\timage: inputs.image,\n\t\tcontainerName: inputs.containerName,\n\t\tlabels: inputs.labels,\n\t\truntimeRootHostPath,\n\t\tconfigContainerPath,\n\t\tmasterKeyEnvFileContainerPath,\n\t\tconfigFingerprint: inputs.configFingerprint,\n\t\tnetwork: inputs.suiNetwork,\n\t\trouting: [\n\t\t\t{\n\t\t\t\tname: SEAL_KEY_SERVER_ENDPOINT_NAME,\n\t\t\t\tentrypoint: SEAL_KEY_SERVER_ENDPOINT_NAME,\n\t\t\t\tservicePort: DEFAULT_KEY_SERVER_PORT,\n\t\t\t},\n\t\t],\n\t\troutedUrl: inputs.routedUrl,\n\t\treadyTimeoutMs: inputs.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS,\n\t\tstopGraceSeconds: 15,\n\t\tcontainerPort: DEFAULT_KEY_SERVER_PORT,\n\t};\n};\n\nexport const buildKeyServerEnsureContainerSpec = (\n\tspec: KeyServerContainerSpec,\n): EnsureContainerSpec => ({\n\tname: spec.containerName,\n\timage: spec.image,\n\tlabels: spec.labels,\n\trecreate: 'on-config-change',\n\tconfigHash: [\n\t\t'seal-key-server',\n\t\t`runtime=${spec.runtimeRootHostPath}`,\n\t\t`config=${spec.configContainerPath}`,\n\t\t`master=${spec.masterKeyEnvFileContainerPath}`,\n\t\t`content=${spec.configFingerprint}`,\n\t\t`network=${spec.network}`,\n\t].join('|'),\n\t// Distilled-doc invariant #3 — MASTER_KEY is NOT here.\n\t// The bind-mounted env-file is sourced by the entrypoint\n\t// shell BEFORE the daemon exec. See file header on the\n\t// L1 `envFiles:` gap.\n\tenv: {\n\t\t...CONTAINER_ENV,\n\t\tCONFIG_PATH: spec.configContainerPath,\n\t\tMASTER_KEY_ENVFILE: spec.masterKeyEnvFileContainerPath,\n\t},\n\tstopGraceSeconds: spec.stopGraceSeconds,\n\tnetworkAttach: [spec.network],\n\t// Distilled-doc invariant #5 — `ports` intentionally absent.\n\textraHosts: HOST_GATEWAY_EXTRA_HOSTS,\n\tmounts: [\n\t\t{\n\t\t\tsource: spec.runtimeRootHostPath,\n\t\t\ttarget: INSIDE_RUNTIME_ROOT,\n\t\t\treadonly: true,\n\t\t},\n\t],\n});\n\n// ---------------------------------------------------------------------------\n// Start procedure — real ContainerRuntime wiring\n// ---------------------------------------------------------------------------\n\n/** Start the long-running key-server container.\n *\n * Wiring:\n *\n * 1. `runtime.ensureContainer` — content-addressed image, label\n * tuple, recreate-on-config-change. Two bind mounts: the\n * rendered yaml (read-only) + the master-key env-file\n * (read-only). NO `ports:` — Traefik dispatches by Host:\n * header on the well-known `seal-key-server` entrypoint port.\n * 2. In-container ready probe via `runtime.exec` — issues an\n * HTTP GET against `http://127.0.0.1:2024/health`. Bounded\n * retries until `readyTimeoutMs`. We shell out to `curl`\n * (present in the vendored `debian:bookworm-slim` base) +\n * fall back to `nc -z` for the stub image which doesn't\n * carry curl. Both probes hit the same socket; curl\n * additionally confirms the binary has parsed CONFIG_PATH\n * and is serving the upstream's `/health` route (returns\n * `{name,version,status:\"up\"}` once boot completes —\n * distilled-doc §\"Container start + ready\").\n *\n * Stop semantics: scope-close runs `ensureContainer`'s finalizer\n * which calls `docker stop` with the Seal-specific grace window. */\nexport const startKeyServer = (\n\truntime: ContainerRuntime,\n\tspec: KeyServerContainerSpec,\n\tname: string,\n): Effect.Effect<{ readonly containerName: string }, SealError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst ensureSpec = buildKeyServerEnsureContainerSpec(spec);\n\t\tconst { labels, ...containerSpec } = ensureSpec;\n\t\tconst handle: ContainerHandle = yield* ensureManagedContainer({\n\t\t\truntime,\n\t\t\tlabels,\n\t\t\tspec: containerSpec,\n\t\t\tmapError: (cause) =>\n\t\t\t\tsealError('container', {\n\t\t\t\t\tname,\n\t\t\t\t\tmessage: `seal key-server (name=${spec.containerName}) ensureContainer failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t}),\n\t\t});\n\n\t\t// Exec-based ready probe — distilled-doc §\"Container start +\n\t\t// ready\". The vendored debian:bookworm-slim base ships\n\t\t// `curl`; the e2e stub image (alpine) ships busybox `nc`. We\n\t\t// probe with curl first (real `/health` round-trip — confirms\n\t\t// the daemon parsed CONFIG_PATH AND bound the listener) and\n\t\t// fall back to `nc -z` (TCP-only — confirms only the socket\n\t\t// is listening). One of the two MUST succeed on a healthy\n\t\t// container.\n\t\t//\n\t\t// `/health` returns `{name, version, status: \"up\"}` once the\n\t\t// binary finishes config + master-key load. Pre-boot we\n\t\t// expect connection-refused → curl returns non-zero, retry.\n\t\tconst directProbeUrl = `http://127.0.0.1:${spec.containerPort}/health`;\n\t\tyield* waitForProbe({\n\t\t\tlabel: `seal.key-server.${name}`,\n\t\t\ttimeoutMs: spec.readyTimeoutMs,\n\t\t\tintervalMs: READY_PROBE_INTERVAL_MS,\n\t\t\tprobe: () =>\n\t\t\t\truntime\n\t\t\t\t\t.exec(handle, [\n\t\t\t\t\t\t'sh',\n\t\t\t\t\t\t'-c',\n\t\t\t\t\t\t`(command -v curl >/dev/null 2>&1 && ` +\n\t\t\t\t\t\t\t`curl -fsS -m 2 ${directProbeUrl} >/dev/null) ` +\n\t\t\t\t\t\t\t`|| nc -z 127.0.0.1 ${spec.containerPort} ` +\n\t\t\t\t\t\t\t`|| exit 1`,\n\t\t\t\t\t])\n\t\t\t\t\t.pipe(Effect.map(exitCodeProbeResult)),\n\t\t}).pipe(\n\t\t\tEffect.mapError((cause) => {\n\t\t\t\tif (cause instanceof ProbeTimeoutError) {\n\t\t\t\t\t// Unwrap so we don't double-wrap an inner `SealError`:\n\t\t\t\t\t// if `lastError` was itself a `SealError` (e.g. an\n\t\t\t\t\t// upstream probe site that already promoted to typed),\n\t\t\t\t\t// re-wrapping inside `sealError('ready', …)` would\n\t\t\t\t\t// leave the cause walker chasing two layers. The\n\t\t\t\t\t// outer `passthroughOrWrap.for<SealError>` in\n\t\t\t\t\t// `index.ts` strips one such layer, but the direct\n\t\t\t\t\t// `sealError('ready', …)` path doesn't — collapse\n\t\t\t\t\t// here at the source.\n\t\t\t\t\tconst inner = cause.lastError ?? cause.lastNotReady ?? cause;\n\t\t\t\t\tif (isSealError(inner)) {\n\t\t\t\t\t\treturn inner;\n\t\t\t\t\t}\n\t\t\t\t\treturn sealError('ready', {\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t`seal key-server never became ready within ${spec.readyTimeoutMs}ms ` +\n\t\t\t\t\t\t\t`(directProbeUrl=${directProbeUrl}, routedUrl=${spec.routedUrl})`,\n\t\t\t\t\t\tcause: inner,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn sealError('ready', {\n\t\t\t\t\tname,\n\t\t\t\t\tmessage: `seal key-server ready-probe exec failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\tcause,\n\t\t\t\t});\n\t\t\t}),\n\t\t);\n\n\t\treturn { containerName: spec.containerName };\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.seal.keyServer.start', {\n\t\t\tattributes: {\n\t\t\t\t[SealSpans.name]: name,\n\t\t\t\t[SealSpans.containerName]: spec.containerName,\n\t\t\t\t[SealSpans.routedUrl]: spec.routedUrl,\n\t\t\t},\n\t\t}),\n\t);\n"],"mappings":";;;;;;;;;;;;AAwEA,MAAa,qBAAqB;;;;AAKlC,MAAa,4BAA4B;AAEzC,MAAM,sBAAsB;;;;AAK5B,MAAa,gBAAkD;CAC9D,aAAa;CACb,oBAAoB;CACpB,UAAU;CACV;AAID,MAAa,wBAAwB,KAAa,OAAe,aAChE,YAAY,IAAI,GAAG,MAAM,QAAQ,SAAS;;;;;;AAa3C,MAAa,0BAA0B,aACtC,mBAAmB,GAAG,SAAS,IAAI,IAAI,SAAS,MAAM,IAAI,SAAS,SAAS,SAAS,IAAI;;AAG1F,MAAM,0BAA0B;;;;;;;;;;;;;;;;;AA0FhC,MAAa,sBAAsB,WAAwD;CAC1F,MAAM,sBAAsB,QAAQ,QAAQ,OAAO,YAAY,CAAC;CAChE,MAAM,MAAM,SAAS,qBAAqB,OAAO,YAAY;AAC7D,KAAI,IAAI,WAAW,KAAK,IAAI,WAAW,KAAK,IAAI,wBAAwB,IAMvE,OAAM,IAAI,MACT,oCAAoC,OAAO,YAAY,iDAC9B,oBAAoB,0WAK7C;CAEF,MAAM,iBAAiB,SAAS,OAAO,YAAY;CACnD,MAAM,sBAAsB,GAAG,oBAAoB,QAAQ,eAAe,GAAG;CAC7E,MAAM,gCAAgC,GAAG,oBAAoB,QAAQ,eAAe,GAAG;AAClF,QAAO;AACZ,QAAO;EACN,OAAO,OAAO;EACd,eAAe,OAAO;EACtB,QAAQ,OAAO;EACf;EACA;EACA;EACA,mBAAmB,OAAO;EAC1B,SAAS,OAAO;EAChB,SAAS,CACR;GACC,MAAM;GACN,YAAY;GACZ,aAAa;GACb,CACD;EACD,WAAW,OAAO;EAClB,gBAAgB,OAAO,kBAAA;EACvB,kBAAkB;EAClB,eAAe;EACf;;AAGF,MAAa,qCACZ,UAC0B;CAC1B,MAAM,KAAK;CACX,OAAO,KAAK;CACZ,QAAQ,KAAK;CACb,UAAU;CACV,YAAY;EACX;EACA,WAAW,KAAK;EAChB,UAAU,KAAK;EACf,UAAU,KAAK;EACf,WAAW,KAAK;EAChB,WAAW,KAAK;EAChB,CAAC,KAAK,IAAI;CAKX,KAAK;EACJ,GAAG;EACH,aAAa,KAAK;EAClB,oBAAoB,KAAK;EACzB;CACD,kBAAkB,KAAK;CACvB,eAAe,CAAC,KAAK,QAAQ;CAE7B,YAAY;CACZ,QAAQ,CACP;EACC,QAAQ,KAAK;EACb,QAAQ;EACR,UAAU;EACV,CACD;CACD;;;;;;;;;;;;;;;;;;;;;;;AA4BD,MAAa,kBACZ,SACA,MACA,SAEA,OAAO,IAAI,aAAa;CAEvB,MAAM,EAAE,QAAQ,GAAG,kBADA,kCAAkC,KACN;CAC/C,MAAM,SAA0B,OAAO,uBAAuB;EAC7D;EACA;EACA,MAAM;EACN,WAAW,UACV,UAAU,aAAa;GACtB;GACA,SAAS,yBAAyB,KAAK,cAAc,4BAA4B,MAAM,OAAO,IAAI,MAAM;GACxG;GACA,CAAC;EACH,CAAC;CAcF,MAAM,iBAAiB,oBAAoB,KAAK,cAAc;AAC9D,QAAO,aAAa;EACnB,OAAO,mBAAmB;EAC1B,WAAW,KAAK;EAChB,YAAY;EACZ,aACC,QACE,KAAK,QAAQ;GACb;GACA;GACA,sDACmB,eAAe,kCACX,KAAK,cAAc;GAE1C,CAAC,CACD,KAAK,OAAO,IAAI,oBAAoB,CAAC;EACxC,CAAC,CAAC,KACF,OAAO,UAAU,UAAU;AAC1B,MAAI,iBAAiB,mBAAmB;GAUvC,MAAM,QAAQ,MAAM,aAAa,MAAM,gBAAgB;AACvD,OAAI,YAAY,MAAM,CACrB,QAAO;AAER,UAAO,UAAU,SAAS;IACzB;IACA,SACC,6CAA6C,KAAK,eAAe,qBAC9C,eAAe,cAAc,KAAK,UAAU;IAChE,OAAO;IACP,CAAC;;AAEH,SAAO,UAAU,SAAS;GACzB;GACA,SAAS,4CAA4C,MAAM,OAAO,IAAI,MAAM;GAC5E;GACA,CAAC;GACD,CACF;AAED,QAAO,EAAE,eAAe,KAAK,eAAe;EAC3C,CAAC,KACF,OAAO,SAAS,wCAAwC,EACvD,YAAY;EACV,UAAU,OAAO;EACjB,UAAU,gBAAgB,KAAK;EAC/B,UAAU,YAAY,KAAK;CAC5B,EACD,CAAC,CACF"}
@@ -1,5 +1,7 @@
1
1
  import { redactText } from "../../substrate/runtime/observability/redaction.mjs";
2
+ import "../../substrate/runtime/observability/index.mjs";
2
3
  import { sealError } from "./errors.mjs";
4
+ import { SealSpans } from "./spans.mjs";
3
5
  import { Duration, Effect } from "effect";
4
6
  //#region src/plugins/seal/keygen.ts
5
7
  /** Entrypoint binary inside the seal image. */
@@ -14,15 +16,20 @@ const KEY_SERVER_CONFIG_BASENAME = "key-server-config.yaml";
14
16
  * small — under 1s. 30s ceiling absorbs container startup overhead
15
17
  * on slow CI runners. */
16
18
  const KEYGEN_TIMEOUT_MS = 3e4;
17
- const MASTER_KEY_REDACTION_RULE = {
19
+ const MASTER_KEY_REDACTION_RULES = [{
18
20
  kind: "pattern",
19
21
  pattern: /^.*master[_\- ]?key.*$/gim,
20
22
  replacement: "[REDACTED master key]"
21
- };
23
+ }, {
24
+ kind: "pattern",
25
+ pattern: /(?<![0-9a-fA-F])[0-9a-fA-F]{64,}(?![0-9a-fA-F])/g,
26
+ replacement: "<REDACTED-HEX-RUN>"
27
+ }];
22
28
  /** Replace any line containing `master_key` / `master-key` / `masterkey`
23
- * (case-insensitive) with the literal `[REDACTED master key]`. Used at
24
- * every site that may surface stdout/stderr from `seal-cli`. */
25
- const redactMasterKey = (s) => redactText(s, [MASTER_KEY_REDACTION_RULE]);
29
+ * (case-insensitive) with `[REDACTED master key]`, AND any standalone
30
+ * hex run of 64+ chars with `<REDACTED-HEX-RUN>`. Used at every site
31
+ * that may surface stdout/stderr from `seal-cli`. */
32
+ const redactMasterKey = (s) => redactText(s, MASTER_KEY_REDACTION_RULES);
26
33
  /** Parse `Master key:` / `Public key:` hex lines from `seal-cli genkey`
27
34
  * stdout. Hex prefix may or may not include `0x` (we strip it).
28
35
  *
@@ -31,8 +38,8 @@ const redactMasterKey = (s) => redactText(s, [MASTER_KEY_REDACTION_RULE]);
31
38
  * stdout so a parser drift doesn't leak the master key into logs. */
32
39
  const parseSealKeygenOutput = (stdout, name) => {
33
40
  const stripHex = (s) => s.startsWith("0x") ? s.slice(2) : s;
34
- const masterMatch = stdout.match(/Master key:\s*(0x)?([0-9a-fA-F]+)/);
35
- const publicMatch = stdout.match(/Public key:\s*(0x)?([0-9a-fA-F]+)/);
41
+ const masterMatch = stdout.match(/Master key:\s*(0x)?([0-9a-fA-F]{64})\b/);
42
+ const publicMatch = stdout.match(/Public key:\s*(0x)?([0-9a-fA-F]{192})\b/);
36
43
  if (!masterMatch || !publicMatch) return Effect.fail(sealError("keygen", {
37
44
  name,
38
45
  message: "seal.keygen: could not parse seal-cli genkey output (Master key: / Public key: lines missing)",
@@ -43,14 +50,6 @@ const parseSealKeygenOutput = (stdout, name) => {
43
50
  publicKey: stripHex(publicMatch[2])
44
51
  });
45
52
  };
46
- /** Decode hex → bytes. Tolerates leading `0x`; fails on odd length. */
47
- const decodeHex = (hex) => {
48
- const stripped = hex.startsWith("0x") ? hex.slice(2) : hex;
49
- if (stripped.length % 2 !== 0) throw new Error("decodeHex: odd-length hex string");
50
- const out = new Uint8Array(stripped.length / 2);
51
- for (let i = 0; i < out.length; i++) out[i] = parseInt(stripped.slice(i * 2, i * 2 + 2), 16);
52
- return out;
53
- };
54
53
  /** Run `seal-cli genkey` inside the cargo-built seal image and
55
54
  * parse the BLS12-381 master + public keys.
56
55
  *
@@ -83,7 +82,7 @@ const runSealKeygen = (runtime, name, image) => Effect.gen(function* () {
83
82
  stderr: redactMasterKey(result.stderr)
84
83
  }));
85
84
  return yield* parseSealKeygenOutput(result.stdout, name);
86
- }).pipe(Effect.withSpan("devstack.plugin.seal.keygen.oneShot", { attributes: { "seal.name": name } }), Effect.timeoutOrElse({
85
+ }).pipe(Effect.withSpan("devstack.plugin.seal.keygen.oneShot", { attributes: { [SealSpans.name]: name } }), Effect.timeoutOrElse({
87
86
  duration: Duration.millis(KEYGEN_TIMEOUT_MS + 5e3),
88
87
  orElse: () => Effect.fail(sealError("keygen", {
89
88
  name,
@@ -91,6 +90,6 @@ const runSealKeygen = (runtime, name, image) => Effect.gen(function* () {
91
90
  }))
92
91
  }));
93
92
  //#endregion
94
- export { KEY_SERVER_CONFIG_BASENAME, MASTER_KEY_ENVFILE_BASENAME, decodeHex, runSealKeygen };
93
+ export { KEY_SERVER_CONFIG_BASENAME, MASTER_KEY_ENVFILE_BASENAME, runSealKeygen };
95
94
 
96
95
  //# sourceMappingURL=keygen.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"keygen.mjs","names":[],"sources":["../../../src/plugins/seal/keygen.ts"],"sourcesContent":["// Seal plugin — BLS12-381 keygen helpers + master-key redactor.\n//\n// Distilled-doc invariant (07-seal.md §\"Generic artifact-publisher-publish\"\n// + §Hard requirements #16): the master-key MUST be redacted from any\n// stdout/stderr that may surface in a SealError. The redactor lives\n// here as the single owner so call sites (`mode/local-keygen.ts`,\n// `key-manager.ts`) all funnel through one regex.\n//\n// The keygen pipeline is REAL — `runtime.runOneShot` against the cargo\n// image runs `seal-cli genkey`, captures stdout, parses the BLS hex\n// pair. The image itself is the seam (`SEAL_CARGO_IMAGE_OVERRIDE` env\n// — see `bootstrap-assets/cargo-image.ts`).\n\nimport { Duration, Effect, type Scope } from 'effect';\n\nimport type { ContainerRuntime, ImageRef } from '../../contracts/container-runtime.ts';\nimport { redactText, type RedactionRule } from '../../substrate/runtime/observability/index.ts';\nimport { sealError, type SealError } from './errors.ts';\n\n// ---------------------------------------------------------------------------\n// Constants — mirror v3 (`seal/internal.ts:115-149`)\n// ---------------------------------------------------------------------------\n\n/** Entrypoint binary inside the seal image. */\nexport const SEAL_KEYGEN_ENTRYPOINT = 'seal-cli';\n\n/** Args for the keygen one-shot. */\nexport const SEAL_KEYGEN_ARGS = ['genkey'] as const;\n\n/** Default master-key env-file basename inside `runtime/seal/`. */\nexport const MASTER_KEY_ENVFILE_BASENAME = 'master-key.env';\n\n/** Default key-server config yaml basename inside `runtime/seal/`. */\nexport const KEY_SERVER_CONFIG_BASENAME = 'key-server-config.yaml';\n\n/** Wall-clock timeout for the keygen one-shot. BLS12-381 keygen is\n * small — under 1s. 30s ceiling absorbs container startup overhead\n * on slow CI runners. */\nconst KEYGEN_TIMEOUT_MS = 30_000;\n\n// ---------------------------------------------------------------------------\n// PersistedBlsKeypair — the cache-stored shape\n// ---------------------------------------------------------------------------\n\n/** Two hex blobs round-tripped through the substrate StateStore. The\n * master key is the secret; the public key is on-chain in the\n * registered `KeyServer` object. Distilled-doc §\"Persistence model\"\n * + §Hard requirements #5 — chainId is folded into the cache key by\n * the ArtifactPublisher substrate. */\nexport interface PersistedBlsKeypair {\n\treadonly masterKey: string;\n\treadonly publicKey: string;\n}\n\n// ---------------------------------------------------------------------------\n// Redaction — distilled-doc invariant #16\n// ---------------------------------------------------------------------------\n\n/** Case-insensitive line-level pattern matching any `master[_-]?key`\n * mention. Mirrors v3's `MASTER_KEY_LINE_RE` (`seal/internal.ts:1343`). */\nconst MASTER_KEY_LINE_RE = /^.*master[_\\- ]?key.*$/gim;\n\nconst MASTER_KEY_REDACTION_RULE: RedactionRule = {\n\tkind: 'pattern',\n\tpattern: MASTER_KEY_LINE_RE,\n\treplacement: '[REDACTED master key]',\n};\n\n/** Replace any line containing `master_key` / `master-key` / `masterkey`\n * (case-insensitive) with the literal `[REDACTED master key]`. Used at\n * every site that may surface stdout/stderr from `seal-cli`. */\nexport const redactMasterKey = (s: string): string => redactText(s, [MASTER_KEY_REDACTION_RULE]);\n\n// ---------------------------------------------------------------------------\n// Output parser — distilled-doc §\"Helpers\"\n// ---------------------------------------------------------------------------\n\n/** Parse `Master key:` / `Public key:` hex lines from `seal-cli genkey`\n * stdout. Hex prefix may or may not include `0x` (we strip it).\n *\n * Returns a typed `PersistedBlsKeypair` on success, or fails with a\n * `SealError({phase: 'keygen'})` carrying the REDACTED tail of the\n * stdout so a parser drift doesn't leak the master key into logs. */\nexport const parseSealKeygenOutput = (\n\tstdout: string,\n\tname: string,\n): Effect.Effect<PersistedBlsKeypair, SealError> => {\n\tconst stripHex = (s: string): string => (s.startsWith('0x') ? s.slice(2) : s);\n\tconst masterMatch = stdout.match(/Master key:\\s*(0x)?([0-9a-fA-F]+)/);\n\tconst publicMatch = stdout.match(/Public key:\\s*(0x)?([0-9a-fA-F]+)/);\n\tif (!masterMatch || !publicMatch) {\n\t\treturn Effect.fail(\n\t\t\tsealError('keygen', {\n\t\t\t\tname,\n\t\t\t\tmessage:\n\t\t\t\t\t'seal.keygen: could not parse seal-cli genkey output (Master key: / Public key: lines missing)',\n\t\t\t\tstdout: redactMasterKey(stdout),\n\t\t\t}),\n\t\t);\n\t}\n\treturn Effect.succeed({\n\t\tmasterKey: stripHex(masterMatch[2]!),\n\t\tpublicKey: stripHex(publicMatch[2]!),\n\t} satisfies PersistedBlsKeypair);\n};\n\n// ---------------------------------------------------------------------------\n// Hex decode — minimal helper\n// ---------------------------------------------------------------------------\n\n/** Decode hex → bytes. Tolerates leading `0x`; fails on odd length. */\nexport const decodeHex = (hex: string): Uint8Array => {\n\tconst stripped = hex.startsWith('0x') ? hex.slice(2) : hex;\n\tif (stripped.length % 2 !== 0) {\n\t\tthrow new Error('decodeHex: odd-length hex string');\n\t}\n\tconst out = new Uint8Array(stripped.length / 2);\n\tfor (let i = 0; i < out.length; i++) {\n\t\tout[i] = parseInt(stripped.slice(i * 2, i * 2 + 2), 16);\n\t}\n\treturn out;\n};\n\n// ---------------------------------------------------------------------------\n// Real keygen one-shot\n// ---------------------------------------------------------------------------\n\n/** Run `seal-cli genkey` inside the cargo-built seal image and\n * parse the BLS12-381 master + public keys.\n *\n * Implementation:\n * 1. `runtime.runOneShot({ image, entrypoint: 'seal-cli', argv:\n * ['genkey'], timeoutMillis: 30s })` — fresh `docker run --rm`.\n * 2. Promote non-zero exit to typed SealError with REDACTED tails.\n * 3. Parse stdout via `parseSealKeygenOutput`.\n *\n * Distilled-doc invariant #16 — every stdout/stderr capture site\n * passes through `redactMasterKey` BEFORE landing in the error. The\n * parser handles the success-path; the failure path does its own\n * redact at the raise site. */\nexport const runSealKeygen = (\n\truntime: ContainerRuntime,\n\tname: string,\n\timage: ImageRef,\n): Effect.Effect<PersistedBlsKeypair, SealError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst result = yield* runtime\n\t\t\t.runOneShot({\n\t\t\t\timage,\n\t\t\t\tentrypoint: SEAL_KEYGEN_ENTRYPOINT,\n\t\t\t\targv: SEAL_KEYGEN_ARGS,\n\t\t\t\ttimeoutMillis: KEYGEN_TIMEOUT_MS,\n\t\t\t})\n\t\t\t.pipe(\n\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\tsealError('keygen', {\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tmessage: `seal-cli genkey one-shot failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\n\t\tif (result.exitCode !== 0) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tsealError('keygen', {\n\t\t\t\t\tname,\n\t\t\t\t\tmessage: `seal-cli genkey exited with code ${result.exitCode}`,\n\t\t\t\t\texitCode: result.exitCode,\n\t\t\t\t\t// Defense-in-depth — the redactor handles success-path\n\t\t\t\t\t// output (where the key is the parsed value) but the\n\t\t\t\t\t// failure path's stdout MAY also carry the key, e.g.\n\t\t\t\t\t// when stderr says \"wrote master key to <log>\".\n\t\t\t\t\tstdout: redactMasterKey(result.stdout),\n\t\t\t\t\tstderr: redactMasterKey(result.stderr),\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\treturn yield* parseSealKeygenOutput(result.stdout, name);\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.seal.keygen.oneShot', {\n\t\t\tattributes: { 'seal.name': name },\n\t\t}),\n\t\tEffect.timeoutOrElse({\n\t\t\tduration: Duration.millis(KEYGEN_TIMEOUT_MS + 5_000),\n\t\t\torElse: () =>\n\t\t\t\tEffect.fail(\n\t\t\t\t\tsealError('keygen', {\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tmessage: `seal.keygen: outer timeout ${KEYGEN_TIMEOUT_MS}ms exceeded`,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t}),\n\t);\n"],"mappings":";;;;;AAwBA,MAAa,yBAAyB;;AAGtC,MAAa,mBAAmB,CAAC,SAAS;;AAG1C,MAAa,8BAA8B;;AAG3C,MAAa,6BAA6B;;;;AAK1C,MAAM,oBAAoB;AAwB1B,MAAM,4BAA2C;CAChD,MAAM;CACN,SAAS;CACT,aAAa;CACb;;;;AAKD,MAAa,mBAAmB,MAAsB,WAAW,GAAG,CAAC,0BAA0B,CAAC;;;;;;;AAYhG,MAAa,yBACZ,QACA,SACmD;CACnD,MAAM,YAAY,MAAuB,EAAE,WAAW,KAAK,GAAG,EAAE,MAAM,EAAE,GAAG;CAC3E,MAAM,cAAc,OAAO,MAAM,oCAAoC;CACrE,MAAM,cAAc,OAAO,MAAM,oCAAoC;AACrE,KAAI,CAAC,eAAe,CAAC,YACpB,QAAO,OAAO,KACb,UAAU,UAAU;EACnB;EACA,SACC;EACD,QAAQ,gBAAgB,OAAO;EAC/B,CAAC,CACF;AAEF,QAAO,OAAO,QAAQ;EACrB,WAAW,SAAS,YAAY,GAAI;EACpC,WAAW,SAAS,YAAY,GAAI;EACpC,CAA+B;;;AAQjC,MAAa,aAAa,QAA4B;CACrD,MAAM,WAAW,IAAI,WAAW,KAAK,GAAG,IAAI,MAAM,EAAE,GAAG;AACvD,KAAI,SAAS,SAAS,MAAM,EAC3B,OAAM,IAAI,MAAM,mCAAmC;CAEpD,MAAM,MAAM,IAAI,WAAW,SAAS,SAAS,EAAE;AAC/C,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,IAC/B,KAAI,KAAK,SAAS,SAAS,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,EAAE,GAAG;AAExD,QAAO;;;;;;;;;;;;;;;AAoBR,MAAa,iBACZ,SACA,MACA,UAEA,OAAO,IAAI,aAAa;CACvB,MAAM,SAAS,OAAO,QACpB,WAAW;EACX;EACA,YAAY;EACZ,MAAM;EACN,eAAe;EACf,CAAC,CACD,KACA,OAAO,OAAO,UACb,OAAO,KACN,UAAU,UAAU;EACnB;EACA,SAAS,oCAAoC,MAAM,OAAO,IAAI,MAAM;EACpE;EACA,CAAC,CACF,CACD,CACD;AAEF,KAAI,OAAO,aAAa,EACvB,QAAO,OAAO,OAAO,KACpB,UAAU,UAAU;EACnB;EACA,SAAS,oCAAoC,OAAO;EACpD,UAAU,OAAO;EAKjB,QAAQ,gBAAgB,OAAO,OAAO;EACtC,QAAQ,gBAAgB,OAAO,OAAO;EACtC,CAAC,CACF;AAGF,QAAO,OAAO,sBAAsB,OAAO,QAAQ,KAAK;EACvD,CAAC,KACF,OAAO,SAAS,uCAAuC,EACtD,YAAY,EAAE,aAAa,MAAM,EACjC,CAAC,EACF,OAAO,cAAc;CACpB,UAAU,SAAS,OAAO,oBAAoB,IAAM;CACpD,cACC,OAAO,KACN,UAAU,UAAU;EACnB;EACA,SAAS,8BAA8B,kBAAkB;EACzD,CAAC,CACF;CACF,CAAC,CACF"}
1
+ {"version":3,"file":"keygen.mjs","names":[],"sources":["../../../src/plugins/seal/keygen.ts"],"sourcesContent":["// Seal plugin — BLS12-381 keygen helpers + master-key redactor.\n//\n// Distilled-doc invariant (07-seal.md §\"Generic artifact-publisher-publish\"\n// + §Hard requirements #16): the master-key MUST be redacted from any\n// stdout/stderr that may surface in a SealError. The redactor lives\n// here as the single owner so call sites (`mode/local-keygen.ts`,\n// `key-manager.ts`) all funnel through one regex.\n//\n// The keygen pipeline is REAL — `runtime.runOneShot` against the cargo\n// image runs `seal-cli genkey`, captures stdout, parses the BLS hex\n// pair. The image itself is the seam (`SEAL_CARGO_IMAGE_OVERRIDE` env\n// — see `bootstrap-assets/cargo-image.ts`).\n\nimport { Duration, Effect, type Scope } from 'effect';\n\nimport type { ContainerRuntime, ImageRef } from '../../contracts/container-runtime.ts';\nimport { redactText, type RedactionRule } from '../../substrate/runtime/observability/index.ts';\nimport { sealError, type SealError } from './errors.ts';\nimport { SealSpans } from './spans.ts';\n\n// ---------------------------------------------------------------------------\n// Constants — mirror v3 (`seal/internal.ts:115-149`)\n// ---------------------------------------------------------------------------\n\n/** Entrypoint binary inside the seal image. */\nexport const SEAL_KEYGEN_ENTRYPOINT = 'seal-cli';\n\n/** Args for the keygen one-shot. */\nexport const SEAL_KEYGEN_ARGS = ['genkey'] as const;\n\n/** Default master-key env-file basename inside `runtime/seal/`. */\nexport const MASTER_KEY_ENVFILE_BASENAME = 'master-key.env';\n\n/** Default key-server config yaml basename inside `runtime/seal/`. */\nexport const KEY_SERVER_CONFIG_BASENAME = 'key-server-config.yaml';\n\n/** Wall-clock timeout for the keygen one-shot. BLS12-381 keygen is\n * small — under 1s. 30s ceiling absorbs container startup overhead\n * on slow CI runners. */\nconst KEYGEN_TIMEOUT_MS = 30_000;\n\n// ---------------------------------------------------------------------------\n// PersistedBlsKeypair — the cache-stored shape\n// ---------------------------------------------------------------------------\n\n/** Two hex blobs round-tripped through the substrate StateStore. The\n * master key is the secret; the public key is on-chain in the\n * registered `KeyServer` object. Distilled-doc §\"Persistence model\"\n * + §Hard requirements #5 — chainId is folded into the cache key by\n * the ArtifactPublisher substrate. */\nexport interface PersistedBlsKeypair {\n\treadonly masterKey: string;\n\treadonly publicKey: string;\n}\n\n// ---------------------------------------------------------------------------\n// Redaction — distilled-doc invariant #16\n// ---------------------------------------------------------------------------\n\n/** Case-insensitive line-level pattern matching any `master[_-]?key`\n * mention. Mirrors v3's `MASTER_KEY_LINE_RE` (`seal/internal.ts:1343`). */\nconst MASTER_KEY_LINE_RE = /^.*master[_\\- ]?key.*$/gim;\n\n/** Defense-in-depth: any contiguous hex run of 64+ chars is treated as\n * a possible BLS12-381 master key (32 bytes = 64 hex chars). The\n * label-based pass catches the canonical `Master key: 0x…` format;\n * this pass catches stray hex emissions that drop the label (e.g. a\n * `log::info!(\"{}\", master)` call site upstream that prints only the\n * hex). Bounded at 64+ to avoid false-positives on shorter hex like\n * 4-byte chain ids or 8-byte object-id prefixes; legitimate Sui\n * object ids are 32 bytes (64 hex chars) and would also trip the\n * rule — acceptable, since a redacted object id is a tractable\n * diagnostic regression while a leaked master key is not.\n *\n * Boundary shape: negative lookbehind/lookahead against the hex class\n * itself (NOT `\\b`). The `\\b` form had a known gap — `0x<hex>` and\n * `<word-prefix>0x<hex>` failed to match because `0` and `x` are\n * both `\\w` characters, so `\\b` couldn't anchor at the start of the\n * hex run. The lookbehind form starts the match anywhere not\n * preceded by a hex character, so an adversarial concat like\n * `...key0xdeadbeef…` redacts the hex run starting right after the\n * non-hex `x`. */\nconst HIGH_ENTROPY_HEX_RE = /(?<![0-9a-fA-F])[0-9a-fA-F]{64,}(?![0-9a-fA-F])/g;\n\nconst MASTER_KEY_REDACTION_RULES: ReadonlyArray<RedactionRule> = [\n\t// Order matters: redact the labeled line first (replaces the whole\n\t// line including the hex), then the standalone-hex pass picks up\n\t// anything left over. Because the first pass replaces the full line\n\t// with a fixed literal containing no hex, the second pass cannot\n\t// double-replace.\n\t{\n\t\tkind: 'pattern',\n\t\tpattern: MASTER_KEY_LINE_RE,\n\t\treplacement: '[REDACTED master key]',\n\t},\n\t{\n\t\tkind: 'pattern',\n\t\tpattern: HIGH_ENTROPY_HEX_RE,\n\t\treplacement: '<REDACTED-HEX-RUN>',\n\t},\n];\n\n/** Replace any line containing `master_key` / `master-key` / `masterkey`\n * (case-insensitive) with `[REDACTED master key]`, AND any standalone\n * hex run of 64+ chars with `<REDACTED-HEX-RUN>`. Used at every site\n * that may surface stdout/stderr from `seal-cli`. */\nexport const redactMasterKey = (s: string): string => redactText(s, MASTER_KEY_REDACTION_RULES);\n\n// ---------------------------------------------------------------------------\n// Output parser — distilled-doc §\"Helpers\"\n// ---------------------------------------------------------------------------\n\n/** Parse `Master key:` / `Public key:` hex lines from `seal-cli genkey`\n * stdout. Hex prefix may or may not include `0x` (we strip it).\n *\n * Returns a typed `PersistedBlsKeypair` on success, or fails with a\n * `SealError({phase: 'keygen'})` carrying the REDACTED tail of the\n * stdout so a parser drift doesn't leak the master key into logs. */\nexport const parseSealKeygenOutput = (\n\tstdout: string,\n\tname: string,\n): Effect.Effect<PersistedBlsKeypair, SealError> => {\n\tconst stripHex = (s: string): string => (s.startsWith('0x') ? s.slice(2) : s);\n\t// Bounded widths — BLS12-381 master is 32 bytes (64 hex chars);\n\t// public key is 96 bytes uncompressed G2 (192 hex chars). The\n\t// trailing `\\b` prevents a greedy slurp if the upstream binary\n\t// ever prints adjacent hex on the same line.\n\tconst masterMatch = stdout.match(/Master key:\\s*(0x)?([0-9a-fA-F]{64})\\b/);\n\tconst publicMatch = stdout.match(/Public key:\\s*(0x)?([0-9a-fA-F]{192})\\b/);\n\tif (!masterMatch || !publicMatch) {\n\t\treturn Effect.fail(\n\t\t\tsealError('keygen', {\n\t\t\t\tname,\n\t\t\t\tmessage:\n\t\t\t\t\t'seal.keygen: could not parse seal-cli genkey output (Master key: / Public key: lines missing)',\n\t\t\t\tstdout: redactMasterKey(stdout),\n\t\t\t}),\n\t\t);\n\t}\n\treturn Effect.succeed({\n\t\tmasterKey: stripHex(masterMatch[2]!),\n\t\tpublicKey: stripHex(publicMatch[2]!),\n\t} satisfies PersistedBlsKeypair);\n};\n\n// ---------------------------------------------------------------------------\n// Real keygen one-shot\n// ---------------------------------------------------------------------------\n\n/** Run `seal-cli genkey` inside the cargo-built seal image and\n * parse the BLS12-381 master + public keys.\n *\n * Implementation:\n * 1. `runtime.runOneShot({ image, entrypoint: 'seal-cli', argv:\n * ['genkey'], timeoutMillis: 30s })` — fresh `docker run --rm`.\n * 2. Promote non-zero exit to typed SealError with REDACTED tails.\n * 3. Parse stdout via `parseSealKeygenOutput`.\n *\n * Distilled-doc invariant #16 — every stdout/stderr capture site\n * passes through `redactMasterKey` BEFORE landing in the error. The\n * parser handles the success-path; the failure path does its own\n * redact at the raise site. */\nexport const runSealKeygen = (\n\truntime: ContainerRuntime,\n\tname: string,\n\timage: ImageRef,\n): Effect.Effect<PersistedBlsKeypair, SealError, Scope.Scope> =>\n\tEffect.gen(function* () {\n\t\tconst result = yield* runtime\n\t\t\t.runOneShot({\n\t\t\t\timage,\n\t\t\t\tentrypoint: SEAL_KEYGEN_ENTRYPOINT,\n\t\t\t\targv: SEAL_KEYGEN_ARGS,\n\t\t\t\ttimeoutMillis: KEYGEN_TIMEOUT_MS,\n\t\t\t})\n\t\t\t.pipe(\n\t\t\t\tEffect.catch((cause) =>\n\t\t\t\t\tEffect.fail(\n\t\t\t\t\t\tsealError('keygen', {\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tmessage: `seal-cli genkey one-shot failed: ${cause.reason}: ${cause.detail}`,\n\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\n\t\tif (result.exitCode !== 0) {\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tsealError('keygen', {\n\t\t\t\t\tname,\n\t\t\t\t\tmessage: `seal-cli genkey exited with code ${result.exitCode}`,\n\t\t\t\t\texitCode: result.exitCode,\n\t\t\t\t\t// Defense-in-depth — the redactor handles success-path\n\t\t\t\t\t// output (where the key is the parsed value) but the\n\t\t\t\t\t// failure path's stdout MAY also carry the key, e.g.\n\t\t\t\t\t// when stderr says \"wrote master key to <log>\".\n\t\t\t\t\tstdout: redactMasterKey(result.stdout),\n\t\t\t\t\tstderr: redactMasterKey(result.stderr),\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\treturn yield* parseSealKeygenOutput(result.stdout, name);\n\t}).pipe(\n\t\tEffect.withSpan('devstack.plugin.seal.keygen.oneShot', {\n\t\t\tattributes: { [SealSpans.name]: name },\n\t\t}),\n\t\tEffect.timeoutOrElse({\n\t\t\tduration: Duration.millis(KEYGEN_TIMEOUT_MS + 5_000),\n\t\t\torElse: () =>\n\t\t\t\tEffect.fail(\n\t\t\t\t\tsealError('keygen', {\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tmessage: `seal.keygen: outer timeout ${KEYGEN_TIMEOUT_MS}ms exceeded`,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t}),\n\t);\n"],"mappings":";;;;;;;AAyBA,MAAa,yBAAyB;;AAGtC,MAAa,mBAAmB,CAAC,SAAS;;AAG1C,MAAa,8BAA8B;;AAG3C,MAAa,6BAA6B;;;;AAK1C,MAAM,oBAAoB;AA6C1B,MAAM,6BAA2D,CAMhE;CACC,MAAM;CACN,SAAS;CACT,aAAa;CACb,EACD;CACC,MAAM;CACN,SAAS;CACT,aAAa;CACb,CACD;;;;;AAMD,MAAa,mBAAmB,MAAsB,WAAW,GAAG,2BAA2B;;;;;;;AAY/F,MAAa,yBACZ,QACA,SACmD;CACnD,MAAM,YAAY,MAAuB,EAAE,WAAW,KAAK,GAAG,EAAE,MAAM,EAAE,GAAG;CAK3E,MAAM,cAAc,OAAO,MAAM,yCAAyC;CAC1E,MAAM,cAAc,OAAO,MAAM,0CAA0C;AAC3E,KAAI,CAAC,eAAe,CAAC,YACpB,QAAO,OAAO,KACb,UAAU,UAAU;EACnB;EACA,SACC;EACD,QAAQ,gBAAgB,OAAO;EAC/B,CAAC,CACF;AAEF,QAAO,OAAO,QAAQ;EACrB,WAAW,SAAS,YAAY,GAAI;EACpC,WAAW,SAAS,YAAY,GAAI;EACpC,CAA+B;;;;;;;;;;;;;;;AAoBjC,MAAa,iBACZ,SACA,MACA,UAEA,OAAO,IAAI,aAAa;CACvB,MAAM,SAAS,OAAO,QACpB,WAAW;EACX;EACA,YAAY;EACZ,MAAM;EACN,eAAe;EACf,CAAC,CACD,KACA,OAAO,OAAO,UACb,OAAO,KACN,UAAU,UAAU;EACnB;EACA,SAAS,oCAAoC,MAAM,OAAO,IAAI,MAAM;EACpE;EACA,CAAC,CACF,CACD,CACD;AAEF,KAAI,OAAO,aAAa,EACvB,QAAO,OAAO,OAAO,KACpB,UAAU,UAAU;EACnB;EACA,SAAS,oCAAoC,OAAO;EACpD,UAAU,OAAO;EAKjB,QAAQ,gBAAgB,OAAO,OAAO;EACtC,QAAQ,gBAAgB,OAAO,OAAO;EACtC,CAAC,CACF;AAGF,QAAO,OAAO,sBAAsB,OAAO,QAAQ,KAAK;EACvD,CAAC,KACF,OAAO,SAAS,uCAAuC,EACtD,YAAY,GAAG,UAAU,OAAO,MAAM,EACtC,CAAC,EACF,OAAO,cAAc;CACpB,UAAU,SAAS,OAAO,oBAAoB,IAAM;CACpD,cACC,OAAO,KACN,UAAU,UAAU;EACnB;EACA,SAAS,8BAA8B,kBAAkB;EACzD,CAAC,CACF;CACF,CAAC,CACF"}
@@ -1,23 +1,45 @@
1
- import { sealError } from "../errors.mjs";
2
- import { acquireLive } from "./live.mjs";
3
- import { Effect } from "effect";
1
+ import { acquireLive, validateLiveInputs } from "./live.mjs";
2
+ import "effect";
4
3
  //#region src/plugins/seal/mode/fork-known.ts
5
4
  /** Resolve the wrapped upstream's known deployment key. Distilled-
6
5
  * doc invariant #13. */
7
6
  const resolveDeploymentNetwork = (upstream) => upstream;
8
- /** Acquire body for the fork-known mode. Delegates to live mode
9
- * with the resolved network. */
7
+ /** Resolve the fork-known overrides + upstream-derived defaults into
8
+ * a validated tuple. Pure synchronous projection — mirrors the
9
+ * factory-boundary `validateLiveInputs` call in `index.ts` for the
10
+ * live branch. Throws on missing fields after fallback (matches the
11
+ * live branch's behaviour — see `validateLiveInputs`). */
12
+ const validateForkKnownInputs = (inputs) => {
13
+ try {
14
+ return validateLiveInputs({
15
+ name: inputs.name,
16
+ network: resolveDeploymentNetwork(inputs.upstream),
17
+ objectId: inputs.objectId,
18
+ keyServerUrl: inputs.keyServerUrl
19
+ });
20
+ } catch (err) {
21
+ if (isSealConfigError(err)) throw {
22
+ ...err,
23
+ message: `seal.fork-known (upstream=${inputs.upstream}): ${err.message}`
24
+ };
25
+ throw err;
26
+ }
27
+ };
28
+ const isSealConfigError = (value) => typeof value === "object" && value !== null && value._tag === "SealConfigError" && typeof value.message === "string";
29
+ /** Acquire body for the fork-known mode. Inputs already pre-validated
30
+ * by the barrel via `validateForkKnownInputs`; delegates the
31
+ * read-side projection to live mode. The `upstream` field rides
32
+ * through for downstream span attribution.
33
+ *
34
+ * Error channel kept typed as `SealError` for forward-compatibility
35
+ * with any future fallible work this body needs to do (currently
36
+ * `acquireLive` is `Effect.sync` so the channel is effectively
37
+ * `never`). */
10
38
  const acquireForkKnown = (inputs) => acquireLive({
11
39
  name: inputs.name,
12
- network: resolveDeploymentNetwork(inputs.upstream),
13
- objectId: inputs.objectId,
14
- keyServerUrl: inputs.keyServerUrl
15
- }).pipe(Effect.mapError((err) => sealError("seal", {
16
- name: inputs.name,
17
- message: `seal.fork-known (upstream=${inputs.upstream}): ${err.message}`,
18
- cause: err
19
- })));
40
+ resolved: inputs.resolved
41
+ });
20
42
  //#endregion
21
- export { acquireForkKnown };
43
+ export { acquireForkKnown, validateForkKnownInputs };
22
44
 
23
45
  //# sourceMappingURL=fork-known.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"fork-known.mjs","names":[],"sources":["../../../../src/plugins/seal/mode/fork-known.ts"],"sourcesContent":["// Seal fork-known mode — *-fork networks route to the wrapped\n// upstream's known key-server deployment.\n//\n// Distilled-doc §\"Startup — `sealKnownKeyServer` (testnet / mainnet\n// / fork)\": structurally IDENTICAL to live mode. The only difference\n// is the network resolver step at the barrel — `*-fork` networks\n// route to the wrapped upstream (mainnet-fork → mainnet,\n// testnet-fork → testnet, devnet-fork → devnet) BEFORE the\n// known-deployment lookup fires.\n//\n// Distilled-doc invariant #13: `Seal()` on `*-fork` MUST route to\n// `sealKnownKeyServer` with the wrapped upstream's deployment. The\n// barrel (`index.ts`) enforces this via `resolveDeploymentNetwork`;\n// this file's mode body simply consumes the resolved network the\n// barrel passed.\n//\n// The mode body re-uses `acquireLive` since the boot pipeline is\n// identical. We expose a distinct factory only so the mode-narrowed\n// factory namespace (`sealFor(network).forkKnown(opts)`) can\n// route by mode without leaking the live-mode internals.\n\nimport { Effect } from 'effect';\n\nimport { acquireLive, type KnownNetwork } from './live.ts';\nimport { sealError, type SealError } from '../errors.ts';\nimport type { SealKnownResolved } from '../registry-publish.ts';\n\n// ---------------------------------------------------------------------------\n// Fork → upstream network mapping\n// ---------------------------------------------------------------------------\n\n/** Map a fork upstream to its known-deployment lookup target. */\nexport type ForkUpstream = 'mainnet' | 'testnet' | 'devnet';\n\n/** Resolve the wrapped upstream's known deployment key. Distilled-\n * doc invariant #13. */\nexport const resolveDeploymentNetwork = (upstream: ForkUpstream): KnownNetwork => upstream;\n\n// ---------------------------------------------------------------------------\n// Inputs\n// ---------------------------------------------------------------------------\n\nexport interface ForkKnownInputs {\n\treadonly name: string;\n\treadonly upstream: ForkUpstream;\n\t/** Explicit overrides (rare the wrapped upstream's known\n\t * deployment is usually authoritative). */\n\treadonly objectId?: string;\n\treadonly keyServerUrl?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Mode acquire\n// ---------------------------------------------------------------------------\n\n/** Acquire body for the fork-known mode. Delegates to live mode\n * with the resolved network. */\nexport const acquireForkKnown = (\n\tinputs: ForkKnownInputs,\n): Effect.Effect<SealKnownResolved, SealError> =>\n\tacquireLive({\n\t\tname: inputs.name,\n\t\tnetwork: resolveDeploymentNetwork(inputs.upstream),\n\t\tobjectId: inputs.objectId,\n\t\tkeyServerUrl: inputs.keyServerUrl,\n\t}).pipe(\n\t\t// Re-tag the error so the cause walker can attribute fork-mode\n\t\t// failures distinctly from live-mode failures.\n\t\tEffect.mapError((err) =>\n\t\t\tsealError('seal', {\n\t\t\t\tname: inputs.name,\n\t\t\t\tmessage: `seal.fork-known (upstream=${inputs.upstream}): ${err.message}`,\n\t\t\t\tcause: err,\n\t\t\t}),\n\t\t),\n\t);\n"],"mappings":";;;;;;AAoCA,MAAa,4BAA4B,aAAyC;;;AAqBlF,MAAa,oBACZ,WAEA,YAAY;CACX,MAAM,OAAO;CACb,SAAS,yBAAyB,OAAO,SAAS;CAClD,UAAU,OAAO;CACjB,cAAc,OAAO;CACrB,CAAC,CAAC,KAGF,OAAO,UAAU,QAChB,UAAU,QAAQ;CACjB,MAAM,OAAO;CACb,SAAS,6BAA6B,OAAO,SAAS,KAAK,IAAI;CAC/D,OAAO;CACP,CAAC,CACF,CACD"}
1
+ {"version":3,"file":"fork-known.mjs","names":[],"sources":["../../../../src/plugins/seal/mode/fork-known.ts"],"sourcesContent":["// Seal fork-known mode — *-fork networks route to the wrapped\n// upstream's known key-server deployment.\n//\n// Distilled-doc §\"Startup — `sealKnownKeyServer` (testnet / mainnet\n// / fork)\": structurally IDENTICAL to live mode. The only difference\n// is the network resolver step at the barrel — `*-fork` networks\n// route to the wrapped upstream (mainnet-fork → mainnet,\n// testnet-fork → testnet, devnet-fork → devnet) BEFORE the\n// known-deployment lookup fires.\n//\n// Distilled-doc invariant #13: `Seal()` on `*-fork` MUST route to\n// `sealKnownKeyServer` with the wrapped upstream's deployment. The\n// barrel (`index.ts`) enforces this via `resolveDeploymentNetwork`;\n// this file's mode body simply consumes the resolved network the\n// barrel passed.\n//\n// The mode body re-uses `acquireLive` since the boot pipeline is\n// identical. We expose a distinct factory only so the mode-narrowed\n// factory namespace (`sealFor(network).forkKnown(opts)`) can\n// route by mode without leaking the live-mode internals.\n\nimport { Effect } from 'effect';\n\nimport { acquireLive, validateLiveInputs, type KnownNetwork } from './live.ts';\nimport type { SealError } from '../errors.ts';\nimport type { SealKnownResolved } from '../registry-publish.ts';\n\n// ---------------------------------------------------------------------------\n// Fork → upstream network mapping\n// ---------------------------------------------------------------------------\n\n/** Map a fork upstream to its known-deployment lookup target. */\nexport type ForkUpstream = 'mainnet' | 'testnet' | 'devnet';\n\n/** Resolve the wrapped upstream's known deployment key. Distilled-\n * doc invariant #13. */\nexport const resolveDeploymentNetwork = (upstream: ForkUpstream): KnownNetwork => upstream;\n\n// ---------------------------------------------------------------------------\n// Inputs\n// ---------------------------------------------------------------------------\n\n/** Pre-validated fork-known inputs. Symmetric with the live mode's\n * `{ name, resolved }` shape — the barrel resolves\n * `upstream → KnownNetwork → validated tuple` synchronously at\n * factory time so both branches reach `acquireLive` with the same\n * structural envelope. */\nexport interface ForkKnownInputs {\n\treadonly name: string;\n\treadonly upstream: ForkUpstream;\n\treadonly resolved: { readonly objectId: string; readonly keyServerUrl: string };\n}\n\n/** Resolve the fork-known overrides + upstream-derived defaults into\n * a validated tuple. Pure synchronous projection — mirrors the\n * factory-boundary `validateLiveInputs` call in `index.ts` for the\n * live branch. Throws on missing fields after fallback (matches the\n * live branch's behaviour — see `validateLiveInputs`). */\nexport const validateForkKnownInputs = (inputs: {\n\treadonly name: string;\n\treadonly upstream: ForkUpstream;\n\treadonly objectId?: string;\n\treadonly keyServerUrl?: string;\n}): { readonly objectId: string; readonly keyServerUrl: string } => {\n\ttry {\n\t\treturn validateLiveInputs({\n\t\t\tname: inputs.name,\n\t\t\tnetwork: resolveDeploymentNetwork(inputs.upstream),\n\t\t\tobjectId: inputs.objectId,\n\t\t\tkeyServerUrl: inputs.keyServerUrl,\n\t\t});\n\t} catch (err) {\n\t\t// Re-throw the original tagged error so downstream\n\t\t// `Effect.catchTag('SealConfigError', …)` still matches.\n\t\t// Wrapping in `new Error(…)` would strip the `_tag` and turn\n\t\t// the typed refusal into an untyped runtime crash. Prepend the\n\t\t// upstream context to the message in-place instead.\n\t\tif (isSealConfigError(err)) {\n\t\t\tthrow {\n\t\t\t\t...err,\n\t\t\t\tmessage: `seal.fork-known (upstream=${inputs.upstream}): ${err.message}`,\n\t\t\t};\n\t\t}\n\t\tthrow err;\n\t}\n};\n\nconst isSealConfigError = (\n\tvalue: unknown,\n): value is { readonly _tag: 'SealConfigError'; readonly message: string; [k: string]: unknown } =>\n\ttypeof value === 'object' &&\n\tvalue !== null &&\n\t(value as { _tag?: unknown })._tag === 'SealConfigError' &&\n\ttypeof (value as { message?: unknown }).message === 'string';\n\n// ---------------------------------------------------------------------------\n// Mode acquire\n// ---------------------------------------------------------------------------\n\n/** Acquire body for the fork-known mode. Inputs already pre-validated\n * by the barrel via `validateForkKnownInputs`; delegates the\n * read-side projection to live mode. The `upstream` field rides\n * through for downstream span attribution.\n *\n * Error channel kept typed as `SealError` for forward-compatibility\n * with any future fallible work this body needs to do (currently\n * `acquireLive` is `Effect.sync` so the channel is effectively\n * `never`). */\nexport const acquireForkKnown = (\n\tinputs: ForkKnownInputs,\n): Effect.Effect<SealKnownResolved, SealError> =>\n\tacquireLive({ name: inputs.name, resolved: inputs.resolved });\n"],"mappings":";;;;;AAoCA,MAAa,4BAA4B,aAAyC;;;;;;AAsBlF,MAAa,2BAA2B,WAK4B;AACnE,KAAI;AACH,SAAO,mBAAmB;GACzB,MAAM,OAAO;GACb,SAAS,yBAAyB,OAAO,SAAS;GAClD,UAAU,OAAO;GACjB,cAAc,OAAO;GACrB,CAAC;UACM,KAAK;AAMb,MAAI,kBAAkB,IAAI,CACzB,OAAM;GACL,GAAG;GACH,SAAS,6BAA6B,OAAO,SAAS,KAAK,IAAI;GAC/D;AAEF,QAAM;;;AAIR,MAAM,qBACL,UAEA,OAAO,UAAU,YACjB,UAAU,QACT,MAA6B,SAAS,qBACvC,OAAQ,MAAgC,YAAY;;;;;;;;;;AAerD,MAAa,oBACZ,WAEA,YAAY;CAAE,MAAM,OAAO;CAAM,UAAU,OAAO;CAAU,CAAC"}
@@ -2,12 +2,14 @@ import { Effect } from "effect";
2
2
 
3
3
  //#region src/plugins/seal/mode/live.d.ts
4
4
  /** Closed set of known deployments. `mainnet` + `devnet` intentionally
5
- * null (distilled-doc cross-ref). v2 plans should canonicalize this
6
- * table for now we mirror v3's structure. */
5
+ * null (no public default key server). `testnet` carries the public
6
+ * key-server URL but `keyServerObjectId` is `null` until a real id is
7
+ * sourced — `validateLiveInputs` forces the caller to supply
8
+ * `objectId` explicitly in that case. */
7
9
  declare const KNOWN_DEPLOYMENTS: {
8
10
  readonly testnet: {
9
- readonly keyServerObjectId: string;
10
- readonly keyServerUrl: "https://seal-keyserver.testnet.mystenlabs.com";
11
+ readonly keyServerObjectId: string | null;
12
+ readonly keyServerUrl: string;
11
13
  };
12
14
  readonly mainnet: null;
13
15
  readonly devnet: null;
@@ -1,13 +1,15 @@
1
1
  import { expectNonEmptyString } from "../../../substrate/runtime/config-validation.mjs";
2
- import { sealConfigError, sealError } from "../errors.mjs";
2
+ import { sealConfigError } from "../errors.mjs";
3
3
  import { Effect } from "effect";
4
4
  //#region src/plugins/seal/mode/live.ts
5
5
  /** Closed set of known deployments. `mainnet` + `devnet` intentionally
6
- * null (distilled-doc cross-ref). v2 plans should canonicalize this
7
- * table for now we mirror v3's structure. */
6
+ * null (no public default key server). `testnet` carries the public
7
+ * key-server URL but `keyServerObjectId` is `null` until a real id is
8
+ * sourced — `validateLiveInputs` forces the caller to supply
9
+ * `objectId` explicitly in that case. */
8
10
  const KNOWN_DEPLOYMENTS = {
9
11
  testnet: {
10
- keyServerObjectId: "0x000000000000000000000000000000000000000000000000000000000000mysten",
12
+ keyServerObjectId: null,
11
13
  keyServerUrl: "https://seal-keyserver.testnet.mystenlabs.com"
12
14
  },
13
15
  mainnet: null,
@@ -35,27 +37,18 @@ const validateLiveInputs = (inputs) => {
35
37
  })
36
38
  };
37
39
  };
38
- /** Acquire body for the live mode. Returns the read-side handle
39
- * ONLY (no manager tag — distilled-doc invariant #15). */
40
- const acquireLive = (inputs) => Effect.gen(function* () {
41
- let resolved;
42
- try {
43
- resolved = validateLiveInputs(inputs);
44
- } catch (err) {
45
- if (typeof err === "object" && err !== null && "_tag" in err && err._tag === "SealConfigError") return yield* Effect.fail(err);
46
- return yield* Effect.fail(sealError("seal", {
47
- name: inputs.name,
48
- message: err instanceof Error ? err.message : String(err),
49
- cause: err
50
- }));
51
- }
40
+ /** Acquire body for the live mode. Validation already ran at the
41
+ * factory boundary (see `index.ts:buildLivePlugin`); this projects
42
+ * the validated bundle into the resolved shape. Returns the
43
+ * read-side handle ONLY (no manager tag — distilled-doc invariant #15). */
44
+ const acquireLive = (inputs) => Effect.sync(() => {
52
45
  return { keyServer: {
53
46
  serverConfigs: [{
54
- objectId: resolved.objectId,
47
+ objectId: inputs.resolved.objectId,
55
48
  weight: 1
56
49
  }],
57
- keyServerUrl: resolved.keyServerUrl,
58
- objectId: resolved.objectId
50
+ keyServerUrl: inputs.resolved.keyServerUrl,
51
+ objectId: inputs.resolved.objectId
59
52
  } };
60
53
  });
61
54
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"live.mjs","names":[],"sources":["../../../../src/plugins/seal/mode/live.ts"],"sourcesContent":["// Seal live mode — testnet / mainnet known key server.\n//\n// Distilled-doc §\"Startup — `sealKnownKeyServer`\": far simpler than\n// the local-keygen path.\n//\n// 1. Look up the known deployment (or accept explicit overrides).\n// 2. Publish the endpoint + state-store entry to the substrate\n// registries (the codegen + manifest emitters consume these).\n// 3. Return the read-side handle.\n//\n// NO chain interactions, NO docker, NO state-store writes, NO\n// keygen. Distilled-doc invariant #15 — the manager tag is NOT\n// produced (we don't own the master key for a remote deployment).\n//\n// Known-deployment lookup: distilled-doc §\"Adjacent Seal references\"\n// → `engine/known-deployments.ts:153-157` carries the\n// `mysten-testnet-1` Open-mode independent server. `mainnet`\n// intentionally empty (Mysten doesn't ship a public default key\n// server on mainnet — production is via Enoki). `devnet`\n// intentionally empty.\n\nimport { Effect } from 'effect';\n\nimport { expectNonEmptyString } from '../../../substrate/runtime/config-validation.ts';\nimport { sealConfigError, sealError, type SealAnyError } from '../errors.ts';\nimport type { SealKeyServerEntry, SealKnownResolved } from '../registry-publish.ts';\n\n// ---------------------------------------------------------------------------\n// Known-deployment table — distilled-doc reference\n// ---------------------------------------------------------------------------\n\n/** Closed set of known deployments. `mainnet` + `devnet` intentionally\n * null (distilled-doc cross-ref). v2 plans should canonicalize this\n * tablefor now we mirror v3's structure. */\nexport const KNOWN_DEPLOYMENTS = {\n\ttestnet: {\n\t\tkeyServerObjectId:\n\t\t\t'0x000000000000000000000000000000000000000000000000000000000000mysten' as string,\n\t\tkeyServerUrl: 'https://seal-keyserver.testnet.mystenlabs.com',\n\t},\n\tmainnet: null,\n\tdevnet: null,\n} as const;\n\nexport type KnownNetwork = keyof typeof KNOWN_DEPLOYMENTS;\n\n// ---------------------------------------------------------------------------\n// Inputs\n// ---------------------------------------------------------------------------\n\n/** Live-mode inputs. Either `network` resolves to a known deployment\n * OR the user supplies explicit `objectId` + `keyServerUrl`\n * overrides. Distilled-doc §\"Configuration\" — the factory throws\n * synchronously if neither path produces a usable tuple. */\nexport interface LiveModeInputs {\n\treadonly name: string;\n\treadonly network?: KnownNetwork;\n\treadonly objectId?: string;\n\treadonly keyServerUrl?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Resolved\n// ---------------------------------------------------------------------------\n\n/** Validate the inputs at the factory boundary. Pure synchronous\n * function. The plugin `start` body is reserved for Effect-flavored\n * work; the throw here matches v3's pattern (distilled-doc\n * §Failure modes). */\nexport const validateLiveInputs = (\n\tinputs: LiveModeInputs,\n): {\n\treadonly objectId: string;\n\treadonly keyServerUrl: string;\n} => {\n\tconst fromNetwork =\n\t\tinputs.network && KNOWN_DEPLOYMENTS[inputs.network] ? KNOWN_DEPLOYMENTS[inputs.network] : null;\n\tconst objectId = inputs.objectId ?? fromNetwork?.keyServerObjectId;\n\tconst keyServerUrl = inputs.keyServerUrl ?? fromNetwork?.keyServerUrl;\n\tconst message = `seal.live: missing required fields. Pass network ('testnet') or set objectId + keyServerUrl explicitly (got network=${String(\n\t\tinputs.network,\n\t)}, objectId=${String(inputs.objectId)}, keyServerUrl=${String(inputs.keyServerUrl)}).`;\n\treturn {\n\t\tobjectId: expectNonEmptyString(objectId, {\n\t\t\tfield: 'objectId',\n\t\t\tmessage,\n\t\t\tmkError: sealConfigError,\n\t\t}),\n\t\tkeyServerUrl: expectNonEmptyString(keyServerUrl, {\n\t\t\tfield: 'keyServerUrl',\n\t\t\tmessage,\n\t\t\tmkError: sealConfigError,\n\t\t}),\n\t};\n};\n\n// ---------------------------------------------------------------------------\n// Mode acquire\n// ---------------------------------------------------------------------------\n\n/** Acquire body for the live mode. Returns the read-side handle\n * ONLY (no manager tag — distilled-doc invariant #15). */\nexport const acquireLive = (\n\tinputs: LiveModeInputs,\n): Effect.Effect<SealKnownResolved, SealAnyError> =>\n\tEffect.gen(function* () {\n\t\t// Validation runs at the factory layer; here we trust the\n\t\t// validated fields. The substrate's registry publishes happen\n\t\t// at the orchestrator layer (manifest emitter walks the\n\t\t// codegen contributions); this body just returns the resolved\n\t\t// value.\n\t\tlet resolved: { readonly objectId: string; readonly keyServerUrl: string };\n\t\ttry {\n\t\t\tresolved = validateLiveInputs(inputs);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\ttypeof err === 'object' &&\n\t\t\t\terr !== null &&\n\t\t\t\t'_tag' in err &&\n\t\t\t\terr._tag === 'SealConfigError'\n\t\t\t) {\n\t\t\t\treturn yield* Effect.fail(err as SealAnyError);\n\t\t\t}\n\t\t\treturn yield* Effect.fail(\n\t\t\t\tsealError('seal', {\n\t\t\t\t\tname: inputs.name,\n\t\t\t\t\tmessage: err instanceof Error ? err.message : String(err),\n\t\t\t\t\tcause: err,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tconst serverConfigs: ReadonlyArray<SealKeyServerEntry> = [\n\t\t\t{ objectId: resolved.objectId, weight: 1 },\n\t\t];\n\t\treturn {\n\t\t\tkeyServer: {\n\t\t\t\tserverConfigs,\n\t\t\t\tkeyServerUrl: resolved.keyServerUrl,\n\t\t\t\tobjectId: resolved.objectId,\n\t\t\t},\n\t\t} satisfies SealKnownResolved;\n\t});\n"],"mappings":";;;;;;;AAkCA,MAAa,oBAAoB;CAChC,SAAS;EACR,mBACC;EACD,cAAc;EACd;CACD,SAAS;CACT,QAAQ;CACR;;;;;AA2BD,MAAa,sBACZ,WAII;CACJ,MAAM,cACL,OAAO,WAAW,kBAAkB,OAAO,WAAW,kBAAkB,OAAO,WAAW;CAC3F,MAAM,WAAW,OAAO,YAAY,aAAa;CACjD,MAAM,eAAe,OAAO,gBAAgB,aAAa;CACzD,MAAM,UAAU,uHAAuH,OACtI,OAAO,QACP,CAAC,aAAa,OAAO,OAAO,SAAS,CAAC,iBAAiB,OAAO,OAAO,aAAa,CAAC;AACpF,QAAO;EACN,UAAU,qBAAqB,UAAU;GACxC,OAAO;GACP;GACA,SAAS;GACT,CAAC;EACF,cAAc,qBAAqB,cAAc;GAChD,OAAO;GACP;GACA,SAAS;GACT,CAAC;EACF;;;;AASF,MAAa,eACZ,WAEA,OAAO,IAAI,aAAa;CAMvB,IAAI;AACJ,KAAI;AACH,aAAW,mBAAmB,OAAO;UAC7B,KAAK;AACb,MACC,OAAO,QAAQ,YACf,QAAQ,QACR,UAAU,OACV,IAAI,SAAS,kBAEb,QAAO,OAAO,OAAO,KAAK,IAAoB;AAE/C,SAAO,OAAO,OAAO,KACpB,UAAU,QAAQ;GACjB,MAAM,OAAO;GACb,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;GACzD,OAAO;GACP,CAAC,CACF;;AAKF,QAAO,EACN,WAAW;EACV,eAAA,CAJD;GAAE,UAAU,SAAS;GAAU,QAAQ;GAAG,CAI5B;EACb,cAAc,SAAS;EACvB,UAAU,SAAS;EACnB,EACD;EACA"}
1
+ {"version":3,"file":"live.mjs","names":[],"sources":["../../../../src/plugins/seal/mode/live.ts"],"sourcesContent":["// Seal live mode — testnet / mainnet known key server.\n//\n// Distilled-doc §\"Startup — `sealKnownKeyServer`\": far simpler than\n// the local-keygen path.\n//\n// 1. Look up the known deployment (or accept explicit overrides).\n// 2. Publish the endpoint + state-store entry to the substrate\n// registries (the codegen + manifest emitters consume these).\n// 3. Return the read-side handle.\n//\n// NO chain interactions, NO docker, NO state-store writes, NO\n// keygen. Distilled-doc invariant #15 — the manager tag is NOT\n// produced (we don't own the master key for a remote deployment).\n//\n// Known-deployment lookup: distilled-doc §\"Adjacent Seal references\"\n// → `engine/known-deployments.ts:153-157` carries the\n// `mysten-testnet-1` Open-mode independent server. `mainnet`\n// intentionally empty (Mysten doesn't ship a public default key\n// server on mainnet — production is via Enoki). `devnet`\n// intentionally empty.\n\nimport { Effect } from 'effect';\n\nimport { expectNonEmptyString } from '../../../substrate/runtime/config-validation.ts';\nimport { sealConfigError } from '../errors.ts';\nimport type { SealKeyServerEntry, SealKnownResolved } from '../registry-publish.ts';\n\n// ---------------------------------------------------------------------------\n// Known-deployment table — distilled-doc reference\n// ---------------------------------------------------------------------------\n\n/** Closed set of known deployments. `mainnet` + `devnet` intentionally\n * null (no public default key server). `testnet` carries the public\n * key-server URL but `keyServerObjectId` is `null` until a real id is\n * sourced`validateLiveInputs` forces the caller to supply\n * `objectId` explicitly in that case. */\nexport const KNOWN_DEPLOYMENTS: {\n\treadonly testnet: {\n\t\treadonly keyServerObjectId: string | null;\n\t\treadonly keyServerUrl: string;\n\t};\n\treadonly mainnet: null;\n\treadonly devnet: null;\n} = {\n\ttestnet: {\n\t\tkeyServerObjectId: null,\n\t\tkeyServerUrl: 'https://seal-keyserver.testnet.mystenlabs.com',\n\t},\n\tmainnet: null,\n\tdevnet: null,\n};\n\nexport type KnownNetwork = keyof typeof KNOWN_DEPLOYMENTS;\n\n// ---------------------------------------------------------------------------\n// Inputs\n// ---------------------------------------------------------------------------\n\n/** Live-mode inputs. Either `network` resolves to a known deployment\n * OR the user supplies explicit `objectId` + `keyServerUrl`\n * overrides. Distilled-doc §\"Configuration\" — the factory throws\n * synchronously if neither path produces a usable tuple. */\nexport interface LiveModeInputs {\n\treadonly name: string;\n\treadonly network?: KnownNetwork;\n\treadonly objectId?: string;\n\treadonly keyServerUrl?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Resolved\n// ---------------------------------------------------------------------------\n\n/** Validate the inputs at the factory boundary. Pure synchronous\n * function. The plugin `start` body is reserved for Effect-flavored\n * work; the throw here matches v3's pattern (distilled-doc\n * §Failure modes). */\nexport const validateLiveInputs = (\n\tinputs: LiveModeInputs,\n): {\n\treadonly objectId: string;\n\treadonly keyServerUrl: string;\n} => {\n\tconst fromNetwork =\n\t\tinputs.network && KNOWN_DEPLOYMENTS[inputs.network] ? KNOWN_DEPLOYMENTS[inputs.network] : null;\n\tconst objectId = inputs.objectId ?? fromNetwork?.keyServerObjectId;\n\tconst keyServerUrl = inputs.keyServerUrl ?? fromNetwork?.keyServerUrl;\n\tconst message = `seal.live: missing required fields. Pass network ('testnet') or set objectId + keyServerUrl explicitly (got network=${String(\n\t\tinputs.network,\n\t)}, objectId=${String(inputs.objectId)}, keyServerUrl=${String(inputs.keyServerUrl)}).`;\n\treturn {\n\t\tobjectId: expectNonEmptyString(objectId, {\n\t\t\tfield: 'objectId',\n\t\t\tmessage,\n\t\t\tmkError: sealConfigError,\n\t\t}),\n\t\tkeyServerUrl: expectNonEmptyString(keyServerUrl, {\n\t\t\tfield: 'keyServerUrl',\n\t\t\tmessage,\n\t\t\tmkError: sealConfigError,\n\t\t}),\n\t};\n};\n\n// ---------------------------------------------------------------------------\n// Mode acquire\n// ---------------------------------------------------------------------------\n\n/** Acquire body for the live mode. Validation already ran at the\n * factory boundary (see `index.ts:buildLivePlugin`); this projects\n * the validated bundle into the resolved shape. Returns the\n * read-side handle ONLY (no manager tag distilled-doc invariant #15). */\nexport const acquireLive = (inputs: {\n\treadonly name: string;\n\treadonly resolved: { readonly objectId: string; readonly keyServerUrl: string };\n}): Effect.Effect<SealKnownResolved> =>\n\tEffect.sync(() => {\n\t\tconst serverConfigs: ReadonlyArray<SealKeyServerEntry> = [\n\t\t\t{ objectId: inputs.resolved.objectId, weight: 1 },\n\t\t];\n\t\treturn {\n\t\t\tkeyServer: {\n\t\t\t\tserverConfigs,\n\t\t\t\tkeyServerUrl: inputs.resolved.keyServerUrl,\n\t\t\t\tobjectId: inputs.resolved.objectId,\n\t\t\t},\n\t\t} satisfies SealKnownResolved;\n\t});\n"],"mappings":";;;;;;;;;AAoCA,MAAa,oBAOT;CACH,SAAS;EACR,mBAAmB;EACnB,cAAc;EACd;CACD,SAAS;CACT,QAAQ;CACR;;;;;AA2BD,MAAa,sBACZ,WAII;CACJ,MAAM,cACL,OAAO,WAAW,kBAAkB,OAAO,WAAW,kBAAkB,OAAO,WAAW;CAC3F,MAAM,WAAW,OAAO,YAAY,aAAa;CACjD,MAAM,eAAe,OAAO,gBAAgB,aAAa;CACzD,MAAM,UAAU,uHAAuH,OACtI,OAAO,QACP,CAAC,aAAa,OAAO,OAAO,SAAS,CAAC,iBAAiB,OAAO,OAAO,aAAa,CAAC;AACpF,QAAO;EACN,UAAU,qBAAqB,UAAU;GACxC,OAAO;GACP;GACA,SAAS;GACT,CAAC;EACF,cAAc,qBAAqB,cAAc;GAChD,OAAO;GACP;GACA,SAAS;GACT,CAAC;EACF;;;;;;AAWF,MAAa,eAAe,WAI3B,OAAO,WAAW;AAIjB,QAAO,EACN,WAAW;EACV,eAAA,CAJD;GAAE,UAAU,OAAO,SAAS;GAAU,QAAQ;GAAG,CAInC;EACb,cAAc,OAAO,SAAS;EAC9B,UAAU,OAAO,SAAS;EAC1B,EACD;EACA"}