@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,19 +1,55 @@
1
+ import { fetchSolanaRpc } from "../solana-assets.js";
1
2
  import { WalletProviderError } from "../wallet-provider-adapter.js";
3
+ import { walletDiagnosticErrorMessage } from "../wallet-redaction.js";
4
+ import { executeTurnkeyReviewedTransaction, prepareTurnkeyReviewedTransaction } from "../turnkey-reviewed-state.js";
5
+ import { Transaction } from "@solana/web3.js";
6
+ import { Turnkey, defaultSolanaAccountAtIndex } from "@turnkey/sdk-server";
2
7
 
3
8
  //#region src/wallet/providers/turnkey-adapter.ts
9
+ const DEFAULT_TURNKEY_API_BASE_URL = "https://api.turnkey.com";
10
+ function clean(value) {
11
+ return String(value ?? "").trim();
12
+ }
13
+ function asProviderError(error, action) {
14
+ if (error instanceof WalletProviderError) {
15
+ return error;
16
+ }
17
+ return new WalletProviderError({
18
+ code: "wallet_provider_unavailable",
19
+ message: `Turnkey ${action} failed: ${walletDiagnosticErrorMessage(error)}`,
20
+ retryable: false,
21
+ cause: error
22
+ });
23
+ }
4
24
  var TurnkeyAdapter = class {
5
25
  constructor(options) {
6
26
  this.id = "turnkey";
7
27
  this.displayName = "Turnkey Wallet";
8
- this.credentials = options.credentials;
28
+ this.clientPromise = null;
29
+ this.credentials = {
30
+ apiPublicKey: clean(options.credentials.apiPublicKey),
31
+ apiPrivateKey: clean(options.credentials.apiPrivateKey),
32
+ organizationId: clean(options.credentials.organizationId) || undefined,
33
+ policyId: clean(options.credentials.policyId) || undefined,
34
+ baseUrl: clean(options.credentials.baseUrl) || undefined,
35
+ rpcUrl: clean(options.credentials.rpcUrl) || undefined,
36
+ defaultSolanaAddress: clean(options.credentials.defaultSolanaAddress) || undefined,
37
+ providerWalletId: clean(options.credentials.providerWalletId) || undefined
38
+ };
39
+ this.walletName = clean(options.walletName) || `FasedAgent Solana ${Date.now()}`;
40
+ this.stateEnv = options.stateEnv ?? process.env;
41
+ this.dependencies = options.dependencies ?? {};
9
42
  this.capabilities = {
10
43
  custodyModel: "provider-managed",
11
44
  supportsCreateWallet: true,
12
- supportsPrepare: false,
13
- supportsSend: false,
45
+ supportsPrepare: true,
46
+ supportsSend: true,
14
47
  supportsRotateKeys: false,
15
48
  supportsResetKeys: false,
16
49
  supportsPasskeyGate: false,
50
+ signingLocation: "server",
51
+ supportsSignTransaction: true,
52
+ supportsSignMessage: false,
17
53
  supportedExecutionModes: ["manual"],
18
54
  supportedChains: ["solana"]
19
55
  };
@@ -22,57 +58,279 @@ var TurnkeyAdapter = class {
22
58
  return chain === "solana";
23
59
  }
24
60
  async health() {
25
- const configured = Boolean(this.credentials.apiPublicKey && this.credentials.apiPrivateKey);
26
- return {
27
- ok: configured,
28
- provider: this.id,
29
- configured,
30
- checkedAt: new Date().toISOString(),
31
- details: configured ? "Turnkey adapter configured for Solana wallet discovery." : "Turnkey adapter is missing API credentials."
32
- };
61
+ const checkedAt = new Date().toISOString();
62
+ const missing = this.missingConfiguration({ requireAddress: false });
63
+ if (missing.length > 0) {
64
+ return {
65
+ ok: false,
66
+ provider: this.id,
67
+ configured: false,
68
+ checkedAt,
69
+ details: `Turnkey requires ${missing.join(", ")}. Use a dedicated API user/sub-organization covered by one restrictive Turnkey policy; the Gateway-held API key must not be authorized by another permissive policy.`
70
+ };
71
+ }
72
+ try {
73
+ const client = await this.getClient();
74
+ const policyResponse = await client.getPolicy({
75
+ organizationId: this.requireOrganizationId(),
76
+ policyId: this.requirePolicyId()
77
+ });
78
+ const policy = policyResponse.policy;
79
+ if (clean(policy?.policyId) !== this.requirePolicyId() || policy?.effect !== "EFFECT_ALLOW" || !clean(policy?.condition)) {
80
+ throw new Error("configured policy reference must resolve to an EFFECT_ALLOW policy with a non-empty condition");
81
+ }
82
+ if (this.credentials.defaultSolanaAddress) {
83
+ await this.getBalance("solana");
84
+ }
85
+ return {
86
+ ok: true,
87
+ provider: this.id,
88
+ configured: true,
89
+ checkedAt,
90
+ details: this.credentials.defaultSolanaAddress ? "Turnkey API, an ALLOW policy reference with a condition, Solana account, and RPC are reachable. Fased requires this policy to be the exclusive OUTCOME_ALLOW for every reviewed signature; this read-only check cannot prove the policy is safe against direct use of the Gateway-held API key." : "Turnkey API and an ALLOW policy reference with a condition are reachable. Create or register a Solana account next; exclusive policy evaluation is verified on every reviewed signature."
91
+ };
92
+ } catch (error) {
93
+ return {
94
+ ok: false,
95
+ provider: this.id,
96
+ configured: true,
97
+ checkedAt,
98
+ details: `Turnkey readiness check failed: ${walletDiagnosticErrorMessage(error)}`
99
+ };
100
+ }
33
101
  }
34
102
  async createWallet() {
35
- throw new WalletProviderError({
36
- code: "wallet_provider_not_implemented",
37
- message: "Turnkey wallet creation is not implemented in the Solana-only wallet runtime"
38
- });
103
+ this.assertConfigured({ requireAddress: false });
104
+ try {
105
+ const created = await (await this.getClient()).createWallet({
106
+ organizationId: this.requireOrganizationId(),
107
+ walletName: this.walletName,
108
+ accounts: [defaultSolanaAccountAtIndex(0)]
109
+ });
110
+ const address = clean(created.addresses[0]);
111
+ if (!address) {
112
+ throw new Error("Turnkey returned no Solana address");
113
+ }
114
+ return {
115
+ ok: true,
116
+ walletId: created.walletId,
117
+ addresses: { solana: address },
118
+ metadata: {
119
+ turnkeyWalletId: created.walletId,
120
+ turnkeyPolicyId: this.requirePolicyId(),
121
+ providerManaged: true
122
+ }
123
+ };
124
+ } catch (error) {
125
+ throw asProviderError(error, "wallet creation");
126
+ }
39
127
  }
40
128
  async getAddresses() {
41
129
  return this.credentials.defaultSolanaAddress ? { solana: this.credentials.defaultSolanaAddress } : {};
42
130
  }
43
131
  async getBalance(chain) {
44
- if (!this.supportsChain(chain)) {
45
- throw new WalletProviderError({
46
- code: "wallet_provider_unsupported_chain",
47
- message: "Turnkey adapter supports Solana only"
48
- });
49
- }
50
- const address = this.credentials.defaultSolanaAddress?.trim();
51
- if (!address) {
132
+ this.ensureSolana(chain);
133
+ this.assertConfigured({ requireAddress: true });
134
+ const address = this.requireAddress();
135
+ const result = await fetchSolanaRpc(this.requireRpcUrl(), "getBalance", [address, { commitment: "confirmed" }]);
136
+ if (typeof result?.value !== "number" && typeof result?.value !== "string") {
52
137
  throw new WalletProviderError({
53
- code: "wallet_provider_invalid_config",
54
- message: "Turnkey wallet has no Solana address configured"
138
+ code: "wallet_provider_unavailable",
139
+ message: "Solana RPC did not return the Turnkey wallet balance",
140
+ retryable: false
55
141
  });
56
142
  }
57
143
  return {
58
144
  ok: true,
59
145
  chain: "solana",
60
146
  address,
61
- balance: "0",
147
+ balance: String(result.value),
62
148
  unit: "lamports"
63
149
  };
64
150
  }
65
- async prepareTx(_request) {
66
- throw new WalletProviderError({
67
- code: "wallet_provider_not_implemented",
68
- message: "Turnkey transaction preparation is not implemented in the Solana-only wallet runtime"
151
+ async prepareTx(request) {
152
+ this.ensureSolana(request.chain);
153
+ this.assertConfigured({ requireAddress: true });
154
+ try {
155
+ const prepared = await prepareTurnkeyReviewedTransaction({
156
+ request,
157
+ signerAddress: this.requireAddress(),
158
+ rpcUrl: this.requireRpcUrl(),
159
+ authorizationContext: this.authorizationContext(),
160
+ env: this.stateEnv
161
+ });
162
+ return {
163
+ ok: true,
164
+ chain: "solana",
165
+ preparedId: prepared.preparedId,
166
+ signer: prepared.signer,
167
+ unsignedTxBase64: prepared.unsignedTxBase64,
168
+ messageBase64: prepared.messageBase64,
169
+ intentDigest: prepared.intentDigest,
170
+ expiresAt: prepared.expiresAt,
171
+ metadata: {
172
+ simulation: prepared.simulation,
173
+ recentBlockhash: prepared.recentBlockhash,
174
+ lastValidBlockHeight: prepared.lastValidBlockHeight,
175
+ expiresAt: prepared.expiresAt,
176
+ turnkeyPolicyId: this.requirePolicyId()
177
+ }
178
+ };
179
+ } catch (error) {
180
+ throw asProviderError(error, "transaction preparation");
181
+ }
182
+ }
183
+ async sendTx(request) {
184
+ this.ensureSolana(request.chain);
185
+ this.assertConfigured({ requireAddress: true });
186
+ try {
187
+ const preparedId = clean(request.preparedId);
188
+ if (!preparedId) {
189
+ throw new WalletProviderError({
190
+ code: "wallet_provider_invalid_config",
191
+ message: "Turnkey manual send requires prepareTx and its reviewed preparedId"
192
+ });
193
+ }
194
+ const executed = await executeTurnkeyReviewedTransaction({
195
+ preparedId,
196
+ request,
197
+ signerAddress: this.requireAddress(),
198
+ rpcUrl: this.requireRpcUrl(),
199
+ authorizationContext: this.authorizationContext(),
200
+ env: this.stateEnv,
201
+ sign: async (unsignedTxBase64) => {
202
+ const unsignedTransaction = Transaction.from(Buffer.from(unsignedTxBase64, "base64"));
203
+ const client = await this.getClient();
204
+ const signedTransaction = this.dependencies.signTransaction ? await this.dependencies.signTransaction({
205
+ client,
206
+ organizationId: this.requireOrganizationId(),
207
+ transaction: unsignedTransaction,
208
+ signerAddress: this.requireAddress()
209
+ }) : await this.signWithTurnkey({
210
+ client,
211
+ transaction: unsignedTransaction
212
+ });
213
+ return Buffer.from(signedTransaction.serialize({
214
+ requireAllSignatures: true,
215
+ verifySignatures: true
216
+ })).toString("base64");
217
+ }
218
+ });
219
+ return {
220
+ ok: true,
221
+ chain: "solana",
222
+ txHash: executed.txHash,
223
+ signer: executed.signer,
224
+ metadata: {
225
+ intentDigest: executed.intentDigest,
226
+ turnkeyPolicyId: this.requirePolicyId(),
227
+ sendAttempts: executed.idempotent ? 0 : 1,
228
+ idempotent: executed.idempotent
229
+ }
230
+ };
231
+ } catch (error) {
232
+ throw asProviderError(error, "transaction signing or broadcast");
233
+ }
234
+ }
235
+ missingConfiguration(options) {
236
+ return [
237
+ !this.credentials.apiPublicKey ? "API public key" : "",
238
+ !this.credentials.apiPrivateKey ? "API private key" : "",
239
+ !this.credentials.organizationId ? "organization ID" : "",
240
+ !this.credentials.policyId ? "policy ID" : "",
241
+ !this.credentials.rpcUrl ? "Solana RPC URL" : "",
242
+ options.requireAddress && !this.credentials.defaultSolanaAddress ? "Solana address" : ""
243
+ ].filter(Boolean);
244
+ }
245
+ assertConfigured(options) {
246
+ const missing = this.missingConfiguration(options);
247
+ if (missing.length > 0) {
248
+ throw new WalletProviderError({
249
+ code: "wallet_provider_invalid_config",
250
+ message: `Turnkey requires ${missing.join(", ")}`
251
+ });
252
+ }
253
+ }
254
+ ensureSolana(chain) {
255
+ if (chain !== "solana") {
256
+ throw new WalletProviderError({
257
+ code: "wallet_provider_unsupported_chain",
258
+ message: "Turnkey adapter supports Solana only"
259
+ });
260
+ }
261
+ }
262
+ requireOrganizationId() {
263
+ return this.credentials.organizationId;
264
+ }
265
+ requirePolicyId() {
266
+ return this.credentials.policyId;
267
+ }
268
+ requireAddress() {
269
+ return this.credentials.defaultSolanaAddress;
270
+ }
271
+ requireRpcUrl() {
272
+ return this.credentials.rpcUrl;
273
+ }
274
+ authorizationContext() {
275
+ return JSON.stringify({
276
+ organizationId: this.requireOrganizationId(),
277
+ policyId: this.requirePolicyId(),
278
+ providerWalletId: this.credentials.providerWalletId ?? null
69
279
  });
70
280
  }
71
- async sendTx(_request) {
72
- throw new WalletProviderError({
73
- code: "wallet_provider_not_implemented",
74
- message: "Turnkey transaction sending is not implemented in the Solana-only wallet runtime"
281
+ async getClient() {
282
+ this.clientPromise ??= Promise.resolve(this.dependencies.createClient ? this.dependencies.createClient() : new Turnkey({
283
+ apiBaseUrl: this.credentials.baseUrl ?? DEFAULT_TURNKEY_API_BASE_URL,
284
+ apiPublicKey: this.credentials.apiPublicKey,
285
+ apiPrivateKey: this.credentials.apiPrivateKey,
286
+ defaultOrganizationId: this.requireOrganizationId()
287
+ }).apiClient());
288
+ return await this.clientPromise;
289
+ }
290
+ async signWithTurnkey(params) {
291
+ const organizationId = this.requireOrganizationId();
292
+ const policyId = this.requirePolicyId();
293
+ const response = await params.client.signTransaction({
294
+ organizationId,
295
+ signWith: this.requireAddress(),
296
+ unsignedTransaction: Buffer.from(params.transaction.serialize({
297
+ requireAllSignatures: false,
298
+ verifySignatures: false
299
+ })).toString("hex"),
300
+ type: "TRANSACTION_TYPE_SOLANA"
75
301
  });
302
+ if (response.activity.status !== "ACTIVITY_STATUS_COMPLETED" || response.activity.type !== "ACTIVITY_TYPE_SIGN_TRANSACTION_V2" || clean(response.activity.organizationId) !== organizationId || !clean(response.activity.id) || !clean(response.signedTransaction)) {
303
+ throw new Error("Turnkey did not complete the expected Solana signing activity");
304
+ }
305
+ let evaluatedPolicies = [];
306
+ for (let attempt = 0; attempt < 4; attempt += 1) {
307
+ const evaluations = await params.client.getPolicyEvaluations({
308
+ organizationId,
309
+ activityId: response.activity.id
310
+ });
311
+ evaluatedPolicies = evaluations.policyEvaluations.flatMap((evaluation) => evaluation.policyEvaluations.map((entry) => ({
312
+ policyId: clean(entry.policyId),
313
+ outcome: clean(entry.outcome)
314
+ })));
315
+ if (evaluatedPolicies.some((entry) => entry.policyId === policyId)) {
316
+ break;
317
+ }
318
+ if (attempt < 3) {
319
+ await new Promise((resolve) => setTimeout(resolve, 50 * (attempt + 1)));
320
+ }
321
+ }
322
+ const matchingOutcomes = evaluatedPolicies.filter((entry) => entry.policyId === policyId).map((entry) => entry.outcome);
323
+ const alternateAllow = evaluatedPolicies.some((entry) => entry.policyId !== policyId && entry.outcome === "OUTCOME_ALLOW");
324
+ if (matchingOutcomes.length === 0 || matchingOutcomes.some((outcome) => outcome !== "OUTCOME_ALLOW") || alternateAllow) {
325
+ throw new Error("the configured Turnkey policy was not the exclusive OUTCOME_ALLOW for this reviewed signing activity");
326
+ }
327
+ let signed;
328
+ try {
329
+ signed = Transaction.from(Buffer.from(response.signedTransaction, "hex"));
330
+ } catch (error) {
331
+ throw new Error("Turnkey returned an invalid signed Solana transaction", { cause: error });
332
+ }
333
+ return signed;
76
334
  }
77
335
  };
78
336
 
@@ -0,0 +1,100 @@
1
+ import { fetchSolanaRpc } from "../solana-assets.js";
2
+ import { WalletProviderError } from "../wallet-provider-adapter.js";
3
+
4
+ //#region src/wallet/providers/wallet-standard-adapter.ts
5
+ /**
6
+ * Server-side discovery half of a Wallet Standard Vault.
7
+ *
8
+ * Signing deliberately cannot be invoked through this adapter. The Control UI
9
+ * uses the browser-only Wallet Standard flow and the Gateway only validates and
10
+ * broadcasts the returned signed transaction.
11
+ */
12
+ var WalletStandardAdapter = class {
13
+ constructor(options = {}) {
14
+ this.id = "wallet-standard";
15
+ this.displayName = "Wallet Standard";
16
+ this.capabilities = {
17
+ custodyModel: "self-hosted",
18
+ supportsCreateWallet: false,
19
+ supportsPrepare: false,
20
+ supportsSend: false,
21
+ supportsRotateKeys: false,
22
+ supportsResetKeys: false,
23
+ supportsPasskeyGate: false,
24
+ signingLocation: "browser",
25
+ supportsSignTransaction: true,
26
+ supportsSignMessage: false,
27
+ supportedExecutionModes: ["manual"],
28
+ supportedChains: ["solana"]
29
+ };
30
+ this.address = options.address?.trim() || undefined;
31
+ this.rpcUrl = options.rpcUrl?.trim() || undefined;
32
+ }
33
+ supportsChain(chain) {
34
+ return chain === "solana";
35
+ }
36
+ async health() {
37
+ const configured = Boolean(this.address && this.rpcUrl);
38
+ return {
39
+ ok: configured,
40
+ provider: this.id,
41
+ configured,
42
+ checkedAt: new Date().toISOString(),
43
+ details: configured ? "Wallet Standard account registered. Signing capability is checked in the local browser before every operation; Wallet Standard does not prove that the account is hardware-backed." : "Attach a Wallet Standard account and configure Solana RPC. For reserve funds, select and verify a hardware-backed account on its device."
44
+ };
45
+ }
46
+ async createWallet() {
47
+ throw new WalletProviderError({
48
+ code: "wallet_provider_browser_required",
49
+ message: "Attach a Solana Wallet Standard account from Fased Control. For reserve funds, use and verify a hardware-backed account on its device"
50
+ });
51
+ }
52
+ async getAddresses() {
53
+ return this.address ? { solana: this.address } : {};
54
+ }
55
+ async getBalance(chain) {
56
+ if (chain !== "solana") {
57
+ throw new WalletProviderError({
58
+ code: "wallet_provider_unsupported_chain",
59
+ message: "Wallet Standard Vault supports Solana only"
60
+ });
61
+ }
62
+ if (!this.address || !this.rpcUrl) {
63
+ throw new WalletProviderError({
64
+ code: "wallet_provider_invalid_config",
65
+ message: "Wallet Standard Vault requires a registered Solana address and RPC URL"
66
+ });
67
+ }
68
+ const result = await fetchSolanaRpc(this.rpcUrl, "getBalance", [this.address, { commitment: "confirmed" }]);
69
+ const balance = result?.value;
70
+ if (typeof balance !== "number" && typeof balance !== "string") {
71
+ throw new WalletProviderError({
72
+ code: "wallet_provider_unavailable",
73
+ message: "Solana RPC did not return a Wallet Standard Vault balance",
74
+ retryable: true
75
+ });
76
+ }
77
+ return {
78
+ ok: true,
79
+ chain: "solana",
80
+ address: this.address,
81
+ balance: String(balance),
82
+ unit: "lamports"
83
+ };
84
+ }
85
+ async prepareTx(_request) {
86
+ throw new WalletProviderError({
87
+ code: "wallet_provider_browser_required",
88
+ message: "Wallet Standard Vault transactions must be prepared through the reviewed browser flow"
89
+ });
90
+ }
91
+ async sendTx(_request) {
92
+ throw new WalletProviderError({
93
+ code: "wallet_provider_browser_required",
94
+ message: "Gateway cannot sign for a Wallet Standard Vault"
95
+ });
96
+ }
97
+ };
98
+
99
+ //#endregion
100
+ export { WalletStandardAdapter };
@@ -0,0 +1,184 @@
1
+ import { resolveLocalSignerControlSocketPath } from "./wallet-runtime-config.js";
2
+ import path from "node:path";
3
+ import { spawnSync } from "node:child_process";
4
+
5
+ //#region src/wallet/signer-network-admin.ts
6
+ const NETWORK_ADMIN_TIMEOUT_MS = 3e4;
7
+ const NETWORK_ADMIN_MAX_OUTPUT_BYTES = 256 * 1024;
8
+ function canonicalSignerWalletId(raw) {
9
+ const normalized = raw.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
10
+ return normalized || "default";
11
+ }
12
+ function parseSignerNetworkSummary(raw, expectedWalletId) {
13
+ let value;
14
+ try {
15
+ value = JSON.parse(raw);
16
+ } catch {
17
+ throw new Error("signer network administration returned invalid JSON");
18
+ }
19
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
20
+ throw new Error("signer network administration returned an invalid summary");
21
+ }
22
+ const record = value;
23
+ const keys = Object.keys(record).toSorted();
24
+ const allowedKeys = record.hash === undefined ? [
25
+ "configured",
26
+ "ready",
27
+ "version",
28
+ "walletId"
29
+ ] : [
30
+ "configured",
31
+ "hash",
32
+ "ready",
33
+ "version",
34
+ "walletId"
35
+ ];
36
+ if (keys.join(",") !== allowedKeys.join(",")) {
37
+ throw new Error("signer network administration returned unsupported summary fields");
38
+ }
39
+ if (record.walletId !== expectedWalletId || typeof record.configured !== "boolean" || !Number.isSafeInteger(record.version) || Number(record.version) < 0 || typeof record.ready !== "boolean" || record.hash !== undefined && (typeof record.hash !== "string" || !/^hmac-sha256:[0-9a-f]{64}$/.test(record.hash))) {
40
+ throw new Error("signer network administration returned an invalid summary");
41
+ }
42
+ return {
43
+ walletId: record.walletId,
44
+ configured: record.configured,
45
+ version: Number(record.version),
46
+ ...typeof record.hash === "string" ? { hash: record.hash } : {},
47
+ ready: record.ready
48
+ };
49
+ }
50
+ function redactSignerNetworkError(raw, secrets) {
51
+ let value = raw;
52
+ for (const secret of secrets.filter(Boolean).toSorted((a, b) => b.length - a.length)) {
53
+ value = value.split(secret).join("[redacted-rpc-url]");
54
+ }
55
+ value = value.replace(/https?:\/\/[^\s"'<>]+/gi, "[redacted-rpc-url]");
56
+ value = value.replace(/\b(api[_-]?key|access[_-]?token|token|key)=([^\s&"']+)/gi, "$1=[redacted]");
57
+ return value.trim().slice(0, 2e3) || "signer network administration failed";
58
+ }
59
+ function signerAdminEnvironment(env) {
60
+ const out = {};
61
+ for (const key of [
62
+ "HOME",
63
+ "PATH",
64
+ "TMPDIR",
65
+ "LANG",
66
+ "LC_ALL",
67
+ "TZ"
68
+ ]) {
69
+ const value = String(env[key] ?? "").trim();
70
+ if (value) {
71
+ out[key] = value;
72
+ }
73
+ }
74
+ return out;
75
+ }
76
+ function runSignerAdmin(params) {
77
+ const child = spawnSync(params.command, params.args, {
78
+ input: params.input,
79
+ env: params.env,
80
+ encoding: "utf8",
81
+ timeout: NETWORK_ADMIN_TIMEOUT_MS,
82
+ maxBuffer: NETWORK_ADMIN_MAX_OUTPUT_BYTES,
83
+ stdio: [
84
+ "pipe",
85
+ "pipe",
86
+ "pipe"
87
+ ]
88
+ });
89
+ if (child.error || child.status !== 0) {
90
+ const detail = [
91
+ child.stderr,
92
+ child.stdout,
93
+ child.error?.message
94
+ ].filter((part) => typeof part === "string" && part.trim().length > 0).join("\n");
95
+ throw new Error(redactSignerNetworkError(detail, params.secrets));
96
+ }
97
+ return child.stdout;
98
+ }
99
+ function assertReadyNetworkSummary(summary, previousVersion) {
100
+ if (!summary.configured || !summary.ready || !summary.hash || summary.version !== previousVersion + 1) {
101
+ throw new Error("signer network update did not acknowledge the exact next ready version");
102
+ }
103
+ return summary;
104
+ }
105
+ function configureSignerOwnedWalletNetwork(params) {
106
+ const env = params.env ?? process.env;
107
+ const walletId = canonicalSignerWalletId(params.walletId);
108
+ const primaryRpcUrl = params.primaryRpcUrl.trim();
109
+ const fallbackRpcUrl = params.fallbackRpcUrl?.trim() || "";
110
+ if (!primaryRpcUrl) {
111
+ throw new Error("signer-owned wallet network requires a primary RPC URL");
112
+ }
113
+ const secrets = [primaryRpcUrl, fallbackRpcUrl];
114
+ const hosting = String(env.FASED_HOST_PROFILE ?? "").trim().toLowerCase() === "hosting";
115
+ if (hosting) {
116
+ return {
117
+ walletId,
118
+ configured: false,
119
+ version: 0,
120
+ ready: false,
121
+ rootAdminRequired: true,
122
+ rootCommand: `/usr/local/sbin/fased-signer-network --wallet-id ${walletId} ` + "--network-file /root/fased-network.json"
123
+ };
124
+ }
125
+ const signerBinPath = params.signerBinPath ?? (String(env.FASED_WALLET_LOCAL_SIGNER_BIN ?? "").trim() || path.join(String(env.HOME ?? ""), ".fased", "bin", "fased-signerd"));
126
+ const controlSocketPath = params.controlSocketPath ?? resolveLocalSignerControlSocketPath(env);
127
+ const adminEnv = signerAdminEnvironment(env);
128
+ const commonArgs = [
129
+ "--control-socket",
130
+ controlSocketPath,
131
+ "--wallet-id",
132
+ walletId
133
+ ];
134
+ const current = parseSignerNetworkSummary(runSignerAdmin({
135
+ command: signerBinPath,
136
+ args: [
137
+ "admin",
138
+ "network",
139
+ "get",
140
+ ...commonArgs
141
+ ],
142
+ env: adminEnv,
143
+ secrets
144
+ }), walletId);
145
+ const input = `${JSON.stringify({
146
+ expectedVersion: current.version,
147
+ primaryRpcUrl,
148
+ ...fallbackRpcUrl ? { fallbackRpcUrl } : {}
149
+ })}\n`;
150
+ const updated = parseSignerNetworkSummary(runSignerAdmin({
151
+ command: signerBinPath,
152
+ args: [
153
+ "admin",
154
+ "network",
155
+ "put",
156
+ ...commonArgs
157
+ ],
158
+ input,
159
+ env: adminEnv,
160
+ secrets
161
+ }), walletId);
162
+ return assertReadyNetworkSummary(updated, current.version);
163
+ }
164
+ /**
165
+ * Hosted policy changes are deliberately unavailable to the app process. New signer-owned
166
+ * wallets are born deny-all; policy expansion requires the root-only installed policy CLI.
167
+ */
168
+ function applyHostedSignerOwnedWalletPolicy(params) {
169
+ void (params.env ?? process.env);
170
+ const walletId = canonicalSignerWalletId(params.walletId);
171
+ if (params.policy.operations.length !== 0 || params.policy.programs.length !== 0 || params.policy.assets.length !== 0) {
172
+ throw new Error("Fresh hosted signer setup accepts only the signer's built-in deny-all policy");
173
+ }
174
+ throw new Error(`Hosted signer policy for ${walletId} requires the root-only ` + "/usr/local/sbin/fased-signer-policy command and a root-owned policy file.");
175
+ }
176
+ const __testing = {
177
+ canonicalSignerWalletId,
178
+ parseSignerNetworkSummary,
179
+ redactSignerNetworkError,
180
+ signerAdminEnvironment
181
+ };
182
+
183
+ //#endregion
184
+ export { configureSignerOwnedWalletNetwork };