@fased/fased 0.1.62 → 0.1.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +38 -30
  3. package/config/dependency-ownership.json +1 -1
  4. package/config/signer-policies/README.md +49 -0
  5. package/config/signer-policies/agent.json.template +32 -0
  6. package/config/signer-policies/mining.json.template +69 -0
  7. package/config/signer-policies/network.json.template +5 -0
  8. package/config/signer-policies/vault.json.template +70 -0
  9. package/config/signer-protocol-v2.json +76 -0
  10. package/config/typescript-noemit-baseline.json +680 -0
  11. package/dist/agents/auth-profiles/store.js +267 -31
  12. package/dist/agents/bash-tools.exec.js +10 -4
  13. package/dist/agents/current-model-catalog.js +3 -3
  14. package/dist/agents/memory-search.js +7 -1
  15. package/dist/agents/model-catalog-access.js +1 -2
  16. package/dist/agents/model-catalog-snapshot.js +1 -1
  17. package/dist/agents/model-catalog-source.js +1 -1
  18. package/dist/agents/model-metadata.js +1 -1
  19. package/dist/agents/model-selection.js +2 -28
  20. package/dist/agents/models-config.providers.js +6 -6
  21. package/dist/agents/pi-embedded-runner/compact.js +15 -7
  22. package/dist/agents/pi-embedded-runner/model.js +1 -1
  23. package/dist/agents/pi-embedded-runner/run/attempt.js +24 -13
  24. package/dist/agents/pi-embedded-runner/run.js +2 -0
  25. package/dist/agents/pi-embedded-runner/tool-split.js +40 -2
  26. package/dist/agents/pi-tool-definition-adapter.js +16 -1
  27. package/dist/agents/pi-tools.js +2 -1
  28. package/dist/agents/sandbox/config.js +1 -1
  29. package/dist/agents/sandbox/context.js +27 -2
  30. package/dist/agents/skills/env-overrides.js +38 -28
  31. package/dist/agents/skills/trust.js +93 -0
  32. package/dist/agents/skills/workspace.js +128 -0
  33. package/dist/agents/skills-clawhub.js +36 -11
  34. package/dist/agents/skills-marketplace-scan.js +49 -0
  35. package/dist/agents/tools/marketplace-offer-draft-tool.js +1 -1
  36. package/dist/agents/tools/mining-tool.js +1 -1
  37. package/dist/agents/tools/session-status-tool.js +1 -1
  38. package/dist/agents/tools/wallet-action-tool.js +172 -36
  39. package/dist/agents/tools/wallet-skill-policy.js +65 -23
  40. package/dist/agents/tools/wallet-tool.js +7 -11
  41. package/dist/auto-reply/reply/directive-handling.fast-lane.js +2 -1
  42. package/dist/auto-reply/reply/directive-handling.impl.js +2 -1
  43. package/dist/auto-reply/reply/directive-handling.model.js +2 -1
  44. package/dist/auto-reply/reply/directive-handling.persist.js +2 -2
  45. package/dist/auto-reply/reply/get-reply-directives-apply.js +2 -0
  46. package/dist/auto-reply/reply/get-reply-inline-actions.js +25 -1
  47. package/dist/auto-reply/reply/model-selection.js +7 -4
  48. package/dist/auto-reply/reply/session-reset-model.js +4 -4
  49. package/dist/brand.js +1 -1
  50. package/dist/build-info.json +3 -3
  51. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  52. package/dist/channel-web.js +2 -2
  53. package/dist/cli/gateway-cli/run.js +8 -0
  54. package/dist/cli/program/command-registry.js +1 -1
  55. package/dist/cli/program/register.onboard.js +2 -3
  56. package/dist/cli/program/register.wallet.js +16 -123
  57. package/dist/cli/providers-cli.js +1 -1
  58. package/dist/cli/sat-cli.js +129 -2
  59. package/dist/cli/update-cli/update-command.js +260 -11
  60. package/dist/commands/auth-choice.apply.api-providers.js +3 -3
  61. package/dist/commands/doctor-config-flow.js +1 -1
  62. package/dist/commands/doctor-legacy-config.js +2 -13
  63. package/dist/commands/model-picker.js +6 -6
  64. package/dist/commands/models/auth.js +1 -1
  65. package/dist/commands/onboard-auth.config-gateways.js +1 -1
  66. package/dist/commands/onboard-auth.credentials.js +32 -8
  67. package/dist/commands/onboard-non-interactive/local/wallet-config.js +28 -27
  68. package/dist/commands/onboard-non-interactive/local.js +5 -1
  69. package/dist/commands/wallet.js +568 -1911
  70. package/dist/config/config.js +2 -2
  71. package/dist/config/io.js +64 -2
  72. package/dist/config/schema.help.js +8 -7
  73. package/dist/config/schema.labels.js +5 -4
  74. package/dist/config/zod-schema.agent-runtime.js +1 -0
  75. package/dist/config/zod-schema.js +5 -0
  76. package/dist/control-ui/assets/{app-DLil9VO1.js → app-bR-fO5ty.js} +1511 -1555
  77. package/dist/control-ui/assets/{config-CU5Zi8Dh.js → config-LeImukCW.js} +10 -10
  78. package/dist/control-ui/assets/{federation-D10Q4eP_.js → federation-DgA9e-Pn.js} +364 -422
  79. package/dist/control-ui/assets/{index-DdE_NIXo.js → index-ckCxHwjy.js} +3 -3
  80. package/dist/control-ui/assets/{mining-BdhMn18r.js → mining-BgHFh0ei.js} +134 -114
  81. package/dist/control-ui/assets/mining-commit-DFpB_4JN.js +2 -0
  82. package/dist/control-ui/assets/{open-external-url-DwSiwMPl.js → open-external-url-ulF1B-sA.js} +3 -3
  83. package/dist/control-ui/assets/{providers-QMn4w2_f.js → providers-CIx9fxc6.js} +2 -2
  84. package/dist/control-ui/assets/{wallet-C2g294QT.js → wallet-DvStR_AT.js} +259 -377
  85. package/dist/control-ui/index.html +1 -1
  86. package/dist/control-ui/version.json +1 -1
  87. package/dist/daemon/systemd-system.js +56 -50
  88. package/dist/extensions/sat-mining/src/protocol-contract.js +43 -3
  89. package/dist/extensions/sat-mining/src/rpc-read.js +235 -67
  90. package/dist/extensions/sat-mining/src/sat-bond-layout.js +5 -2
  91. package/dist/extensions/sat-mining/src/signer-codec-manifest.js +406 -0
  92. package/dist/extensions/sat-mining/src/solana-submit.js +1038 -397
  93. package/dist/extensions/sat-mining/src/submission-ledger.js +349 -0
  94. package/dist/federation/auto-connect.js +98 -8
  95. package/dist/federation/marketplace-capability-adapter.js +33 -7
  96. package/dist/federation/marketplace-delivery-outbox.js +196 -0
  97. package/dist/federation/marketplace-delivery.js +351 -215
  98. package/dist/federation/marketplace-direct-payment.js +272 -141
  99. package/dist/federation/marketplace-escrow.js +607 -249
  100. package/dist/federation/marketplace-settlement-ledger.js +352 -0
  101. package/dist/federation/offers.js +9 -7
  102. package/dist/federation/peer-auth-v2.js +529 -0
  103. package/dist/gateway/a2a-http.js +425 -96
  104. package/dist/gateway/a2a-settlement.js +259 -153
  105. package/dist/gateway/a2a-task-store.js +524 -0
  106. package/dist/gateway/auth.js +38 -2
  107. package/dist/gateway/config-reload.js +46 -33
  108. package/dist/gateway/durable-capacity.js +31 -0
  109. package/dist/gateway/federation-http.js +540 -135
  110. package/dist/gateway/federation-marketplace-run-store.js +397 -0
  111. package/dist/gateway/federation-marketplace.js +535 -230
  112. package/dist/gateway/mutating-admin-rpc-rate-limit.js +5 -0
  113. package/dist/gateway/security-path.js +1 -1
  114. package/dist/gateway/server-http.js +1084 -1205
  115. package/dist/gateway/server-methods/models.js +1 -1
  116. package/dist/gateway/server-methods/secrets.js +40 -0
  117. package/dist/gateway/server-methods.js +1 -2
  118. package/dist/gateway/server-reload-handlers.js +196 -66
  119. package/dist/gateway/server-runtime-config.js +1 -1
  120. package/dist/gateway/server-secrets-runtime.js +288 -0
  121. package/dist/gateway/server.impl.js +73 -42
  122. package/dist/gateway/sessions-patch.js +3 -5
  123. package/dist/index.js +4 -2
  124. package/dist/infra/fasedhub.js +64 -1
  125. package/dist/infra/local-source-paired-update.js +538 -0
  126. package/dist/infra/restart.js +41 -10
  127. package/dist/infra/update-runner.js +96 -0
  128. package/dist/light-update-status.js +11 -11
  129. package/dist/memory/backend-config.js +2 -1
  130. package/dist/memory/session-files.js +16 -2
  131. package/dist/plugin-sdk/{accounts-DxblobYM.js → accounts-Brn3-uWN.js} +1 -1
  132. package/dist/plugin-sdk/{actions-D4UNimWa.js → actions-DRu135h0.js} +2 -2
  133. package/dist/plugin-sdk/{active-listener-CFuy106s.js → active-listener-B_NMtgPL.js} +1 -1
  134. package/dist/plugin-sdk/{audio-preflight-Bwi2Oq03.js → audio-preflight-BYxAt775.js} +27 -27
  135. package/dist/plugin-sdk/{audit-Cs0K7LBp.js → audit-C5d2z5U1.js} +1 -1
  136. package/dist/plugin-sdk/{channel-access-D5aHoTY8.js → channel-access-CcFRdRPO.js} +1 -1
  137. package/dist/plugin-sdk/{channel-access-configure-Dvch9mMQ.js → channel-access-configure-DaI5wevh.js} +1 -1
  138. package/dist/plugin-sdk/channel-plugin-common.d.ts +3 -3
  139. package/dist/plugin-sdk/channel-plugin-common.js +4 -4
  140. package/dist/plugin-sdk/{chunk-B0FUGc5A.js → chunk-CyoyqpbG.js} +1 -1
  141. package/dist/plugin-sdk/{chunk-items-DzT4L4Ty.js → chunk-items-DIRHG2gJ.js} +1 -1
  142. package/dist/plugin-sdk/command-status.d.ts +2 -2
  143. package/dist/plugin-sdk/command-status.js +27 -27
  144. package/dist/plugin-sdk/{commands-registry-DmDRhRAU.js → commands-registry-BfqdEWdF.js} +2 -2
  145. package/dist/plugin-sdk/{common-CfUOowOp.js → common-HCcXU-NR.js} +1 -1
  146. package/dist/plugin-sdk/{config-mxULv0fQ.js → config-DlWVeLFB.js} +7113 -6877
  147. package/dist/plugin-sdk/{config-schema-BrkmtFxB.js → config-schema-BOT7kHb6.js} +6779 -3696
  148. package/dist/plugin-sdk/device-pair.d.ts +1 -1
  149. package/dist/plugin-sdk/discord.d.ts +6 -6
  150. package/dist/plugin-sdk/discord.js +19 -19
  151. package/dist/plugin-sdk/file-lock.js +35 -4
  152. package/dist/plugin-sdk/{filesystem-manager-ZoHU8oA7.js → filesystem-manager-DoI8IBNF.js} +1 -1
  153. package/dist/plugin-sdk/{group-mentions-BHRff6j8.d.ts → group-mentions-q3hUTCt7.d.ts} +1 -1
  154. package/dist/plugin-sdk/{handle-action-DbVCF9HZ.js → handle-action-hvwapMKg.js} +13 -13
  155. package/dist/plugin-sdk/{helpers-BXbdgs5H.js → helpers-DMBU4oTo.js} +1 -1
  156. package/dist/plugin-sdk/{image-ops-D7jPxaph.js → image-ops-DQi0n_Tt.js} +1 -1
  157. package/dist/plugin-sdk/index.d.ts +21 -39
  158. package/dist/plugin-sdk/index.js +29 -29
  159. package/dist/plugin-sdk/{login-BRxww6nv.js → login-Ca583Okc.js} +3 -3
  160. package/dist/plugin-sdk/{login-qr-DJXsk9XH.js → login-qr-CGciBSNP.js} +3 -3
  161. package/dist/plugin-sdk/{manager-Y2S_5IlI.js → manager-BegWxNYX.js} +4 -4
  162. package/dist/plugin-sdk/{markdown-tables-DHLFQqaF.js → markdown-tables-DCOXEUfZ.js} +1 -1
  163. package/dist/plugin-sdk/{media-Czo4carg.js → media-CAdQF5TG.js} +47 -47
  164. package/dist/plugin-sdk/{memory-search-DTjIMw8J.js → memory-search-CrFPOeTH.js} +4 -1
  165. package/dist/plugin-sdk/{monitor-M_ta2lMc.js → monitor-BCFDaqJ-.js} +31 -31
  166. package/dist/plugin-sdk/{monitor-wYVncM9w.js → monitor-BgbjRiPM.js} +32 -32
  167. package/dist/plugin-sdk/{openresponses-http-B2GmeSt4.js → openresponses-http-DFf87SMM.js} +27 -27
  168. package/dist/plugin-sdk/{optional-runtime-dependency-DdMbxS24.js → optional-runtime-dependency-0dznm3ZO.js} +1 -1
  169. package/dist/plugin-sdk/{outbound-Db8mRN6P.js → outbound-BgVDdHxx.js} +6 -6
  170. package/dist/plugin-sdk/{outbound-attachment-BqFjcypb.js → outbound-attachment-QqTnIhZL.js} +2 -2
  171. package/dist/plugin-sdk/{pairing-message-B3bHYGaw.d.ts → pairing-message-CS-9BHug.d.ts} +2 -2
  172. package/dist/plugin-sdk/{pairing-message-B3GC_7CD.js → pairing-message-D0CoLHRJ.js} +1 -1
  173. package/dist/plugin-sdk/{pairing-store-CQikgIbw.js → pairing-store-BChahgI2.js} +2 -2
  174. package/dist/plugin-sdk/{pi-model-discovery-CY3m5zJP.js → pi-model-discovery-BX_JLcEJ.js} +1 -1
  175. package/dist/plugin-sdk/{pi-model-discovery-runtime-DSh1T2pn.js → pi-model-discovery-runtime-DxTMz_XF.js} +2 -2
  176. package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +2 -2
  177. package/dist/plugin-sdk/{pw-ai-AFUqn-tQ.js → pw-ai-natjh3rm.js} +3 -3
  178. package/dist/plugin-sdk/{qmd-manager-DSyx77KY.js → qmd-manager-CgRaTxUq.js} +1 -1
  179. package/dist/plugin-sdk/{query-expansion-CAI2kKLQ.js → query-expansion-BG3FgzF7.js} +14 -3
  180. package/dist/plugin-sdk/{replies-Fzh9PhXl.js → replies-ChYo5ZQM.js} +2 -2
  181. package/dist/plugin-sdk/{resolve-outbound-target-KpF3co6T.js → resolve-outbound-target-D-KGgHJZ.js} +1 -1
  182. package/dist/plugin-sdk/{resolve-route-CDl74O19.js → resolve-route-C8tvQm8Z.js} +1 -1
  183. package/dist/plugin-sdk/{retry-policy-D4uiqUOG.js → retry-policy-C6SjKjQA.js} +1 -1
  184. package/dist/plugin-sdk/{runtime-Bb6KRnCC.js → runtime-2B9_WKoI.js} +8 -3
  185. package/dist/plugin-sdk/{runtime-dependency-DLDmB94f.js → runtime-dependency-DczkvPxn.js} +2 -2
  186. package/dist/plugin-sdk/sat-runtime.d.ts +549 -309
  187. package/dist/plugin-sdk/sat-runtime.js +29 -29
  188. package/dist/plugin-sdk/{send-C4k4JuJN.js → send-B6KkGKZD.js} +6 -6
  189. package/dist/plugin-sdk/{send-D-uDKGIq.js → send-CFzGKJXo.js} +6 -6
  190. package/dist/plugin-sdk/{send-Du8ykP1k.js → send-DCO441U7.js} +8 -8
  191. package/dist/plugin-sdk/{send-5nFktR1n.js → send-gDoGA-7e.js} +5 -5
  192. package/dist/plugin-sdk/{send-Bfzf11VY.js → send-q9HXrSwK.js} +7 -7
  193. package/dist/plugin-sdk/{session-CS-Td9EM.js → session-DHD4ZKyG.js} +2 -2
  194. package/dist/plugin-sdk/{skill-commands-CFAlXWHk.js → skill-commands-FKEPLS7T.js} +201 -26
  195. package/dist/plugin-sdk/{slack-CxE1mfzj.js → slack-BUTt8cxK.js} +39 -39
  196. package/dist/plugin-sdk/{slack-actions-BcMkNv1Z.js → slack-actions-DhbMcp8M.js} +11 -11
  197. package/dist/plugin-sdk/slack.d.ts +6 -6
  198. package/dist/plugin-sdk/slack.js +9 -9
  199. package/dist/plugin-sdk/{sticker-cache-CGzGWu00.js → sticker-cache-D0wHVqjt.js} +3 -3
  200. package/dist/plugin-sdk/{tables-bFXyRpkx.js → tables-B3jr0Pvq.js} +1 -1
  201. package/dist/plugin-sdk/{targets-DH7a9lKB.js → targets-CtSbTxYX.js} +1 -1
  202. package/dist/plugin-sdk/{telegram-actions-DaEcYQ8r.js → telegram-actions-CC_qN4v0.js} +30 -30
  203. package/dist/plugin-sdk/telegram.d.ts +6 -6
  204. package/dist/plugin-sdk/telegram.js +8 -8
  205. package/dist/plugin-sdk/{thread-bindings.lifecycle-CgOvvdw8.js → thread-bindings.lifecycle-QbkNl-m6.js} +3 -3
  206. package/dist/plugin-sdk/{thread-bindings.state-CQpk44Hq.js → thread-bindings.state-D9hg_M1c.js} +2 -2
  207. package/dist/plugin-sdk/tmp-fased-dir-xOTGlzBE.d.ts +486 -0
  208. package/dist/plugin-sdk/{types-vcJrC_uv.d.ts → types-C3avNytw.d.ts} +3 -4
  209. package/dist/plugin-sdk/{types-DyhXnYUr.d.ts → types-D0kDG8l0.d.ts} +3 -2
  210. package/dist/plugin-sdk/{types-DFAW-n1J.d.ts → types-DWfbSAaM.d.ts} +2 -2
  211. package/dist/plugin-sdk/{types.plugin-_fbu40Re.d.ts → types.plugin-BcSBq42x.d.ts} +8 -3
  212. package/dist/plugin-sdk/{web-CInY-lCv.js → web-BXsJ1vqe.js} +32 -32
  213. package/dist/plugin-sdk/{whatsapp-actions-BtSc2CBv.js → whatsapp-actions-Bj_rOncr.js} +13 -13
  214. package/dist/plugin-sdk/{whatsapp-heartbeat-Bg9TuYzl.js → whatsapp-heartbeat-B1WHkJIg.js} +2 -2
  215. package/dist/plugin-sdk/whatsapp.d.ts +13 -13
  216. package/dist/plugin-sdk/whatsapp.js +12 -12
  217. package/dist/plugin-sdk/{wsl-C4DGFkOd.js → wsl-J-HscWxS.js} +3 -3
  218. package/dist/plugin-sdk/{zod-schema.providers-core-BEbNizPe.d.ts → zod-schema.providers-core-CIzCjXH9.d.ts} +61 -61
  219. package/dist/providers/refresh.js +1 -1
  220. package/dist/providers/registry.js +1 -1
  221. package/dist/secrets/apply.js +1 -1
  222. package/dist/secrets/runtime.js +1 -1
  223. package/dist/wallet/external-submission-ledger.js +376 -0
  224. package/dist/wallet/legacy-embedded-keystore.js +40 -0
  225. package/dist/wallet/local-socket-signer-archive.js +30 -0
  226. package/dist/wallet/local-socket-signer-lifecycle.js +97 -0
  227. package/dist/wallet/local-socket-signer-policy.js +166 -0
  228. package/dist/wallet/local-socket-signer-protocol.js +561 -118
  229. package/dist/wallet/native-signer-wallet-id.js +25 -0
  230. package/dist/wallet/providers/alchemy-adapter.js +3 -0
  231. package/dist/wallet/providers/local-socket-signer-adapter.js +380 -105
  232. package/dist/wallet/providers/turnkey-adapter.js +292 -34
  233. package/dist/wallet/providers/wallet-standard-adapter.js +100 -0
  234. package/dist/wallet/signer-network-admin.js +184 -0
  235. package/dist/wallet/signer-protocol-v2.generated.js +90 -0
  236. package/dist/wallet/solana-bond-signing.js +157 -69
  237. package/dist/wallet/solana-reviewed-transaction.js +375 -0
  238. package/dist/wallet/solana-swap.js +520 -64
  239. package/dist/wallet/solana-transaction-inspection.js +106 -4
  240. package/dist/wallet/solana-trigger.js +658 -320
  241. package/dist/wallet/turnkey-reviewed-state.js +370 -0
  242. package/dist/wallet/wallet-approval-auth.js +17 -28
  243. package/dist/wallet/wallet-atomic-state.js +53 -0
  244. package/dist/wallet/wallet-canary.js +0 -1
  245. package/dist/wallet/wallet-inbound-events.js +16 -11
  246. package/dist/wallet/wallet-policy-simulation.js +1 -1
  247. package/dist/wallet/wallet-policy.js +90 -36
  248. package/dist/wallet/wallet-provider-capabilities.js +28 -4
  249. package/dist/wallet/wallet-provider-registry.js +57 -44
  250. package/dist/wallet/wallet-provider-resolver.js +62 -63
  251. package/dist/wallet/wallet-runtime-config.js +28 -41
  252. package/dist/wallet/wallet-secrets-store.js +22 -0
  253. package/dist/wallet/wallet-send-approvals.js +1891 -589
  254. package/dist/wallet/wallet-send-execution-ledger.js +292 -0
  255. package/dist/wallet/wallet-settlement-links.js +14 -13
  256. package/dist/wallet/wallet-standard-review.js +353 -0
  257. package/dist/wallet/wallet-status.js +0 -9
  258. package/dist/wallet/wallet-task-ledger.js +16 -2
  259. package/dist/web/auto-reply/heartbeat-runner.js +1 -1
  260. package/dist/web/auto-reply/monitor.js +2 -2
  261. package/dist/wizard/host-security-capability.js +14 -23
  262. package/dist/wizard/onboarding.finalize.js +63 -184
  263. package/dist/wizard/onboarding.host-security.js +117 -1367
  264. package/dist/wizard/onboarding.js +172 -217
  265. package/dist/wizard/onboarding.wallet.js +232 -785
  266. package/extensions/acpx/package.json +1 -1
  267. package/extensions/bluebubbles/package.json +1 -1
  268. package/extensions/copilot-proxy/package.json +1 -1
  269. package/extensions/diagnostics-otel/package.json +1 -1
  270. package/extensions/fased-federation/package.json +1 -1
  271. package/extensions/google-gemini-cli-auth/package.json +1 -1
  272. package/extensions/imessage/package.json +1 -1
  273. package/extensions/irc/package.json +1 -1
  274. package/extensions/line/package.json +1 -1
  275. package/extensions/llm-task/package.json +1 -1
  276. package/extensions/lobster/package.json +1 -1
  277. package/extensions/matrix/CHANGELOG.md +12 -0
  278. package/extensions/matrix/package.json +1 -1
  279. package/extensions/mattermost/package.json +1 -1
  280. package/extensions/memory-core/package.json +2 -2
  281. package/extensions/memory-lancedb/package.json +1 -1
  282. package/extensions/minimax-portal-auth/package.json +1 -1
  283. package/extensions/msteams/CHANGELOG.md +12 -0
  284. package/extensions/msteams/package.json +1 -1
  285. package/extensions/nextcloud-talk/package.json +1 -1
  286. package/extensions/nostr/CHANGELOG.md +12 -0
  287. package/extensions/nostr/package.json +1 -1
  288. package/extensions/open-prose/package.json +1 -1
  289. package/extensions/sat-mining/index.ts +498 -153
  290. package/extensions/sat-mining/package.json +1 -1
  291. package/extensions/sat-mining/signer-codec-schema.v1.json +374 -0
  292. package/extensions/sat-mining/src/audit-store.ts +50 -5
  293. package/extensions/sat-mining/src/claim-service.ts +85 -14
  294. package/extensions/sat-mining/src/config.ts +9 -0
  295. package/extensions/sat-mining/src/cycle-progress.ts +16 -8
  296. package/extensions/sat-mining/src/epoch-service.ts +9 -5
  297. package/extensions/sat-mining/src/gateway-runner.ts +21 -1
  298. package/extensions/sat-mining/src/protocol-contract.ts +45 -1
  299. package/extensions/sat-mining/src/recovery-service.ts +312 -0
  300. package/extensions/sat-mining/src/round-watcher.ts +391 -81
  301. package/extensions/sat-mining/src/rpc-read.ts +330 -89
  302. package/extensions/sat-mining/src/runtime.ts +14 -0
  303. package/extensions/sat-mining/src/sat-bond-layout.ts +6 -0
  304. package/extensions/sat-mining/src/signer-codec-manifest.ts +429 -0
  305. package/extensions/sat-mining/src/solana-submit.ts +1199 -428
  306. package/extensions/sat-mining/src/submission-ledger.ts +433 -0
  307. package/extensions/signal/package.json +1 -1
  308. package/extensions/synology-chat/package.json +1 -1
  309. package/extensions/tlon/package.json +1 -1
  310. package/extensions/twitch/CHANGELOG.md +12 -0
  311. package/extensions/twitch/package.json +1 -1
  312. package/extensions/voice-call/CHANGELOG.md +12 -0
  313. package/extensions/voice-call/package.json +1 -1
  314. package/extensions/zalo/CHANGELOG.md +12 -0
  315. package/extensions/zalo/package.json +1 -1
  316. package/extensions/zalouser/CHANGELOG.md +12 -0
  317. package/extensions/zalouser/package.json +1 -1
  318. package/install.sh +4955 -0
  319. package/package.json +23 -5
  320. package/scripts/fased-host-updater.mjs +1421 -0
  321. package/scripts/fased-host-updaterctl.mjs +186 -0
  322. package/scripts/fased-managed-service.sh +36 -0
  323. package/scripts/fased-managed-updater.mjs +3065 -156
  324. package/scripts/fased-signer-enroll-hosting.sh +275 -0
  325. package/scripts/fased-signer-network-hosting.sh +143 -0
  326. package/scripts/fased-signer-owner-policy.mjs +1430 -0
  327. package/scripts/fased-signer-policy-hosting.sh +50 -0
  328. package/scripts/fased-signer-policy-local.sh +26 -0
  329. package/scripts/hosted-release-manifest.mjs +185 -0
  330. package/scripts/install-fased-signerd.sh +183 -108
  331. package/scripts/install-managed-runtime.mjs +212 -10
  332. package/scripts/managed-runtime-layout.mjs +75 -3
  333. package/scripts/migrate-hosted-signer-v2.mjs +58 -0
  334. package/scripts/start-managed.sh +169 -360
  335. package/dist/control-ui/assets/mining-commit-R-6nu87p.js +0 -2
  336. package/dist/plugin-sdk/tmp-fased-dir-CS6zsYEE.d.ts +0 -77
  337. package/dist/wallet/local-socket-signer-broker.js +0 -224
  338. package/dist/wallet/local-socket-signer-custody.js +0 -42
  339. package/dist/wallet/providers/embedded-keystore-adapter.js +0 -402
  340. package/dist/wallet/providers/privy-adapter.js +0 -80
  341. package/dist/wallet/wallet-custody.js +0 -1836
@@ -1,9 +1,14 @@
1
1
  import { loadConfig } from "../config/io.js";
2
2
  import "../config/config.js";
3
+ import { resolveWalletRuntimeConfig } from "../wallet/wallet-runtime-config.js";
4
+ import { readWalletProviderRegistry, resolveWalletUserRole } from "../wallet/wallet-provider-registry.js";
3
5
  import { buildPublishedFederationOffers } from "../federation/offers.js";
4
6
  import { normalizeHandle, resolveFederationBaseUrl, resolveFederationHandle } from "../federation/runtime.js";
7
+ import { createOrExecuteWalletSend, getWalletSendApprovalRequest } from "../wallet/wallet-send-approvals.js";
8
+ import { FEDERATION_A2A_RPC_PATH, FEDERATION_PEER_HEADERS, authorizeFederationPeerRequestV2 } from "../federation/peer-auth-v2.js";
5
9
  import { orchestrateA2aTaskSettlement } from "./a2a-settlement.js";
6
- import { randomUUID } from "node:crypto";
10
+ import { authorizeDurableA2aTask, claimDurableA2aPaymentChallenge, claimDurableA2aTaskExecution, issueDurableA2aPaymentChallenge, readDurableA2aPaymentChallenge, readDurableA2aTask, reserveDurableA2aTask, updateDurableA2aTask } from "./a2a-task-store.js";
11
+ import { createHash, randomUUID } from "node:crypto";
7
12
 
8
13
  //#region src/gateway/a2a-http.ts
9
14
  const OFFER_SCHEMA_ID = "https://schemas.fased.ai/fased-agent-offer-v0.json";
@@ -105,18 +110,15 @@ async function readJsonBody(req, maxBytes) {
105
110
  });
106
111
  });
107
112
  }
108
- function extractSenderHandle(req, params, domain) {
109
- const fromHeader = typeof req.headers["x-fased-sender-handle"] === "string" ? req.headers["x-fased-sender-handle"] : "";
110
- const fromParams = typeof params?.senderHandle === "string" ? params.senderHandle : isRecord(params?.sender) && typeof params.sender.handle === "string" ? params.sender.handle : "";
111
- const handle = fromHeader || fromParams;
112
- return normalizeHandle(handle, domain);
113
- }
114
113
  function taskHasPaidReferences(task) {
115
114
  if (!isRecord(task)) {
116
115
  return false;
117
116
  }
118
117
  return task.invoice !== undefined || task.invoiceRef !== undefined || task.receipt !== undefined || task.receiptRef !== undefined;
119
118
  }
119
+ function requestHasPaidReferences(task, params) {
120
+ return taskHasPaidReferences(task) || params?.invoice !== undefined || params?.receipt !== undefined;
121
+ }
120
122
  function extractOfferId(taskInput, params) {
121
123
  if (isRecord(taskInput) && typeof taskInput.offerId === "string") {
122
124
  return taskInput.offerId.trim();
@@ -361,9 +363,21 @@ function extractMarketplacePaymentSummary(taskInput, params) {
361
363
  ...payer ? { payer } : {},
362
364
  ...payee ? { payee } : {},
363
365
  ...typeof receipt?.txRef === "string" && receipt.txRef.trim() ? { txRef: receipt.txRef.trim() } : {},
364
- ...typeof receipt?.settledAt === "string" && receipt.settledAt.trim() ? { settledAt: receipt.settledAt.trim() } : {}
366
+ ...typeof receipt?.settledAt === "string" && receipt.settledAt.trim() ? { settledAt: receipt.settledAt.trim() } : {},
367
+ ...typeof receipt?.challengeId === "string" && receipt.challengeId.trim() ? { challengeId: receipt.challengeId.trim() } : {},
368
+ ...typeof receipt?.paymentMemo === "string" && receipt.paymentMemo.trim() ? { paymentMemo: receipt.paymentMemo.trim() } : {}
365
369
  };
366
370
  }
371
+ function fixedOfferAmountBaseUnits(offer) {
372
+ const amount = offer.pricing.amount;
373
+ const decimals = offer.paymentDefaults?.assetDecimals;
374
+ if (typeof amount !== "number" || !Number.isFinite(amount) || amount <= 0 || typeof decimals !== "number" || !Number.isInteger(decimals) || decimals < 0 || decimals > 18) {
375
+ return null;
376
+ }
377
+ const scaled = amount * 10 ** decimals;
378
+ const rounded = Math.round(scaled);
379
+ return Number.isSafeInteger(rounded) && Math.abs(scaled - rounded) < 1e-6 ? rounded : null;
380
+ }
367
381
  function buildCanonicalResultPayload(task, actor) {
368
382
  const input = isRecord(task.input) ? task.input : null;
369
383
  const prompt = input && typeof input.prompt === "string" ? input.prompt.trim() : "";
@@ -417,19 +431,15 @@ function toTaskSnapshot(task) {
417
431
  createdAt: task.createdAt,
418
432
  updatedAt: task.updatedAt,
419
433
  output: task.output,
420
- error: task.error
434
+ error: task.error,
435
+ settlement: task.settlement,
436
+ paymentRecovery: task.paymentRecovery
421
437
  };
422
438
  }
423
439
  function writeSseEvent(res, event, data) {
424
440
  res.write(`event: ${event}\n`);
425
441
  res.write(`data: ${JSON.stringify(data)}\n\n`);
426
442
  }
427
- function buildAuthHeaders(apiToken) {
428
- if (!apiToken) {
429
- return {};
430
- }
431
- return { Authorization: `Bearer ${apiToken}` };
432
- }
433
443
  function headerValue(value) {
434
444
  if (Array.isArray(value)) {
435
445
  return typeof value[0] === "string" ? value[0] : "";
@@ -487,7 +497,6 @@ function createA2aHandler(opts) {
487
497
  const profileVersion = opts.profileVersion ?? "v0.2";
488
498
  const rpcPath = opts.rpcPath ?? "/a2a";
489
499
  const streamPath = opts.streamPath ?? "/a2a/stream";
490
- const tierCacheTtlMs = opts.tierCacheTtlMs ?? 3e4;
491
500
  const url = new URL(opts.origin);
492
501
  const domain = url.hostname;
493
502
  const federationBaseUrl = resolveFederationBaseUrl(process.env);
@@ -499,26 +508,187 @@ function createA2aHandler(opts) {
499
508
  });
500
509
  const agentId = opts.agentId?.trim() || process.env.FASED_A2A_AGENT_ID?.trim() || handle;
501
510
  const tasks = new Map();
502
- const tierCache = new Map();
503
511
  const federationBaseUrlResolved = opts.federationBaseUrl?.trim() || process.env.FASED_FEDERATION_BASE_URL?.trim() || federationBaseUrl;
504
512
  const federationApiToken = opts.federationApiToken?.trim() || process.env.FASED_FEDERATION_API_TOKEN?.trim();
505
513
  const settlementOrchestrator = opts.settlementOrchestrator ?? (async (params) => await orchestrateA2aTaskSettlement({
506
514
  taskId: params.taskId,
507
515
  taskInput: params.taskInput,
516
+ invoice: params.invoice,
517
+ receipt: params.receipt,
518
+ offer: params.offer,
519
+ challenge: params.challenge,
508
520
  senderHandle: params.senderHandle,
509
521
  env: params.env
510
522
  }));
511
- function updateTask(task, patch) {
512
- if (patch.status) {
513
- task.status = patch.status;
523
+ async function ensureReviewedRefundApproval(task, recovery) {
524
+ if (recovery.status !== "refund-required" || recovery.approvalRequestId) {
525
+ return recovery;
526
+ }
527
+ const challenge = readDurableA2aPaymentChallenge({
528
+ taskId: task.taskId,
529
+ env: process.env
530
+ });
531
+ if (!challenge || challenge.status !== "claimed") {
532
+ return {
533
+ ...recovery,
534
+ reason: `${recovery.reason}; reviewed refund preparation is blocked because the claimed seller challenge is unavailable`,
535
+ updatedAt: new Date().toISOString()
536
+ };
537
+ }
538
+ const registry = readWalletProviderRegistry(process.env);
539
+ const candidates = registry.wallets.filter((wallet) => resolveWalletUserRole(wallet) === "agent" && wallet.addresses?.solana?.trim() === challenge.payeeAddress);
540
+ if (candidates.length !== 1) {
541
+ return {
542
+ ...recovery,
543
+ reason: `${recovery.reason}; reviewed refund preparation requires exactly one Agent wallet matching the paid seller address`,
544
+ updatedAt: new Date().toISOString()
545
+ };
546
+ }
547
+ const wallet = candidates[0];
548
+ const cfg = loadConfig();
549
+ const created = await createOrExecuteWalletSend({
550
+ payload: {
551
+ actionKind: "send",
552
+ chain: "solana",
553
+ to: challenge.payerAddress,
554
+ amount: String(challenge.amount),
555
+ ...challenge.asset.kind === "spl-token" ? { program: challenge.asset.address } : {},
556
+ memo: `fased:a2a-refund:v1:${challenge.challengeId}`,
557
+ walletId: wallet.id,
558
+ walletName: wallet.name,
559
+ providerId: wallet.providerId
560
+ },
561
+ requestedBy: "a2a-refund",
562
+ executionIntentId: `a2a-refund:${challenge.challengeId}`,
563
+ sendPath: "reviewed",
564
+ settlementContext: {
565
+ taskId: task.taskId,
566
+ invoiceId: challenge.invoiceId,
567
+ senderHandle: challenge.senderHandle
568
+ },
569
+ config: resolveWalletRuntimeConfig(cfg, process.env),
570
+ runtimeConfig: cfg,
571
+ providerIdOverride: wallet.providerId,
572
+ env: process.env
573
+ });
574
+ if (!created.ok) {
575
+ return {
576
+ ...recovery,
577
+ reason: `${recovery.reason}; reviewed refund preparation failed: ${created.message ?? created.code ?? "unknown error"}`,
578
+ updatedAt: new Date().toISOString()
579
+ };
580
+ }
581
+ if (created.mode !== "manual") {
582
+ return {
583
+ ...recovery,
584
+ reason: `${recovery.reason}; reviewed refund preparation failed closed because the reviewed path did not return a manual approval`,
585
+ updatedAt: new Date().toISOString()
586
+ };
587
+ }
588
+ return {
589
+ ...recovery,
590
+ approvalRequestId: created.request.id,
591
+ reason: `${recovery.reason}; reviewed refund approval ${created.request.id} is pending operator and signer-owned WebAuthn authorization`,
592
+ updatedAt: new Date().toISOString()
593
+ };
594
+ }
595
+ async function reconcileReviewedRefund(task) {
596
+ const recovery = task.paymentRecovery;
597
+ if (recovery?.status !== "refund-required" || !recovery.approvalRequestId) {
598
+ return;
599
+ }
600
+ const challenge = readDurableA2aPaymentChallenge({
601
+ taskId: task.taskId,
602
+ env: process.env
603
+ });
604
+ const approval = getWalletSendApprovalRequest({
605
+ requestId: recovery.approvalRequestId,
606
+ env: process.env
607
+ });
608
+ if (!challenge || approval?.status !== "executed" || !approval.result?.txHash || approval.payload.to !== challenge.payerAddress || approval.payload.amount !== String(challenge.amount) || approval.payload.memo !== `fased:a2a-refund:v1:${challenge.challengeId}` || (challenge.asset.kind === "spl-token" ? approval.payload.program !== challenge.asset.address : Boolean(approval.payload.program))) {
609
+ return;
610
+ }
611
+ const refunded = {
612
+ ...recovery,
613
+ status: "refunded",
614
+ refundTxRef: approval.result.txHash,
615
+ reason: `reviewed refund ${approval.result.txHash} executed through signer-owned authorization`,
616
+ updatedAt: new Date().toISOString()
617
+ };
618
+ const durable = await updateDurableA2aTask({
619
+ taskId: task.taskId,
620
+ paymentRecovery: refunded,
621
+ env: process.env
622
+ });
623
+ task.paymentRecovery = durable.paymentRecovery;
624
+ task.updatedAt = durable.updatedAt;
625
+ }
626
+ function taskFromDurable(record) {
627
+ return {
628
+ taskId: record.taskId,
629
+ status: record.status,
630
+ createdAt: record.createdAt,
631
+ updatedAt: record.updatedAt,
632
+ input: record.input,
633
+ output: record.output,
634
+ error: record.error,
635
+ marketplacePayment: record.marketplacePayment,
636
+ settlement: record.settlement,
637
+ paymentRecovery: record.paymentRecovery,
638
+ timers: [],
639
+ subscribers: new Set()
640
+ };
641
+ }
642
+ function resolveTask(taskId) {
643
+ const active = tasks.get(taskId);
644
+ if (active) {
645
+ return active;
514
646
  }
515
- if (patch.output !== undefined) {
516
- task.output = patch.output;
647
+ const durable = readDurableA2aTask({
648
+ taskId,
649
+ env: process.env
650
+ });
651
+ if (!durable) {
652
+ return undefined;
517
653
  }
518
- if (patch.error !== undefined) {
519
- task.error = patch.error;
654
+ const task = taskFromDurable(durable);
655
+ tasks.set(taskId, task);
656
+ return task;
657
+ }
658
+ async function updateTask(task, patch) {
659
+ const paymentRecovery = patch.paymentRecovery ?? ((patch.status === "failed" || patch.status === "canceled") && task.settlement?.status === "executed" && task.settlement.txHash ? {
660
+ status: "refund-required",
661
+ paymentTxRef: task.settlement.txHash,
662
+ reason: patch.error ?? `paid task entered terminal state ${patch.status}; seller must refund or resolve the dispute`,
663
+ updatedAt: new Date().toISOString()
664
+ } : undefined);
665
+ const durable = await updateDurableA2aTask({
666
+ taskId: task.taskId,
667
+ ...patch.status ? { status: patch.status } : {},
668
+ ...patch.output !== undefined ? { output: patch.output } : {},
669
+ ...patch.error !== undefined ? { error: patch.error } : {},
670
+ ...patch.settlement !== undefined ? { settlement: patch.settlement } : {},
671
+ ...paymentRecovery !== undefined ? { paymentRecovery } : {},
672
+ env: process.env
673
+ });
674
+ if (durable.paymentRecovery?.status === "refund-required" && !durable.paymentRecovery.approvalRequestId) {
675
+ const reviewedRecovery = await ensureReviewedRefundApproval(task, durable.paymentRecovery);
676
+ if (reviewedRecovery !== durable.paymentRecovery) {
677
+ const refreshed = await updateDurableA2aTask({
678
+ taskId: task.taskId,
679
+ paymentRecovery: reviewedRecovery,
680
+ env: process.env
681
+ });
682
+ durable.paymentRecovery = refreshed.paymentRecovery;
683
+ durable.updatedAt = refreshed.updatedAt;
684
+ }
520
685
  }
521
- task.updatedAt = new Date().toISOString();
686
+ task.status = durable.status;
687
+ task.output = durable.output;
688
+ task.error = durable.error;
689
+ task.settlement = durable.settlement;
690
+ task.paymentRecovery = durable.paymentRecovery;
691
+ task.updatedAt = durable.updatedAt;
522
692
  const snapshot = toTaskSnapshot(task);
523
693
  for (const subscriber of task.subscribers) {
524
694
  if (subscriber.writableEnded || subscriber.destroyed) {
@@ -538,81 +708,74 @@ function createA2aHandler(opts) {
538
708
  }
539
709
  task.timers = [];
540
710
  }
541
- async function resolveSenderTier(senderHandle) {
542
- if (!senderHandle) {
543
- return "unverified";
544
- }
545
- const cached = tierCache.get(senderHandle);
546
- if (cached && cached.expiresAt > Date.now()) {
547
- return cached.tier;
548
- }
549
- if (!federationBaseUrlResolved) {
550
- return "unverified";
551
- }
552
- const endpoint = new URL(`/api/federation/directory/${encodeURIComponent(senderHandle)}`, federationBaseUrlResolved);
553
- try {
554
- const res = await fetch(endpoint, { headers: {
555
- ...buildAuthHeaders(federationApiToken),
556
- accept: "application/json"
557
- } });
558
- let tier = "unverified";
559
- if (res.ok) {
560
- const body = await res.json();
561
- if (isRecord(body)) {
562
- const status = typeof body.status === "string" ? body.status : "";
563
- if (status === "verified") {
564
- tier = "verified";
565
- } else if (status === "revoked") {
566
- tier = "blocked";
567
- } else {
568
- tier = "unverified";
569
- }
570
- }
571
- } else if (res.status === 404) {
572
- tier = "unverified";
573
- }
574
- tierCache.set(senderHandle, {
575
- tier,
576
- expiresAt: Date.now() + tierCacheTtlMs
577
- });
578
- return tier;
579
- } catch {
580
- return "unverified";
581
- }
711
+ async function releaseTaskExecution(task) {
712
+ const release = task.executionRelease;
713
+ task.executionRelease = undefined;
714
+ await release?.();
582
715
  }
583
- function createTask(input, marketplacePayment) {
584
- const createdAt = new Date().toISOString();
585
- const requestedTaskId = isRecord(input) && typeof input.taskId === "string" ? input.taskId.trim() : "";
586
- const taskId = requestedTaskId && !tasks.has(requestedTaskId) ? requestedTaskId : randomUUID();
587
- const task = {
716
+ async function createTask(params) {
717
+ const requestedTaskId = isRecord(params.input) && typeof params.input.taskId === "string" ? params.input.taskId.trim() : "";
718
+ const taskId = requestedTaskId || randomUUID();
719
+ const reserved = await reserveDurableA2aTask({
588
720
  taskId,
589
- status: "queued",
590
- createdAt,
591
- updatedAt: createdAt,
592
- input,
593
- ...marketplacePayment ? { marketplacePayment } : {},
594
- timers: [],
595
- subscribers: new Set()
721
+ senderHandle: params.senderHandle,
722
+ input: params.input,
723
+ marketplacePayment: params.marketplacePayment,
724
+ accessToken: params.accessToken,
725
+ env: process.env
726
+ });
727
+ const existing = tasks.get(taskId);
728
+ const task = existing ?? taskFromDurable(reserved.record);
729
+ if (!existing) {
730
+ tasks.set(task.taskId, task);
731
+ }
732
+ return {
733
+ task,
734
+ created: reserved.created,
735
+ accessToken: reserved.accessToken
596
736
  };
737
+ }
738
+ function requestTaskAccessToken(req, params) {
739
+ const header = headerValue(req.headers["x-fased-task-token"]).trim();
740
+ const param = typeof params?.taskAccessToken === "string" ? params.taskAccessToken.trim() : "";
741
+ return header || param;
742
+ }
743
+ function anonymousSenderKey(req) {
744
+ const client = opts.peerAuthClientIp ?? req.socket?.remoteAddress ?? "unknown";
745
+ const digest = createHash("sha256").update(client, "utf8").digest("hex").slice(0, 24);
746
+ return `anonymous:${digest}`;
747
+ }
748
+ function scheduleTaskExecution(task) {
749
+ if (isTerminal(task.status) || task.timers.length > 0) {
750
+ void releaseTaskExecution(task);
751
+ return;
752
+ }
597
753
  const queuedToRunning = setTimeout(() => {
598
754
  if (task.status !== "queued") {
599
755
  return;
600
756
  }
601
- updateTask(task, { status: "running" });
757
+ void updateTask(task, { status: "running" }).catch(async (error) => {
758
+ task.error = error instanceof Error ? error.message : String(error);
759
+ clearTaskTimers(task);
760
+ await releaseTaskExecution(task);
761
+ });
602
762
  }, 10);
603
763
  const runningToDone = setTimeout(() => {
604
764
  if (task.status === "canceled") {
765
+ void releaseTaskExecution(task);
605
766
  return;
606
767
  }
607
- updateTask(task, {
768
+ void updateTask(task, {
608
769
  status: "succeeded",
609
770
  output: buildCanonicalResultPayload(task, handle)
771
+ }).catch((error) => {
772
+ task.error = error instanceof Error ? error.message : String(error);
773
+ }).finally(async () => {
774
+ clearTaskTimers(task);
775
+ await releaseTaskExecution(task);
610
776
  });
611
- clearTaskTimers(task);
612
777
  }, 50);
613
778
  task.timers.push(queuedToRunning, runningToDone);
614
- tasks.set(task.taskId, task);
615
- return task;
616
779
  }
617
780
  return async (req, res) => {
618
781
  const parsed = new URL(req.url ?? "/", opts.origin);
@@ -640,7 +803,11 @@ function createA2aHandler(opts) {
640
803
  "payments",
641
804
  "service-offers"
642
805
  ],
643
- auth: { type: "none" },
806
+ auth: {
807
+ type: "task-capability-and-federation-peer-v2",
808
+ paidTasks: "signed-federation-peer-v2-required",
809
+ taskAccess: "x-fased-task-token-header-or-json-rpc-taskAccessToken-required"
810
+ },
644
811
  metadata: {
645
812
  apBridgeEnabled: opts.includeApBridgeMetadata ?? true,
646
813
  supportedObjects: [
@@ -669,7 +836,20 @@ function createA2aHandler(opts) {
669
836
  });
670
837
  return true;
671
838
  }
672
- const task = tasks.get(taskId);
839
+ const accessToken = requestTaskAccessToken(req);
840
+ const authorized = authorizeDurableA2aTask({
841
+ taskId,
842
+ accessToken,
843
+ env: process.env
844
+ });
845
+ if (!authorized) {
846
+ sendJson(res, 404, {
847
+ status: "not_found",
848
+ reason: "task not found"
849
+ });
850
+ return true;
851
+ }
852
+ const task = resolveTask(taskId);
673
853
  if (!task) {
674
854
  sendJson(res, 404, {
675
855
  status: "not_found",
@@ -682,6 +862,7 @@ function createA2aHandler(opts) {
682
862
  res.setHeader("Cache-Control", "no-cache, no-transform");
683
863
  res.setHeader("Connection", "keep-alive");
684
864
  res.setHeader("X-Accel-Buffering", "no");
865
+ res.setHeader("Referrer-Policy", "no-referrer");
685
866
  writeSseEvent(res, "task.snapshot", toTaskSnapshot(task));
686
867
  if (isTerminal(task.status)) {
687
868
  res.end();
@@ -718,11 +899,31 @@ function createA2aHandler(opts) {
718
899
  return true;
719
900
  }
720
901
  const params = isRecord(rpc.params) ? rpc.params : undefined;
721
- const senderHandle = extractSenderHandle(req, params, domain);
722
- const senderTier = await resolveSenderTier(senderHandle);
723
- if (senderTier === "blocked") {
724
- sendRpcError(res, id, -32040, "blocked sender");
725
- return true;
902
+ let senderHandle = anonymousSenderKey(req);
903
+ let senderTier = "unverified";
904
+ const signedProtocolHeader = headerValue(req.headers[FEDERATION_PEER_HEADERS.protocolVersion]);
905
+ if (signedProtocolHeader) {
906
+ if (rpcPath !== FEDERATION_A2A_RPC_PATH) {
907
+ sendRpcError(res, id, -32040, "signed A2A requires the canonical /a2a endpoint");
908
+ return true;
909
+ }
910
+ const peerAuth = await authorizeFederationPeerRequestV2({
911
+ req,
912
+ body: body.value,
913
+ recipientHandle: handle,
914
+ expectedPath: FEDERATION_A2A_RPC_PATH,
915
+ directoryBaseUrl: federationBaseUrlResolved,
916
+ directoryApiToken: federationApiToken,
917
+ clientIp: opts.peerAuthClientIp,
918
+ env: process.env,
919
+ deps: opts.peerAuthDeps
920
+ });
921
+ if (!peerAuth.ok) {
922
+ sendRpcError(res, id, -32040, peerAuth.reason, peerAuth.statusCode, { code: peerAuth.code });
923
+ return true;
924
+ }
925
+ senderHandle = peerAuth.senderHandle;
926
+ senderTier = "verified";
726
927
  }
727
928
  if (rpc.method === "a2a.ping" || rpc.method === "ping") {
728
929
  sendRpcResult(res, id, {
@@ -750,9 +951,45 @@ function createA2aHandler(opts) {
750
951
  sendRpcResult(res, id, { offer });
751
952
  return true;
752
953
  }
954
+ if (rpc.method === "payments.prepare" || rpc.method === "payment.prepare" || rpc.method === "payments/prepare") {
955
+ if (senderTier !== "verified") {
956
+ sendRpcError(res, id, -32041, "payment challenge requires verified sender");
957
+ return true;
958
+ }
959
+ const taskId = typeof params?.taskId === "string" ? params.taskId.trim() : "";
960
+ const offerId = typeof params?.offerId === "string" ? params.offerId.trim() : "";
961
+ const payerAddress = typeof params?.payerAddress === "string" ? params.payerAddress.trim() : "";
962
+ const offer = findOfferById(offerId, offers);
963
+ const payment = offer?.paymentDefaults;
964
+ const amount = offer ? fixedOfferAmountBaseUnits(offer) : null;
965
+ const payer = normalizeAddressForChain("solana", payerAddress);
966
+ const payee = normalizeAddressForChain("solana", payment?.payee.address);
967
+ const asset = payment ? extractCanonicalAsset(payment.asset, "solana") : null;
968
+ if (!taskId || !offer || !payment || !amount || !payer || !payee || !asset) {
969
+ sendRpcError(res, id, -32602, "invalid fixed-price Solana payment challenge request");
970
+ return true;
971
+ }
972
+ try {
973
+ const challenge = await issueDurableA2aPaymentChallenge({
974
+ taskId,
975
+ senderHandle,
976
+ offerId: offer.id,
977
+ payerAddress: payer,
978
+ payeeAddress: payee,
979
+ amount,
980
+ currency: payment.currency,
981
+ asset,
982
+ env: process.env
983
+ });
984
+ sendRpcResult(res, id, challenge);
985
+ } catch (error) {
986
+ sendRpcError(res, id, -32055, error instanceof Error ? error.message : String(error));
987
+ }
988
+ return true;
989
+ }
753
990
  if (rpc.method === "tasks.create" || rpc.method === "task.create" || rpc.method === "tasks/create") {
754
991
  const taskInput = params && "task" in params ? params.task : params;
755
- const hasPaidReferences = taskHasPaidReferences(taskInput);
992
+ const hasPaidReferences = requestHasPaidReferences(taskInput, params);
756
993
  const offerIssue = validateOfferReference(taskInput, params, offers);
757
994
  if (offerIssue) {
758
995
  sendRpcError(res, id, offerIssue.code, offerIssue.message, 200, offerIssue.data);
@@ -772,13 +1009,39 @@ function createA2aHandler(opts) {
772
1009
  sendRpcError(res, id, -32041, "paid task requires verified sender");
773
1010
  return true;
774
1011
  }
775
- const task = createTask(taskInput, extractMarketplacePaymentSummary(taskInput, params));
1012
+ let taskResult;
1013
+ try {
1014
+ taskResult = await createTask({
1015
+ input: taskInput,
1016
+ marketplacePayment: extractMarketplacePaymentSummary(taskInput, params),
1017
+ senderHandle,
1018
+ accessToken: requestTaskAccessToken(req, params)
1019
+ });
1020
+ } catch (error) {
1021
+ sendRpcError(res, id, -32054, error instanceof Error ? error.message : String(error));
1022
+ return true;
1023
+ }
1024
+ const task = taskResult.task;
776
1025
  let settlement;
777
- if (hasPaidReferences) {
1026
+ const executionRelease = isTerminal(task.status) ? null : await claimDurableA2aTaskExecution({
1027
+ taskId: task.taskId,
1028
+ env: process.env
1029
+ });
1030
+ if (executionRelease) {
1031
+ task.executionRelease = executionRelease;
1032
+ }
1033
+ if (hasPaidReferences && executionRelease && (!task.settlement || task.settlement.status !== "executed")) {
778
1034
  try {
779
1035
  settlement = await settlementOrchestrator({
780
1036
  taskId: task.taskId,
781
1037
  taskInput,
1038
+ invoice: params?.invoice,
1039
+ receipt: params?.receipt,
1040
+ offer: findOfferById(extractOfferId(taskInput, params), offers),
1041
+ challenge: readDurableA2aPaymentChallenge({
1042
+ taskId: task.taskId,
1043
+ env: process.env
1044
+ }),
782
1045
  senderHandle,
783
1046
  senderTier,
784
1047
  env: process.env
@@ -789,10 +1052,37 @@ function createA2aHandler(opts) {
789
1052
  reason: `settlement orchestration error: ${String(err)}`
790
1053
  };
791
1054
  }
1055
+ if (settlement.status === "executed") {
1056
+ try {
1057
+ await claimDurableA2aPaymentChallenge({
1058
+ taskId: task.taskId,
1059
+ challengeId: settlement.challengeId ?? "",
1060
+ senderHandle,
1061
+ payerAddress: settlement.payerAddress ?? "",
1062
+ txRef: settlement.txHash ?? "",
1063
+ env: process.env
1064
+ });
1065
+ } catch (error) {
1066
+ settlement = {
1067
+ status: "failed",
1068
+ reason: error instanceof Error ? error.message : String(error)
1069
+ };
1070
+ }
1071
+ }
1072
+ await updateTask(task, { settlement });
1073
+ } else {
1074
+ settlement = task.settlement;
1075
+ }
1076
+ const settlementAllowsExecution = !hasPaidReferences || task.settlement?.status === "executed";
1077
+ if (executionRelease && settlementAllowsExecution) {
1078
+ scheduleTaskExecution(task);
1079
+ } else if (executionRelease) {
1080
+ await releaseTaskExecution(task);
792
1081
  }
793
1082
  sendRpcResult(res, id, {
794
1083
  taskId: task.taskId,
795
1084
  status: task.status,
1085
+ ...taskResult.accessToken ? { taskAccessToken: taskResult.accessToken } : {},
796
1086
  streamUrl: `${new URL(streamPath, visibleOrigin).toString()}?taskId=${encodeURIComponent(task.taskId)}`,
797
1087
  ...settlement ? { settlement } : {}
798
1088
  });
@@ -804,11 +1094,44 @@ function createA2aHandler(opts) {
804
1094
  sendRpcError(res, id, -32602, "missing taskId");
805
1095
  return true;
806
1096
  }
807
- const task = tasks.get(taskId);
1097
+ const authorized = authorizeDurableA2aTask({
1098
+ taskId,
1099
+ accessToken: requestTaskAccessToken(req, params),
1100
+ env: process.env
1101
+ });
1102
+ const task = authorized ? resolveTask(taskId) : undefined;
808
1103
  if (!task) {
809
1104
  sendRpcError(res, id, -32044, "task not found");
810
1105
  return true;
811
1106
  }
1107
+ await reconcileReviewedRefund(task);
1108
+ sendRpcResult(res, id, toTaskSnapshot(task));
1109
+ return true;
1110
+ }
1111
+ if (rpc.method === "tasks.refund.prepare" || rpc.method === "task.refund.prepare" || rpc.method === "tasks/refund/prepare") {
1112
+ if (senderTier !== "verified") {
1113
+ sendRpcError(res, id, -32041, "refund preparation requires the verified paying peer");
1114
+ return true;
1115
+ }
1116
+ const taskId = typeof params?.taskId === "string" ? params.taskId.trim() : "";
1117
+ const authorized = taskId ? authorizeDurableA2aTask({
1118
+ taskId,
1119
+ accessToken: requestTaskAccessToken(req, params),
1120
+ env: process.env
1121
+ }) : false;
1122
+ const task = authorized ? resolveTask(taskId) : undefined;
1123
+ if (!task?.paymentRecovery || task.paymentRecovery.status !== "refund-required") {
1124
+ sendRpcError(res, id, -32044, "refund-required task not found");
1125
+ return true;
1126
+ }
1127
+ const recovery = await ensureReviewedRefundApproval(task, task.paymentRecovery);
1128
+ const durable = await updateDurableA2aTask({
1129
+ taskId,
1130
+ paymentRecovery: recovery,
1131
+ env: process.env
1132
+ });
1133
+ task.paymentRecovery = durable.paymentRecovery;
1134
+ task.updatedAt = durable.updatedAt;
812
1135
  sendRpcResult(res, id, toTaskSnapshot(task));
813
1136
  return true;
814
1137
  }
@@ -818,14 +1141,20 @@ function createA2aHandler(opts) {
818
1141
  sendRpcError(res, id, -32602, "missing taskId");
819
1142
  return true;
820
1143
  }
821
- const task = tasks.get(taskId);
1144
+ const authorized = authorizeDurableA2aTask({
1145
+ taskId,
1146
+ accessToken: requestTaskAccessToken(req, params),
1147
+ env: process.env
1148
+ });
1149
+ const task = authorized ? resolveTask(taskId) : undefined;
822
1150
  if (!task) {
823
1151
  sendRpcError(res, id, -32044, "task not found");
824
1152
  return true;
825
1153
  }
826
1154
  if (!isTerminal(task.status)) {
827
1155
  clearTaskTimers(task);
828
- updateTask(task, { status: "canceled" });
1156
+ await updateTask(task, { status: "canceled" });
1157
+ await releaseTaskExecution(task);
829
1158
  }
830
1159
  sendRpcResult(res, id, toTaskSnapshot(task));
831
1160
  return true;