@fased/fased 0.1.62 → 0.1.64

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 (341) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +38 -30
  3. package/config/dependency-ownership.json +1 -1
  4. package/config/signer-policies/README.md +49 -0
  5. package/config/signer-policies/agent.json.template +32 -0
  6. package/config/signer-policies/mining.json.template +69 -0
  7. package/config/signer-policies/network.json.template +5 -0
  8. package/config/signer-policies/vault.json.template +70 -0
  9. package/config/signer-protocol-v2.json +76 -0
  10. package/config/typescript-noemit-baseline.json +680 -0
  11. package/dist/agents/auth-profiles/store.js +267 -31
  12. package/dist/agents/bash-tools.exec.js +10 -4
  13. package/dist/agents/current-model-catalog.js +3 -3
  14. package/dist/agents/memory-search.js +7 -1
  15. package/dist/agents/model-catalog-access.js +1 -2
  16. package/dist/agents/model-catalog-snapshot.js +1 -1
  17. package/dist/agents/model-catalog-source.js +1 -1
  18. package/dist/agents/model-metadata.js +1 -1
  19. package/dist/agents/model-selection.js +2 -28
  20. package/dist/agents/models-config.providers.js +6 -6
  21. package/dist/agents/pi-embedded-runner/compact.js +15 -7
  22. package/dist/agents/pi-embedded-runner/model.js +1 -1
  23. package/dist/agents/pi-embedded-runner/run/attempt.js +24 -13
  24. package/dist/agents/pi-embedded-runner/run.js +2 -0
  25. package/dist/agents/pi-embedded-runner/tool-split.js +40 -2
  26. package/dist/agents/pi-tool-definition-adapter.js +16 -1
  27. package/dist/agents/pi-tools.js +2 -1
  28. package/dist/agents/sandbox/config.js +1 -1
  29. package/dist/agents/sandbox/context.js +27 -2
  30. package/dist/agents/skills/env-overrides.js +38 -28
  31. package/dist/agents/skills/trust.js +93 -0
  32. package/dist/agents/skills/workspace.js +128 -0
  33. package/dist/agents/skills-clawhub.js +36 -11
  34. package/dist/agents/skills-marketplace-scan.js +49 -0
  35. package/dist/agents/tools/marketplace-offer-draft-tool.js +1 -1
  36. package/dist/agents/tools/mining-tool.js +1 -1
  37. package/dist/agents/tools/session-status-tool.js +1 -1
  38. package/dist/agents/tools/wallet-action-tool.js +172 -36
  39. package/dist/agents/tools/wallet-skill-policy.js +65 -23
  40. package/dist/agents/tools/wallet-tool.js +7 -11
  41. package/dist/auto-reply/reply/directive-handling.fast-lane.js +2 -1
  42. package/dist/auto-reply/reply/directive-handling.impl.js +2 -1
  43. package/dist/auto-reply/reply/directive-handling.model.js +2 -1
  44. package/dist/auto-reply/reply/directive-handling.persist.js +2 -2
  45. package/dist/auto-reply/reply/get-reply-directives-apply.js +2 -0
  46. package/dist/auto-reply/reply/get-reply-inline-actions.js +25 -1
  47. package/dist/auto-reply/reply/model-selection.js +7 -4
  48. package/dist/auto-reply/reply/session-reset-model.js +4 -4
  49. package/dist/brand.js +1 -1
  50. package/dist/build-info.json +3 -3
  51. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  52. package/dist/channel-web.js +2 -2
  53. package/dist/cli/gateway-cli/run.js +8 -0
  54. package/dist/cli/program/command-registry.js +1 -1
  55. package/dist/cli/program/register.onboard.js +2 -3
  56. package/dist/cli/program/register.wallet.js +16 -123
  57. package/dist/cli/providers-cli.js +1 -1
  58. package/dist/cli/sat-cli.js +129 -2
  59. package/dist/cli/update-cli/update-command.js +260 -11
  60. package/dist/commands/auth-choice.apply.api-providers.js +3 -3
  61. package/dist/commands/doctor-config-flow.js +1 -1
  62. package/dist/commands/doctor-legacy-config.js +2 -13
  63. package/dist/commands/model-picker.js +6 -6
  64. package/dist/commands/models/auth.js +1 -1
  65. package/dist/commands/onboard-auth.config-gateways.js +1 -1
  66. package/dist/commands/onboard-auth.credentials.js +32 -8
  67. package/dist/commands/onboard-non-interactive/local/wallet-config.js +28 -27
  68. package/dist/commands/onboard-non-interactive/local.js +5 -1
  69. package/dist/commands/wallet.js +568 -1911
  70. package/dist/config/config.js +2 -2
  71. package/dist/config/io.js +64 -2
  72. package/dist/config/schema.help.js +8 -7
  73. package/dist/config/schema.labels.js +5 -4
  74. package/dist/config/zod-schema.agent-runtime.js +1 -0
  75. package/dist/config/zod-schema.js +5 -0
  76. package/dist/control-ui/assets/{app-DLil9VO1.js → app-bR-fO5ty.js} +1511 -1555
  77. package/dist/control-ui/assets/{config-CU5Zi8Dh.js → config-LeImukCW.js} +10 -10
  78. package/dist/control-ui/assets/{federation-D10Q4eP_.js → federation-DgA9e-Pn.js} +364 -422
  79. package/dist/control-ui/assets/{index-DdE_NIXo.js → index-ckCxHwjy.js} +3 -3
  80. package/dist/control-ui/assets/{mining-BdhMn18r.js → mining-BgHFh0ei.js} +134 -114
  81. package/dist/control-ui/assets/mining-commit-DFpB_4JN.js +2 -0
  82. package/dist/control-ui/assets/{open-external-url-DwSiwMPl.js → open-external-url-ulF1B-sA.js} +3 -3
  83. package/dist/control-ui/assets/{providers-QMn4w2_f.js → providers-CIx9fxc6.js} +2 -2
  84. package/dist/control-ui/assets/{wallet-C2g294QT.js → wallet-DvStR_AT.js} +259 -377
  85. package/dist/control-ui/index.html +1 -1
  86. package/dist/control-ui/version.json +1 -1
  87. package/dist/daemon/systemd-system.js +56 -50
  88. package/dist/extensions/sat-mining/src/protocol-contract.js +43 -3
  89. package/dist/extensions/sat-mining/src/rpc-read.js +235 -67
  90. package/dist/extensions/sat-mining/src/sat-bond-layout.js +5 -2
  91. package/dist/extensions/sat-mining/src/signer-codec-manifest.js +406 -0
  92. package/dist/extensions/sat-mining/src/solana-submit.js +1038 -397
  93. package/dist/extensions/sat-mining/src/submission-ledger.js +349 -0
  94. package/dist/federation/auto-connect.js +98 -8
  95. package/dist/federation/marketplace-capability-adapter.js +33 -7
  96. package/dist/federation/marketplace-delivery-outbox.js +196 -0
  97. package/dist/federation/marketplace-delivery.js +351 -215
  98. package/dist/federation/marketplace-direct-payment.js +272 -141
  99. package/dist/federation/marketplace-escrow.js +607 -249
  100. package/dist/federation/marketplace-settlement-ledger.js +352 -0
  101. package/dist/federation/offers.js +9 -7
  102. package/dist/federation/peer-auth-v2.js +529 -0
  103. package/dist/gateway/a2a-http.js +425 -96
  104. package/dist/gateway/a2a-settlement.js +259 -153
  105. package/dist/gateway/a2a-task-store.js +524 -0
  106. package/dist/gateway/auth.js +38 -2
  107. package/dist/gateway/config-reload.js +46 -33
  108. package/dist/gateway/durable-capacity.js +31 -0
  109. package/dist/gateway/federation-http.js +540 -135
  110. package/dist/gateway/federation-marketplace-run-store.js +397 -0
  111. package/dist/gateway/federation-marketplace.js +535 -230
  112. package/dist/gateway/mutating-admin-rpc-rate-limit.js +5 -0
  113. package/dist/gateway/security-path.js +1 -1
  114. package/dist/gateway/server-http.js +1084 -1205
  115. package/dist/gateway/server-methods/models.js +1 -1
  116. package/dist/gateway/server-methods/secrets.js +40 -0
  117. package/dist/gateway/server-methods.js +1 -2
  118. package/dist/gateway/server-reload-handlers.js +196 -66
  119. package/dist/gateway/server-runtime-config.js +1 -1
  120. package/dist/gateway/server-secrets-runtime.js +288 -0
  121. package/dist/gateway/server.impl.js +73 -42
  122. package/dist/gateway/sessions-patch.js +3 -5
  123. package/dist/index.js +4 -2
  124. package/dist/infra/fasedhub.js +64 -1
  125. package/dist/infra/local-source-paired-update.js +538 -0
  126. package/dist/infra/restart.js +41 -10
  127. package/dist/infra/update-runner.js +96 -0
  128. package/dist/light-update-status.js +11 -11
  129. package/dist/memory/backend-config.js +2 -1
  130. package/dist/memory/session-files.js +16 -2
  131. package/dist/plugin-sdk/{accounts-DxblobYM.js → accounts-Brn3-uWN.js} +1 -1
  132. package/dist/plugin-sdk/{actions-D4UNimWa.js → actions-DRu135h0.js} +2 -2
  133. package/dist/plugin-sdk/{active-listener-CFuy106s.js → active-listener-B_NMtgPL.js} +1 -1
  134. package/dist/plugin-sdk/{audio-preflight-Bwi2Oq03.js → audio-preflight-BYxAt775.js} +27 -27
  135. package/dist/plugin-sdk/{audit-Cs0K7LBp.js → audit-C5d2z5U1.js} +1 -1
  136. package/dist/plugin-sdk/{channel-access-D5aHoTY8.js → channel-access-CcFRdRPO.js} +1 -1
  137. package/dist/plugin-sdk/{channel-access-configure-Dvch9mMQ.js → channel-access-configure-DaI5wevh.js} +1 -1
  138. package/dist/plugin-sdk/channel-plugin-common.d.ts +3 -3
  139. package/dist/plugin-sdk/channel-plugin-common.js +4 -4
  140. package/dist/plugin-sdk/{chunk-B0FUGc5A.js → chunk-CyoyqpbG.js} +1 -1
  141. package/dist/plugin-sdk/{chunk-items-DzT4L4Ty.js → chunk-items-DIRHG2gJ.js} +1 -1
  142. package/dist/plugin-sdk/command-status.d.ts +2 -2
  143. package/dist/plugin-sdk/command-status.js +27 -27
  144. package/dist/plugin-sdk/{commands-registry-DmDRhRAU.js → commands-registry-BfqdEWdF.js} +2 -2
  145. package/dist/plugin-sdk/{common-CfUOowOp.js → common-HCcXU-NR.js} +1 -1
  146. package/dist/plugin-sdk/{config-mxULv0fQ.js → config-DlWVeLFB.js} +7113 -6877
  147. package/dist/plugin-sdk/{config-schema-BrkmtFxB.js → config-schema-BOT7kHb6.js} +6779 -3696
  148. package/dist/plugin-sdk/device-pair.d.ts +1 -1
  149. package/dist/plugin-sdk/discord.d.ts +6 -6
  150. package/dist/plugin-sdk/discord.js +19 -19
  151. package/dist/plugin-sdk/file-lock.js +35 -4
  152. package/dist/plugin-sdk/{filesystem-manager-ZoHU8oA7.js → filesystem-manager-DoI8IBNF.js} +1 -1
  153. package/dist/plugin-sdk/{group-mentions-BHRff6j8.d.ts → group-mentions-q3hUTCt7.d.ts} +1 -1
  154. package/dist/plugin-sdk/{handle-action-DbVCF9HZ.js → handle-action-hvwapMKg.js} +13 -13
  155. package/dist/plugin-sdk/{helpers-BXbdgs5H.js → helpers-DMBU4oTo.js} +1 -1
  156. package/dist/plugin-sdk/{image-ops-D7jPxaph.js → image-ops-DQi0n_Tt.js} +1 -1
  157. package/dist/plugin-sdk/index.d.ts +21 -39
  158. package/dist/plugin-sdk/index.js +29 -29
  159. package/dist/plugin-sdk/{login-BRxww6nv.js → login-Ca583Okc.js} +3 -3
  160. package/dist/plugin-sdk/{login-qr-DJXsk9XH.js → login-qr-CGciBSNP.js} +3 -3
  161. package/dist/plugin-sdk/{manager-Y2S_5IlI.js → manager-BegWxNYX.js} +4 -4
  162. package/dist/plugin-sdk/{markdown-tables-DHLFQqaF.js → markdown-tables-DCOXEUfZ.js} +1 -1
  163. package/dist/plugin-sdk/{media-Czo4carg.js → media-CAdQF5TG.js} +47 -47
  164. package/dist/plugin-sdk/{memory-search-DTjIMw8J.js → memory-search-CrFPOeTH.js} +4 -1
  165. package/dist/plugin-sdk/{monitor-M_ta2lMc.js → monitor-BCFDaqJ-.js} +31 -31
  166. package/dist/plugin-sdk/{monitor-wYVncM9w.js → monitor-BgbjRiPM.js} +32 -32
  167. package/dist/plugin-sdk/{openresponses-http-B2GmeSt4.js → openresponses-http-DFf87SMM.js} +27 -27
  168. package/dist/plugin-sdk/{optional-runtime-dependency-DdMbxS24.js → optional-runtime-dependency-0dznm3ZO.js} +1 -1
  169. package/dist/plugin-sdk/{outbound-Db8mRN6P.js → outbound-BgVDdHxx.js} +6 -6
  170. package/dist/plugin-sdk/{outbound-attachment-BqFjcypb.js → outbound-attachment-QqTnIhZL.js} +2 -2
  171. package/dist/plugin-sdk/{pairing-message-B3bHYGaw.d.ts → pairing-message-CS-9BHug.d.ts} +2 -2
  172. package/dist/plugin-sdk/{pairing-message-B3GC_7CD.js → pairing-message-D0CoLHRJ.js} +1 -1
  173. package/dist/plugin-sdk/{pairing-store-CQikgIbw.js → pairing-store-BChahgI2.js} +2 -2
  174. package/dist/plugin-sdk/{pi-model-discovery-CY3m5zJP.js → pi-model-discovery-BX_JLcEJ.js} +1 -1
  175. package/dist/plugin-sdk/{pi-model-discovery-runtime-DSh1T2pn.js → pi-model-discovery-runtime-DxTMz_XF.js} +2 -2
  176. package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +2 -2
  177. package/dist/plugin-sdk/{pw-ai-AFUqn-tQ.js → pw-ai-natjh3rm.js} +3 -3
  178. package/dist/plugin-sdk/{qmd-manager-DSyx77KY.js → qmd-manager-CgRaTxUq.js} +1 -1
  179. package/dist/plugin-sdk/{query-expansion-CAI2kKLQ.js → query-expansion-BG3FgzF7.js} +14 -3
  180. package/dist/plugin-sdk/{replies-Fzh9PhXl.js → replies-ChYo5ZQM.js} +2 -2
  181. package/dist/plugin-sdk/{resolve-outbound-target-KpF3co6T.js → resolve-outbound-target-D-KGgHJZ.js} +1 -1
  182. package/dist/plugin-sdk/{resolve-route-CDl74O19.js → resolve-route-C8tvQm8Z.js} +1 -1
  183. package/dist/plugin-sdk/{retry-policy-D4uiqUOG.js → retry-policy-C6SjKjQA.js} +1 -1
  184. package/dist/plugin-sdk/{runtime-Bb6KRnCC.js → runtime-2B9_WKoI.js} +8 -3
  185. package/dist/plugin-sdk/{runtime-dependency-DLDmB94f.js → runtime-dependency-DczkvPxn.js} +2 -2
  186. package/dist/plugin-sdk/sat-runtime.d.ts +549 -309
  187. package/dist/plugin-sdk/sat-runtime.js +29 -29
  188. package/dist/plugin-sdk/{send-C4k4JuJN.js → send-B6KkGKZD.js} +6 -6
  189. package/dist/plugin-sdk/{send-D-uDKGIq.js → send-CFzGKJXo.js} +6 -6
  190. package/dist/plugin-sdk/{send-Du8ykP1k.js → send-DCO441U7.js} +8 -8
  191. package/dist/plugin-sdk/{send-5nFktR1n.js → send-gDoGA-7e.js} +5 -5
  192. package/dist/plugin-sdk/{send-Bfzf11VY.js → send-q9HXrSwK.js} +7 -7
  193. package/dist/plugin-sdk/{session-CS-Td9EM.js → session-DHD4ZKyG.js} +2 -2
  194. package/dist/plugin-sdk/{skill-commands-CFAlXWHk.js → skill-commands-FKEPLS7T.js} +201 -26
  195. package/dist/plugin-sdk/{slack-CxE1mfzj.js → slack-BUTt8cxK.js} +39 -39
  196. package/dist/plugin-sdk/{slack-actions-BcMkNv1Z.js → slack-actions-DhbMcp8M.js} +11 -11
  197. package/dist/plugin-sdk/slack.d.ts +6 -6
  198. package/dist/plugin-sdk/slack.js +9 -9
  199. package/dist/plugin-sdk/{sticker-cache-CGzGWu00.js → sticker-cache-D0wHVqjt.js} +3 -3
  200. package/dist/plugin-sdk/{tables-bFXyRpkx.js → tables-B3jr0Pvq.js} +1 -1
  201. package/dist/plugin-sdk/{targets-DH7a9lKB.js → targets-CtSbTxYX.js} +1 -1
  202. package/dist/plugin-sdk/{telegram-actions-DaEcYQ8r.js → telegram-actions-CC_qN4v0.js} +30 -30
  203. package/dist/plugin-sdk/telegram.d.ts +6 -6
  204. package/dist/plugin-sdk/telegram.js +8 -8
  205. package/dist/plugin-sdk/{thread-bindings.lifecycle-CgOvvdw8.js → thread-bindings.lifecycle-QbkNl-m6.js} +3 -3
  206. package/dist/plugin-sdk/{thread-bindings.state-CQpk44Hq.js → thread-bindings.state-D9hg_M1c.js} +2 -2
  207. package/dist/plugin-sdk/tmp-fased-dir-xOTGlzBE.d.ts +486 -0
  208. package/dist/plugin-sdk/{types-vcJrC_uv.d.ts → types-C3avNytw.d.ts} +3 -4
  209. package/dist/plugin-sdk/{types-DyhXnYUr.d.ts → types-D0kDG8l0.d.ts} +3 -2
  210. package/dist/plugin-sdk/{types-DFAW-n1J.d.ts → types-DWfbSAaM.d.ts} +2 -2
  211. package/dist/plugin-sdk/{types.plugin-_fbu40Re.d.ts → types.plugin-BcSBq42x.d.ts} +8 -3
  212. package/dist/plugin-sdk/{web-CInY-lCv.js → web-BXsJ1vqe.js} +32 -32
  213. package/dist/plugin-sdk/{whatsapp-actions-BtSc2CBv.js → whatsapp-actions-Bj_rOncr.js} +13 -13
  214. package/dist/plugin-sdk/{whatsapp-heartbeat-Bg9TuYzl.js → whatsapp-heartbeat-B1WHkJIg.js} +2 -2
  215. package/dist/plugin-sdk/whatsapp.d.ts +13 -13
  216. package/dist/plugin-sdk/whatsapp.js +12 -12
  217. package/dist/plugin-sdk/{wsl-C4DGFkOd.js → wsl-J-HscWxS.js} +3 -3
  218. package/dist/plugin-sdk/{zod-schema.providers-core-BEbNizPe.d.ts → zod-schema.providers-core-CIzCjXH9.d.ts} +61 -61
  219. package/dist/providers/refresh.js +1 -1
  220. package/dist/providers/registry.js +1 -1
  221. package/dist/secrets/apply.js +1 -1
  222. package/dist/secrets/runtime.js +1 -1
  223. package/dist/wallet/external-submission-ledger.js +376 -0
  224. package/dist/wallet/legacy-embedded-keystore.js +40 -0
  225. package/dist/wallet/local-socket-signer-archive.js +30 -0
  226. package/dist/wallet/local-socket-signer-lifecycle.js +97 -0
  227. package/dist/wallet/local-socket-signer-policy.js +166 -0
  228. package/dist/wallet/local-socket-signer-protocol.js +561 -118
  229. package/dist/wallet/native-signer-wallet-id.js +25 -0
  230. package/dist/wallet/providers/alchemy-adapter.js +3 -0
  231. package/dist/wallet/providers/local-socket-signer-adapter.js +380 -105
  232. package/dist/wallet/providers/turnkey-adapter.js +292 -34
  233. package/dist/wallet/providers/wallet-standard-adapter.js +100 -0
  234. package/dist/wallet/signer-network-admin.js +184 -0
  235. package/dist/wallet/signer-protocol-v2.generated.js +90 -0
  236. package/dist/wallet/solana-bond-signing.js +157 -69
  237. package/dist/wallet/solana-reviewed-transaction.js +375 -0
  238. package/dist/wallet/solana-swap.js +520 -64
  239. package/dist/wallet/solana-transaction-inspection.js +106 -4
  240. package/dist/wallet/solana-trigger.js +658 -320
  241. package/dist/wallet/turnkey-reviewed-state.js +370 -0
  242. package/dist/wallet/wallet-approval-auth.js +17 -28
  243. package/dist/wallet/wallet-atomic-state.js +53 -0
  244. package/dist/wallet/wallet-canary.js +0 -1
  245. package/dist/wallet/wallet-inbound-events.js +16 -11
  246. package/dist/wallet/wallet-policy-simulation.js +1 -1
  247. package/dist/wallet/wallet-policy.js +90 -36
  248. package/dist/wallet/wallet-provider-capabilities.js +28 -4
  249. package/dist/wallet/wallet-provider-registry.js +57 -44
  250. package/dist/wallet/wallet-provider-resolver.js +62 -63
  251. package/dist/wallet/wallet-runtime-config.js +28 -41
  252. package/dist/wallet/wallet-secrets-store.js +22 -0
  253. package/dist/wallet/wallet-send-approvals.js +1891 -589
  254. package/dist/wallet/wallet-send-execution-ledger.js +292 -0
  255. package/dist/wallet/wallet-settlement-links.js +14 -13
  256. package/dist/wallet/wallet-standard-review.js +353 -0
  257. package/dist/wallet/wallet-status.js +0 -9
  258. package/dist/wallet/wallet-task-ledger.js +16 -2
  259. package/dist/web/auto-reply/heartbeat-runner.js +1 -1
  260. package/dist/web/auto-reply/monitor.js +2 -2
  261. package/dist/wizard/host-security-capability.js +14 -23
  262. package/dist/wizard/onboarding.finalize.js +63 -184
  263. package/dist/wizard/onboarding.host-security.js +117 -1367
  264. package/dist/wizard/onboarding.js +172 -217
  265. package/dist/wizard/onboarding.wallet.js +232 -785
  266. package/extensions/acpx/package.json +1 -1
  267. package/extensions/bluebubbles/package.json +1 -1
  268. package/extensions/copilot-proxy/package.json +1 -1
  269. package/extensions/diagnostics-otel/package.json +1 -1
  270. package/extensions/fased-federation/package.json +1 -1
  271. package/extensions/google-gemini-cli-auth/package.json +1 -1
  272. package/extensions/imessage/package.json +1 -1
  273. package/extensions/irc/package.json +1 -1
  274. package/extensions/line/package.json +1 -1
  275. package/extensions/llm-task/package.json +1 -1
  276. package/extensions/lobster/package.json +1 -1
  277. package/extensions/matrix/CHANGELOG.md +12 -0
  278. package/extensions/matrix/package.json +1 -1
  279. package/extensions/mattermost/package.json +1 -1
  280. package/extensions/memory-core/package.json +2 -2
  281. package/extensions/memory-lancedb/package.json +1 -1
  282. package/extensions/minimax-portal-auth/package.json +1 -1
  283. package/extensions/msteams/CHANGELOG.md +12 -0
  284. package/extensions/msteams/package.json +1 -1
  285. package/extensions/nextcloud-talk/package.json +1 -1
  286. package/extensions/nostr/CHANGELOG.md +12 -0
  287. package/extensions/nostr/package.json +1 -1
  288. package/extensions/open-prose/package.json +1 -1
  289. package/extensions/sat-mining/index.ts +498 -153
  290. package/extensions/sat-mining/package.json +1 -1
  291. package/extensions/sat-mining/signer-codec-schema.v1.json +374 -0
  292. package/extensions/sat-mining/src/audit-store.ts +50 -5
  293. package/extensions/sat-mining/src/claim-service.ts +85 -14
  294. package/extensions/sat-mining/src/config.ts +9 -0
  295. package/extensions/sat-mining/src/cycle-progress.ts +16 -8
  296. package/extensions/sat-mining/src/epoch-service.ts +9 -5
  297. package/extensions/sat-mining/src/gateway-runner.ts +21 -1
  298. package/extensions/sat-mining/src/protocol-contract.ts +45 -1
  299. package/extensions/sat-mining/src/recovery-service.ts +312 -0
  300. package/extensions/sat-mining/src/round-watcher.ts +391 -81
  301. package/extensions/sat-mining/src/rpc-read.ts +330 -89
  302. package/extensions/sat-mining/src/runtime.ts +14 -0
  303. package/extensions/sat-mining/src/sat-bond-layout.ts +6 -0
  304. package/extensions/sat-mining/src/signer-codec-manifest.ts +429 -0
  305. package/extensions/sat-mining/src/solana-submit.ts +1199 -428
  306. package/extensions/sat-mining/src/submission-ledger.ts +433 -0
  307. package/extensions/signal/package.json +1 -1
  308. package/extensions/synology-chat/package.json +1 -1
  309. package/extensions/tlon/package.json +1 -1
  310. package/extensions/twitch/CHANGELOG.md +12 -0
  311. package/extensions/twitch/package.json +1 -1
  312. package/extensions/voice-call/CHANGELOG.md +12 -0
  313. package/extensions/voice-call/package.json +1 -1
  314. package/extensions/zalo/CHANGELOG.md +12 -0
  315. package/extensions/zalo/package.json +1 -1
  316. package/extensions/zalouser/CHANGELOG.md +12 -0
  317. package/extensions/zalouser/package.json +1 -1
  318. package/install.sh +4955 -0
  319. package/package.json +23 -5
  320. package/scripts/fased-host-updater.mjs +1421 -0
  321. package/scripts/fased-host-updaterctl.mjs +186 -0
  322. package/scripts/fased-managed-service.sh +36 -0
  323. package/scripts/fased-managed-updater.mjs +3065 -156
  324. package/scripts/fased-signer-enroll-hosting.sh +275 -0
  325. package/scripts/fased-signer-network-hosting.sh +143 -0
  326. package/scripts/fased-signer-owner-policy.mjs +1430 -0
  327. package/scripts/fased-signer-policy-hosting.sh +50 -0
  328. package/scripts/fased-signer-policy-local.sh +26 -0
  329. package/scripts/hosted-release-manifest.mjs +185 -0
  330. package/scripts/install-fased-signerd.sh +183 -108
  331. package/scripts/install-managed-runtime.mjs +212 -10
  332. package/scripts/managed-runtime-layout.mjs +75 -3
  333. package/scripts/migrate-hosted-signer-v2.mjs +58 -0
  334. package/scripts/start-managed.sh +169 -360
  335. package/dist/control-ui/assets/mining-commit-R-6nu87p.js +0 -2
  336. package/dist/plugin-sdk/tmp-fased-dir-CS6zsYEE.d.ts +0 -77
  337. package/dist/wallet/local-socket-signer-broker.js +0 -224
  338. package/dist/wallet/local-socket-signer-custody.js +0 -42
  339. package/dist/wallet/providers/embedded-keystore-adapter.js +0 -402
  340. package/dist/wallet/providers/privy-adapter.js +0 -80
  341. package/dist/wallet/wallet-custody.js +0 -1836
@@ -0,0 +1,538 @@
1
+ import { resolveStateDir } from "../config/paths.js";
2
+ import { runCommandWithTimeout } from "../process/exec.js";
3
+ import path from "node:path";
4
+ import fs from "node:fs/promises";
5
+ import { createHash, randomUUID } from "node:crypto";
6
+ import * as tar from "tar";
7
+
8
+ //#region src/infra/local-source-paired-update.ts
9
+ const JOURNAL_SCHEMA_VERSION = 1;
10
+ const PHASES = new Set([
11
+ "prepared",
12
+ "app-active",
13
+ "signer-active",
14
+ "gateway-verified",
15
+ "committing",
16
+ "rolling-back"
17
+ ]);
18
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
19
+ const SHA_PATTERN = /^[a-f0-9]{40}$/;
20
+ const VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z]+(?:[.-][0-9A-Za-z]+)*)?$/;
21
+ function resolveContext(env = process.env) {
22
+ const stateDir = path.resolve(resolveStateDir(env));
23
+ const updateRoot = path.join(stateDir, "source-paired-update");
24
+ return {
25
+ stateDir,
26
+ updateRoot,
27
+ transactionsDir: path.join(updateRoot, "transactions"),
28
+ journalPath: path.join(updateRoot, "transaction.json")
29
+ };
30
+ }
31
+ function pathIsInside(parent, candidate) {
32
+ const relative = path.relative(path.resolve(parent), path.resolve(candidate));
33
+ return relative !== "" && !relative.startsWith("..") && !path.isAbsolute(relative);
34
+ }
35
+ async function fsyncPath(target) {
36
+ const handle = await fs.open(target, "r");
37
+ try {
38
+ await handle.sync();
39
+ } finally {
40
+ await handle.close();
41
+ }
42
+ }
43
+ async function sha256File(filePath) {
44
+ const bytes = await fs.readFile(filePath);
45
+ return createHash("sha256").update(bytes).digest("hex");
46
+ }
47
+ function validateRelease(value, label) {
48
+ const release = value;
49
+ if (!release || !SHA_PATTERN.test(release.sha ?? "") || !VERSION_PATTERN.test(release.version ?? "")) {
50
+ throw new Error(`Local source paired update has an invalid ${label} release identity`);
51
+ }
52
+ return {
53
+ sha: release.sha,
54
+ version: release.version
55
+ };
56
+ }
57
+ function validateJournal(context, value) {
58
+ const journal = value;
59
+ if (!journal || journal.schemaVersion !== JOURNAL_SCHEMA_VERSION || journal.kind !== "source-checkout" || !UUID_PATTERN.test(journal.transactionId ?? "") || !PHASES.has(journal.phase) || typeof journal.sourceRoot !== "string" || !path.isAbsolute(journal.sourceRoot) || typeof journal.transactionDir !== "string" || path.resolve(journal.transactionDir) !== path.join(context.transactionsDir, journal.transactionId ?? "") || !pathIsInside(context.updateRoot, journal.transactionDir) || path.resolve(journal.controllerPath ?? "") !== path.join(journal.transactionDir, "controller", "fased-managed-updater.mjs") || typeof journal.previous?.branch !== "string" && journal.previous?.branch !== null || typeof journal.previous?.branch === "string" && (!journal.previous.branch || journal.previous.branch.includes("..") || !/^[0-9A-Za-z._/-]+$/.test(journal.previous.branch)) || typeof journal.distSnapshot?.path !== "string" || path.resolve(journal.distSnapshot.path) !== path.join(journal.transactionDir, "dist.tar.gz") || !/^[a-f0-9]{64}$/.test(journal.distSnapshot?.sha256 ?? "") || !Number.isSafeInteger(journal.distSnapshot?.size) || (journal.distSnapshot?.size ?? -1) <= 0) {
60
+ throw new Error("Local source paired update journal is invalid");
61
+ }
62
+ const previous = validateRelease(journal.previous, "previous");
63
+ const needsTarget = new Set([
64
+ "app-active",
65
+ "signer-active",
66
+ "gateway-verified",
67
+ "committing"
68
+ ]).has(journal.phase);
69
+ const target = journal.target === null ? null : validateRelease(journal.target, "target");
70
+ if (needsTarget && target === null) {
71
+ throw new Error("Local source paired update journal is missing its target release identity");
72
+ }
73
+ return {
74
+ ...journal,
75
+ sourceRoot: path.resolve(journal.sourceRoot),
76
+ previous: {
77
+ ...previous,
78
+ branch: journal.previous.branch
79
+ },
80
+ target
81
+ };
82
+ }
83
+ async function writeJournal(context, journal, phase = journal.phase, exclusive = false) {
84
+ const next = validateJournal(context, {
85
+ ...journal,
86
+ phase,
87
+ updatedAt: new Date().toISOString()
88
+ });
89
+ await fs.mkdir(context.updateRoot, {
90
+ recursive: true,
91
+ mode: 448
92
+ });
93
+ if (exclusive) {
94
+ const handle = await fs.open(context.journalPath, "wx", 384);
95
+ try {
96
+ await handle.writeFile(`${JSON.stringify(next, null, 2)}\n`);
97
+ await handle.sync();
98
+ } finally {
99
+ await handle.close();
100
+ }
101
+ } else {
102
+ const temporary = `${context.journalPath}.tmp-${process.pid}-${Date.now()}`;
103
+ const handle = await fs.open(temporary, "wx", 384);
104
+ try {
105
+ await handle.writeFile(`${JSON.stringify(next, null, 2)}\n`);
106
+ await handle.sync();
107
+ } finally {
108
+ await handle.close();
109
+ }
110
+ await fs.rename(temporary, context.journalPath);
111
+ }
112
+ await fsyncPath(context.updateRoot);
113
+ return next;
114
+ }
115
+ async function readLocalSourcePairedUpdateJournal(env = process.env) {
116
+ const context = resolveContext(env);
117
+ try {
118
+ return validateJournal(context, JSON.parse(await fs.readFile(context.journalPath, "utf8")));
119
+ } catch (error) {
120
+ if (error.code === "ENOENT") {
121
+ return null;
122
+ }
123
+ throw error;
124
+ }
125
+ }
126
+ async function runExact(argv, options) {
127
+ const result = await runCommandWithTimeout(argv, {
128
+ cwd: options.cwd,
129
+ timeoutMs: options.timeoutMs,
130
+ env: options.env
131
+ });
132
+ if (result.code !== 0) {
133
+ const detail = (result.stderr || result.stdout).trim().split("\n").slice(-5).join("\n");
134
+ throw new Error(`${options.label} failed${detail ? `: ${detail}` : ""}`);
135
+ }
136
+ return result.stdout.trim();
137
+ }
138
+ async function readGitHead(sourceRoot, timeoutMs, env) {
139
+ const sha = await runExact([
140
+ "git",
141
+ "-C",
142
+ sourceRoot,
143
+ "rev-parse",
144
+ "HEAD"
145
+ ], {
146
+ cwd: sourceRoot,
147
+ timeoutMs,
148
+ env,
149
+ label: "git HEAD verification"
150
+ });
151
+ if (!SHA_PATTERN.test(sha)) {
152
+ throw new Error("Source checkout did not report an exact Git commit");
153
+ }
154
+ return sha;
155
+ }
156
+ async function readPackageVersion(sourceRoot) {
157
+ const parsed = JSON.parse(await fs.readFile(path.join(sourceRoot, "package.json"), "utf8"));
158
+ const version = typeof parsed.version === "string" ? parsed.version.trim() : "";
159
+ if (!VERSION_PATTERN.test(version)) {
160
+ throw new Error("Source checkout package.json has no exact release version");
161
+ }
162
+ return version;
163
+ }
164
+ async function copyController(sourceRoot, transactionDir) {
165
+ const controllerDir = path.join(transactionDir, "controller");
166
+ await fs.mkdir(controllerDir, {
167
+ recursive: true,
168
+ mode: 448
169
+ });
170
+ for (const name of ["fased-managed-updater.mjs", "managed-runtime-layout.mjs"]) {
171
+ const source = path.join(sourceRoot, "scripts", name);
172
+ const stat = await fs.lstat(source);
173
+ if (!stat.isFile() || stat.isSymbolicLink()) {
174
+ throw new Error(`Source checkout is missing a safe signer transaction controller: ${source}`);
175
+ }
176
+ const destination = path.join(controllerDir, name);
177
+ await fs.copyFile(source, destination);
178
+ await fs.chmod(destination, name.endsWith("updater.mjs") ? 448 : 384);
179
+ await fsyncPath(destination);
180
+ }
181
+ await fsyncPath(controllerDir);
182
+ return path.join(controllerDir, "fased-managed-updater.mjs");
183
+ }
184
+ async function isLocalSourceSignerConfigured(env = process.env) {
185
+ const stateDir = resolveContext(env).stateDir;
186
+ for (const candidate of [path.join(stateDir, "bin", "fased-signerd"), path.join(stateDir, "wallet", "signerd-v2.db")]) {
187
+ const found = await fs.lstat(candidate).then((stat) => stat.isFile() && !stat.isSymbolicLink()).catch(() => false);
188
+ if (found) {
189
+ return true;
190
+ }
191
+ }
192
+ try {
193
+ const registry = JSON.parse(await fs.readFile(path.join(stateDir, "wallet", "provider-registry.v1.json"), "utf8"));
194
+ return (registry.wallets ?? []).some((wallet) => wallet?.providerId === "local-socket-signer");
195
+ } catch {
196
+ return false;
197
+ }
198
+ }
199
+ async function prepareLocalSourcePairedUpdate(params) {
200
+ const env = params.env ?? process.env;
201
+ const context = resolveContext(env);
202
+ if (await readLocalSourcePairedUpdateJournal(env)) {
203
+ throw new Error("An unfinished Local source app/signer transaction must be recovered first");
204
+ }
205
+ const sourceRoot = path.resolve(params.sourceRoot);
206
+ const previousSha = await readGitHead(sourceRoot, params.timeoutMs, env);
207
+ const previousVersion = await readPackageVersion(sourceRoot);
208
+ const branchResult = await runCommandWithTimeout([
209
+ "git",
210
+ "-C",
211
+ sourceRoot,
212
+ "symbolic-ref",
213
+ "--quiet",
214
+ "--short",
215
+ "HEAD"
216
+ ], {
217
+ cwd: sourceRoot,
218
+ timeoutMs: params.timeoutMs,
219
+ env
220
+ });
221
+ const branch = branchResult.code === 0 && branchResult.stdout.trim() ? branchResult.stdout.trim() : null;
222
+ if (branch !== null && (branch.includes("..") || !/^[0-9A-Za-z._/-]+$/.test(branch))) {
223
+ throw new Error("Source checkout branch name is unsafe for transactional rollback");
224
+ }
225
+ const transactionId = randomUUID();
226
+ const transactionDir = path.join(context.transactionsDir, transactionId);
227
+ await fs.mkdir(transactionDir, {
228
+ recursive: true,
229
+ mode: 448
230
+ });
231
+ try {
232
+ const distRoot = path.join(sourceRoot, "dist");
233
+ const distStat = await fs.lstat(distRoot);
234
+ if (!distStat.isDirectory() || distStat.isSymbolicLink()) {
235
+ throw new Error("Source checkout has no safe built dist directory to snapshot");
236
+ }
237
+ const distSnapshotPath = path.join(transactionDir, "dist.tar.gz");
238
+ await tar.c({
239
+ cwd: sourceRoot,
240
+ file: distSnapshotPath,
241
+ gzip: true,
242
+ portable: true,
243
+ noMtime: true
244
+ }, ["dist"]);
245
+ await fs.chmod(distSnapshotPath, 384);
246
+ await fsyncPath(distSnapshotPath);
247
+ const distSnapshotStat = await fs.lstat(distSnapshotPath);
248
+ const controllerPath = await copyController(sourceRoot, transactionDir);
249
+ const now = new Date().toISOString();
250
+ const journal = {
251
+ schemaVersion: 1,
252
+ kind: "source-checkout",
253
+ transactionId,
254
+ transactionDir,
255
+ sourceRoot,
256
+ controllerPath,
257
+ phase: "prepared",
258
+ previous: {
259
+ sha: previousSha,
260
+ version: previousVersion,
261
+ branch
262
+ },
263
+ target: null,
264
+ distSnapshot: {
265
+ path: distSnapshotPath,
266
+ sha256: await sha256File(distSnapshotPath),
267
+ size: distSnapshotStat.size
268
+ },
269
+ createdAt: now,
270
+ updatedAt: now
271
+ };
272
+ await fsyncPath(transactionDir);
273
+ return await writeJournal(context, journal, "prepared", true);
274
+ } catch (error) {
275
+ await fs.rm(transactionDir, {
276
+ recursive: true,
277
+ force: true
278
+ });
279
+ throw error;
280
+ }
281
+ }
282
+ async function markLocalSourceAppActive(params) {
283
+ if (params.journal.phase !== "prepared") {
284
+ throw new Error(`Cannot activate source app from phase ${params.journal.phase}`);
285
+ }
286
+ const context = resolveContext(params.env ?? process.env);
287
+ const target = validateRelease({
288
+ sha: params.targetSha,
289
+ version: params.targetVersion
290
+ }, "target");
291
+ return await writeJournal(context, {
292
+ ...params.journal,
293
+ target
294
+ }, "app-active");
295
+ }
296
+ async function runSignerController(params) {
297
+ const args = [
298
+ params.journal.controllerPath,
299
+ "local-signer",
300
+ params.action
301
+ ];
302
+ if (params.action === "verify") {
303
+ if (!params.journal.target) {
304
+ throw new Error("Cannot verify a Local signer without a target release");
305
+ }
306
+ args.push("--version", params.journal.target.version, "--expected-commit", params.journal.target.sha, "--timeout", String(Math.ceil(params.timeoutMs / 1e3)));
307
+ }
308
+ await runExact([process.execPath, ...args], {
309
+ cwd: path.dirname(params.journal.controllerPath),
310
+ timeoutMs: params.timeoutMs,
311
+ env: params.env,
312
+ label: `Local signer ${params.action}`
313
+ });
314
+ }
315
+ async function activateLocalSourceSigner(params) {
316
+ if (params.journal.phase !== "app-active" || !params.journal.target) {
317
+ throw new Error(`Cannot activate Local signer from phase ${params.journal.phase}`);
318
+ }
319
+ const env = params.env ?? process.env;
320
+ const installer = path.join(params.journal.sourceRoot, "scripts", "install-fased-signerd.sh");
321
+ const stat = await fs.lstat(installer);
322
+ if (!stat.isFile() || stat.isSymbolicLink()) {
323
+ throw new Error("Updated source checkout is missing its safe Local signer installer");
324
+ }
325
+ await runExact([
326
+ "bash",
327
+ installer,
328
+ "--version",
329
+ params.journal.target.version,
330
+ "--expected-commit",
331
+ params.journal.target.sha,
332
+ "--defer-commit"
333
+ ], {
334
+ cwd: params.journal.sourceRoot,
335
+ timeoutMs: params.timeoutMs,
336
+ env,
337
+ label: "Local signer prepare and activation"
338
+ });
339
+ return await writeJournal(resolveContext(env), params.journal, "signer-active");
340
+ }
341
+ async function verifyLocalSourceSigner(params) {
342
+ if (!new Set(["signer-active", "gateway-verified"]).has(params.journal.phase)) {
343
+ throw new Error(`Cannot verify Local signer from phase ${params.journal.phase}`);
344
+ }
345
+ await runSignerController({
346
+ journal: params.journal,
347
+ action: "verify",
348
+ timeoutMs: params.timeoutMs,
349
+ env: params.env ?? process.env
350
+ });
351
+ }
352
+ async function markLocalSourceGatewayVerified(journal, env = process.env) {
353
+ if (journal.phase !== "signer-active") {
354
+ throw new Error(`Cannot record Gateway verification from phase ${journal.phase}`);
355
+ }
356
+ return await writeJournal(resolveContext(env), journal, "gateway-verified");
357
+ }
358
+ async function removeTransaction(journal, env) {
359
+ const context = resolveContext(env);
360
+ await fs.rm(context.journalPath, { force: true });
361
+ await fsyncPath(context.updateRoot);
362
+ await fs.rm(journal.transactionDir, {
363
+ recursive: true,
364
+ force: true
365
+ });
366
+ await fsyncPath(context.transactionsDir);
367
+ }
368
+ async function commitLocalSourcePairedUpdate(params) {
369
+ const env = params.env ?? process.env;
370
+ let journal = params.journal;
371
+ if (journal.phase !== "gateway-verified" && journal.phase !== "committing") {
372
+ throw new Error(`Cannot commit Local source pair from phase ${journal.phase}`);
373
+ }
374
+ if (journal.phase !== "committing") {
375
+ journal = await writeJournal(resolveContext(env), journal, "committing");
376
+ }
377
+ await runSignerController({
378
+ journal,
379
+ action: "commit",
380
+ timeoutMs: params.timeoutMs,
381
+ env
382
+ });
383
+ await removeTransaction(journal, env);
384
+ }
385
+ async function restoreSourceApplication(params) {
386
+ const { journal, timeoutMs, env } = params;
387
+ const snapshotStat = await fs.lstat(journal.distSnapshot.path);
388
+ if (!snapshotStat.isFile() || snapshotStat.isSymbolicLink() || snapshotStat.size !== journal.distSnapshot.size || await sha256File(journal.distSnapshot.path) !== journal.distSnapshot.sha256) {
389
+ throw new Error("Local source rollback dist snapshot failed integrity verification");
390
+ }
391
+ if (journal.previous.branch) {
392
+ await runExact([
393
+ "git",
394
+ "-C",
395
+ journal.sourceRoot,
396
+ "checkout",
397
+ journal.previous.branch
398
+ ], {
399
+ cwd: journal.sourceRoot,
400
+ timeoutMs,
401
+ env,
402
+ label: "source rollback branch checkout"
403
+ });
404
+ await runExact([
405
+ "git",
406
+ "-C",
407
+ journal.sourceRoot,
408
+ "reset",
409
+ "--hard",
410
+ journal.previous.sha
411
+ ], {
412
+ cwd: journal.sourceRoot,
413
+ timeoutMs,
414
+ env,
415
+ label: "source rollback commit restore"
416
+ });
417
+ } else {
418
+ await runExact([
419
+ "git",
420
+ "-C",
421
+ journal.sourceRoot,
422
+ "checkout",
423
+ "--detach",
424
+ journal.previous.sha
425
+ ], {
426
+ cwd: journal.sourceRoot,
427
+ timeoutMs,
428
+ env,
429
+ label: "source rollback detached commit restore"
430
+ });
431
+ }
432
+ await runExact([
433
+ "pnpm",
434
+ "install",
435
+ "--offline",
436
+ "--frozen-lockfile"
437
+ ], {
438
+ cwd: journal.sourceRoot,
439
+ timeoutMs,
440
+ env,
441
+ label: "offline source dependency rollback"
442
+ });
443
+ await fs.rm(path.join(journal.sourceRoot, "dist"), {
444
+ recursive: true,
445
+ force: true
446
+ });
447
+ await tar.x({
448
+ cwd: journal.sourceRoot,
449
+ file: journal.distSnapshot.path,
450
+ strict: true,
451
+ filter: (entryPath) => entryPath === "dist" || entryPath.startsWith("dist/")
452
+ });
453
+ if (await readGitHead(journal.sourceRoot, timeoutMs, env) !== journal.previous.sha) {
454
+ throw new Error("Local source rollback restored the wrong Git commit");
455
+ }
456
+ if (await readPackageVersion(journal.sourceRoot) !== journal.previous.version) {
457
+ throw new Error("Local source rollback restored the wrong package version");
458
+ }
459
+ }
460
+ async function rollbackLocalSourcePairedUpdate(params) {
461
+ const env = params.env ?? process.env;
462
+ let journal = params.journal;
463
+ if (journal.phase !== "rolling-back") {
464
+ journal = await writeJournal(resolveContext(env), journal, "rolling-back");
465
+ }
466
+ const failures = [];
467
+ try {
468
+ await runSignerController({
469
+ journal,
470
+ action: "rollback",
471
+ timeoutMs: params.timeoutMs,
472
+ env
473
+ });
474
+ } catch (error) {
475
+ failures.push(`signer: ${String(error)}`);
476
+ }
477
+ if (failures.length === 0) {
478
+ try {
479
+ await restoreSourceApplication({
480
+ journal,
481
+ timeoutMs: params.timeoutMs,
482
+ env
483
+ });
484
+ } catch (error) {
485
+ failures.push(`application: ${String(error)}`);
486
+ }
487
+ }
488
+ if (failures.length > 0) {
489
+ throw new Error(`Local source paired rollback is incomplete (${failures.join("; ")}). Re-run fased update after correcting the failure.`);
490
+ }
491
+ await removeTransaction(journal, env);
492
+ }
493
+ async function recoverLocalSourcePairedUpdate(params) {
494
+ const env = params.env ?? process.env;
495
+ const journal = await readLocalSourcePairedUpdateJournal(env);
496
+ if (!journal) {
497
+ return "none";
498
+ }
499
+ if (journal.phase === "gateway-verified" || journal.phase === "committing") {
500
+ await commitLocalSourcePairedUpdate({
501
+ journal,
502
+ timeoutMs: params.timeoutMs,
503
+ env
504
+ });
505
+ return "committed";
506
+ }
507
+ await rollbackLocalSourcePairedUpdate({
508
+ journal,
509
+ timeoutMs: params.timeoutMs,
510
+ env
511
+ });
512
+ return "rolled-back";
513
+ }
514
+ async function assertLocalSourcePairedGatewayStartAllowed(params) {
515
+ const env = params.env ?? process.env;
516
+ const journal = await readLocalSourcePairedUpdateJournal(env);
517
+ if (!journal) {
518
+ return;
519
+ }
520
+ if (journal.phase !== "signer-active" && journal.phase !== "gateway-verified" && journal.phase !== "committing") {
521
+ throw new Error(`Gateway startup is blocked by an unfinished Local source app/signer update (${journal.phase}). Run fased update to recover it.`);
522
+ }
523
+ if (!journal.target || path.resolve(params.runtimeRoot) !== journal.sourceRoot) {
524
+ throw new Error("Gateway startup is blocked because the source update target root does not match");
525
+ }
526
+ const timeoutMs = params.timeoutMs ?? 5e3;
527
+ const [sha, version] = await Promise.all([readGitHead(journal.sourceRoot, timeoutMs, env), readPackageVersion(journal.sourceRoot)]);
528
+ if (sha !== journal.target.sha || version !== journal.target.version) {
529
+ throw new Error("Gateway startup is blocked because the source update target identity changed");
530
+ }
531
+ }
532
+ const __testing = {
533
+ resolveContext,
534
+ validateJournal
535
+ };
536
+
537
+ //#endregion
538
+ export { activateLocalSourceSigner, assertLocalSourcePairedGatewayStartAllowed, commitLocalSourcePairedUpdate, isLocalSourceSignerConfigured, markLocalSourceAppActive, markLocalSourceGatewayVerified, prepareLocalSourcePairedUpdate, readLocalSourcePairedUpdateJournal, recoverLocalSourcePairedUpdate, rollbackLocalSourcePairedUpdate, verifyLocalSourceSigner };
@@ -151,44 +151,75 @@ function deferGatewayRestartUntilIdle(opts) {
151
151
  const pollMs = Math.max(10, Math.floor(pollMsRaw));
152
152
  const maxWaitMsRaw = opts.maxWaitMs ?? DEFAULT_DEFERRAL_MAX_WAIT_MS;
153
153
  const maxWaitMs = Math.max(pollMs, Math.floor(maxWaitMsRaw));
154
- let pending;
154
+ let pendingPoll = null;
155
+ let pending = false;
156
+ const handle = {
157
+ cancel: () => {
158
+ if (!pending || !pendingPoll) {
159
+ return false;
160
+ }
161
+ clearInterval(pendingPoll);
162
+ pendingPoll = null;
163
+ pending = false;
164
+ return true;
165
+ },
166
+ isPending: () => pending
167
+ };
168
+ let pendingCount;
155
169
  try {
156
- pending = opts.getPendingCount();
170
+ pendingCount = opts.getPendingCount();
157
171
  } catch (err) {
158
172
  opts.hooks?.onCheckError?.(err);
159
173
  emitGatewayRestart();
160
- return;
174
+ return handle;
161
175
  }
162
- if (pending <= 0) {
176
+ if (pendingCount <= 0) {
163
177
  opts.hooks?.onReady?.();
164
178
  emitGatewayRestart();
165
- return;
179
+ return handle;
166
180
  }
167
- opts.hooks?.onDeferring?.(pending);
181
+ opts.hooks?.onDeferring?.(pendingCount);
168
182
  const startedAt = Date.now();
169
- const poll = setInterval(() => {
183
+ pending = true;
184
+ pendingPoll = setInterval(() => {
170
185
  let current;
171
186
  try {
172
187
  current = opts.getPendingCount();
173
188
  } catch (err) {
174
- clearInterval(poll);
189
+ if (!pending) {
190
+ return;
191
+ }
192
+ pending = false;
193
+ if (pendingPoll) {
194
+ clearInterval(pendingPoll);
195
+ pendingPoll = null;
196
+ }
175
197
  opts.hooks?.onCheckError?.(err);
176
198
  emitGatewayRestart();
177
199
  return;
178
200
  }
179
201
  if (current <= 0) {
180
- clearInterval(poll);
202
+ pending = false;
203
+ if (pendingPoll) {
204
+ clearInterval(pendingPoll);
205
+ pendingPoll = null;
206
+ }
181
207
  opts.hooks?.onReady?.();
182
208
  emitGatewayRestart();
183
209
  return;
184
210
  }
185
211
  const elapsedMs = Date.now() - startedAt;
186
212
  if (elapsedMs >= maxWaitMs) {
187
- clearInterval(poll);
213
+ pending = false;
214
+ if (pendingPoll) {
215
+ clearInterval(pendingPoll);
216
+ pendingPoll = null;
217
+ }
188
218
  opts.hooks?.onTimeout?.(current, elapsedMs);
189
219
  emitGatewayRestart();
190
220
  }
191
221
  }, pollMs);
222
+ return handle;
192
223
  }
193
224
  function formatSpawnDetail(result) {
194
225
  const clean = (value) => {