@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
@@ -1,6 +1,5 @@
1
1
  import { defaultRuntime } from "../../runtime.js";
2
2
  import { resolveAgentDir, resolveDefaultAgentId, resolveSessionAgentId } from "../../agents/agent-scope.js";
3
- import { listProviderBrandManifests } from "../../providers/registry.js";
4
3
  import { DEFAULT_PROVIDER } from "../../agents/defaults.js";
5
4
  import { normalizeSecretInput } from "../../utils/normalize-secret-input.js";
6
5
  import { normalizeProviderId } from "../../agents/provider-id.js";
@@ -11,6 +10,7 @@ import { loadConfig, writeConfigFile } from "../../config/io.js";
11
10
  import "../../config/config.js";
12
11
  import { resolveProfileUnusableUntilForDisplay } from "../../agents/auth-profiles/usage.js";
13
12
  import "../../agents/auth-profiles.js";
13
+ import { listProviderBrandManifests } from "../../providers/registry.js";
14
14
  import { ensureFasedModelsJson } from "../../agents/models-config.js";
15
15
  import { deriveModelMetadata } from "../../agents/model-metadata.js";
16
16
  import { ErrorCodes, errorShape } from "../protocol/schema/error-codes.js";
@@ -0,0 +1,40 @@
1
+ import { logMutatingAdminRpcAudit } from "./mutating-admin-rpc-audit.js";
2
+ import { ErrorCodes, errorShape } from "../protocol/schema/error-codes.js";
3
+ import "../protocol/index.js";
4
+ import { sanitizeGatewaySecretsRuntimeError } from "../server-secrets-runtime.js";
5
+
6
+ //#region src/gateway/server-methods/secrets.ts
7
+ function createSecretsHandlers(params) {
8
+ return { "secrets.reload": async ({ respond, client, context }) => {
9
+ try {
10
+ const result = await params.reloadSecrets();
11
+ logMutatingAdminRpcAudit({
12
+ context,
13
+ client,
14
+ method: "secrets.reload",
15
+ outcome: "succeeded",
16
+ details: { warningCount: result.warningCount }
17
+ });
18
+ respond(true, {
19
+ ok: true,
20
+ warningCount: result.warningCount
21
+ });
22
+ } catch (err) {
23
+ const safe = sanitizeGatewaySecretsRuntimeError(err);
24
+ logMutatingAdminRpcAudit({
25
+ context,
26
+ client,
27
+ method: "secrets.reload",
28
+ outcome: "failed",
29
+ details: { code: safe.code }
30
+ });
31
+ respond(false, undefined, errorShape(ErrorCodes.UNAVAILABLE, safe.message, {
32
+ retryable: true,
33
+ details: { code: safe.code }
34
+ }));
35
+ }
36
+ } };
37
+ }
38
+
39
+ //#endregion
40
+ export { createSecretsHandlers };
@@ -55,10 +55,9 @@ const CONTROL_PLANE_WRITE_METHODS = new Set([
55
55
  ]);
56
56
  const SAT_MINING_MUTATION_METHODS = new Set([
57
57
  "sat.openCycle",
58
- "sat.bootstrapRegistryReserve",
58
+ "sat.topUpRegistryReserve",
59
59
  "sat.refillRegistryReserveFromTreasury",
60
60
  "sat.runProtocolMaintenanceOnce",
61
- "sat.setProtocolRecipients",
62
61
  "sat.claimProtocolTreasury",
63
62
  "sat.claimProtocolDistributorSat",
64
63
  "sat.initMinerCapital",
@@ -19,76 +19,201 @@ function shouldInvalidateGatewayModelCatalog(changedPaths) {
19
19
  return changedPaths.some((path) => path === "models" || path.startsWith("models.") || path === "agents.defaults.model" || path.startsWith("agents.defaults.model.") || path === "agents.defaults.models" || path.startsWith("agents.defaults.models."));
20
20
  }
21
21
  function createGatewayReloadHandlers(params) {
22
- const applyHotReload = async (plan, nextConfig) => {
23
- setGatewaySigusr1RestartPolicy({ allowExternal: isRestartEnabled(nextConfig) });
24
- const state = params.getState();
25
- const nextState = { ...state };
26
- if (plan.reloadHooks) {
27
- try {
28
- nextState.hooksConfig = resolveHooksConfig(nextConfig);
29
- } catch (err) {
30
- params.logHooks.warn(`hooks config reload failed: ${String(err)}`);
31
- }
32
- }
33
- if (plan.restartHeartbeat) {
34
- nextState.heartbeatRunner.updateConfig(nextConfig);
35
- }
36
- resetDirectoryCache();
37
- if (shouldInvalidateGatewayModelCatalog(plan.changedPaths)) {
38
- markGatewayModelCatalogStaleForReload();
39
- }
40
- if (plan.restartCron) {
41
- state.cronState.cron.stop();
42
- nextState.cronState = buildGatewayCronService({
43
- cfg: nextConfig,
44
- deps: params.deps,
45
- broadcast: params.broadcast
22
+ const createHotReloadTransaction = (plan) => {
23
+ const originalState = params.getState();
24
+ let workingState = { ...originalState };
25
+ let policyMutated = false;
26
+ let heartbeatMutated = false;
27
+ let cronMutated = false;
28
+ let browserMutated = false;
29
+ let gmailMutated = false;
30
+ let concurrencyMutated = false;
31
+ const channelsMutated = [];
32
+ let applyStarted = false;
33
+ let rollbackStarted = false;
34
+ const publishState = () => {
35
+ params.setState({ ...workingState });
36
+ };
37
+ const startGmailWatcherForReload = async (config, phase) => {
38
+ let failed = false;
39
+ await startGmailWatcherWithLogs({
40
+ cfg: config,
41
+ log: {
42
+ info: (message) => params.logHooks.info(message),
43
+ warn: () => params.logHooks.warn(`gmail watcher ${phase} did not start`),
44
+ error: () => {
45
+ failed = true;
46
+ params.logHooks.error(`gmail watcher ${phase} failed to start`);
47
+ }
48
+ },
49
+ onSkipped: () => params.logHooks.info(`skipping gmail watcher ${phase} (FASED_SKIP_GMAIL_WATCHER=1)`)
46
50
  });
47
- void nextState.cronState.cron.start().catch((err) => params.logCron.error(`failed to start: ${String(err)}`));
48
- }
49
- if (plan.restartBrowserControl) {
50
- if (state.browserControl) {
51
- await state.browserControl.stop().catch(() => {});
51
+ if (failed) {
52
+ throw new Error(`gmail watcher ${phase} failed`);
52
53
  }
53
- try {
54
- nextState.browserControl = await startBrowserControlServerIfEnabled();
55
- } catch (err) {
56
- params.logBrowser.error(`server failed to start: ${String(err)}`);
54
+ };
55
+ const apply = async (nextConfig) => {
56
+ if (applyStarted) {
57
+ throw new Error("hot reload transaction already started");
57
58
  }
58
- }
59
- if (plan.restartGmailWatcher) {
60
- await stopGmailWatcher().catch(() => {});
61
- await startGmailWatcherWithLogs({
62
- cfg: nextConfig,
63
- log: params.logHooks,
64
- onSkipped: () => params.logHooks.info("skipping gmail watcher restart (FASED_SKIP_GMAIL_WATCHER=1)")
65
- });
66
- }
67
- if (plan.restartChannels.size > 0) {
68
- if (isTruthyEnvValue(process.env.FASED_SKIP_CHANNELS) || isTruthyEnvValue(process.env.FASED_SKIP_PROVIDERS)) {
69
- params.logChannels.info("skipping channel reload (FASED_SKIP_CHANNELS=1 or FASED_SKIP_PROVIDERS=1)");
70
- } else {
71
- const restartChannel = async (name) => {
72
- params.logChannels.info(`restarting ${name} channel`);
73
- await params.stopChannel(name);
74
- await params.startChannel(name);
75
- };
76
- for (const channel of plan.restartChannels) {
77
- await restartChannel(channel);
59
+ applyStarted = true;
60
+ policyMutated = true;
61
+ setGatewaySigusr1RestartPolicy({ allowExternal: isRestartEnabled(nextConfig) });
62
+ if (plan.reloadHooks) {
63
+ workingState.hooksConfig = resolveHooksConfig(nextConfig);
64
+ }
65
+ if (plan.restartHeartbeat) {
66
+ heartbeatMutated = true;
67
+ workingState.heartbeatRunner.updateConfig(nextConfig);
68
+ }
69
+ resetDirectoryCache();
70
+ if (shouldInvalidateGatewayModelCatalog(plan.changedPaths)) {
71
+ markGatewayModelCatalogStaleForReload();
72
+ }
73
+ if (plan.restartCron) {
74
+ cronMutated = true;
75
+ workingState.cronState.cron.stop();
76
+ workingState.cronState = buildGatewayCronService({
77
+ cfg: nextConfig,
78
+ deps: params.deps,
79
+ broadcast: params.broadcast
80
+ });
81
+ publishState();
82
+ await workingState.cronState.cron.start();
83
+ }
84
+ if (plan.restartBrowserControl) {
85
+ browserMutated = true;
86
+ try {
87
+ await workingState.browserControl?.stop();
88
+ } finally {
89
+ workingState.browserControl = null;
90
+ publishState();
78
91
  }
92
+ workingState.browserControl = await startBrowserControlServerIfEnabled();
93
+ publishState();
79
94
  }
80
- }
81
- setCommandLaneConcurrency(CommandLane.Cron, nextConfig.cron?.maxConcurrentRuns ?? 1);
82
- setCommandLaneConcurrency(CommandLane.Main, resolveAgentMaxConcurrent(nextConfig));
83
- setCommandLaneConcurrency(CommandLane.Subagent, resolveSubagentMaxConcurrent(nextConfig));
84
- if (plan.hotReasons.length > 0) {
85
- params.logReload.info(`config hot reload applied (${plan.hotReasons.join(", ")})`);
86
- } else if (plan.noopPaths.length > 0) {
87
- params.logReload.info(`config change applied (dynamic reads: ${plan.noopPaths.join(", ")})`);
88
- }
89
- params.setState(nextState);
95
+ if (plan.restartGmailWatcher) {
96
+ gmailMutated = true;
97
+ await stopGmailWatcher();
98
+ await startGmailWatcherForReload(nextConfig, "apply");
99
+ }
100
+ if (plan.restartChannels.size > 0) {
101
+ if (isTruthyEnvValue(process.env.FASED_SKIP_CHANNELS) || isTruthyEnvValue(process.env.FASED_SKIP_PROVIDERS)) {
102
+ params.logChannels.info("skipping channel reload (FASED_SKIP_CHANNELS=1 or FASED_SKIP_PROVIDERS=1)");
103
+ } else {
104
+ for (const channel of plan.restartChannels) {
105
+ channelsMutated.push(channel);
106
+ params.logChannels.info(`restarting ${channel} channel`);
107
+ await params.stopChannel(channel);
108
+ await params.startChannel(channel);
109
+ }
110
+ }
111
+ }
112
+ concurrencyMutated = true;
113
+ setCommandLaneConcurrency(CommandLane.Cron, nextConfig.cron?.maxConcurrentRuns ?? 1);
114
+ setCommandLaneConcurrency(CommandLane.Main, resolveAgentMaxConcurrent(nextConfig));
115
+ setCommandLaneConcurrency(CommandLane.Subagent, resolveSubagentMaxConcurrent(nextConfig));
116
+ if (plan.hotReasons.length > 0) {
117
+ params.logReload.info(`config hot reload applied (${plan.hotReasons.join(", ")})`);
118
+ } else if (plan.noopPaths.length > 0) {
119
+ params.logReload.info(`config change applied (dynamic reads: ${plan.noopPaths.join(", ")})`);
120
+ }
121
+ publishState();
122
+ };
123
+ const rollback = async (previousConfig) => {
124
+ if (!applyStarted || rollbackStarted) {
125
+ return;
126
+ }
127
+ rollbackStarted = true;
128
+ const failures = [];
129
+ const capture = async (operation) => {
130
+ try {
131
+ await operation();
132
+ return true;
133
+ } catch (error) {
134
+ failures.push(error);
135
+ return false;
136
+ }
137
+ };
138
+ if (concurrencyMutated) {
139
+ await capture(() => {
140
+ setCommandLaneConcurrency(CommandLane.Cron, previousConfig.cron?.maxConcurrentRuns ?? 1);
141
+ setCommandLaneConcurrency(CommandLane.Main, resolveAgentMaxConcurrent(previousConfig));
142
+ setCommandLaneConcurrency(CommandLane.Subagent, resolveSubagentMaxConcurrent(previousConfig));
143
+ });
144
+ }
145
+ for (const channel of channelsMutated.toReversed()) {
146
+ const stopped = await capture(async () => await params.stopChannel(channel));
147
+ if (stopped) {
148
+ await capture(async () => await params.startChannel(channel));
149
+ }
150
+ }
151
+ if (gmailMutated) {
152
+ const stopped = await capture(async () => await stopGmailWatcher());
153
+ if (stopped) {
154
+ await capture(async () => await startGmailWatcherForReload(previousConfig, "rollback"));
155
+ }
156
+ }
157
+ if (browserMutated) {
158
+ const candidateBrowser = workingState.browserControl;
159
+ const candidateStopped = await capture(async () => await candidateBrowser?.stop());
160
+ workingState.browserControl = null;
161
+ publishState();
162
+ if (candidateStopped) {
163
+ let restoredBrowser = null;
164
+ const restored = await capture(async () => {
165
+ restoredBrowser = await startBrowserControlServerIfEnabled();
166
+ });
167
+ if (restored) {
168
+ workingState.browserControl = restoredBrowser;
169
+ publishState();
170
+ }
171
+ }
172
+ }
173
+ if (cronMutated) {
174
+ await capture(() => workingState.cronState.cron.stop());
175
+ workingState.cronState = originalState.cronState;
176
+ publishState();
177
+ await capture(async () => await originalState.cronState.cron.start());
178
+ }
179
+ if (heartbeatMutated) {
180
+ const restored = await capture(() => workingState.heartbeatRunner.updateConfig(previousConfig));
181
+ if (!restored) {
182
+ await capture(() => workingState.heartbeatRunner.stop());
183
+ }
184
+ }
185
+ workingState.hooksConfig = originalState.hooksConfig;
186
+ if (policyMutated) {
187
+ await capture(() => setGatewaySigusr1RestartPolicy({ allowExternal: isRestartEnabled(previousConfig) }));
188
+ }
189
+ resetDirectoryCache();
190
+ if (shouldInvalidateGatewayModelCatalog(plan.changedPaths)) {
191
+ markGatewayModelCatalogStaleForReload();
192
+ }
193
+ publishState();
194
+ if (failures.length > 0) {
195
+ throw new Error(`hot reload rollback incomplete (${failures.length} component failure(s))`);
196
+ }
197
+ };
198
+ return {
199
+ apply,
200
+ rollback
201
+ };
202
+ };
203
+ const applyHotReload = async (plan, nextConfig) => {
204
+ await createHotReloadTransaction(plan).apply(nextConfig);
90
205
  };
91
206
  let restartPending = false;
207
+ let restartDeferral = null;
208
+ const cancelPendingGatewayRestart = () => {
209
+ const cancelled = restartDeferral?.cancel() ?? false;
210
+ restartDeferral = null;
211
+ restartPending = false;
212
+ if (cancelled) {
213
+ params.logReload.info("cancelled deferred config restart before evaluating the latest revision");
214
+ }
215
+ return cancelled;
216
+ };
92
217
  const requestGatewayRestart = (plan, nextConfig) => {
93
218
  setGatewaySigusr1RestartPolicy({ allowExternal: isRestartEnabled(nextConfig) });
94
219
  const reasons = plan.restartReasons.length ? plan.restartReasons.join(", ") : plan.changedPaths.join(", ");
@@ -123,30 +248,33 @@ function createGatewayReloadHandlers(params) {
123
248
  const active = getActiveCounts();
124
249
  if (active.totalActive > 0) {
125
250
  if (restartPending) {
126
- params.logReload.info(`config change requires gateway restart (${reasons}) — already waiting for operations to complete`);
127
- return;
251
+ cancelPendingGatewayRestart();
128
252
  }
129
253
  restartPending = true;
130
254
  const initialDetails = formatActiveDetails(active);
131
255
  params.logReload.warn(`config change requires gateway restart (${reasons}) — deferring until ${initialDetails.join(", ")} complete`);
132
- deferGatewayRestartUntilIdle({
256
+ const deferral = deferGatewayRestartUntilIdle({
133
257
  getPendingCount: () => getActiveCounts().totalActive,
134
258
  hooks: {
135
259
  onReady: () => {
136
260
  restartPending = false;
261
+ restartDeferral = null;
137
262
  params.logReload.info("all operations and replies completed; restarting gateway now");
138
263
  },
139
264
  onTimeout: (_pending, elapsedMs) => {
140
265
  const remaining = formatActiveDetails(getActiveCounts());
141
266
  restartPending = false;
267
+ restartDeferral = null;
142
268
  params.logReload.warn(`restart timeout after ${elapsedMs}ms with ${remaining.join(", ")} still active; restarting anyway`);
143
269
  },
144
270
  onCheckError: (err) => {
145
271
  restartPending = false;
272
+ restartDeferral = null;
146
273
  params.logReload.warn(`restart deferral check failed (${String(err)}); restarting gateway now`);
147
274
  }
148
275
  }
149
276
  });
277
+ restartDeferral = deferral.isPending() ? deferral : null;
150
278
  } else {
151
279
  params.logReload.warn(`config change requires gateway restart (${reasons})`);
152
280
  const emitted = emitGatewayRestart();
@@ -157,6 +285,8 @@ function createGatewayReloadHandlers(params) {
157
285
  };
158
286
  return {
159
287
  applyHotReload,
288
+ cancelPendingGatewayRestart,
289
+ createHotReloadTransaction,
160
290
  requestGatewayRestart
161
291
  };
162
292
  }
@@ -1,7 +1,7 @@
1
1
  import { isLoopbackHost, isTrustedProxyAddress, isValidIPv4, resolveGatewayBindHost } from "./net.js";
2
2
  import { resolveWalletRuntimeConfig } from "../wallet/wallet-runtime-config.js";
3
- import { resolveWalletApprovalAuthMode } from "../wallet/wallet-approval-auth.js";
4
3
  import { normalizeControlUiBasePath } from "./control-ui-shared.js";
4
+ import { resolveWalletApprovalAuthMode } from "../wallet/wallet-approval-auth.js";
5
5
  import { resolveHooksConfig } from "./hooks.js";
6
6
  import { assertGatewayAuthConfigured, resolveGatewayAuth } from "./auth.js";
7
7
 
@@ -0,0 +1,288 @@
1
+ import { resolveMainSessionKeyFromConfig } from "../config/sessions/main-session.js";
2
+ import "../config/sessions.js";
3
+ import { enqueueSystemEvent } from "../infra/system-events.js";
4
+ import { activateSecretsRuntimeSnapshot, clearSecretsRuntimeSnapshot, getActiveSecretsRuntimeSnapshot, prepareSecretsRuntimeSnapshot } from "../secrets/runtime.js";
5
+ import { buildGatewayReloadPlan, diffConfigPaths, resolveGatewayReloadSettings } from "./config-reload.js";
6
+ import { isDeepStrictEqual } from "node:util";
7
+
8
+ //#region src/gateway/server-secrets-runtime.ts
9
+ var GatewaySecretsRuntimeError = class extends Error {
10
+ constructor(code, message, options) {
11
+ super(message, options);
12
+ this.name = "GatewaySecretsRuntimeError";
13
+ this.code = code;
14
+ }
15
+ };
16
+ function sanitizeGatewaySecretsRuntimeError(error) {
17
+ if (error instanceof GatewaySecretsRuntimeError) {
18
+ return {
19
+ code: error.code,
20
+ message: error.message
21
+ };
22
+ }
23
+ return {
24
+ code: "SECRETS_RELOAD_FAILED",
25
+ message: "Secret reload failed without changing the active runtime snapshot. Run `fased secrets audit --check` for local diagnostics."
26
+ };
27
+ }
28
+ function runtimeError(code, message, cause) {
29
+ return new GatewaySecretsRuntimeError(code, message, cause === undefined ? undefined : { cause });
30
+ }
31
+ function normalizeRuntimeError(error, fallbackCode, fallbackMessage) {
32
+ return error instanceof GatewaySecretsRuntimeError ? error : runtimeError(fallbackCode, fallbackMessage, error);
33
+ }
34
+ function invalidSnapshotError(snapshot) {
35
+ const paths = [...new Set(snapshot.issues.map((issue) => issue.path.trim() || "<root>"))].slice(0, 8);
36
+ const suffix = paths.length > 0 ? ` Invalid paths: ${paths.join(", ")}.` : "";
37
+ return runtimeError("SECRETS_CONFIG_INVALID", `Secret reload refused an invalid Gateway config.${suffix} Run \`fased doctor\` locally before retrying.`);
38
+ }
39
+ function missingSnapshotError() {
40
+ return runtimeError("SECRETS_CONFIG_MISSING", "Secret reload refused to replace the active snapshot because the Gateway config file is missing.");
41
+ }
42
+ function staleSourceError() {
43
+ return runtimeError("SECRETS_SOURCE_STALE", "Secret reload discarded a stale config revision; retry after the current config change finishes.");
44
+ }
45
+ function cloneConfig(config) {
46
+ return structuredClone(config);
47
+ }
48
+ function sameSourceSnapshot(left, right) {
49
+ if (left.exists !== right.exists || left.valid !== right.valid) {
50
+ return false;
51
+ }
52
+ if (left.hash && right.hash) {
53
+ return left.hash === right.hash;
54
+ }
55
+ return isDeepStrictEqual(left.config, right.config);
56
+ }
57
+ function planNeedsHotApply(plan) {
58
+ return plan.hotReasons.length > 0 || plan.reloadHooks || plan.restartGmailWatcher || plan.restartBrowserControl || plan.restartCron || plan.restartHeartbeat || plan.restartChannels.size > 0;
59
+ }
60
+ function assertManualSourceChangeAllowed(params) {
61
+ const changedPaths = diffConfigPaths(params.previous, params.next);
62
+ if (changedPaths.length === 0) {
63
+ return;
64
+ }
65
+ const plan = buildGatewayReloadPlan(changedPaths);
66
+ const settings = resolveGatewayReloadSettings(params.next);
67
+ if (settings.mode === "restart" || plan.restartGateway) {
68
+ throw runtimeError("SECRETS_SOURCE_RESTART_REQUIRED", "Secret reload refused config changes that require a Gateway restart. Let the config reloader restart the Gateway, then retry.");
69
+ }
70
+ if (planNeedsHotApply(plan)) {
71
+ throw runtimeError("SECRETS_SOURCE_HOT_RELOAD_REQUIRED", "Secret reload refused config changes that require live component reconfiguration. Let the config reloader apply them, then retry.");
72
+ }
73
+ }
74
+ function createGatewaySecretsRuntimeController(params) {
75
+ const prepareSnapshot = params.prepareSnapshot ?? prepareSecretsRuntimeSnapshot;
76
+ const activateSnapshot = params.activateSnapshot ?? activateSecretsRuntimeSnapshot;
77
+ const getActiveSnapshot = params.getActiveSnapshot ?? getActiveSecretsRuntimeSnapshot;
78
+ const clearSnapshot = params.clearSnapshot ?? clearSecretsRuntimeSnapshot;
79
+ let activeSourceConfig = null;
80
+ let degraded = false;
81
+ let closed = false;
82
+ let latestGeneration = 0;
83
+ let operationTail = Promise.resolve();
84
+ let shutdownPromise = null;
85
+ const runExclusive = (operation) => {
86
+ const result = operationTail.then(operation, operation);
87
+ operationTail = result.then(() => undefined, () => undefined);
88
+ return result;
89
+ };
90
+ const runTracked = (operation) => {
91
+ const generation = ++latestGeneration;
92
+ return runExclusive(async () => await operation(generation));
93
+ };
94
+ const assertCurrent = (generation) => {
95
+ if (closed) {
96
+ throw runtimeError("SECRETS_RUNTIME_CLOSED", "Secret reload was cancelled because the Gateway is shutting down.");
97
+ }
98
+ if (generation !== latestGeneration) {
99
+ throw staleSourceError();
100
+ }
101
+ };
102
+ const emitTransition = (code) => {
103
+ if (params.emitTransition) {
104
+ params.emitTransition(code);
105
+ return;
106
+ }
107
+ const text = code === "SECRETS_RELOADER_DEGRADED" ? `[${code}] Secret reload failed; the Gateway kept its last-known-good runtime snapshot.` : `[${code}] Secret references recovered and the Gateway activated a new runtime snapshot.`;
108
+ enqueueSystemEvent(text, {
109
+ sessionKey: resolveMainSessionKeyFromConfig(),
110
+ contextKey: "gateway-secrets-runtime",
111
+ trusted: true
112
+ });
113
+ };
114
+ const recordReloadFailure = (error) => {
115
+ const safe = sanitizeGatewaySecretsRuntimeError(error);
116
+ params.log.warn(`[SECRETS_RELOADER_DEGRADED] secret reload failed; keeping last-known-good runtime snapshot (${safe.code}): ${safe.message}`);
117
+ if (degraded || closed) {
118
+ return;
119
+ }
120
+ degraded = true;
121
+ emitTransition("SECRETS_RELOADER_DEGRADED");
122
+ };
123
+ const recordReloadSuccess = () => {
124
+ if (!degraded) {
125
+ return;
126
+ }
127
+ degraded = false;
128
+ params.log.info("[SECRETS_RELOADER_RECOVERED] secret runtime snapshot recovered");
129
+ emitTransition("SECRETS_RELOADER_RECOVERED");
130
+ };
131
+ const logWarnings = (prepared) => {
132
+ for (const warning of prepared.warnings) {
133
+ params.log.warn(`[${warning.code}] ${warning.message}`);
134
+ }
135
+ };
136
+ const prepareSafely = async (config) => {
137
+ try {
138
+ return await prepareSnapshot({ config });
139
+ } catch (error) {
140
+ throw normalizeRuntimeError(error, "SECRETS_RESOLUTION_FAILED", "One or more required secret references could not be resolved. Run `fased secrets audit --check` locally before retrying.");
141
+ }
142
+ };
143
+ const requireReloadableSnapshot = (snapshot) => {
144
+ if (!snapshot.exists) {
145
+ throw missingSnapshotError();
146
+ }
147
+ if (!snapshot.valid) {
148
+ throw invalidSnapshotError(snapshot);
149
+ }
150
+ };
151
+ const assertSnapshotStillCurrent = async (expected) => {
152
+ const current = await params.readConfigSnapshot();
153
+ requireReloadableSnapshot(current);
154
+ if (!sameSourceSnapshot(expected, current)) {
155
+ throw staleSourceError();
156
+ }
157
+ };
158
+ const restoreSnapshot = (previous) => {
159
+ try {
160
+ if (previous) {
161
+ activateSnapshot(previous);
162
+ } else {
163
+ clearSnapshot();
164
+ }
165
+ } catch {
166
+ clearSnapshot();
167
+ }
168
+ };
169
+ const activateStartup = (snapshot) => runTracked(async (generation) => {
170
+ if (!snapshot.valid) {
171
+ throw invalidSnapshotError(snapshot);
172
+ }
173
+ assertCurrent(generation);
174
+ const prepared = await prepareSafely(snapshot.config);
175
+ assertCurrent(generation);
176
+ activateSnapshot(prepared);
177
+ activeSourceConfig = cloneConfig(snapshot.config);
178
+ logWarnings(prepared);
179
+ return prepared;
180
+ });
181
+ const activateHotReload = (snapshot, transaction) => runTracked(async (generation) => {
182
+ try {
183
+ requireReloadableSnapshot(snapshot);
184
+ assertCurrent(generation);
185
+ await assertSnapshotStillCurrent(snapshot);
186
+ assertCurrent(generation);
187
+ const prepared = await prepareSafely(snapshot.config);
188
+ assertCurrent(generation);
189
+ await assertSnapshotStillCurrent(snapshot);
190
+ assertCurrent(generation);
191
+ const previous = getActiveSnapshot();
192
+ activateSnapshot(prepared);
193
+ try {
194
+ await transaction.apply(prepared.config);
195
+ assertCurrent(generation);
196
+ await assertSnapshotStillCurrent(snapshot);
197
+ assertCurrent(generation);
198
+ } catch (error) {
199
+ restoreSnapshot(previous);
200
+ if (previous) {
201
+ try {
202
+ await transaction.rollback(previous.config);
203
+ } catch (rollbackError) {
204
+ throw runtimeError("SECRETS_HOT_APPLY_FAILED", "Gateway hot reload failed. The last-known-good secret snapshot was restored, but one or more live components could not be restored and remain stopped.", rollbackError);
205
+ }
206
+ }
207
+ throw normalizeRuntimeError(error, "SECRETS_HOT_APPLY_FAILED", "Gateway hot reload failed; the last-known-good secret snapshot and live component state were restored.");
208
+ }
209
+ activeSourceConfig = cloneConfig(snapshot.config);
210
+ logWarnings(prepared);
211
+ recordReloadSuccess();
212
+ return prepared;
213
+ } catch (error) {
214
+ const safe = normalizeRuntimeError(error, "SECRETS_RELOAD_FAILED", "Secret reload failed without changing the active runtime snapshot.");
215
+ recordReloadFailure(safe);
216
+ throw safe;
217
+ }
218
+ });
219
+ const validateRestart = (snapshot) => runTracked(async (generation) => {
220
+ try {
221
+ requireReloadableSnapshot(snapshot);
222
+ assertCurrent(generation);
223
+ await assertSnapshotStillCurrent(snapshot);
224
+ assertCurrent(generation);
225
+ const prepared = await prepareSafely(snapshot.config);
226
+ assertCurrent(generation);
227
+ await assertSnapshotStillCurrent(snapshot);
228
+ assertCurrent(generation);
229
+ logWarnings(prepared);
230
+ return { warningCount: prepared.warnings.length };
231
+ } catch (error) {
232
+ const safe = normalizeRuntimeError(error, "SECRETS_RELOAD_FAILED", "Secret validation failed; the Gateway restart was not scheduled.");
233
+ recordReloadFailure(safe);
234
+ throw safe;
235
+ }
236
+ });
237
+ const reloadFromConfig = () => runTracked(async (generation) => {
238
+ try {
239
+ assertCurrent(generation);
240
+ const snapshot = await params.readConfigSnapshot();
241
+ requireReloadableSnapshot(snapshot);
242
+ if (!activeSourceConfig) {
243
+ throw runtimeError("SECRETS_RELOAD_FAILED", "Secret reload is unavailable before the startup snapshot is active.");
244
+ }
245
+ assertManualSourceChangeAllowed({
246
+ previous: activeSourceConfig,
247
+ next: snapshot.config
248
+ });
249
+ const prepared = await prepareSafely(snapshot.config);
250
+ assertCurrent(generation);
251
+ await assertSnapshotStillCurrent(snapshot);
252
+ assertCurrent(generation);
253
+ activateSnapshot(prepared);
254
+ activeSourceConfig = cloneConfig(snapshot.config);
255
+ logWarnings(prepared);
256
+ recordReloadSuccess();
257
+ return { warningCount: prepared.warnings.length };
258
+ } catch (error) {
259
+ const safe = normalizeRuntimeError(error, "SECRETS_RELOAD_FAILED", "Secret reload failed without changing the active runtime snapshot.");
260
+ recordReloadFailure(safe);
261
+ throw safe;
262
+ }
263
+ });
264
+ const shutdown = () => {
265
+ if (shutdownPromise) {
266
+ return shutdownPromise;
267
+ }
268
+ closed = true;
269
+ latestGeneration += 1;
270
+ shutdownPromise = (async () => {
271
+ await operationTail;
272
+ activeSourceConfig = null;
273
+ degraded = false;
274
+ clearSnapshot();
275
+ })();
276
+ return shutdownPromise;
277
+ };
278
+ return {
279
+ activateStartup,
280
+ activateHotReload,
281
+ validateRestart,
282
+ reloadFromConfig,
283
+ shutdown
284
+ };
285
+ }
286
+
287
+ //#endregion
288
+ export { createGatewaySecretsRuntimeController, sanitizeGatewaySecretsRuntimeError };