@fased/fased 0.1.61 → 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 (514) hide show
  1. package/CHANGELOG.md +43 -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/acp/client.js +2 -2
  12. package/dist/acp/secret-file.js +2 -2
  13. package/dist/agents/agent-scope.js +2 -2
  14. package/dist/agents/apply-patch.js +8 -8
  15. package/dist/agents/auth-profiles/paths.js +2 -2
  16. package/dist/agents/auth-profiles/store.js +269 -33
  17. package/dist/agents/bash-tools.exec.js +10 -4
  18. package/dist/agents/bash-tools.shared.js +2 -2
  19. package/dist/agents/cli-credentials.js +4 -4
  20. package/dist/agents/current-model-catalog.js +3 -3
  21. package/dist/agents/docs-path.js +3 -3
  22. package/dist/agents/embedded-pi-mcp.js +4 -4
  23. package/dist/agents/identity-avatar.js +3 -3
  24. package/dist/agents/identity-file.js +2 -2
  25. package/dist/agents/memory-search.js +7 -1
  26. package/dist/agents/model-catalog-access.js +1 -2
  27. package/dist/agents/model-catalog-snapshot.js +1 -1
  28. package/dist/agents/model-catalog-source.js +1 -1
  29. package/dist/agents/model-metadata.js +1 -1
  30. package/dist/agents/model-selection.js +2 -28
  31. package/dist/agents/models-config.providers.js +6 -6
  32. package/dist/agents/openai-codex-app-server.js +5 -5
  33. package/dist/agents/pi-embedded-runner/compact.js +15 -7
  34. package/dist/agents/pi-embedded-runner/model.js +1 -1
  35. package/dist/agents/pi-embedded-runner/run/attempt.js +24 -13
  36. package/dist/agents/pi-embedded-runner/run.js +2 -0
  37. package/dist/agents/pi-embedded-runner/tool-split.js +40 -2
  38. package/dist/agents/pi-embedded-subscribe.raw-stream.js +3 -3
  39. package/dist/agents/pi-extensions/compaction-safeguard.js +3 -3
  40. package/dist/agents/pi-model-discovery.js +6 -6
  41. package/dist/agents/pi-project-settings.js +3 -3
  42. package/dist/agents/pi-tool-definition-adapter.js +16 -1
  43. package/dist/agents/pi-tools.js +2 -1
  44. package/dist/agents/sandbox/config.js +1 -1
  45. package/dist/agents/sandbox/context.js +27 -2
  46. package/dist/agents/sandbox/fs-bridge.js +2 -2
  47. package/dist/agents/session-dirs.js +4 -4
  48. package/dist/agents/session-write-lock.js +13 -13
  49. package/dist/agents/shell-utils.js +5 -5
  50. package/dist/agents/skills/bundled-dir.js +4 -4
  51. package/dist/agents/skills/env-overrides.js +38 -28
  52. package/dist/agents/skills/local-loader.js +6 -6
  53. package/dist/agents/skills/plugin-skills.js +2 -2
  54. package/dist/agents/skills/trust.js +93 -0
  55. package/dist/agents/skills/workspace.js +141 -13
  56. package/dist/agents/skills-clawhub.js +36 -11
  57. package/dist/agents/skills-install-download.js +7 -7
  58. package/dist/agents/skills-install-plan.js +2 -2
  59. package/dist/agents/skills-install.js +2 -2
  60. package/dist/agents/skills-marketplace-scan.js +49 -0
  61. package/dist/agents/skills-status.js +2 -2
  62. package/dist/agents/subagent-depth.js +2 -2
  63. package/dist/agents/system-prompt-params.js +2 -2
  64. package/dist/agents/tools/marketplace-offer-draft-tool.js +1 -1
  65. package/dist/agents/tools/mining-tool.js +1 -1
  66. package/dist/agents/tools/session-status-tool.js +1 -1
  67. package/dist/agents/tools/wallet-action-tool.js +172 -36
  68. package/dist/agents/tools/wallet-skill-policy.js +65 -23
  69. package/dist/agents/tools/wallet-tool.js +7 -11
  70. package/dist/agents/workspace.js +22 -22
  71. package/dist/auto-reply/reply/agent-runner-execution.js +2 -2
  72. package/dist/auto-reply/reply/agent-runner.js +2 -2
  73. package/dist/auto-reply/reply/commands-export-session.js +7 -7
  74. package/dist/auto-reply/reply/directive-handling.fast-lane.js +2 -1
  75. package/dist/auto-reply/reply/directive-handling.impl.js +2 -1
  76. package/dist/auto-reply/reply/directive-handling.model.js +2 -1
  77. package/dist/auto-reply/reply/directive-handling.persist.js +2 -2
  78. package/dist/auto-reply/reply/get-reply-directives-apply.js +2 -0
  79. package/dist/auto-reply/reply/get-reply-inline-actions.js +25 -1
  80. package/dist/auto-reply/reply/model-selection.js +7 -4
  81. package/dist/auto-reply/reply/post-compaction-audit.js +3 -3
  82. package/dist/auto-reply/reply/post-compaction-context.js +3 -3
  83. package/dist/auto-reply/reply/session-reset-model.js +4 -4
  84. package/dist/auto-reply/reply/session.js +3 -3
  85. package/dist/auto-reply/skill-commands.js +3 -3
  86. package/dist/auto-reply/status.js +6 -6
  87. package/dist/brand.js +1 -1
  88. package/dist/browser/chrome.executables.js +3 -3
  89. package/dist/browser/chrome.js +3 -3
  90. package/dist/browser/chrome.profile-decoration.js +6 -6
  91. package/dist/browser/profiles-service.js +2 -2
  92. package/dist/browser/server-context.js +2 -2
  93. package/dist/browser/trash.js +4 -4
  94. package/dist/build-info.json +3 -3
  95. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  96. package/dist/canvas-host/server.js +4 -4
  97. package/dist/capabilities/catalog.js +3 -3
  98. package/dist/channel-web.js +2 -2
  99. package/dist/channels/plugins/catalog.js +3 -3
  100. package/dist/cli/browser-cli-extension.js +6 -6
  101. package/dist/cli/command-format.js +2 -2
  102. package/dist/cli/cron-cli/register.cron-simple.js +2 -2
  103. package/dist/cli/dns-cli.js +9 -9
  104. package/dist/cli/gateway-cli/dev.js +5 -5
  105. package/dist/cli/gateway-cli/run.js +10 -2
  106. package/dist/cli/hooks-cli.js +5 -5
  107. package/dist/cli/lightweight/gateway-runtime-probe.js +2 -2
  108. package/dist/cli/memory-cli.js +7 -7
  109. package/dist/cli/nodes-media-utils.js +2 -2
  110. package/dist/cli/plugins-cli.js +2 -2
  111. package/dist/cli/program/command-registry.js +1 -1
  112. package/dist/cli/program/register.onboard.js +2 -3
  113. package/dist/cli/program/register.wallet.js +16 -123
  114. package/dist/cli/providers-cli.js +1 -1
  115. package/dist/cli/sat-cli.js +129 -2
  116. package/dist/cli/secrets-cli.js +3 -3
  117. package/dist/cli/update-cli/update-command.js +260 -11
  118. package/dist/cli/windows-argv.js +2 -2
  119. package/dist/commands/auth-choice.apply.api-providers.js +3 -3
  120. package/dist/commands/dashboard-link.js +3 -3
  121. package/dist/commands/doctor-config-flow.js +1 -1
  122. package/dist/commands/doctor-install.js +5 -5
  123. package/dist/commands/doctor-legacy-config.js +2 -13
  124. package/dist/commands/doctor-memory-search.js +2 -2
  125. package/dist/commands/doctor-platform-notes.js +2 -2
  126. package/dist/commands/doctor-sandbox.js +2 -2
  127. package/dist/commands/doctor-state-integrity.js +23 -23
  128. package/dist/commands/doctor-workspace.js +3 -3
  129. package/dist/commands/doctor.js +3 -3
  130. package/dist/commands/managed-up.js +2 -2
  131. package/dist/commands/model-picker.js +6 -6
  132. package/dist/commands/models/auth.js +1 -1
  133. package/dist/commands/onboard-auth.config-gateways.js +1 -1
  134. package/dist/commands/onboard-auth.credentials.js +35 -11
  135. package/dist/commands/onboard-non-interactive/local/wallet-config.js +28 -27
  136. package/dist/commands/onboard-non-interactive/local.js +5 -1
  137. package/dist/commands/onboarding/plugin-install.js +2 -2
  138. package/dist/commands/sessions-cleanup.js +2 -2
  139. package/dist/commands/signal-install.js +6 -6
  140. package/dist/commands/status-all/channels.js +2 -2
  141. package/dist/commands/wallet.js +570 -1913
  142. package/dist/config/cache-utils.js +2 -2
  143. package/dist/config/config.js +2 -2
  144. package/dist/config/includes.js +5 -5
  145. package/dist/config/io.js +66 -4
  146. package/dist/config/paths.js +3 -3
  147. package/dist/config/sat-runtime-ids.js +3 -3
  148. package/dist/config/schema.help.js +8 -7
  149. package/dist/config/schema.labels.js +5 -4
  150. package/dist/config/sessions/disk-budget.js +6 -6
  151. package/dist/config/sessions/paths.js +2 -2
  152. package/dist/config/sessions/store.js +17 -17
  153. package/dist/config/sessions/transcript.js +4 -4
  154. package/dist/config/talk.js +2 -2
  155. package/dist/config/zod-schema.agent-runtime.js +1 -0
  156. package/dist/config/zod-schema.js +5 -0
  157. package/dist/control-ui/assets/{app-BXA4gPvN.js → app-bR-fO5ty.js} +1511 -1555
  158. package/dist/control-ui/assets/{config-CU5Zi8Dh.js → config-LeImukCW.js} +10 -10
  159. package/dist/control-ui/assets/{federation-D10Q4eP_.js → federation-DgA9e-Pn.js} +364 -422
  160. package/dist/control-ui/assets/{index-D2QbJhVg.js → index-ckCxHwjy.js} +3 -3
  161. package/dist/control-ui/assets/{mining-BdhMn18r.js → mining-BgHFh0ei.js} +134 -114
  162. package/dist/control-ui/assets/mining-commit-DFpB_4JN.js +2 -0
  163. package/dist/control-ui/assets/{open-external-url-DwSiwMPl.js → open-external-url-ulF1B-sA.js} +3 -3
  164. package/dist/control-ui/assets/{providers-QMn4w2_f.js → providers-CIx9fxc6.js} +2 -2
  165. package/dist/control-ui/assets/{wallet-C2g294QT.js → wallet-DvStR_AT.js} +259 -377
  166. package/dist/control-ui/index.html +1 -1
  167. package/dist/control-ui/version.json +1 -1
  168. package/dist/cron/service/store.js +2 -2
  169. package/dist/cron/store.js +6 -6
  170. package/dist/daemon/systemd-system.js +60 -54
  171. package/dist/discord/monitor/thread-bindings.state.js +2 -2
  172. package/dist/extensions/sat-mining/src/protocol-contract.js +43 -3
  173. package/dist/extensions/sat-mining/src/rpc-read.js +235 -67
  174. package/dist/extensions/sat-mining/src/sat-bond-layout.js +14 -11
  175. package/dist/extensions/sat-mining/src/signer-codec-manifest.js +406 -0
  176. package/dist/extensions/sat-mining/src/solana-submit.js +1038 -397
  177. package/dist/extensions/sat-mining/src/submission-ledger.js +349 -0
  178. package/dist/federation/auto-connect.js +98 -8
  179. package/dist/federation/marketplace-capability-adapter.js +33 -7
  180. package/dist/federation/marketplace-delivery-outbox.js +196 -0
  181. package/dist/federation/marketplace-delivery.js +351 -215
  182. package/dist/federation/marketplace-direct-payment.js +272 -141
  183. package/dist/federation/marketplace-escrow.js +607 -249
  184. package/dist/federation/marketplace-settlement-ledger.js +352 -0
  185. package/dist/federation/offers.js +9 -7
  186. package/dist/federation/peer-auth-v2.js +529 -0
  187. package/dist/gateway/a2a-http.js +425 -96
  188. package/dist/gateway/a2a-settlement.js +259 -153
  189. package/dist/gateway/a2a-task-store.js +524 -0
  190. package/dist/gateway/auth.js +38 -2
  191. package/dist/gateway/config-reload.js +46 -33
  192. package/dist/gateway/control-ui-boot-check.js +6 -6
  193. package/dist/gateway/control-ui-login.js +7 -7
  194. package/dist/gateway/control-ui.js +9 -9
  195. package/dist/gateway/durable-capacity.js +31 -0
  196. package/dist/gateway/federation-http.js +540 -135
  197. package/dist/gateway/federation-marketplace-run-store.js +397 -0
  198. package/dist/gateway/federation-marketplace.js +535 -230
  199. package/dist/gateway/hooks-mapping.js +4 -4
  200. package/dist/gateway/mutating-admin-rpc-rate-limit.js +5 -0
  201. package/dist/gateway/security-path.js +1 -1
  202. package/dist/gateway/server-discovery.js +2 -2
  203. package/dist/gateway/server-http.js +1088 -1209
  204. package/dist/gateway/server-methods/chat.js +3 -3
  205. package/dist/gateway/server-methods/models.js +1 -1
  206. package/dist/gateway/server-methods/secrets.js +40 -0
  207. package/dist/gateway/server-methods/sessions.js +6 -6
  208. package/dist/gateway/server-methods/usage.js +2 -2
  209. package/dist/gateway/server-methods.js +1 -2
  210. package/dist/gateway/server-reload-handlers.js +196 -66
  211. package/dist/gateway/server-runtime-config.js +1 -1
  212. package/dist/gateway/server-secrets-runtime.js +288 -0
  213. package/dist/gateway/server.impl.js +73 -42
  214. package/dist/gateway/session-compaction-checkpoints.js +4 -4
  215. package/dist/gateway/session-utils.fs.js +24 -24
  216. package/dist/gateway/session-utils.js +6 -6
  217. package/dist/gateway/sessions-patch.js +3 -5
  218. package/dist/hooks/bundled-dir.js +4 -4
  219. package/dist/hooks/gmail-setup-utils.js +6 -6
  220. package/dist/hooks/import-url.js +2 -2
  221. package/dist/hooks/loader.js +4 -4
  222. package/dist/hooks/workspace.js +7 -7
  223. package/dist/index.js +4 -2
  224. package/dist/infra/archive.js +17 -17
  225. package/dist/infra/boundary-file-read.js +2 -2
  226. package/dist/infra/boundary-path.js +15 -15
  227. package/dist/infra/brew.js +2 -2
  228. package/dist/infra/control-ui-assets.js +14 -14
  229. package/dist/infra/device-auth-store.js +8 -8
  230. package/dist/infra/device-identity.js +8 -8
  231. package/dist/infra/dotenv.js +2 -2
  232. package/dist/infra/exec-approvals.js +8 -8
  233. package/dist/infra/exec-command-resolution.js +4 -4
  234. package/dist/infra/exec-safe-bin-trust.js +2 -2
  235. package/dist/infra/fased-root.js +5 -5
  236. package/dist/infra/fasedhub.js +64 -1
  237. package/dist/infra/fs-safe.js +14 -14
  238. package/dist/infra/gateway-lock.js +11 -11
  239. package/dist/infra/git-commit.js +5 -5
  240. package/dist/infra/git-root.js +4 -4
  241. package/dist/infra/hosted-runtime-artifact.js +3 -3
  242. package/dist/infra/is-main.js +2 -2
  243. package/dist/infra/json-file.js +7 -7
  244. package/dist/infra/local-source-paired-update.js +538 -0
  245. package/dist/infra/managed-runtime-bootstrap.js +6 -6
  246. package/dist/infra/outbound/delivery-queue.js +16 -16
  247. package/dist/infra/path-env.js +3 -3
  248. package/dist/infra/ports-lsof.js +4 -4
  249. package/dist/infra/provider-usage.auth.js +3 -3
  250. package/dist/infra/restart.js +41 -10
  251. package/dist/infra/safe-open-sync.js +2 -2
  252. package/dist/infra/session-cost-usage.js +9 -9
  253. package/dist/infra/shell-env.js +2 -2
  254. package/dist/infra/state-migrations.fs.js +6 -6
  255. package/dist/infra/state-migrations.js +23 -23
  256. package/dist/infra/tmp-fased-dir.js +6 -6
  257. package/dist/infra/update-runner.js +96 -0
  258. package/dist/infra/widearea-dns.js +3 -3
  259. package/dist/infra/wsl.js +2 -2
  260. package/dist/light-update-status.js +11 -11
  261. package/dist/line/accounts.js +2 -2
  262. package/dist/line/download.js +2 -2
  263. package/dist/logging/config.js +3 -3
  264. package/dist/logging/logger.js +7 -7
  265. package/dist/managed/federation.js +3 -3
  266. package/dist/managed/tunnel.js +3 -3
  267. package/dist/media/store.js +13 -13
  268. package/dist/media-understanding/runner.js +3 -3
  269. package/dist/memory/backend-config.js +2 -1
  270. package/dist/memory/embeddings.js +2 -2
  271. package/dist/memory/internal.js +10 -10
  272. package/dist/memory/manager-sync-ops.js +7 -7
  273. package/dist/memory/repair-executor.js +17 -17
  274. package/dist/memory/session-files.js +16 -2
  275. package/dist/node-host/invoke-system-run-plan.js +8 -8
  276. package/dist/node-host/invoke.js +2 -2
  277. package/dist/node-host/runner.js +3 -3
  278. package/dist/pairing/pairing-store.js +3 -3
  279. package/dist/plugin-sdk/{accounts-DxblobYM.js → accounts-Brn3-uWN.js} +1 -1
  280. package/dist/plugin-sdk/{actions-D4UNimWa.js → actions-DRu135h0.js} +2 -2
  281. package/dist/plugin-sdk/{active-listener-CFuy106s.js → active-listener-B_NMtgPL.js} +1 -1
  282. package/dist/plugin-sdk/{audio-preflight-Bv0hUOWL.js → audio-preflight-BYxAt775.js} +27 -27
  283. package/dist/plugin-sdk/{audit-Cs0K7LBp.js → audit-C5d2z5U1.js} +1 -1
  284. package/dist/plugin-sdk/{channel-access-D5aHoTY8.js → channel-access-CcFRdRPO.js} +1 -1
  285. package/dist/plugin-sdk/{channel-access-configure-Dvch9mMQ.js → channel-access-configure-DaI5wevh.js} +1 -1
  286. package/dist/plugin-sdk/channel-plugin-common.d.ts +3 -3
  287. package/dist/plugin-sdk/channel-plugin-common.js +4 -4
  288. package/dist/plugin-sdk/{chunk-B0FUGc5A.js → chunk-CyoyqpbG.js} +1 -1
  289. package/dist/plugin-sdk/{chunk-items-Bk--NU3E.js → chunk-items-DIRHG2gJ.js} +1 -1
  290. package/dist/plugin-sdk/command-status.d.ts +2 -2
  291. package/dist/plugin-sdk/command-status.js +27 -27
  292. package/dist/plugin-sdk/{commands-registry-DmDRhRAU.js → commands-registry-BfqdEWdF.js} +2 -2
  293. package/dist/plugin-sdk/{common-CfUOowOp.js → common-HCcXU-NR.js} +1 -1
  294. package/dist/plugin-sdk/{config-mxULv0fQ.js → config-DlWVeLFB.js} +7113 -6877
  295. package/dist/plugin-sdk/{config-schema-CGW6J3Pv.js → config-schema-BOT7kHb6.js} +6779 -3696
  296. package/dist/plugin-sdk/device-pair.d.ts +1 -1
  297. package/dist/plugin-sdk/discord.d.ts +5 -5
  298. package/dist/plugin-sdk/discord.js +19 -19
  299. package/dist/plugin-sdk/file-lock.js +35 -4
  300. package/dist/plugin-sdk/{filesystem-manager-ZoHU8oA7.js → filesystem-manager-DoI8IBNF.js} +1 -1
  301. package/dist/plugin-sdk/{group-mentions-BHRff6j8.d.ts → group-mentions-q3hUTCt7.d.ts} +1 -1
  302. package/dist/plugin-sdk/{handle-action-DbVCF9HZ.js → handle-action-hvwapMKg.js} +13 -13
  303. package/dist/plugin-sdk/{helpers-BXbdgs5H.js → helpers-DMBU4oTo.js} +1 -1
  304. package/dist/plugin-sdk/{image-ops-D7jPxaph.js → image-ops-DQi0n_Tt.js} +1 -1
  305. package/dist/plugin-sdk/index.d.ts +9 -27
  306. package/dist/plugin-sdk/index.js +29 -29
  307. package/dist/plugin-sdk/json-store.js +6 -6
  308. package/dist/plugin-sdk/{login-BRxww6nv.js → login-Ca583Okc.js} +3 -3
  309. package/dist/plugin-sdk/{login-qr-DJXsk9XH.js → login-qr-CGciBSNP.js} +3 -3
  310. package/dist/plugin-sdk/{manager-Y2S_5IlI.js → manager-BegWxNYX.js} +4 -4
  311. package/dist/plugin-sdk/{markdown-tables-DHLFQqaF.js → markdown-tables-DCOXEUfZ.js} +1 -1
  312. package/dist/plugin-sdk/{media-Czo4carg.js → media-CAdQF5TG.js} +47 -47
  313. package/dist/plugin-sdk/{memory-search-DTjIMw8J.js → memory-search-CrFPOeTH.js} +4 -1
  314. package/dist/plugin-sdk/{monitor-B9Cmt_Je.js → monitor-BCFDaqJ-.js} +31 -31
  315. package/dist/plugin-sdk/{monitor-B71iwAgC.js → monitor-BgbjRiPM.js} +32 -32
  316. package/dist/plugin-sdk/{openresponses-http-Du4GMmwo.js → openresponses-http-DFf87SMM.js} +27 -27
  317. package/dist/plugin-sdk/{optional-runtime-dependency-DdMbxS24.js → optional-runtime-dependency-0dznm3ZO.js} +1 -1
  318. package/dist/plugin-sdk/{outbound-Db8mRN6P.js → outbound-BgVDdHxx.js} +6 -6
  319. package/dist/plugin-sdk/{outbound-attachment-BqFjcypb.js → outbound-attachment-QqTnIhZL.js} +2 -2
  320. package/dist/plugin-sdk/{pairing-message-BMkkS038.d.ts → pairing-message-CS-9BHug.d.ts} +2 -2
  321. package/dist/plugin-sdk/{pairing-message-B3GC_7CD.js → pairing-message-D0CoLHRJ.js} +1 -1
  322. package/dist/plugin-sdk/{pairing-store-CQikgIbw.js → pairing-store-BChahgI2.js} +2 -2
  323. package/dist/plugin-sdk/{pi-model-discovery-CY3m5zJP.js → pi-model-discovery-BX_JLcEJ.js} +1 -1
  324. package/dist/plugin-sdk/{pi-model-discovery-runtime-DSh1T2pn.js → pi-model-discovery-runtime-DxTMz_XF.js} +2 -2
  325. package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +2 -2
  326. package/dist/plugin-sdk/{pw-ai-AFUqn-tQ.js → pw-ai-natjh3rm.js} +3 -3
  327. package/dist/plugin-sdk/{qmd-manager-DSyx77KY.js → qmd-manager-CgRaTxUq.js} +1 -1
  328. package/dist/plugin-sdk/{query-expansion-CAI2kKLQ.js → query-expansion-BG3FgzF7.js} +14 -3
  329. package/dist/plugin-sdk/{replies-Fzh9PhXl.js → replies-ChYo5ZQM.js} +2 -2
  330. package/dist/plugin-sdk/{resolve-outbound-target-KpF3co6T.js → resolve-outbound-target-D-KGgHJZ.js} +1 -1
  331. package/dist/plugin-sdk/{resolve-route-CDl74O19.js → resolve-route-C8tvQm8Z.js} +1 -1
  332. package/dist/plugin-sdk/{retry-policy-D4uiqUOG.js → retry-policy-C6SjKjQA.js} +1 -1
  333. package/dist/plugin-sdk/{runtime-Bb6KRnCC.js → runtime-2B9_WKoI.js} +8 -3
  334. package/dist/plugin-sdk/{runtime-dependency-DLDmB94f.js → runtime-dependency-DczkvPxn.js} +2 -2
  335. package/dist/plugin-sdk/sat-runtime.d.ts +549 -309
  336. package/dist/plugin-sdk/sat-runtime.js +29 -29
  337. package/dist/plugin-sdk/{send-C4k4JuJN.js → send-B6KkGKZD.js} +6 -6
  338. package/dist/plugin-sdk/{send-D-uDKGIq.js → send-CFzGKJXo.js} +6 -6
  339. package/dist/plugin-sdk/{send-Du8ykP1k.js → send-DCO441U7.js} +8 -8
  340. package/dist/plugin-sdk/{send-5nFktR1n.js → send-gDoGA-7e.js} +5 -5
  341. package/dist/plugin-sdk/{send-Bfzf11VY.js → send-q9HXrSwK.js} +7 -7
  342. package/dist/plugin-sdk/{session-CS-Td9EM.js → session-DHD4ZKyG.js} +2 -2
  343. package/dist/plugin-sdk/{skill-commands-CFAlXWHk.js → skill-commands-FKEPLS7T.js} +201 -26
  344. package/dist/plugin-sdk/{slack-D_bbE6Yd.js → slack-BUTt8cxK.js} +39 -39
  345. package/dist/plugin-sdk/{slack-actions-BcMkNv1Z.js → slack-actions-DhbMcp8M.js} +11 -11
  346. package/dist/plugin-sdk/slack.d.ts +5 -5
  347. package/dist/plugin-sdk/slack.js +9 -9
  348. package/dist/plugin-sdk/{sticker-cache-Dqo9nRhi.js → sticker-cache-D0wHVqjt.js} +3 -3
  349. package/dist/plugin-sdk/{tables-bFXyRpkx.js → tables-B3jr0Pvq.js} +1 -1
  350. package/dist/plugin-sdk/{targets-DH7a9lKB.js → targets-CtSbTxYX.js} +1 -1
  351. package/dist/plugin-sdk/{telegram-actions-Cnag7JTH.js → telegram-actions-CC_qN4v0.js} +30 -30
  352. package/dist/plugin-sdk/telegram.d.ts +5 -5
  353. package/dist/plugin-sdk/telegram.js +8 -8
  354. package/dist/plugin-sdk/{thread-bindings.lifecycle-CgOvvdw8.js → thread-bindings.lifecycle-QbkNl-m6.js} +3 -3
  355. package/dist/plugin-sdk/{thread-bindings.state-CQpk44Hq.js → thread-bindings.state-D9hg_M1c.js} +2 -2
  356. package/dist/plugin-sdk/tmp-fased-dir-xOTGlzBE.d.ts +486 -0
  357. package/dist/plugin-sdk/{types-CLIvQaVg.d.ts → types-C3avNytw.d.ts} +3 -4
  358. package/dist/plugin-sdk/{types-DyhXnYUr.d.ts → types-D0kDG8l0.d.ts} +3 -2
  359. package/dist/plugin-sdk/{types-BYDL6dQj.d.ts → types-DWfbSAaM.d.ts} +2 -2
  360. package/dist/plugin-sdk/{types.plugin-_fbu40Re.d.ts → types.plugin-BcSBq42x.d.ts} +8 -3
  361. package/dist/plugin-sdk/{web-BInKQkc4.js → web-BXsJ1vqe.js} +32 -32
  362. package/dist/plugin-sdk/{whatsapp-actions-BtSc2CBv.js → whatsapp-actions-Bj_rOncr.js} +13 -13
  363. package/dist/plugin-sdk/{whatsapp-heartbeat-Bg9TuYzl.js → whatsapp-heartbeat-B1WHkJIg.js} +2 -2
  364. package/dist/plugin-sdk/whatsapp.d.ts +5 -5
  365. package/dist/plugin-sdk/whatsapp.js +12 -12
  366. package/dist/plugin-sdk/{wsl-C4DGFkOd.js → wsl-J-HscWxS.js} +3 -3
  367. package/dist/plugins/bundled-dir.js +3 -3
  368. package/dist/plugins/discovery.js +11 -11
  369. package/dist/plugins/loader.js +13 -13
  370. package/dist/plugins/manifest-registry.js +2 -2
  371. package/dist/plugins/manifest.js +4 -4
  372. package/dist/plugins/path-safety.js +3 -3
  373. package/dist/plugins/status-cache.js +9 -9
  374. package/dist/plugins/update.js +3 -3
  375. package/dist/plugins/web-search-install-catalog.js +3 -3
  376. package/dist/providers/refresh.js +1 -1
  377. package/dist/providers/registry.js +1 -1
  378. package/dist/secrets/apply.js +17 -17
  379. package/dist/secrets/audit.js +11 -11
  380. package/dist/secrets/runtime.js +1 -1
  381. package/dist/secrets/shared.js +9 -9
  382. package/dist/security/scan-paths.js +2 -2
  383. package/dist/shared/config-eval.js +2 -2
  384. package/dist/shared/pid-alive.js +2 -2
  385. package/dist/tasks/standing-orders.js +5 -5
  386. package/dist/tasks/task-flow-registry.js +5 -5
  387. package/dist/tasks/task-registry.js +5 -5
  388. package/dist/tasks/workflow-definitions.js +6 -6
  389. package/dist/telegram/token.js +5 -5
  390. package/dist/utils.js +5 -5
  391. package/dist/wallet/external-submission-ledger.js +376 -0
  392. package/dist/wallet/legacy-embedded-keystore.js +40 -0
  393. package/dist/wallet/local-socket-signer-archive.js +30 -0
  394. package/dist/wallet/local-socket-signer-lifecycle.js +97 -0
  395. package/dist/wallet/local-socket-signer-policy.js +166 -0
  396. package/dist/wallet/local-socket-signer-protocol.js +561 -118
  397. package/dist/wallet/native-signer-wallet-id.js +25 -0
  398. package/dist/wallet/providers/alchemy-adapter.js +3 -0
  399. package/dist/wallet/providers/local-socket-signer-adapter.js +382 -107
  400. package/dist/wallet/providers/turnkey-adapter.js +292 -34
  401. package/dist/wallet/providers/wallet-standard-adapter.js +100 -0
  402. package/dist/wallet/signer-network-admin.js +184 -0
  403. package/dist/wallet/signer-protocol-v2.generated.js +90 -0
  404. package/dist/wallet/solana-bond-signing.js +157 -69
  405. package/dist/wallet/solana-reviewed-transaction.js +375 -0
  406. package/dist/wallet/solana-swap.js +520 -64
  407. package/dist/wallet/solana-transaction-inspection.js +106 -4
  408. package/dist/wallet/solana-trigger.js +658 -320
  409. package/dist/wallet/turnkey-reviewed-state.js +370 -0
  410. package/dist/wallet/wallet-approval-auth.js +20 -31
  411. package/dist/wallet/wallet-atomic-state.js +53 -0
  412. package/dist/wallet/wallet-audit-log.js +5 -5
  413. package/dist/wallet/wallet-canary.js +0 -1
  414. package/dist/wallet/wallet-inbound-events.js +19 -14
  415. package/dist/wallet/wallet-observability.js +5 -5
  416. package/dist/wallet/wallet-policy-simulation.js +1 -1
  417. package/dist/wallet/wallet-policy.js +95 -41
  418. package/dist/wallet/wallet-provider-capabilities.js +28 -4
  419. package/dist/wallet/wallet-provider-registry.js +64 -51
  420. package/dist/wallet/wallet-provider-resolver.js +62 -63
  421. package/dist/wallet/wallet-runtime-config.js +31 -44
  422. package/dist/wallet/wallet-secrets-store.js +44 -22
  423. package/dist/wallet/wallet-send-approvals.js +1894 -592
  424. package/dist/wallet/wallet-send-execution-ledger.js +292 -0
  425. package/dist/wallet/wallet-settlement-links.js +17 -16
  426. package/dist/wallet/wallet-standard-review.js +353 -0
  427. package/dist/wallet/wallet-status.js +0 -9
  428. package/dist/wallet/wallet-task-ledger.js +16 -2
  429. package/dist/web/accounts.js +3 -3
  430. package/dist/web/auth-store.js +18 -18
  431. package/dist/web/auto-reply/heartbeat-runner.js +1 -1
  432. package/dist/web/auto-reply/monitor.js +2 -2
  433. package/dist/web/session.js +4 -4
  434. package/dist/wizard/host-security-capability.js +15 -24
  435. package/dist/wizard/onboarding.finalize.js +63 -184
  436. package/dist/wizard/onboarding.host-security.js +118 -1368
  437. package/dist/wizard/onboarding.js +180 -242
  438. package/dist/wizard/onboarding.wallet.js +323 -829
  439. package/extensions/acpx/package.json +1 -1
  440. package/extensions/bluebubbles/package.json +1 -1
  441. package/extensions/copilot-proxy/package.json +1 -1
  442. package/extensions/diagnostics-otel/package.json +1 -1
  443. package/extensions/fased-federation/package.json +1 -1
  444. package/extensions/google-gemini-cli-auth/package.json +1 -1
  445. package/extensions/imessage/package.json +1 -1
  446. package/extensions/irc/package.json +1 -1
  447. package/extensions/line/package.json +1 -1
  448. package/extensions/llm-task/package.json +1 -1
  449. package/extensions/lobster/package.json +1 -1
  450. package/extensions/matrix/CHANGELOG.md +18 -0
  451. package/extensions/matrix/package.json +1 -1
  452. package/extensions/mattermost/package.json +1 -1
  453. package/extensions/memory-core/package.json +2 -2
  454. package/extensions/memory-lancedb/package.json +1 -1
  455. package/extensions/minimax-portal-auth/package.json +1 -1
  456. package/extensions/msteams/CHANGELOG.md +18 -0
  457. package/extensions/msteams/package.json +1 -1
  458. package/extensions/nextcloud-talk/package.json +1 -1
  459. package/extensions/nostr/CHANGELOG.md +18 -0
  460. package/extensions/nostr/package.json +1 -1
  461. package/extensions/open-prose/package.json +1 -1
  462. package/extensions/sat-mining/index.ts +498 -153
  463. package/extensions/sat-mining/package.json +1 -1
  464. package/extensions/sat-mining/signer-codec-schema.v1.json +374 -0
  465. package/extensions/sat-mining/src/audit-store.ts +50 -5
  466. package/extensions/sat-mining/src/claim-service.ts +85 -14
  467. package/extensions/sat-mining/src/config.ts +9 -0
  468. package/extensions/sat-mining/src/cycle-progress.ts +16 -8
  469. package/extensions/sat-mining/src/epoch-service.ts +9 -5
  470. package/extensions/sat-mining/src/gateway-runner.ts +21 -1
  471. package/extensions/sat-mining/src/protocol-contract.ts +45 -1
  472. package/extensions/sat-mining/src/recovery-service.ts +312 -0
  473. package/extensions/sat-mining/src/round-watcher.ts +391 -81
  474. package/extensions/sat-mining/src/rpc-read.ts +330 -89
  475. package/extensions/sat-mining/src/runtime.ts +14 -0
  476. package/extensions/sat-mining/src/sat-bond-layout.ts +6 -0
  477. package/extensions/sat-mining/src/signer-codec-manifest.ts +429 -0
  478. package/extensions/sat-mining/src/solana-submit.ts +1199 -428
  479. package/extensions/sat-mining/src/submission-ledger.ts +433 -0
  480. package/extensions/signal/package.json +1 -1
  481. package/extensions/synology-chat/package.json +1 -1
  482. package/extensions/tlon/package.json +1 -1
  483. package/extensions/twitch/CHANGELOG.md +18 -0
  484. package/extensions/twitch/package.json +1 -1
  485. package/extensions/voice-call/CHANGELOG.md +18 -0
  486. package/extensions/voice-call/package.json +1 -1
  487. package/extensions/zalo/CHANGELOG.md +18 -0
  488. package/extensions/zalo/package.json +1 -1
  489. package/extensions/zalouser/CHANGELOG.md +18 -0
  490. package/extensions/zalouser/package.json +1 -1
  491. package/install.sh +4955 -0
  492. package/package.json +24 -5
  493. package/scripts/fased-host-updater.mjs +1421 -0
  494. package/scripts/fased-host-updaterctl.mjs +186 -0
  495. package/scripts/fased-managed-service.sh +36 -0
  496. package/scripts/fased-managed-updater.mjs +3065 -156
  497. package/scripts/fased-signer-enroll-hosting.sh +275 -0
  498. package/scripts/fased-signer-network-hosting.sh +143 -0
  499. package/scripts/fased-signer-owner-policy.mjs +1430 -0
  500. package/scripts/fased-signer-policy-hosting.sh +50 -0
  501. package/scripts/fased-signer-policy-local.sh +26 -0
  502. package/scripts/hosted-release-manifest.mjs +185 -0
  503. package/scripts/install-fased-signerd.sh +217 -0
  504. package/scripts/install-managed-runtime.mjs +212 -10
  505. package/scripts/managed-runtime-layout.mjs +75 -3
  506. package/scripts/migrate-hosted-signer-v2.mjs +58 -0
  507. package/scripts/start-managed.sh +169 -360
  508. package/dist/control-ui/assets/mining-commit-R-6nu87p.js +0 -2
  509. package/dist/plugin-sdk/tmp-fased-dir-BdFQvrvw.d.ts +0 -77
  510. package/dist/wallet/local-socket-signer-broker.js +0 -224
  511. package/dist/wallet/local-socket-signer-custody.js +0 -42
  512. package/dist/wallet/providers/embedded-keystore-adapter.js +0 -402
  513. package/dist/wallet/providers/privy-adapter.js +0 -80
  514. package/dist/wallet/wallet-custody.js +0 -1836
@@ -0,0 +1,370 @@
1
+ import { withFileLock } from "../plugin-sdk/file-lock.js";
2
+ import "../infra/file-lock.js";
3
+ import { ensureWalletStateDir } from "./wallet-runtime-config.js";
4
+ import { WalletProviderError } from "./wallet-provider-adapter.js";
5
+ import { broadcastReviewedSolanaTransaction, buildReviewedSolanaTransaction, computeReviewedSolanaRequestDigest, reconcileReviewedSolanaTransaction, validateReviewedSolanaSignedTransaction } from "./solana-reviewed-transaction.js";
6
+ import syncFs from "node:fs";
7
+ import path from "node:path";
8
+ import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
9
+
10
+ //#region src/wallet/turnkey-reviewed-state.ts
11
+ const STATE_FILE_NAME = "turnkey-reviews.v1.json";
12
+ const REVIEW_TTL_MS = 2 * 60 * 1e3;
13
+ const STATE_FILE_MODE = 384;
14
+ const MAX_REVIEW_RECORDS = 1e4;
15
+ const MAX_RETAINED_TERMINAL_REVIEWS = 5e3;
16
+ const TERMINAL_REVIEW_RETENTION_MS = 30 * 24 * 60 * 6e4;
17
+ const REVIEW_LOCK_OPTIONS = {
18
+ retries: {
19
+ retries: 80,
20
+ factor: 1.15,
21
+ minTimeout: 20,
22
+ maxTimeout: 200,
23
+ randomize: true
24
+ },
25
+ stale: 3e4
26
+ };
27
+ let reviewStateLock = Promise.resolve();
28
+ function statePath(env) {
29
+ return path.join(ensureWalletStateDir(env).rootDir, STATE_FILE_NAME);
30
+ }
31
+ function readFile(env) {
32
+ const filePath = statePath(env);
33
+ if (!syncFs.existsSync(filePath)) {
34
+ return {
35
+ version: 1,
36
+ reviews: []
37
+ };
38
+ }
39
+ try {
40
+ const parsed = JSON.parse(syncFs.readFileSync(filePath, "utf8"));
41
+ if (parsed.version === 1 && Array.isArray(parsed.reviews)) {
42
+ return parsed;
43
+ }
44
+ } catch {}
45
+ throw new WalletProviderError({
46
+ code: "wallet_provider_unavailable",
47
+ message: "Turnkey reviewed transaction state is invalid; repair it before signing",
48
+ retryable: false
49
+ });
50
+ }
51
+ function saveFile(file, env) {
52
+ const filePath = statePath(env);
53
+ const temporary = `${filePath}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
54
+ let descriptor;
55
+ try {
56
+ descriptor = syncFs.openSync(temporary, "wx", STATE_FILE_MODE);
57
+ syncFs.writeFileSync(descriptor, `${JSON.stringify(file, null, 2)}\n`, "utf8");
58
+ syncFs.fsyncSync(descriptor);
59
+ syncFs.closeSync(descriptor);
60
+ descriptor = undefined;
61
+ syncFs.renameSync(temporary, filePath);
62
+ try {
63
+ syncFs.chmodSync(filePath, STATE_FILE_MODE);
64
+ } catch {}
65
+ try {
66
+ const directory = syncFs.openSync(path.dirname(filePath), "r");
67
+ try {
68
+ syncFs.fsyncSync(directory);
69
+ } finally {
70
+ syncFs.closeSync(directory);
71
+ }
72
+ } catch {}
73
+ } catch (error) {
74
+ if (descriptor !== undefined) {
75
+ syncFs.closeSync(descriptor);
76
+ }
77
+ try {
78
+ syncFs.unlinkSync(temporary);
79
+ } catch {}
80
+ throw error;
81
+ }
82
+ }
83
+ function secureEqual(left, right) {
84
+ const leftBytes = Buffer.from(left, "utf8");
85
+ const rightBytes = Buffer.from(right, "utf8");
86
+ return leftBytes.length === rightBytes.length && timingSafeEqual(leftBytes, rightBytes);
87
+ }
88
+ function compactReviewState(file, nowMs = Date.now()) {
89
+ const terminal = file.reviews.filter((review) => review.status === "broadcast" || review.status === "failed").toSorted((left, right) => Date.parse(left.createdAt) - Date.parse(right.createdAt));
90
+ const removable = new Set(terminal.filter((review, index) => nowMs - Date.parse(review.createdAt) > TERMINAL_REVIEW_RETENTION_MS || terminal.length - index > MAX_RETAINED_TERMINAL_REVIEWS).map((review) => review.preparedId));
91
+ return {
92
+ version: 1,
93
+ reviews: file.reviews.filter((review) => !removable.has(review.preparedId))
94
+ };
95
+ }
96
+ function requireReviewCapacity(file) {
97
+ if (file.reviews.length >= MAX_REVIEW_RECORDS) {
98
+ throw new WalletProviderError({
99
+ code: "wallet_provider_unavailable",
100
+ message: "Turnkey review state reached its durable safety limit; reconcile unresolved reviews",
101
+ retryable: false
102
+ });
103
+ }
104
+ }
105
+ function digest(value) {
106
+ return createHash("sha256").update(value, "utf8").digest("base64url");
107
+ }
108
+ function normalizedRpcUrlDigest(rpcUrl) {
109
+ let normalized;
110
+ try {
111
+ const parsed = new URL(rpcUrl.trim());
112
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
113
+ throw new Error("unsupported protocol");
114
+ }
115
+ normalized = parsed.toString();
116
+ } catch {
117
+ throw new WalletProviderError({
118
+ code: "wallet_provider_invalid_config",
119
+ message: "Turnkey review requires a valid HTTP(S) Solana RPC URL"
120
+ });
121
+ }
122
+ return digest(normalized);
123
+ }
124
+ function preparedIdentity(params) {
125
+ return digest([
126
+ "fased-turnkey-reviewed-v1",
127
+ params.approvalRequestId,
128
+ params.requestDigest,
129
+ params.rpcUrlDigest,
130
+ params.authorizationContextDigest
131
+ ].join("\0"));
132
+ }
133
+ function toPrepareResult(record) {
134
+ return {
135
+ preparedId: record.preparedId,
136
+ signer: record.signer,
137
+ unsignedTxBase64: record.unsignedTxBase64,
138
+ messageBase64: record.messageBase64,
139
+ intentDigest: record.intentDigest,
140
+ expiresAt: record.expiresAt,
141
+ recentBlockhash: record.recentBlockhash,
142
+ lastValidBlockHeight: record.lastValidBlockHeight,
143
+ simulation: {
144
+ ok: true,
145
+ ...typeof record.simulationUnitsConsumed === "number" && Number.isFinite(record.simulationUnitsConsumed) ? { unitsConsumed: record.simulationUnitsConsumed } : {}
146
+ }
147
+ };
148
+ }
149
+ async function withReviewLock(env, task) {
150
+ const run = async () => await withFileLock(statePath(env), REVIEW_LOCK_OPTIONS, async () => await task());
151
+ const current = reviewStateLock.then(run, run);
152
+ reviewStateLock = current.then(() => undefined, () => undefined);
153
+ return await current;
154
+ }
155
+ async function prepareTurnkeyReviewedTransaction(params) {
156
+ const env = params.env ?? process.env;
157
+ const approvalRequestId = params.request.requestId?.trim();
158
+ if (!approvalRequestId) {
159
+ throw new WalletProviderError({
160
+ code: "wallet_provider_invalid_config",
161
+ message: "Turnkey preparation requires a stable approval request ID"
162
+ });
163
+ }
164
+ const requestDigest = computeReviewedSolanaRequestDigest({
165
+ request: params.request,
166
+ signer: params.signerAddress.trim()
167
+ });
168
+ const expectedRpcUrlDigest = normalizedRpcUrlDigest(params.rpcUrl);
169
+ const expectedAuthorizationContextDigest = digest(params.authorizationContext);
170
+ const preparedId = preparedIdentity({
171
+ approvalRequestId,
172
+ requestDigest,
173
+ rpcUrlDigest: expectedRpcUrlDigest,
174
+ authorizationContextDigest: expectedAuthorizationContextDigest
175
+ });
176
+ return await withReviewLock(env, async () => {
177
+ const file = compactReviewState(readFile(env));
178
+ const existing = file.reviews.find((review) => review.approvalRequestId === approvalRequestId || review.preparedId === preparedId);
179
+ if (existing) {
180
+ const sameImmutableRequest = existing.approvalRequestId === approvalRequestId && secureEqual(existing.preparedId, preparedId) && secureEqual(existing.signer, params.signerAddress.trim()) && secureEqual(existing.requestDigest, requestDigest) && secureEqual(existing.rpcUrlDigest, expectedRpcUrlDigest) && secureEqual(existing.authorizationContextDigest, expectedAuthorizationContextDigest);
181
+ if (!sameImmutableRequest) {
182
+ throw new WalletProviderError({
183
+ code: "wallet_provider_invalid_config",
184
+ message: "Turnkey approval request ID is already bound to a different immutable transaction",
185
+ retryable: false
186
+ });
187
+ }
188
+ if (existing.status === "failed") {
189
+ throw new WalletProviderError({
190
+ code: "wallet_provider_unavailable",
191
+ message: `${existing.failureReason ?? "Turnkey reviewed transaction failed"}; create a new approval request`,
192
+ retryable: false
193
+ });
194
+ }
195
+ if (existing.status === "prepared" && Date.parse(existing.expiresAt) <= Date.now()) {
196
+ throw new WalletProviderError({
197
+ code: "wallet_provider_invalid_config",
198
+ message: "Turnkey prepared review expired; create a new approval request",
199
+ retryable: false
200
+ });
201
+ }
202
+ return toPrepareResult(existing);
203
+ }
204
+ requireReviewCapacity(file);
205
+ const prepared = await buildReviewedSolanaTransaction({
206
+ request: params.request,
207
+ signerAddress: params.signerAddress,
208
+ rpcUrl: params.rpcUrl
209
+ });
210
+ if (!secureEqual(prepared.signer, params.signerAddress.trim())) {
211
+ throw new WalletProviderError({
212
+ code: "wallet_provider_unavailable",
213
+ message: "Turnkey transaction builder returned a different signer"
214
+ });
215
+ }
216
+ const now = Date.now();
217
+ const record = {
218
+ approvalRequestId,
219
+ preparedId,
220
+ createdAt: new Date(now).toISOString(),
221
+ expiresAt: new Date(now + REVIEW_TTL_MS).toISOString(),
222
+ status: "prepared",
223
+ signer: prepared.signer,
224
+ requestDigest,
225
+ intentDigest: prepared.intentDigest,
226
+ unsignedTxBase64: prepared.unsignedTxBase64,
227
+ messageBase64: prepared.messageBase64,
228
+ recentBlockhash: prepared.recentBlockhash,
229
+ lastValidBlockHeight: prepared.lastValidBlockHeight,
230
+ rpcUrlDigest: expectedRpcUrlDigest,
231
+ authorizationContextDigest: expectedAuthorizationContextDigest,
232
+ simulationUnitsConsumed: prepared.simulation.unitsConsumed
233
+ };
234
+ file.reviews.push(record);
235
+ saveFile(file, env);
236
+ return toPrepareResult(record);
237
+ });
238
+ }
239
+ async function executeTurnkeyReviewedTransaction(params) {
240
+ const env = params.env ?? process.env;
241
+ const preparedId = params.preparedId.trim();
242
+ if (!preparedId) {
243
+ throw new WalletProviderError({
244
+ code: "wallet_provider_invalid_config",
245
+ message: "Turnkey send requires a prepared review ID"
246
+ });
247
+ }
248
+ return await withReviewLock(env, async () => {
249
+ const file = readFile(env);
250
+ const review = file.reviews.find((record) => record.preparedId === preparedId);
251
+ if (!review) {
252
+ throw new WalletProviderError({
253
+ code: "wallet_provider_invalid_config",
254
+ message: "Turnkey prepared review is unknown; prepare and review the transaction again"
255
+ });
256
+ }
257
+ if (review.status === "broadcast" && review.txHash) {
258
+ return {
259
+ txHash: review.txHash,
260
+ signer: review.signer,
261
+ intentDigest: review.intentDigest,
262
+ idempotent: true
263
+ };
264
+ }
265
+ if (review.status === "broadcasting" || review.status === "unknown") {
266
+ if (!review.txHash) {
267
+ throw new WalletProviderError({
268
+ code: "wallet_provider_ambiguous",
269
+ message: "Turnkey broadcast is in progress or unknown; do not submit it again",
270
+ retryable: false
271
+ });
272
+ }
273
+ let reconciled;
274
+ try {
275
+ reconciled = await reconcileReviewedSolanaTransaction({
276
+ rpcUrl: params.rpcUrl,
277
+ expectedTxHash: review.txHash,
278
+ lastValidBlockHeight: review.lastValidBlockHeight
279
+ });
280
+ } catch {
281
+ throw new WalletProviderError({
282
+ code: "wallet_provider_ambiguous",
283
+ message: `Turnkey broadcast remains unknown; reconcile signature ${review.txHash} before any new send`,
284
+ retryable: false
285
+ });
286
+ }
287
+ if (reconciled.state === "landed") {
288
+ review.status = "broadcast";
289
+ saveFile(file, env);
290
+ return {
291
+ txHash: review.txHash,
292
+ signer: review.signer,
293
+ intentDigest: review.intentDigest,
294
+ idempotent: true
295
+ };
296
+ }
297
+ if (reconciled.state === "failed" || reconciled.state === "expired") {
298
+ review.status = "failed";
299
+ review.failureReason = reconciled.state === "failed" ? reconciled.reason : `reviewed transaction expired at block height ${review.lastValidBlockHeight} without landing`;
300
+ saveFile(file, env);
301
+ throw new WalletProviderError({
302
+ code: "wallet_provider_unavailable",
303
+ message: `${review.failureReason}; prepare and review a new transaction`,
304
+ retryable: false
305
+ });
306
+ }
307
+ throw new WalletProviderError({
308
+ code: "wallet_provider_ambiguous",
309
+ message: `Turnkey broadcast remains pending; reconcile signature ${review.txHash} before any new send`,
310
+ retryable: false
311
+ });
312
+ }
313
+ if (review.status === "failed") {
314
+ throw new WalletProviderError({
315
+ code: "wallet_provider_unavailable",
316
+ message: `${review.failureReason ?? "Turnkey reviewed transaction failed"}; prepare and review a new transaction`,
317
+ retryable: false
318
+ });
319
+ }
320
+ if (Date.parse(review.expiresAt) <= Date.now()) {
321
+ throw new WalletProviderError({
322
+ code: "wallet_provider_invalid_config",
323
+ message: "Turnkey prepared review expired; prepare and review a new transaction"
324
+ });
325
+ }
326
+ const expectedRequestDigest = computeReviewedSolanaRequestDigest({
327
+ request: params.request,
328
+ signer: params.signerAddress
329
+ });
330
+ if (review.approvalRequestId !== undefined && !secureEqual(review.approvalRequestId, params.request.requestId?.trim() ?? "") || !secureEqual(review.signer, params.signerAddress) || !secureEqual(review.requestDigest, expectedRequestDigest) || !secureEqual(review.rpcUrlDigest, normalizedRpcUrlDigest(params.rpcUrl)) || !secureEqual(review.authorizationContextDigest, digest(params.authorizationContext))) {
331
+ throw new WalletProviderError({
332
+ code: "wallet_provider_invalid_config",
333
+ message: "Turnkey execution context does not match the immutable prepared review"
334
+ });
335
+ }
336
+ const signedTxBase64 = await params.sign(review.unsignedTxBase64);
337
+ const verified = validateReviewedSolanaSignedTransaction({
338
+ unsignedTxBase64: review.unsignedTxBase64,
339
+ signedTxBase64,
340
+ signerAddress: review.signer
341
+ });
342
+ review.status = "broadcasting";
343
+ review.txHash = verified.txHash;
344
+ review.signedTxBase64 = verified.signedBytes.toString("base64");
345
+ saveFile(file, env);
346
+ try {
347
+ const txHash = await broadcastReviewedSolanaTransaction({
348
+ rpcUrl: params.rpcUrl,
349
+ signedTxBase64: review.signedTxBase64,
350
+ expectedTxHash: verified.txHash
351
+ });
352
+ review.status = "broadcast";
353
+ review.txHash = txHash;
354
+ saveFile(file, env);
355
+ return {
356
+ txHash,
357
+ signer: review.signer,
358
+ intentDigest: review.intentDigest,
359
+ idempotent: false
360
+ };
361
+ } catch (error) {
362
+ review.status = "unknown";
363
+ saveFile(file, env);
364
+ throw error;
365
+ }
366
+ });
367
+ }
368
+
369
+ //#endregion
370
+ export { executeTurnkeyReviewedTransaction, prepareTurnkeyReviewedTransaction };
@@ -1,5 +1,6 @@
1
1
  import { ensureWalletStateDir } from "./wallet-runtime-config.js";
2
- import fs from "node:fs";
2
+ import { serializeWalletState, writeWalletStateFileAtomically } from "./wallet-atomic-state.js";
3
+ import syncFs from "node:fs";
3
4
  import path from "node:path";
4
5
  import { createHash, createPublicKey, randomBytes, timingSafeEqual, verify } from "node:crypto";
5
6
 
@@ -73,22 +74,12 @@ function rpIdFromHost(host) {
73
74
  }
74
75
  }
75
76
  function normalizeState(input) {
76
- if (!input || typeof input !== "object") {
77
- return {
78
- version: 2,
79
- passkeys: [],
80
- challenges: [],
81
- grants: []
82
- };
77
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
78
+ throw new Error("wallet approval auth state must be an object");
83
79
  }
84
80
  const parsed = input;
85
- if (parsed.version !== 2) {
86
- return {
87
- version: 2,
88
- passkeys: [],
89
- challenges: [],
90
- grants: []
91
- };
81
+ if (parsed.version !== 2 || !Array.isArray(parsed.passkeys) || !Array.isArray(parsed.challenges) || !Array.isArray(parsed.grants)) {
82
+ throw new Error("wallet approval auth state has an unsupported shape");
92
83
  }
93
84
  const passkeys = Array.isArray(parsed.passkeys) ? parsed.passkeys.map((entry) => {
94
85
  if (!entry || typeof entry !== "object") {
@@ -109,6 +100,9 @@ function normalizeState(input) {
109
100
  transports: Array.isArray(value.transports) ? value.transports.map((v) => String(v)) : undefined
110
101
  };
111
102
  }).filter((entry) => entry !== null) : [];
103
+ if (passkeys.length !== parsed.passkeys.length) {
104
+ throw new Error("wallet approval auth state contains an invalid passkey");
105
+ }
112
106
  const challenges = Array.isArray(parsed.challenges) ? parsed.challenges.map((entry) => {
113
107
  if (!entry || typeof entry !== "object") {
114
108
  return null;
@@ -137,6 +131,9 @@ function normalizeState(input) {
137
131
  status: value.status
138
132
  };
139
133
  }).filter((entry) => entry !== null) : [];
134
+ if (challenges.length !== parsed.challenges.length || challenges.some((entry) => !entry.id || !entry.challenge || !entry.host || !entry.rpId)) {
135
+ throw new Error("wallet approval auth state contains an invalid challenge");
136
+ }
140
137
  const grants = Array.isArray(parsed.grants) ? parsed.grants.map((entry) => {
141
138
  if (!entry || typeof entry !== "object") {
142
139
  return null;
@@ -154,6 +151,9 @@ function normalizeState(input) {
154
151
  expiresAt: value.expiresAt
155
152
  };
156
153
  }).filter((entry) => entry !== null) : [];
154
+ if (grants.length !== parsed.grants.length || grants.some((entry) => !entry.host)) {
155
+ throw new Error("wallet approval auth state contains an invalid grant");
156
+ }
157
157
  return {
158
158
  version: 2,
159
159
  passkeys,
@@ -163,7 +163,7 @@ function normalizeState(input) {
163
163
  }
164
164
  function loadState(env = process.env) {
165
165
  const statePath = resolveStatePath(env);
166
- if (!fs.existsSync(statePath)) {
166
+ if (!syncFs.existsSync(statePath)) {
167
167
  return {
168
168
  version: 2,
169
169
  passkeys: [],
@@ -172,26 +172,15 @@ function loadState(env = process.env) {
172
172
  };
173
173
  }
174
174
  try {
175
- const raw = fs.readFileSync(statePath, "utf8");
175
+ const raw = syncFs.readFileSync(statePath, "utf8");
176
176
  return normalizeState(JSON.parse(raw));
177
- } catch {
178
- return {
179
- version: 2,
180
- passkeys: [],
181
- challenges: [],
182
- grants: []
183
- };
177
+ } catch (error) {
178
+ throw new Error("wallet approval auth state is unreadable; refusing to reset credentials", { cause: error });
184
179
  }
185
180
  }
186
181
  function saveState(state, env = process.env) {
187
182
  const statePath = resolveStatePath(env);
188
- fs.writeFileSync(statePath, `${JSON.stringify(state, null, 2)}\n`, {
189
- encoding: "utf8",
190
- mode: 384
191
- });
192
- try {
193
- fs.chmodSync(statePath, 384);
194
- } catch {}
183
+ writeWalletStateFileAtomically(statePath, serializeWalletState(state));
195
184
  }
196
185
  function pruneState(state) {
197
186
  const now = nowMs();
@@ -0,0 +1,53 @@
1
+ import syncFs from "node:fs";
2
+ import path from "node:path";
3
+ import { randomBytes } from "node:crypto";
4
+
5
+ //#region src/wallet/wallet-atomic-state.ts
6
+ const WALLET_STATE_FILE_MODE = 384;
7
+ /**
8
+ * Replace a wallet state file durably without ever exposing a partially-written
9
+ * destination. Callers remain responsible for validating the full document
10
+ * before trusting it and for serializing read/modify/write operations.
11
+ */
12
+ function writeWalletStateFileAtomically(filePath, contents) {
13
+ const directoryPath = path.dirname(filePath);
14
+ const temporaryPath = path.join(directoryPath, `.${path.basename(filePath)}.${process.pid}.${randomBytes(8).toString("hex")}.tmp`);
15
+ let descriptor;
16
+ let renamed = false;
17
+ try {
18
+ descriptor = syncFs.openSync(temporaryPath, "wx", WALLET_STATE_FILE_MODE);
19
+ syncFs.writeFileSync(descriptor, contents, { encoding: "utf8" });
20
+ syncFs.fsyncSync(descriptor);
21
+ syncFs.closeSync(descriptor);
22
+ descriptor = undefined;
23
+ syncFs.renameSync(temporaryPath, filePath);
24
+ renamed = true;
25
+ try {
26
+ syncFs.chmodSync(filePath, WALLET_STATE_FILE_MODE);
27
+ } catch {}
28
+ const directoryDescriptor = syncFs.openSync(directoryPath, "r");
29
+ try {
30
+ syncFs.fsyncSync(directoryDescriptor);
31
+ } finally {
32
+ syncFs.closeSync(directoryDescriptor);
33
+ }
34
+ } catch (error) {
35
+ if (descriptor !== undefined) {
36
+ try {
37
+ syncFs.closeSync(descriptor);
38
+ } catch {}
39
+ }
40
+ if (!renamed) {
41
+ try {
42
+ syncFs.unlinkSync(temporaryPath);
43
+ } catch {}
44
+ }
45
+ throw error;
46
+ }
47
+ }
48
+ function serializeWalletState(value) {
49
+ return `${JSON.stringify(value, null, 2)}\n`;
50
+ }
51
+
52
+ //#endregion
53
+ export { serializeWalletState, writeWalletStateFileAtomically };
@@ -1,5 +1,5 @@
1
1
  import { ensureWalletStateDir } from "./wallet-runtime-config.js";
2
- import fs from "node:fs";
2
+ import syncFs from "node:fs";
3
3
  import { randomBytes } from "node:crypto";
4
4
 
5
5
  //#region src/wallet/wallet-audit-log.ts
@@ -15,22 +15,22 @@ function appendWalletAuditEntry(params) {
15
15
  actor: params.actor?.trim() || "system",
16
16
  details: params.details ?? {}
17
17
  };
18
- fs.appendFileSync(paths.auditLogPath, `${JSON.stringify(entry)}\n`, {
18
+ syncFs.appendFileSync(paths.auditLogPath, `${JSON.stringify(entry)}\n`, {
19
19
  encoding: "utf8",
20
20
  mode: 384
21
21
  });
22
22
  try {
23
- fs.chmodSync(paths.auditLogPath, 384);
23
+ syncFs.chmodSync(paths.auditLogPath, 384);
24
24
  } catch {}
25
25
  return entry;
26
26
  }
27
27
  function readWalletAuditEntries(params) {
28
28
  const paths = ensureWalletStateDir(params?.env ?? process.env);
29
- if (!fs.existsSync(paths.auditLogPath)) {
29
+ if (!syncFs.existsSync(paths.auditLogPath)) {
30
30
  return [];
31
31
  }
32
32
  const limit = Math.max(1, Math.min(500, params?.limit ?? 100));
33
- const raw = fs.readFileSync(paths.auditLogPath, "utf8");
33
+ const raw = syncFs.readFileSync(paths.auditLogPath, "utf8");
34
34
  const lines = raw.split("\n").map((line) => line.trim()).filter(Boolean);
35
35
  const out = [];
36
36
  for (let i = lines.length - 1; i >= 0; i -= 1) {
@@ -341,7 +341,6 @@ async function runWalletProviderCanaryReport(params) {
341
341
  actor: "wallet-canary",
342
342
  config: params.wallet,
343
343
  providerIdOverride: providerId,
344
- approvalHost: "127.0.0.1",
345
344
  env
346
345
  });
347
346
  pushStep(steps, {
@@ -1,10 +1,11 @@
1
1
  import { ensureWalletStateDir } from "./wallet-runtime-config.js";
2
2
  import { readWalletProviderRegistry, resolveWalletSelection } from "./wallet-provider-registry.js";
3
+ import { serializeWalletState, writeWalletStateFileAtomically } from "./wallet-atomic-state.js";
3
4
  import { buildWalletProviderCapabilityMatrix, providerSupportsChainOperation } from "./wallet-provider-capabilities.js";
4
5
  import { walletDiagnosticErrorString } from "./wallet-redaction.js";
5
6
  import { createWalletProviderAdapter, resolveWalletProviderId } from "./wallet-provider-resolver.js";
6
7
  import { appendWalletAuditEntry, readWalletAuditEntries } from "./wallet-audit-log.js";
7
- import fs from "node:fs";
8
+ import syncFs from "node:fs";
8
9
  import path from "node:path";
9
10
  import { randomBytes } from "node:crypto";
10
11
 
@@ -26,6 +27,7 @@ function normalizeProviderId(value) {
26
27
  case "local-socket-signer":
27
28
  case "alchemy":
28
29
  case "turnkey":
30
+ case "wallet-standard":
29
31
  case "privy": return value;
30
32
  default: return null;
31
33
  }
@@ -115,9 +117,12 @@ function defaultLedger() {
115
117
  }
116
118
  function normalizeLedger(raw) {
117
119
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
118
- return defaultLedger();
120
+ throw new Error("wallet inbound ledger must be an object");
119
121
  }
120
122
  const value = raw;
123
+ if (value.version !== 1 || !Array.isArray(value.snapshots) || !Array.isArray(value.events) || typeof value.updatedAt !== "string") {
124
+ throw new Error("wallet inbound ledger has an unsupported shape");
125
+ }
121
126
  const snapshots = Array.isArray(value.snapshots) ? value.snapshots.filter((entry) => {
122
127
  if (!entry || typeof entry !== "object") {
123
128
  return false;
@@ -134,6 +139,9 @@ function normalizeLedger(raw) {
134
139
  unit: entry.unit,
135
140
  updatedAt: entry.updatedAt
136
141
  })) : [];
142
+ if (snapshots.length !== value.snapshots.length) {
143
+ throw new Error("wallet inbound ledger contains an invalid balance snapshot");
144
+ }
137
145
  const events = Array.isArray(value.events) ? value.events.filter((entry) => {
138
146
  if (!entry || typeof entry !== "object") {
139
147
  return false;
@@ -164,24 +172,27 @@ function normalizeLedger(raw) {
164
172
  } : undefined,
165
173
  metadata: entry.metadata && typeof entry.metadata === "object" ? entry.metadata : undefined
166
174
  })) : [];
175
+ if (events.length !== value.events.length) {
176
+ throw new Error("wallet inbound ledger contains an invalid event");
177
+ }
167
178
  return {
168
179
  version: 1,
169
180
  snapshots,
170
181
  events,
171
- updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : nowIso(),
182
+ updatedAt: value.updatedAt,
172
183
  lastReconciledAt: typeof value.lastReconciledAt === "string" ? value.lastReconciledAt : undefined
173
184
  };
174
185
  }
175
186
  function readLedger(env = process.env) {
176
187
  const filePath = inboundLedgerPath(env);
177
- if (!fs.existsSync(filePath)) {
188
+ if (!syncFs.existsSync(filePath)) {
178
189
  return defaultLedger();
179
190
  }
180
191
  try {
181
- const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
192
+ const parsed = JSON.parse(syncFs.readFileSync(filePath, "utf8"));
182
193
  return normalizeLedger(parsed);
183
- } catch {
184
- return defaultLedger();
194
+ } catch (error) {
195
+ throw new Error("wallet inbound ledger is unreadable; refusing to reset event history", { cause: error });
185
196
  }
186
197
  }
187
198
  function writeLedger(ledger, env = process.env) {
@@ -191,13 +202,7 @@ function writeLedger(ledger, env = process.env) {
191
202
  version: 1,
192
203
  updatedAt: nowIso()
193
204
  };
194
- fs.writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`, {
195
- encoding: "utf8",
196
- mode: 384
197
- });
198
- try {
199
- fs.chmodSync(filePath, 384);
200
- } catch {}
205
+ writeWalletStateFileAtomically(filePath, serializeWalletState(payload));
201
206
  }
202
207
  function findWalletById(env, walletId) {
203
208
  if (!walletId) {