@fased/fased 0.1.62 → 0.1.65

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 (342) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +44 -29
  3. package/config/dependency-ownership.json +1 -1
  4. package/config/signer-policies/README.md +58 -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 +78 -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-MaQnPa5G.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-D4YMr1fA.js} +3 -3
  80. package/dist/control-ui/assets/mining-commit-DFpB_4JN.js +2 -0
  81. package/dist/control-ui/assets/{mining-BdhMn18r.js → mining-qMYs4aD-.js} +70 -50
  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 +291 -84
  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 +1274 -390
  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-I4IngVlJ.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-DLQ6_lLK.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-D_8FVI1C.js} +6798 -3695
  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-B4KF4Kpo.js} +31 -31
  166. package/dist/plugin-sdk/{monitor-wYVncM9w.js → monitor-Bb6x1KAG.js} +32 -32
  167. package/dist/plugin-sdk/{openresponses-http-B2GmeSt4.js → openresponses-http-DCTO8JkL.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-B3GC_7CD.js → pairing-message-D0CoLHRJ.js} +1 -1
  172. package/dist/plugin-sdk/{pairing-message-B3bHYGaw.d.ts → pairing-message-DHPDFZbC.d.ts} +2 -2
  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 +565 -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-BHmvqgjH.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-By5AcorL.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-DGnBz1YT.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-EJGTmL1Q.d.ts +486 -0
  208. package/dist/plugin-sdk/{types-vcJrC_uv.d.ts → types-BdwdFCD6.d.ts} +2 -3
  209. package/dist/plugin-sdk/{types-DFAW-n1J.d.ts → types-BrCpYMxn.d.ts} +2 -2
  210. package/dist/plugin-sdk/{types-DyhXnYUr.d.ts → types-D0kDG8l0.d.ts} +3 -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-DUJwrTYs.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 +578 -117
  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 +92 -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 +93 -37
  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 +18 -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 +18 -0
  284. package/extensions/msteams/package.json +1 -1
  285. package/extensions/nextcloud-talk/package.json +1 -1
  286. package/extensions/nostr/CHANGELOG.md +18 -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 +587 -154
  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 +91 -5
  293. package/extensions/sat-mining/src/claim-service.ts +85 -14
  294. package/extensions/sat-mining/src/client.ts +13 -0
  295. package/extensions/sat-mining/src/config.ts +9 -0
  296. package/extensions/sat-mining/src/cycle-progress.ts +16 -8
  297. package/extensions/sat-mining/src/epoch-service.ts +9 -5
  298. package/extensions/sat-mining/src/gateway-runner.ts +21 -1
  299. package/extensions/sat-mining/src/protocol-contract.ts +45 -1
  300. package/extensions/sat-mining/src/recovery-service.ts +312 -0
  301. package/extensions/sat-mining/src/round-watcher.ts +391 -81
  302. package/extensions/sat-mining/src/rpc-read.ts +431 -106
  303. package/extensions/sat-mining/src/runtime.ts +16 -0
  304. package/extensions/sat-mining/src/sat-bond-layout.ts +6 -0
  305. package/extensions/sat-mining/src/signer-codec-manifest.ts +429 -0
  306. package/extensions/sat-mining/src/solana-submit.ts +1544 -436
  307. package/extensions/sat-mining/src/submission-ledger.ts +434 -0
  308. package/extensions/signal/package.json +1 -1
  309. package/extensions/synology-chat/package.json +1 -1
  310. package/extensions/tlon/package.json +1 -1
  311. package/extensions/twitch/CHANGELOG.md +18 -0
  312. package/extensions/twitch/package.json +1 -1
  313. package/extensions/voice-call/CHANGELOG.md +18 -0
  314. package/extensions/voice-call/package.json +1 -1
  315. package/extensions/zalo/CHANGELOG.md +18 -0
  316. package/extensions/zalo/package.json +1 -1
  317. package/extensions/zalouser/CHANGELOG.md +18 -0
  318. package/extensions/zalouser/package.json +1 -1
  319. package/install.sh +4951 -0
  320. package/package.json +23 -5
  321. package/scripts/fased-host-updater.mjs +1421 -0
  322. package/scripts/fased-host-updaterctl.mjs +186 -0
  323. package/scripts/fased-managed-service.sh +36 -0
  324. package/scripts/fased-managed-updater.mjs +3065 -156
  325. package/scripts/fased-signer-enroll-hosting.sh +275 -0
  326. package/scripts/fased-signer-network-hosting.sh +143 -0
  327. package/scripts/fased-signer-owner-policy.mjs +1442 -0
  328. package/scripts/fased-signer-policy-hosting.sh +50 -0
  329. package/scripts/fased-signer-policy-local.sh +26 -0
  330. package/scripts/hosted-release-manifest.mjs +185 -0
  331. package/scripts/install-fased-signerd.sh +183 -108
  332. package/scripts/install-managed-runtime.mjs +212 -10
  333. package/scripts/managed-runtime-layout.mjs +75 -3
  334. package/scripts/migrate-hosted-signer-v2.mjs +58 -0
  335. package/scripts/start-managed.sh +173 -360
  336. package/dist/control-ui/assets/mining-commit-R-6nu87p.js +0 -2
  337. package/dist/plugin-sdk/tmp-fased-dir-CS6zsYEE.d.ts +0 -77
  338. package/dist/wallet/local-socket-signer-broker.js +0 -224
  339. package/dist/wallet/local-socket-signer-custody.js +0 -42
  340. package/dist/wallet/providers/embedded-keystore-adapter.js +0 -402
  341. package/dist/wallet/providers/privy-adapter.js +0 -80
  342. package/dist/wallet/wallet-custody.js +0 -1836
@@ -105,6 +105,7 @@ if [[ "${FASED_MANAGED_INTERNAL:-0}" != "1" ]]; then
105
105
  fi
106
106
 
107
107
  set -euo pipefail
108
+ umask 077
108
109
 
109
110
  NODE_BIN="$(resolve_node_bin || true)"
110
111
  if [[ -z "$NODE_BIN" ]]; then
@@ -187,12 +188,53 @@ mask_secret() {
187
188
  local raw="$1"
188
189
  local n=${#raw}
189
190
  if [[ $n -le 10 ]]; then
190
- printf "%s" "$raw"
191
+ printf "%s" "[redacted]"
191
192
  return
192
193
  fi
193
194
  printf "%s...%s" "${raw:0:6}" "${raw: -4}"
194
195
  }
195
196
 
197
+ read_private_zrok_reservation() {
198
+ local file="$1"
199
+ local owner="" mode="" links="" size=""
200
+ [[ -f "$file" && ! -L "$file" ]] || return 1
201
+ read -r owner mode links size <<<"$(stat -c '%u %a %h %s' "$file" 2>/dev/null || true)"
202
+ [[ "$mode" =~ ^[0-7]{3,4}$ ]] || return 1
203
+ [[ "$owner" == "$(id -u)" && "$links" == "1" && "$size" =~ ^[0-9]+$ && \
204
+ "$size" -gt 0 && "$size" -le 4096 ]] || return 1
205
+ chmod 0600 "$file"
206
+ local token=""
207
+ IFS= read -r token <"$file" || true
208
+ [[ -n "$token" ]] || return 1
209
+ printf '%s' "$token"
210
+ }
211
+
212
+ write_private_zrok_reservation() {
213
+ local file="$1"
214
+ local token="$2"
215
+ local temp_file=""
216
+ [[ -n "$token" ]] || return 1
217
+ mkdir -p "$(dirname "$file")"
218
+ chmod 0700 "$(dirname "$file")" 2>/dev/null || true
219
+ temp_file="$(mktemp "${file}.tmp.XXXXXXXX")"
220
+ trap 'rm -f -- "${temp_file:-}"' RETURN
221
+ printf '%s\n' "$token" >"$temp_file"
222
+ chmod 0600 "$temp_file"
223
+ mv -f -- "$temp_file" "$file"
224
+ temp_file=""
225
+ chmod 0600 "$file"
226
+ trap - RETURN
227
+ }
228
+
229
+ filter_zrok_runtime_output() {
230
+ local line=""
231
+ while IFS= read -r line || [[ -n "$line" ]]; do
232
+ if [[ "$line" == *"issuedAt of token is in the future"* ]]; then
233
+ printf '%s\n' '[zrok] clock-skew-auth-failure'
234
+ fi
235
+ done
236
+ }
237
+
196
238
  is_gateway_listener_ready() {
197
239
  (echo >"/dev/tcp/127.0.0.1/${FASED_GATEWAY_PORT}") >/dev/null 2>&1
198
240
  }
@@ -206,21 +248,6 @@ abs_int() {
206
248
  printf '%s\n' "$value"
207
249
  }
208
250
 
209
- can_run_privileged_time_sync_command() {
210
- if [[ "$(id -u)" -eq 0 ]]; then
211
- return 0
212
- fi
213
- command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1
214
- }
215
-
216
- run_privileged_time_sync_command() {
217
- if [[ "$(id -u)" -eq 0 ]]; then
218
- "$@"
219
- return $?
220
- fi
221
- sudo -n "$@"
222
- }
223
-
224
251
  fetch_remote_epoch_from_http_date() {
225
252
  local url="$1"
226
253
  local date_header=""
@@ -261,21 +288,13 @@ measure_managed_clock_skew_seconds() {
261
288
  }
262
289
 
263
290
  zrok_log_indicates_clock_skew() {
264
- tail -n 80 "$ZROK_RUNTIME_LOG" 2>/dev/null | grep -Fqi "issuedAt of token is in the future"
291
+ tail -n 80 "$ZROK_RUNTIME_LOG" 2>/dev/null | grep -Fqi "[zrok] clock-skew-auth-failure"
265
292
  }
266
293
 
267
294
  attempt_managed_clock_sync_repair() {
268
- if ! can_run_privileged_time_sync_command; then
269
- return 1
270
- fi
271
- echo "[tunnel] Attempting automatic host clock sync repair..."
272
- run_privileged_time_sync_command timedatectl set-ntp true >/dev/null 2>&1 || true
273
- run_privileged_time_sync_command systemctl restart systemd-timesyncd >/dev/null 2>&1 || \
274
- run_privileged_time_sync_command systemctl restart chronyd >/dev/null 2>&1 || true
275
- if command -v chronyc >/dev/null 2>&1; then
276
- run_privileged_time_sync_command chronyc -a makestep >/dev/null 2>&1 || true
277
- fi
278
- sleep 2
295
+ # Host time synchronization is installed during root bootstrap. The running
296
+ # Gateway intentionally has no privilege path for changing the host clock.
297
+ return 1
279
298
  }
280
299
 
281
300
  ensure_managed_clock_sync() {
@@ -293,7 +312,7 @@ ensure_managed_clock_sync() {
293
312
 
294
313
  echo "[tunnel] WARNING: Host clock skew detected (${skew_seconds}s versus public control plane)."
295
314
  if ! attempt_managed_clock_sync_repair; then
296
- echo "[tunnel] WARNING: Automatic host clock repair requires root or passwordless sudo."
315
+ echo "[tunnel] WARNING: Repair only from the provider root console using the exact tagged, attested Hosting release; never run the app checkout with sudo."
297
316
  return 1
298
317
  fi
299
318
 
@@ -315,7 +334,8 @@ start_initial_zrok_share() {
315
334
 
316
335
  while (( attempt <= attempts )); do
317
336
  echo "[tunnel] Starting tunnel for ${slug} (attempt ${attempt}/${attempts})..."
318
- "$ZROK_BIN" share reserved "$RES_TOKEN" --headless >>"$ZROK_RUNTIME_LOG" 2>&1 &
337
+ "$ZROK_BIN" share reserved "$RES_TOKEN" --headless 2>&1 \
338
+ | filter_zrok_runtime_output >>"$ZROK_RUNTIME_LOG" &
319
339
  ZROK_PID=$!
320
340
  echo "$ZROK_PID" > "$FASED_CONFIG_DIR/.zrok-pid"
321
341
  sleep 5
@@ -349,8 +369,7 @@ start_initial_zrok_share() {
349
369
 
350
370
  echo "[tunnel] WARNING: zrok share died during startup."
351
371
  if [[ "$VERBOSE_STARTUP" != "1" ]]; then
352
- echo "[debug] Last zrok startup logs:"
353
- tail -n 40 "$ZROK_RUNTIME_LOG" || true
372
+ echo "[debug] zrok output was reduced to non-secret diagnostics in $ZROK_RUNTIME_LOG"
354
373
  fi
355
374
  if zrok_log_indicates_clock_skew; then
356
375
  echo "[tunnel] Detected zrok auth failure caused by host clock skew."
@@ -454,6 +473,7 @@ mkdir -p "$FASED_CONFIG_DIR"
454
473
  mkdir -p "$LOG_DIR"
455
474
  : > "$ZROK_RUNTIME_LOG"
456
475
  : > "$WALLET_SETUP_LOG"
476
+ chmod 0600 "$ZROK_RUNTIME_LOG" "$WALLET_SETUP_LOG"
457
477
  SERVICE_GATEWAY_TOKEN="${FASED_GATEWAY_TOKEN:-}"
458
478
  if [ ! -f "$GW_TOKEN_PATH" ]; then
459
479
  if [[ -n "$SERVICE_GATEWAY_TOKEN" ]]; then
@@ -480,15 +500,11 @@ start_gateway_if_needed
480
500
  # 0a. Start local key signer daemon (fased-signerd) if available
481
501
  SIGNERD_BIN="${FASED_CONFIG_DIR}/bin/fased-signerd"
482
502
  SIGNERD_SOCKET="${FASED_CONFIG_DIR}/wallet/local-signer.sock"
483
- SIGNERD_BACKEND_SOCKET="$SIGNERD_SOCKET"
484
503
  SIGNERD_MATERIAL_DIR="${FASED_CONFIG_DIR}/wallet"
485
- SIGNERD_PASSPHRASE_FILE="$SIGNERD_MATERIAL_DIR/passphrase"
486
- SIGNERD_EVM_KEYSTORE="$SIGNERD_MATERIAL_DIR/keystore-evm.v1.enc"
487
- SIGNERD_SOL_KEYSTORE="$SIGNERD_MATERIAL_DIR/keystore-solana.v1.enc"
504
+ SIGNERD_CONTROL_SOCKET="${SIGNERD_MATERIAL_DIR}/local-signer-control.sock"
505
+ SIGNERD_STATE_DB="${SIGNERD_MATERIAL_DIR}/signerd-v2.db"
506
+ SIGNERD_MASTER_KEY="${SIGNERD_MATERIAL_DIR}/signerd-v2.master.key"
488
507
  SIGNERD_LOG="${LOG_DIR}/fased-signerd.log"
489
- SIGNERD_BROKER_LOG="${LOG_DIR}/local-signer-broker.log"
490
- SIGNER_MAINTENANCE_HELPER="/usr/local/sbin/fased-signer-maintenance"
491
- SIGNER_ISOLATION_HELPER="/usr/local/sbin/fased-signer-isolation"
492
508
  CONFIG_JSON="${FASED_CONFIG_DIR}/fased.json"
493
509
  SIGNERD_ENV_FILE="${FASED_CONFIG_DIR}/wallet/signer.env"
494
510
  WALLET_REGISTRY_JSON="${FASED_CONFIG_DIR}/wallet/provider-registry.v1.json"
@@ -513,14 +529,16 @@ load_wallet_signer_env_from_config() {
513
529
  [[ "$line" == *=* ]] || continue
514
530
  local key="${line%%=*}"
515
531
  local value="${line#*=}"
516
- if [[ "$key" =~ ^FASED_WALLET_(EVM|SOLANA)_(RPC_URL|KEYSTORE_PATH)(__[A-Za-z0-9_-]+)?$ ]] \
532
+ if [[ "$key" =~ ^FASED_WALLET_SOLANA_RPC_URL(__[A-Za-z0-9_-]+)?$ ]] \
517
533
  || [[ "$key" == "FASED_WALLET_CHAINS" ]] \
518
- || [[ "$key" == "FASED_WALLET_PASSPHRASE_FILE" ]] \
519
534
  || [[ "$key" == "FASED_WALLET_LOCAL_SIGNER_SOCKET" ]] \
520
- || [[ "$key" == "FASED_WALLET_LOCAL_SIGNER_BACKEND_SOCKET" ]] \
535
+ || [[ "$key" == "FASED_WALLET_LOCAL_SIGNER_CONTROL_SOCKET" ]] \
536
+ || [[ "$key" == "FASED_WALLET_LOCAL_SIGNER_STATE_DB" ]] \
537
+ || [[ "$key" == "FASED_WALLET_LOCAL_SIGNER_MASTER_KEY" ]] \
521
538
  || [[ "$key" == "FASED_WALLET_SIGNER_STATE_DIR" ]] \
522
- || [[ "$key" == "FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER" ]] \
523
539
  || [[ "$key" == "FASED_WALLET_LOCAL_SIGNER_BIN" ]] \
540
+ || [[ "$key" == "FASED_SAT_PROGRAM_ID" ]] \
541
+ || [[ "$key" == "FASED_SAT_ENABLE_ALT_V0" ]] \
524
542
  || [[ "$key" =~ ^FASED_WALLET_LOCAL_SIGNER_(ROLE|DIRECT_SIGNING|CAPS_ENABLED|SOLANA_MAX_PER_TX|SOLANA_MAX_DAILY|SOLANA_ALLOW_PROGRAMS)(__[A-Za-z0-9_-]+)?$ ]]; then
525
543
  export "$key=$value"
526
544
  fi
@@ -530,14 +548,16 @@ load_wallet_signer_env_from_config() {
530
548
  | to_entries[]
531
549
  | select(
532
550
  .key
533
- | test("^FASED_WALLET_(EVM|SOLANA)_(RPC_URL|KEYSTORE_PATH)(__[A-Za-z0-9_-]+)?$")
551
+ | test("^FASED_WALLET_SOLANA_RPC_URL(__[A-Za-z0-9_-]+)?$")
534
552
  or . == "FASED_WALLET_CHAINS"
535
- or . == "FASED_WALLET_PASSPHRASE_FILE"
536
553
  or . == "FASED_WALLET_LOCAL_SIGNER_SOCKET"
537
- or . == "FASED_WALLET_LOCAL_SIGNER_BACKEND_SOCKET"
554
+ or . == "FASED_WALLET_LOCAL_SIGNER_CONTROL_SOCKET"
555
+ or . == "FASED_WALLET_LOCAL_SIGNER_STATE_DB"
556
+ or . == "FASED_WALLET_LOCAL_SIGNER_MASTER_KEY"
538
557
  or . == "FASED_WALLET_SIGNER_STATE_DIR"
539
- or . == "FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER"
540
558
  or . == "FASED_WALLET_LOCAL_SIGNER_BIN"
559
+ or . == "FASED_SAT_PROGRAM_ID"
560
+ or . == "FASED_SAT_ENABLE_ALT_V0"
541
561
  or test("^FASED_WALLET_LOCAL_SIGNER_(ROLE|DIRECT_SIGNING|CAPS_ENABLED|SOLANA_MAX_PER_TX|SOLANA_MAX_DAILY|SOLANA_ALLOW_PROGRAMS)(__[A-Za-z0-9_-]+)?$")
542
562
  )
543
563
  | "\(.key)=\(.value|tostring)"
@@ -551,100 +571,32 @@ load_wallet_signer_env_file() {
551
571
  fi
552
572
 
553
573
  set -a
554
- # signer.env is generated by onboarding.wallet.ts; only import export lines, not the launch command.
555
- source <(grep -E '^export FASED_WALLET_' "$SIGNERD_ENV_FILE" || true)
556
- set +a
557
- }
558
-
559
- has_scoped_wallet_env_value() {
560
- local prefix="$1"
561
- local name=""
562
- while IFS= read -r name; do
563
- [[ -n "$name" ]] || continue
564
- if [[ -n "${!name:-}" ]]; then
565
- return 0
566
- fi
567
- done < <(compgen -A variable "${prefix}__" || true)
568
- return 1
569
- }
570
-
571
- normalize_wallet_env_suffix() {
572
- local raw="${1:-}"
573
- printf '%s' "$raw" \
574
- | tr '[:upper:]' '[:lower:]' \
575
- | sed -E 's/[^a-z0-9]+/_/g; s/^_+//; s/_+$//'
576
- }
577
-
578
- normalize_wallet_filename_id() {
579
- local raw="${1:-}"
580
- printf '%s' "$raw" \
581
- | tr '[:upper:]' '[:lower:]' \
582
- | sed -E 's/[^a-z0-9_-]+/-/g; s/^-+//; s/-+$//'
583
- }
584
-
585
- hydrate_scoped_wallet_keystore_env_from_registry() {
586
- local material_dir="$1"
587
- if [[ ! -f "$WALLET_REGISTRY_JSON" ]] || ! command -v jq >/dev/null 2>&1; then
588
- return 0
589
- fi
590
-
591
- while IFS=$'\t' read -r wallet_id provider_id; do
592
- [[ -n "$wallet_id" ]] || continue
593
- if [[ "$provider_id" != "local-socket-signer" && "$provider_id" != "embedded-keystore" ]]; then
594
- continue
595
- fi
596
- local env_suffix
597
- local file_suffix
598
- env_suffix="$(normalize_wallet_env_suffix "$wallet_id")"
599
- file_suffix="$(normalize_wallet_filename_id "$wallet_id")"
600
- [[ -n "$env_suffix" && -n "$file_suffix" ]] || continue
601
-
602
- local sol_key="FASED_WALLET_SOLANA_KEYSTORE_PATH__${env_suffix^^}"
603
- if [[ -z "${!sol_key:-}" ]]; then
604
- local sol_candidate="${material_dir}/keystore-solana-${file_suffix}.v1.enc"
605
- if [[ -f "$sol_candidate" ]]; then
606
- export "$sol_key=$sol_candidate"
607
- fi
608
- fi
609
-
610
- local evm_key="FASED_WALLET_EVM_KEYSTORE_PATH__${env_suffix^^}"
611
- if [[ -z "${!evm_key:-}" ]]; then
612
- local evm_candidate="${material_dir}/keystore-evm-${file_suffix}.v1.enc"
613
- if [[ -f "$evm_candidate" ]]; then
614
- export "$evm_key=$evm_candidate"
615
- fi
616
- fi
617
- done < <(
618
- jq -r '
619
- (.wallets // [])
620
- | .[]
621
- | select(.id != null and .providerId != null)
622
- | "\(.id|tostring)\t\(.providerId|tostring)"
623
- ' "$WALLET_REGISTRY_JSON" 2>/dev/null || true
574
+ # Older signer.env files may contain Node-era key/passphrase variables. Import only
575
+ # the non-custody settings required by the native signer, never every wallet variable.
576
+ source <(
577
+ grep -E '^export FASED_WALLET_(SOLANA_RPC_URL(__[A-Za-z0-9_-]+)?|CHAINS|SIGNER_STATE_DIR|WEBAUTHN_(RP_ID|ORIGINS)|LOCAL_SIGNER_(SOCKET|CONTROL_SOCKET|STATE_DB|MASTER_KEY|BIN|ROLE|DIRECT_SIGNING|CAPS_ENABLED|SOLANA_MAX_PER_TX|SOLANA_MAX_DAILY|SOLANA_ALLOW_PROGRAMS)(__[A-Za-z0-9_-]+)?)=' "$SIGNERD_ENV_FILE" || true
624
578
  )
579
+ set +a
625
580
  }
626
581
 
627
- resolve_signerd_keystore_export() {
628
- local explicit_value="$1"
629
- local scoped_prefix="$2"
630
- local default_path="$3"
631
-
632
- if has_scoped_wallet_env_value "$scoped_prefix"; then
633
- printf '\n'
634
- return 0
635
- fi
636
-
637
- if [[ -n "$explicit_value" && "$explicit_value" != "$default_path" ]]; then
638
- printf '%s\n' "$explicit_value"
639
- return 0
640
- fi
641
-
642
- if [[ -n "$explicit_value" ]]; then
643
- printf '%s\n' "$explicit_value"
644
- return 0
645
- fi
646
-
647
- printf '%s\n' "$default_path"
582
+ clear_legacy_wallet_key_env() {
583
+ local key
584
+ while IFS= read -r key; do
585
+ case "$key" in
586
+ FASED_WALLET_KEYSTORE_PATH|FASED_WALLET_KEYSTORE_PATH__*|\
587
+ FASED_WALLET_SOLANA_KEYSTORE_PATH|FASED_WALLET_SOLANA_KEYSTORE_PATH__*|\
588
+ FASED_WALLET_EVM_KEYSTORE_PATH|FASED_WALLET_EVM_KEYSTORE_PATH__*|\
589
+ FASED_WALLET_PASSPHRASE|FASED_WALLET_PASSPHRASE__*|\
590
+ FASED_WALLET_PASSPHRASE_FILE|FASED_WALLET_PASSPHRASE_FILE__*|\
591
+ FASED_WALLET_PRIVATE_KEY|FASED_WALLET_PRIVATE_KEY__*|\
592
+ FASED_WALLET_SECRET_KEY|FASED_WALLET_SECRET_KEY__*|\
593
+ FASED_WALLET_KEYPAIR|FASED_WALLET_KEYPAIR__*|\
594
+ FASED_WALLET_MNEMONIC|FASED_WALLET_MNEMONIC__*|\
595
+ FASED_WALLET_SEED|FASED_WALLET_SEED__*)
596
+ unset "$key"
597
+ ;;
598
+ esac
599
+ done < <(compgen -A variable | grep -E '^FASED_WALLET_' || true)
648
600
  }
649
601
 
650
602
  resolve_wallet_chains_from_config() {
@@ -693,34 +645,18 @@ registry_has_local_signer_wallet() {
693
645
  ' "$WALLET_REGISTRY_JSON" >/dev/null 2>&1
694
646
  }
695
647
 
696
- has_local_signer_keystore_material() {
697
- if [[ -n "${FASED_WALLET_SOLANA_KEYSTORE_PATH:-}" ]] || has_scoped_wallet_env_value "FASED_WALLET_SOLANA_KEYSTORE_PATH"; then
698
- return 0
699
- fi
700
- local candidate
701
- for candidate in "$SIGNERD_MATERIAL_DIR"/keystore-solana*.v1.enc "$SIGNERD_MATERIAL_DIR"/keystore-evm*.v1.enc; do
702
- [[ -f "$candidate" ]] && return 0
703
- done
704
- return 1
705
- }
706
-
707
648
  should_start_signerd() {
708
- registry_has_local_signer_wallet || has_local_signer_keystore_material
649
+ registry_has_local_signer_wallet
709
650
  }
710
651
 
711
652
  collect_existing_signerd_pids() {
712
- local pid_file app_pid_file
713
- pid_file="$(resolve_local_signer_sidecar_path "$SIGNERD_BACKEND_SOCKET" "pid")"
714
- app_pid_file="$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "pid")"
653
+ local pid_file
654
+ pid_file="$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "pid")"
715
655
  {
716
656
  if [[ -f "$pid_file" ]]; then
717
657
  cat "$pid_file" 2>/dev/null || true
718
658
  fi
719
- if [[ "$app_pid_file" != "$pid_file" && -f "$app_pid_file" ]]; then
720
- cat "$app_pid_file" 2>/dev/null || true
721
- fi
722
659
  pgrep -f "$SIGNERD_BIN" 2>/dev/null || true
723
- pgrep -f "wallet signer broker" 2>/dev/null || true
724
660
  } | awk '/^[0-9]+$/ { if (!seen[$1]++) print $1 }'
725
661
  }
726
662
 
@@ -737,16 +673,8 @@ dump_existing_signerd_processes() {
737
673
  }
738
674
 
739
675
  stop_existing_signerd() {
740
- local pid_file app_pid_file
741
- pid_file="$(resolve_local_signer_sidecar_path "$SIGNERD_BACKEND_SOCKET" "pid")"
742
- app_pid_file="$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "pid")"
743
- if signer_isolation_helper_available; then
744
- run_signer_isolation_helper stop "$SIGNERD_BACKEND_SOCKET" "$pid_file" >/dev/null 2>&1 || true
745
- if [[ "$SIGNERD_SOCKET" != "$SIGNERD_BACKEND_SOCKET" ]]; then
746
- run_signer_isolation_helper stop "$SIGNERD_SOCKET" "$app_pid_file" >/dev/null 2>&1 || true
747
- fi
748
- return 0
749
- fi
676
+ local pid_file
677
+ pid_file="$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "pid")"
750
678
  local pid=""
751
679
  while IFS= read -r pid; do
752
680
  [[ "$pid" =~ ^[0-9]+$ ]] || continue
@@ -757,7 +685,7 @@ stop_existing_signerd() {
757
685
  [[ "$pid" =~ ^[0-9]+$ ]] || continue
758
686
  kill -9 "$pid" >/dev/null 2>&1 || true
759
687
  done < <(collect_existing_signerd_pids)
760
- rm -f "$SIGNERD_SOCKET" "$SIGNERD_BACKEND_SOCKET" "$pid_file" "$app_pid_file"
688
+ rm -f "$SIGNERD_SOCKET" "$SIGNERD_CONTROL_SOCKET" "$pid_file"
761
689
  }
762
690
 
763
691
  wait_for_signerd_ready() {
@@ -766,7 +694,7 @@ wait_for_signerd_ready() {
766
694
  while true; do
767
695
  local active_count
768
696
  active_count="$(count_existing_signerd_pids)"
769
- if [[ "$active_count" == "1" && -S "$SIGNERD_BACKEND_SOCKET" ]]; then
697
+ if [[ "$active_count" == "1" && -S "$SIGNERD_SOCKET" && -S "$SIGNERD_CONTROL_SOCKET" ]]; then
770
698
  return 0
771
699
  fi
772
700
  if [[ "$active_count" -gt 1 ]]; then
@@ -785,194 +713,70 @@ wait_for_signerd_ready() {
785
713
  done
786
714
  }
787
715
 
788
- wait_for_signer_broker_ready() {
789
- local retries="$1"
790
- local count=0
791
- while true; do
792
- if [[ -S "$SIGNERD_SOCKET" ]]; then
793
- return 0
794
- fi
795
- sleep 1
796
- count=$((count + 1))
797
- if [[ $count -ge $retries ]]; then
798
- echo "[signerd] ERROR: signer broker did not create app socket within ${retries}s."
799
- tail -n 40 "$SIGNERD_BROKER_LOG" 2>/dev/null || true
800
- return 1
801
- fi
802
- done
803
- }
804
-
805
- collect_wallet_env_args() {
806
- local key value
807
- while IFS='=' read -r key value; do
808
- [[ "$key" == FASED_WALLET_* ]] || continue
809
- printf '%s=%s\0' "$key" "$value"
810
- done < <(env)
811
- }
812
-
813
- current_app_user() {
814
- id -un 2>/dev/null || printf '%s\n' "${USER:-app}"
815
- }
816
-
817
- signer_isolation_helper_available() {
818
- [[ -n "${FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER:-}" ]] || return 1
819
- [[ -x "$SIGNER_MAINTENANCE_HELPER" || -x "$SIGNER_ISOLATION_HELPER" ]] || return 1
820
- command -v sudo >/dev/null 2>&1 || return 1
821
- }
822
-
823
- run_signer_isolation_helper() {
824
- if [[ -x "$SIGNER_MAINTENANCE_HELPER" ]]; then
825
- sudo -n -E "$SIGNER_MAINTENANCE_HELPER" "$@"
826
- else
827
- local app_user
828
- app_user="$(current_app_user)"
829
- sudo -n -E "$SIGNER_ISOLATION_HELPER" "$app_user" "$FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER" "$@"
830
- fi
831
- }
832
-
833
716
  start_signerd_process() {
834
717
  local pid_file audit_log
835
- pid_file="$(resolve_local_signer_sidecar_path "$SIGNERD_BACKEND_SOCKET" "pid")"
836
- audit_log="$(resolve_local_signer_sidecar_path "$SIGNERD_BACKEND_SOCKET" "audit")"
837
- if [[ -n "${FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER:-}" ]]; then
838
- if signer_isolation_helper_available; then
839
- run_signer_isolation_helper start-signerd \
840
- "$SIGNERD_BIN" \
841
- "$SIGNERD_BACKEND_SOCKET" \
842
- "$pid_file" \
843
- "$audit_log" \
844
- >>"$SIGNERD_LOG" 2>&1 &
845
- return 0
846
- fi
847
- if ! command -v sudo >/dev/null 2>&1; then
848
- return 1
849
- fi
850
- local env_args=()
851
- while IFS= read -r -d '' env_arg; do
852
- env_args+=("$env_arg")
853
- done < <(collect_wallet_env_args)
854
- sudo -n -u "$FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER" -H env "${env_args[@]}" \
855
- "$SIGNERD_BIN" \
856
- -socket "$SIGNERD_BACKEND_SOCKET" \
857
- -pid-file "$pid_file" \
858
- -audit-log "$audit_log" \
859
- >>"$SIGNERD_LOG" 2>&1 &
860
- return 0
861
- fi
718
+ pid_file="$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "pid")"
719
+ audit_log="$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "audit")"
862
720
  "$SIGNERD_BIN" \
863
- -socket "$SIGNERD_BACKEND_SOCKET" \
721
+ -socket "$SIGNERD_SOCKET" \
722
+ -control-socket "$SIGNERD_CONTROL_SOCKET" \
723
+ -state-db "$SIGNERD_STATE_DB" \
724
+ -master-key "$SIGNERD_MASTER_KEY" \
864
725
  -pid-file "$pid_file" \
865
726
  -audit-log "$audit_log" \
866
727
  >>"$SIGNERD_LOG" 2>&1 &
867
728
  }
868
729
 
869
- start_signer_broker_process() {
870
- if [[ "$SIGNERD_SOCKET" == "$SIGNERD_BACKEND_SOCKET" ]]; then
871
- return 0
872
- fi
873
- local gateway_entry
874
- gateway_entry="$(resolve_gateway_cli_entry || true)"
875
- if [[ -z "$gateway_entry" ]]; then
876
- echo "[signerd] ERROR: signer broker CLI unavailable under $FASED_ROOT/dist"
877
- return 1
878
- fi
879
- if [[ -n "${FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER:-}" ]]; then
880
- if signer_isolation_helper_available; then
881
- run_signer_isolation_helper start-broker \
882
- "$NODE_BIN" \
883
- "$gateway_entry" \
884
- "$SIGNERD_SOCKET" \
885
- "$SIGNERD_BACKEND_SOCKET" \
886
- "$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "pid")" \
887
- "$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "audit")" \
888
- >>"$SIGNERD_BROKER_LOG" 2>&1 &
889
- return 0
890
- fi
891
- if ! command -v sudo >/dev/null 2>&1; then
892
- return 1
893
- fi
894
- local env_args=()
895
- while IFS= read -r -d '' env_arg; do
896
- env_args+=("$env_arg")
897
- done < <(collect_wallet_env_args)
898
- sudo -n -u "$FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER" -H env "${env_args[@]}" \
899
- "$NODE_BIN" "$gateway_entry" wallet signer broker \
900
- --socket "$SIGNERD_SOCKET" \
901
- --backend-socket "$SIGNERD_BACKEND_SOCKET" \
902
- --pid-file "$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "pid")" \
903
- --audit-log "$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "audit")" \
904
- >>"$SIGNERD_BROKER_LOG" 2>&1 &
905
- return 0
906
- fi
907
- "$NODE_BIN" "$gateway_entry" wallet signer broker \
908
- --socket "$SIGNERD_SOCKET" \
909
- --backend-socket "$SIGNERD_BACKEND_SOCKET" \
910
- --pid-file "$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "pid")" \
911
- --audit-log "$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "audit")" \
912
- >>"$SIGNERD_BROKER_LOG" 2>&1 &
913
- }
914
-
915
730
  load_wallet_signer_env_from_config
916
731
  load_wallet_signer_env_file
732
+ clear_legacy_wallet_key_env
917
733
  SIGNERD_BIN="${FASED_WALLET_LOCAL_SIGNER_BIN:-$SIGNERD_BIN}"
918
734
  SIGNERD_MATERIAL_DIR="${FASED_WALLET_SIGNER_STATE_DIR:-$SIGNERD_MATERIAL_DIR}"
919
- if [[ -n "${FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER:-}" ]]; then
920
- SIGNERD_BROKER_LOG="$(dirname "${FASED_WALLET_LOCAL_SIGNER_SOCKET:-$SIGNERD_SOCKET}")/local-signer-broker.log"
921
- fi
922
- hydrate_scoped_wallet_keystore_env_from_registry "$SIGNERD_MATERIAL_DIR"
923
- if should_start_signerd; then
735
+ SIGNERD_CONTROL_SOCKET="${FASED_WALLET_LOCAL_SIGNER_CONTROL_SOCKET:-$SIGNERD_MATERIAL_DIR/local-signer-control.sock}"
736
+ SIGNERD_STATE_DB="${FASED_WALLET_LOCAL_SIGNER_STATE_DB:-$SIGNERD_MATERIAL_DIR/signerd-v2.db}"
737
+ SIGNERD_MASTER_KEY="${FASED_WALLET_LOCAL_SIGNER_MASTER_KEY:-$SIGNERD_MATERIAL_DIR/signerd-v2.master.key}"
738
+ HOSTED_ROOT_SIGNER=0
739
+ if [[ "${FASED_HOST_PROFILE:-}" == "hosting" ]]; then
740
+ HOSTED_ROOT_SIGNER=1
741
+ SIGNERD_SOCKET="/run/fased-signerd/app.sock"
742
+ export FASED_WALLET_LOCAL_SIGNER_SOCKET="$SIGNERD_SOCKET"
743
+ unset FASED_WALLET_LOCAL_SIGNER_BACKEND_SOCKET
744
+ unset FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER
745
+ if [[ -S "$SIGNERD_SOCKET" ]]; then
746
+ SIGNERD_STARTUP_MODE="external"
747
+ echo "==> Using root-managed fased-signerd service (socket: $SIGNERD_SOCKET)"
748
+ else
749
+ mark_signerd_degraded "root-managed fased-signerd socket is unavailable. Repair only from the provider root console using the exact tagged, attested Hosting release; never run the app checkout with sudo."
750
+ fi
751
+ elif should_start_signerd; then
924
752
  SIGNERD_STARTUP_MODE="healthy"
925
753
  SIGNERD_SOCKET="${FASED_WALLET_LOCAL_SIGNER_SOCKET:-$SIGNERD_SOCKET}"
926
- SIGNERD_BACKEND_SOCKET="${FASED_WALLET_LOCAL_SIGNER_BACKEND_SOCKET:-$SIGNERD_SOCKET}"
927
- SIGNERD_EVM_KEYSTORE="$(resolve_signerd_keystore_export "${FASED_WALLET_EVM_KEYSTORE_PATH:-}" "FASED_WALLET_EVM_KEYSTORE_PATH" "$SIGNERD_MATERIAL_DIR/keystore-evm.v1.enc")"
928
- SIGNERD_SOL_KEYSTORE="$(resolve_signerd_keystore_export "${FASED_WALLET_SOLANA_KEYSTORE_PATH:-}" "FASED_WALLET_SOLANA_KEYSTORE_PATH" "$SIGNERD_MATERIAL_DIR/keystore-solana.v1.enc")"
929
- SIGNERD_PASSPHRASE="${FASED_WALLET_PASSPHRASE:-}"
930
- SIGNERD_PASSPHRASE_FILE="${FASED_WALLET_PASSPHRASE_FILE:-}"
754
+ unset FASED_WALLET_LOCAL_SIGNER_BACKEND_SOCKET
755
+ unset FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER
931
756
  SIGNERD_CHAINS="${FASED_WALLET_CHAINS:-$(resolve_wallet_chains_from_config)}"
932
757
  export FASED_WALLET_LOCAL_SIGNER_SOCKET="$SIGNERD_SOCKET"
933
- export FASED_WALLET_LOCAL_SIGNER_BACKEND_SOCKET="$SIGNERD_BACKEND_SOCKET"
934
758
  export FASED_WALLET_SIGNER_STATE_DIR="$SIGNERD_MATERIAL_DIR"
935
759
  export FASED_WALLET_CHAINS="${SIGNERD_CHAINS:-evm,solana}"
936
- if [[ -n "$SIGNERD_EVM_KEYSTORE" ]]; then
937
- export FASED_WALLET_EVM_KEYSTORE_PATH="$SIGNERD_EVM_KEYSTORE"
938
- else
939
- unset FASED_WALLET_EVM_KEYSTORE_PATH
940
- fi
941
- if [[ -n "$SIGNERD_SOL_KEYSTORE" ]]; then
942
- export FASED_WALLET_SOLANA_KEYSTORE_PATH="$SIGNERD_SOL_KEYSTORE"
943
- else
944
- unset FASED_WALLET_SOLANA_KEYSTORE_PATH
945
- fi
946
- if [[ -n "$SIGNERD_PASSPHRASE" ]]; then
947
- export FASED_WALLET_PASSPHRASE="$SIGNERD_PASSPHRASE"
948
- unset FASED_WALLET_PASSPHRASE_FILE
949
- else
950
- SIGNERD_PASSPHRASE_FILE="${SIGNERD_PASSPHRASE_FILE:-$SIGNERD_MATERIAL_DIR/passphrase}"
951
- export FASED_WALLET_PASSPHRASE_FILE="$SIGNERD_PASSPHRASE_FILE"
952
- unset FASED_WALLET_PASSPHRASE
953
- fi
760
+ unset FASED_WALLET_SOLANA_KEYSTORE_PATH
761
+ unset FASED_WALLET_EVM_KEYSTORE_PATH
762
+ unset FASED_WALLET_PASSPHRASE
763
+ unset FASED_WALLET_PASSPHRASE_FILE
954
764
  if [[ -f "$SIGNERD_BIN" ]]; then
955
- if [[ -S "$SIGNERD_SOCKET" ]] || [[ -S "$SIGNERD_BACKEND_SOCKET" ]] || [[ -f "$(resolve_local_signer_sidecar_path "$SIGNERD_BACKEND_SOCKET" "pid")" ]] || [[ "$(count_existing_signerd_pids)" -gt 0 ]]; then
765
+ if [[ -S "$SIGNERD_SOCKET" ]] || [[ -f "$(resolve_local_signer_sidecar_path "$SIGNERD_SOCKET" "pid")" ]] || [[ "$(count_existing_signerd_pids)" -gt 0 ]]; then
956
766
  echo "==> Restarting fased-signerd to apply current wallet chain/runtime config..."
957
767
  stop_existing_signerd
958
768
  fi
959
769
  echo "==> Starting fased-signerd (Go key signer)..."
960
770
  mkdir -p "$LOG_DIR"
961
- mkdir -p "$(dirname "$SIGNERD_LOG")" "$(dirname "$SIGNERD_BROKER_LOG")" 2>/dev/null || true
771
+ mkdir -p "$(dirname "$SIGNERD_LOG")" 2>/dev/null || true
962
772
  if start_signerd_process; then
963
773
  SIGNERD_PID=$!
964
774
  else
965
- mark_signerd_degraded "failed to start isolated fased-signerd as ${FASED_WALLET_LOCAL_SIGNER_RUN_AS_USER:-current user}. Check sudoers and $SIGNERD_LOG"
775
+ mark_signerd_degraded "failed to start fased-signerd as the current Local user. Check $SIGNERD_LOG"
966
776
  SIGNERD_PID=""
967
777
  fi
968
778
  if [[ -n "$SIGNERD_PID" ]] && wait_for_signerd_ready "$SIGNERD_READY_TIMEOUT_SECONDS"; then
969
- if ! start_signer_broker_process; then
970
- mark_signerd_degraded "fased-signerd started but signer broker failed. Check $SIGNERD_BROKER_LOG"
971
- elif wait_for_signer_broker_ready "$SIGNERD_READY_TIMEOUT_SECONDS"; then
972
- echo "==> fased-signerd started (PID=$SIGNERD_PID, socket: $SIGNERD_BACKEND_SOCKET)"
973
- else
974
- mark_signerd_degraded "fased-signerd broker did not become ready. Check $SIGNERD_BROKER_LOG"
975
- fi
779
+ echo "==> fased-signerd started (PID=$SIGNERD_PID, socket: $SIGNERD_SOCKET)"
976
780
  else
977
781
  mark_signerd_degraded "fased-signerd did not create socket. Check $SIGNERD_LOG"
978
782
  fi
@@ -1024,9 +828,11 @@ start_health_monitor() {
1024
828
  ensure_managed_clock_sync || true
1025
829
  fi
1026
830
  if [[ -n "$RES_TOKEN" ]]; then
1027
- "$ZROK_BIN" share reserved "$RES_TOKEN" --headless >>"$ZROK_RUNTIME_LOG" 2>&1 &
831
+ "$ZROK_BIN" share reserved "$RES_TOKEN" --headless 2>&1 \
832
+ | filter_zrok_runtime_output >>"$ZROK_RUNTIME_LOG" &
1028
833
  else
1029
- "$ZROK_BIN" share public "http://127.0.0.1:${FASED_GATEWAY_PORT}" --unique-name "$SLUG" >>"$ZROK_RUNTIME_LOG" 2>&1 &
834
+ "$ZROK_BIN" share public "http://127.0.0.1:${FASED_GATEWAY_PORT}" --unique-name "$SLUG" 2>&1 \
835
+ | filter_zrok_runtime_output >>"$ZROK_RUNTIME_LOG" &
1030
836
  fi
1031
837
  pid=$!
1032
838
  echo "$pid" > "$FASED_CONFIG_DIR/.zrok-pid"
@@ -1217,8 +1023,12 @@ echo "[tunnel] Target Slug: $SLUG"
1217
1023
  RES_FILE="$FASED_CONFIG_DIR/${SLUG}.zrok-reservation"
1218
1024
  RES_TOKEN=""
1219
1025
  if [[ -f "$RES_FILE" ]]; then
1220
- RES_TOKEN=$(cat "$RES_FILE")
1221
- echo "[tunnel] Found cached reservation: $RES_TOKEN"
1026
+ RES_TOKEN="$(read_private_zrok_reservation "$RES_FILE" || true)"
1027
+ if [[ -n "$RES_TOKEN" ]]; then
1028
+ echo "[tunnel] Found a private cached reservation (token hidden)."
1029
+ else
1030
+ echo "[tunnel] Ignoring an unsafe or unreadable cached reservation file."
1031
+ fi
1222
1032
  fi
1223
1033
 
1224
1034
  # Recovery when exact slug file is missing: use the only reservation token in config dir.
@@ -1226,14 +1036,16 @@ if [[ -z "$RES_TOKEN" ]]; then
1226
1036
  mapfile -t RES_FILES < <(ls "$FASED_CONFIG_DIR"/*.zrok-reservation 2>/dev/null || true)
1227
1037
  if [[ ${#RES_FILES[@]} -eq 1 ]]; then
1228
1038
  RES_FILE="${RES_FILES[0]}"
1229
- RES_TOKEN=$(cat "$RES_FILE")
1039
+ RES_TOKEN="$(read_private_zrok_reservation "$RES_FILE" || true)"
1230
1040
  RECOVERED_BASENAME=$(basename "$RES_FILE")
1231
1041
  RECOVERED_SLUG="${RECOVERED_BASENAME%.zrok-reservation}"
1232
1042
  if [[ -n "$RECOVERED_SLUG" ]]; then
1233
1043
  SLUG="$RECOVERED_SLUG"
1234
1044
  echo "[tunnel] Recovered slug from cached reservation filename: $SLUG"
1235
1045
  fi
1236
- echo "[tunnel] Recovered cached reservation: $RES_TOKEN"
1046
+ if [[ -n "$RES_TOKEN" ]]; then
1047
+ echo "[tunnel] Recovered a private cached reservation (token hidden)."
1048
+ fi
1237
1049
  fi
1238
1050
  fi
1239
1051
 
@@ -1274,7 +1086,7 @@ if [[ "$MANAGED_TUNNEL_DISABLED" != "1" && "$ZROK_TOKEN" != "null" && -n "$ZROK_
1274
1086
  # zrok enable (idempotent-ish, or just try)
1275
1087
  # Remove --force as it's not supported in v1.1+
1276
1088
  # We ignore error if already enabled, but capture output to be safe
1277
- "$ZROK_BIN" enable "$ZROK_TOKEN" --description "fased-agent" 2>/dev/null || true
1089
+ "$ZROK_BIN" enable "$ZROK_TOKEN" --description "fased-agent" >/dev/null 2>&1 || true
1278
1090
 
1279
1091
  # If no token, check if we already reserved it (recovery from lost file)
1280
1092
  if [[ -z "$RES_TOKEN" ]]; then
@@ -1283,9 +1095,10 @@ if [[ "$MANAGED_TUNNEL_DISABLED" != "1" && "$ZROK_TOKEN" != "null" && -n "$ZROK_
1283
1095
  EXISTING_TOKEN=$(echo "$OVERVIEW_JSON" | jq -r --arg SLUG "$SLUG" '(.shares // [])[] | select(.frontendEndpoints[] | contains($SLUG)) | .token' 2>/dev/null | head -n 1 || true)
1284
1096
 
1285
1097
  if [[ -n "$EXISTING_TOKEN" ]]; then
1286
- echo "[tunnel] Recovered existing token: $EXISTING_TOKEN"
1098
+ echo "[tunnel] Recovered an existing reservation (token hidden)."
1287
1099
  RES_TOKEN="$EXISTING_TOKEN"
1288
- echo "$RES_TOKEN" > "$RES_FILE"
1100
+ write_private_zrok_reservation "$RES_FILE" "$RES_TOKEN"
1101
+ unset EXISTING_TOKEN OVERVIEW_JSON
1289
1102
  fi
1290
1103
  fi
1291
1104
 
@@ -1293,25 +1106,27 @@ if [[ "$MANAGED_TUNNEL_DISABLED" != "1" && "$ZROK_TOKEN" != "null" && -n "$ZROK_
1293
1106
  if [[ -z "$RES_TOKEN" ]]; then
1294
1107
  echo "[tunnel] Reserving public share..."
1295
1108
  # Use --json-output to parse output reliably; separate stderr
1296
- PARAMS="--unique-name $SLUG --backend-mode proxy --json-output"
1109
+ ZROK_RESERVE_ARGS=(--unique-name "$SLUG" --backend-mode proxy --json-output)
1297
1110
 
1298
1111
  # Capture logic: stdout to variable, stderr to temp file
1299
- ZROK_LOG="/tmp/zrok-reserve.log"
1300
- rm -f "$ZROK_LOG"
1112
+ ZROK_LOG="$(mktemp "$FASED_CONFIG_DIR/.zrok-reserve.XXXXXXXX")"
1113
+ chmod 0600 "$ZROK_LOG"
1114
+ OUT=""
1301
1115
 
1302
- if OUT=$("$ZROK_BIN" reserve public "http://127.0.0.1:${FASED_GATEWAY_PORT}" $PARAMS 2> "$ZROK_LOG"); then
1116
+ if OUT=$("$ZROK_BIN" reserve public "http://127.0.0.1:${FASED_GATEWAY_PORT}" "${ZROK_RESERVE_ARGS[@]}" 2> "$ZROK_LOG"); then
1303
1117
  RES_TOKEN=$(echo "$OUT" | jq -r '.token // empty')
1304
1118
  else
1305
- echo "[tunnel] Reserve failed. Log:"
1306
- cat "$ZROK_LOG"
1119
+ echo "[tunnel] Reservation request failed; provider output was suppressed because it may contain credentials."
1307
1120
  fi
1121
+ rm -f -- "$ZROK_LOG"
1122
+ unset ZROK_LOG ZROK_RESERVE_ARGS OUT
1308
1123
 
1309
1124
  if [[ -z "$RES_TOKEN" ]]; then
1310
- echo "[tunnel] Reservation failed or already reserved. Output: $OUT"
1125
+ echo "[tunnel] Reservation failed or was already reserved; secret-bearing output was not logged."
1311
1126
  disable_managed_tunnel "Could not establish reserved tunnel for '$SLUG'."
1312
1127
  else
1313
- echo "$RES_TOKEN" > "$RES_FILE"
1314
- echo "[tunnel] Reserved: $RES_TOKEN"
1128
+ write_private_zrok_reservation "$RES_FILE" "$RES_TOKEN"
1129
+ echo "[tunnel] Reserved a private share (token hidden)."
1315
1130
  fi
1316
1131
  fi
1317
1132
 
@@ -1439,13 +1254,11 @@ TAILSCALE_ADMIN_URL="N/A"
1439
1254
  TAILSCALE_SSH_CMD="N/A"
1440
1255
  TAILSCALE_SERVE_READY=0
1441
1256
  if command -v tailscale >/dev/null 2>&1; then
1442
- if [[ "${FASED_TAILSCALE_AUTO_SERVE:-1}" == "1" ]]; then
1257
+ if [[ "${FASED_TAILSCALE_AUTO_SERVE:-1}" == "1" && "${FASED_HOST_PROFILE:-}" != "hosting" ]]; then
1443
1258
  tailscale serve --bg "http://127.0.0.1:${FASED_GATEWAY_PORT}" >/dev/null 2>&1 || \
1444
- printf '%s\n' "${FASED_GATEWAY_PORT}" | sudo -n /usr/local/sbin/fased-host-maintenance tailscale-serve >/dev/null 2>&1 || \
1445
1259
  tailscale serve https / "http://127.0.0.1:${FASED_GATEWAY_PORT}" >/dev/null 2>&1 || true
1446
1260
  fi
1447
- if tailscale serve status 2>/dev/null | grep -q "127.0.0.1:${FASED_GATEWAY_PORT}" || \
1448
- sudo -n /usr/local/sbin/fased-host-maintenance tailscale-serve-status 2>/dev/null | grep -q "127.0.0.1:${FASED_GATEWAY_PORT}"; then
1261
+ if tailscale serve status 2>/dev/null | grep -q "127.0.0.1:${FASED_GATEWAY_PORT}"; then
1449
1262
  TAILSCALE_SERVE_READY=1
1450
1263
  fi
1451
1264
  if command -v jq >/dev/null 2>&1; then
@@ -1465,22 +1278,20 @@ FED_TOKEN_ID="N/A"
1465
1278
  FED_EXPIRES_AT="N/A"
1466
1279
  FED_AGENT_SLUG="N/A"
1467
1280
  FED_PUBLIC_URL="N/A"
1468
- FED_ZROK_TOKEN=""
1281
+ FED_ZROK_CREDENTIAL_STATE="not present"
1469
1282
  if command -v jq >/dev/null 2>&1; then
1470
1283
  FED_HANDLE=$(jq -r '.handle // "N/A"' "$TOKEN_PATH" 2>/dev/null || echo "N/A")
1471
1284
  FED_TOKEN_ID=$(jq -r '.tokenId // "N/A"' "$TOKEN_PATH" 2>/dev/null || echo "N/A")
1472
1285
  FED_EXPIRES_AT=$(jq -r '.expiresAt // "N/A"' "$TOKEN_PATH" 2>/dev/null || echo "N/A")
1473
1286
  FED_AGENT_SLUG=$(jq -r '.agentSlug // "N/A"' "$TOKEN_PATH" 2>/dev/null || echo "N/A")
1474
1287
  FED_PUBLIC_URL=$(jq -r '.publicUrl // "N/A"' "$TOKEN_PATH" 2>/dev/null || echo "N/A")
1475
- FED_ZROK_TOKEN=$(jq -r '.zrokToken // empty' "$TOKEN_PATH" 2>/dev/null || true)
1476
- fi
1477
- FED_ZROK_TOKEN_MASKED="N/A"
1478
- if [[ -n "$FED_ZROK_TOKEN" ]]; then
1479
- FED_ZROK_TOKEN_MASKED=$(mask_secret "$FED_ZROK_TOKEN")
1288
+ if jq -e '.zrokToken | type == "string" and length > 0' "$TOKEN_PATH" >/dev/null 2>&1; then
1289
+ FED_ZROK_CREDENTIAL_STATE="present (hidden)"
1290
+ fi
1480
1291
  fi
1481
- RES_TOKEN_MASKED="N/A"
1292
+ RES_TOKEN_STATE="not present"
1482
1293
  if [[ -n "${RES_TOKEN:-}" ]]; then
1483
- RES_TOKEN_MASKED=$(mask_secret "$RES_TOKEN")
1294
+ RES_TOKEN_STATE="present (hidden)"
1484
1295
  fi
1485
1296
  GATEWAY_TOKEN_MASKED=$(mask_secret "$(tr -d '\n' < "$GW_TOKEN_PATH")")
1486
1297
 
@@ -1497,11 +1308,11 @@ echo " Token ID: $FED_TOKEN_ID"
1497
1308
  echo " Expires At: $FED_EXPIRES_AT"
1498
1309
  echo " Agent Slug: $FED_AGENT_SLUG"
1499
1310
  echo " Public URL (token): $FED_PUBLIC_URL"
1500
- echo " zrokToken: $FED_ZROK_TOKEN_MASKED"
1311
+ echo " zrok credential: $FED_ZROK_CREDENTIAL_STATE"
1501
1312
  echo "Federation/A2A Tunnel (zrok)"
1502
1313
  echo " PID: ${ZROK_PID:-N/A}"
1503
1314
  echo " Slug: ${SLUG:-N/A}"
1504
- echo " Reservation token: $RES_TOKEN_MASKED"
1315
+ echo " Reservation: $RES_TOKEN_STATE"
1505
1316
  echo " Public URL (A2A): $FINAL_URL"
1506
1317
  echo " Runtime log: $ZROK_RUNTIME_LOG"
1507
1318
  if [[ "$MANAGED_TUNNEL_DISABLED" == "1" ]]; then
@@ -1583,7 +1394,9 @@ cleanup_managed_runtime() {
1583
1394
  kill "$ZROK_MONITOR_PID" 2>/dev/null || true
1584
1395
  fi
1585
1396
  rm -f "$FASED_CONFIG_DIR/.zrok-pid" "$ZROK_MONITOR_PID_FILE" 2>/dev/null || true
1586
- stop_existing_signerd >/dev/null 2>&1 || true
1397
+ if [[ "${HOSTED_ROOT_SIGNER:-0}" != "1" ]]; then
1398
+ stop_existing_signerd >/dev/null 2>&1 || true
1399
+ fi
1587
1400
  force_stop_local_gateway
1588
1401
  }
1589
1402