@ixo/editor 6.33.0 → 6.35.0

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 (526) hide show
  1. package/dist/BidConfig-YLGSEIOS.js +154 -0
  2. package/dist/BidConfig-YLGSEIOS.js.map +1 -0
  3. package/dist/BidFlowDetail-U2SX5M7F.js +365 -0
  4. package/dist/BidFlowDetail-U2SX5M7F.js.map +1 -0
  5. package/dist/CalendarEventCreateConfig-J2LU6LJO.js +155 -0
  6. package/dist/CalendarEventCreateConfig-J2LU6LJO.js.map +1 -0
  7. package/dist/CalendarEventCreateFlowDetail-ZWHZWDOK.js +174 -0
  8. package/dist/CalendarEventCreateFlowDetail-ZWHZWDOK.js.map +1 -0
  9. package/dist/CalendarEventListConfig-GQNNF4ZB.js +116 -0
  10. package/dist/CalendarEventListConfig-GQNNF4ZB.js.map +1 -0
  11. package/dist/CalendarEventListFlowDetail-SSRTOXIX.js +58 -0
  12. package/dist/CalendarEventListFlowDetail-SSRTOXIX.js.map +1 -0
  13. package/dist/CalendarEventUpdateConfig-KACZA6GH.js +133 -0
  14. package/dist/CalendarEventUpdateConfig-KACZA6GH.js.map +1 -0
  15. package/dist/CalendarEventUpdateFlowDetail-CD6NHHOU.js +155 -0
  16. package/dist/CalendarEventUpdateFlowDetail-CD6NHHOU.js.map +1 -0
  17. package/dist/ClaimConfig-3HKPGK55.js +200 -0
  18. package/dist/ClaimConfig-3HKPGK55.js.map +1 -0
  19. package/dist/ClaimFlowDetail-I4OQSHAB.js +641 -0
  20. package/dist/ClaimFlowDetail-I4OQSHAB.js.map +1 -0
  21. package/dist/CollectionLifecycleConfig-LCCGZ3CJ.js +149 -0
  22. package/dist/CollectionLifecycleConfig-LCCGZ3CJ.js.map +1 -0
  23. package/dist/CollectionLifecycleFlowDetail-LQHKB227.js +647 -0
  24. package/dist/CollectionLifecycleFlowDetail-LQHKB227.js.map +1 -0
  25. package/dist/CollectionUsersConfig-RI2X3YY2.js +271 -0
  26. package/dist/CollectionUsersConfig-RI2X3YY2.js.map +1 -0
  27. package/dist/CollectionUsersFlowDetail-LHXVCCPQ.js +1276 -0
  28. package/dist/CollectionUsersFlowDetail-LHXVCCPQ.js.map +1 -0
  29. package/dist/CredentialStoreConfig-G66AQDGZ.js +75 -0
  30. package/dist/CredentialStoreConfig-G66AQDGZ.js.map +1 -0
  31. package/dist/CredentialStoreFlowDetail-FL7QAM3S.js +99 -0
  32. package/dist/CredentialStoreFlowDetail-FL7QAM3S.js.map +1 -0
  33. package/dist/DesignPodConfig-LJ7H2CZ6.js +8 -0
  34. package/dist/DesignPodConfig-LJ7H2CZ6.js.map +1 -0
  35. package/dist/DesignPodFlowDetail-JHJWGNVY.js +309 -0
  36. package/dist/DesignPodFlowDetail-JHJWGNVY.js.map +1 -0
  37. package/dist/DomainCardPreviewConfig-Q3X5M4WF.js +37 -0
  38. package/dist/DomainCardPreviewConfig-Q3X5M4WF.js.map +1 -0
  39. package/dist/DomainCardPreviewFlowDetail-Y2FE7O5Z.js +131 -0
  40. package/dist/DomainCardPreviewFlowDetail-Y2FE7O5Z.js.map +1 -0
  41. package/dist/DomainIndexerLookupConfig-N4VONQUY.js +41 -0
  42. package/dist/DomainIndexerLookupConfig-N4VONQUY.js.map +1 -0
  43. package/dist/DomainIndexerLookupFlowDetail-GJ7WWK7I.js +70 -0
  44. package/dist/DomainIndexerLookupFlowDetail-GJ7WWK7I.js.map +1 -0
  45. package/dist/DomainSignConfig-XFIXROVK.js +47 -0
  46. package/dist/DomainSignConfig-XFIXROVK.js.map +1 -0
  47. package/dist/DomainSignFlowDetail-BXZ6JBPR.js +206 -0
  48. package/dist/DomainSignFlowDetail-BXZ6JBPR.js.map +1 -0
  49. package/dist/DomainSingleSelectionConfig-ZNKIXB4P.js +101 -0
  50. package/dist/DomainSingleSelectionConfig-ZNKIXB4P.js.map +1 -0
  51. package/dist/DomainSingleSelectionFlowDetail-HWTQXSLA.js +147 -0
  52. package/dist/DomainSingleSelectionFlowDetail-HWTQXSLA.js.map +1 -0
  53. package/dist/EmailSendConfig-YEGZ5Q77.js +215 -0
  54. package/dist/EmailSendConfig-YEGZ5Q77.js.map +1 -0
  55. package/dist/EntityCreateOracleConfig-UZ6ZIMP5.js +150 -0
  56. package/dist/EntityCreateOracleConfig-UZ6ZIMP5.js.map +1 -0
  57. package/dist/EntityCreateOracleFlowDetail-H2X7CPYU.js +120 -0
  58. package/dist/EntityCreateOracleFlowDetail-H2X7CPYU.js.map +1 -0
  59. package/dist/EntitySingleSelectionConfig-DL57KNKM.js +30 -0
  60. package/dist/EntitySingleSelectionConfig-DL57KNKM.js.map +1 -0
  61. package/dist/EntitySingleSelectionFlowDetail-GFQGX3GA.js +118 -0
  62. package/dist/EntitySingleSelectionFlowDetail-GFQGX3GA.js.map +1 -0
  63. package/dist/EntityTransferConfig-JVZ3H35B.js +62 -0
  64. package/dist/EntityTransferConfig-JVZ3H35B.js.map +1 -0
  65. package/dist/EntityTransferFlowDetail-XEXM34XB.js +132 -0
  66. package/dist/EntityTransferFlowDetail-XEXM34XB.js.map +1 -0
  67. package/dist/EvalEngineConfig-CHC4IRN3.js +464 -0
  68. package/dist/EvalEngineConfig-CHC4IRN3.js.map +1 -0
  69. package/dist/EvalEngineFlowDetail-PUFRNO4U.js +4291 -0
  70. package/dist/EvalEngineFlowDetail-PUFRNO4U.js.map +1 -0
  71. package/dist/EvaluateBidConfig-OE4CM43G.js +151 -0
  72. package/dist/EvaluateBidConfig-OE4CM43G.js.map +1 -0
  73. package/dist/EvaluateBidFlowDetail-2EXGNBYC.js +564 -0
  74. package/dist/EvaluateBidFlowDetail-2EXGNBYC.js.map +1 -0
  75. package/dist/EvaluateClaimConfig-3D4F5LHU.js +297 -0
  76. package/dist/EvaluateClaimConfig-3D4F5LHU.js.map +1 -0
  77. package/dist/EvaluateClaimFlowDetail-QKHJVEDE.js +2237 -0
  78. package/dist/EvaluateClaimFlowDetail-QKHJVEDE.js.map +1 -0
  79. package/dist/FormSubmitConfig-UFZYMLUN.js +59 -0
  80. package/dist/FormSubmitConfig-UFZYMLUN.js.map +1 -0
  81. package/dist/FormSubmitFlowDetail-IAHDJS6P.js +169 -0
  82. package/dist/FormSubmitFlowDetail-IAHDJS6P.js.map +1 -0
  83. package/dist/GovernanceAuthzExecFlowDetail-SQBGU5BX.js +166 -0
  84. package/dist/GovernanceAuthzExecFlowDetail-SQBGU5BX.js.map +1 -0
  85. package/dist/GovernanceAuthzGrantFlowDetail-DZPNLANT.js +88 -0
  86. package/dist/GovernanceAuthzGrantFlowDetail-DZPNLANT.js.map +1 -0
  87. package/dist/GovernanceAuthzRevokeFlowDetail-3JZ4IUJG.js +88 -0
  88. package/dist/GovernanceAuthzRevokeFlowDetail-3JZ4IUJG.js.map +1 -0
  89. package/dist/GovernanceChainVoteFlowDetail-475UDNG6.js +83 -0
  90. package/dist/GovernanceChainVoteFlowDetail-475UDNG6.js.map +1 -0
  91. package/dist/GovernanceConfigConfig-V3WM4WBP.js +30 -0
  92. package/dist/GovernanceConfigConfig-V3WM4WBP.js.map +1 -0
  93. package/dist/GovernanceConfigFlowDetail-SQ5PPDRX.js +267 -0
  94. package/dist/GovernanceConfigFlowDetail-SQ5PPDRX.js.map +1 -0
  95. package/dist/GovernanceContractExecuteFlowDetail-H2ZV6W2E.js +113 -0
  96. package/dist/GovernanceContractExecuteFlowDetail-H2ZV6W2E.js.map +1 -0
  97. package/dist/GovernanceContractInstantiateFlowDetail-YJJMGM54.js +144 -0
  98. package/dist/GovernanceContractInstantiateFlowDetail-YJJMGM54.js.map +1 -0
  99. package/dist/GovernanceContractManageCw20FlowDetail-OCBMW3YJ.js +72 -0
  100. package/dist/GovernanceContractManageCw20FlowDetail-OCBMW3YJ.js.map +1 -0
  101. package/dist/GovernanceContractMigrateFlowDetail-JDNIKTT3.js +104 -0
  102. package/dist/GovernanceContractMigrateFlowDetail-JDNIKTT3.js.map +1 -0
  103. package/dist/GovernanceContractUpdateAdminFlowDetail-SZBOAOCC.js +68 -0
  104. package/dist/GovernanceContractUpdateAdminFlowDetail-SZBOAOCC.js.map +1 -0
  105. package/dist/GovernanceCustomMessageFlowDetail-CXD4ZATO.js +78 -0
  106. package/dist/GovernanceCustomMessageFlowDetail-CXD4ZATO.js.map +1 -0
  107. package/dist/GovernanceDaoAcceptToMarketplaceFlowDetail-Q6ZBNY7Z.js +98 -0
  108. package/dist/GovernanceDaoAcceptToMarketplaceFlowDetail-Q6ZBNY7Z.js.map +1 -0
  109. package/dist/GovernanceDaoAdminExecFlowDetail-JAEAY2US.js +94 -0
  110. package/dist/GovernanceDaoAdminExecFlowDetail-JAEAY2US.js.map +1 -0
  111. package/dist/GovernanceDaoCreateEntityFlowDetail-7RVNTVAB.js +96 -0
  112. package/dist/GovernanceDaoCreateEntityFlowDetail-7RVNTVAB.js.map +1 -0
  113. package/dist/GovernanceDaoJoinFlowDetail-XYCTCNHO.js +68 -0
  114. package/dist/GovernanceDaoJoinFlowDetail-XYCTCNHO.js.map +1 -0
  115. package/dist/GovernanceDaoManageStorageFlowDetail-LMLYLYYC.js +93 -0
  116. package/dist/GovernanceDaoManageStorageFlowDetail-LMLYLYYC.js.map +1 -0
  117. package/dist/GovernanceDaoManageSubDaosFlowDetail-YUFQ67JN.js +84 -0
  118. package/dist/GovernanceDaoManageSubDaosFlowDetail-YUFQ67JN.js.map +1 -0
  119. package/dist/GovernanceDaoUpdateInfoFlowDetail-G5FIBY4L.js +104 -0
  120. package/dist/GovernanceDaoUpdateInfoFlowDetail-G5FIBY4L.js.map +1 -0
  121. package/dist/GovernanceMemberProposalConfig-IGPXEFDB.js +42 -0
  122. package/dist/GovernanceMemberProposalConfig-IGPXEFDB.js.map +1 -0
  123. package/dist/GovernanceMemberProposalFlowDetail-T3VURONF.js +240 -0
  124. package/dist/GovernanceMemberProposalFlowDetail-T3VURONF.js.map +1 -0
  125. package/dist/GovernanceNftBurnFlowDetail-AG4I2O7H.js +69 -0
  126. package/dist/GovernanceNftBurnFlowDetail-AG4I2O7H.js.map +1 -0
  127. package/dist/GovernanceNftManageCollectionsFlowDetail-UAAGO3Q6.js +71 -0
  128. package/dist/GovernanceNftManageCollectionsFlowDetail-UAAGO3Q6.js.map +1 -0
  129. package/dist/GovernanceNftTransferFlowDetail-KXM7DTOV.js +130 -0
  130. package/dist/GovernanceNftTransferFlowDetail-KXM7DTOV.js.map +1 -0
  131. package/dist/GovernanceSettingsProposalConfig-4SLJTBLW.js +42 -0
  132. package/dist/GovernanceSettingsProposalConfig-4SLJTBLW.js.map +1 -0
  133. package/dist/GovernanceSettingsProposalFlowDetail-VFZPSCLR.js +165 -0
  134. package/dist/GovernanceSettingsProposalFlowDetail-VFZPSCLR.js.map +1 -0
  135. package/dist/GovernanceStakingStakeFlowDetail-ULLJ7FLM.js +123 -0
  136. package/dist/GovernanceStakingStakeFlowDetail-ULLJ7FLM.js.map +1 -0
  137. package/dist/GovernanceStakingStakeToGroupFlowDetail-CSPKJA3H.js +84 -0
  138. package/dist/GovernanceStakingStakeToGroupFlowDetail-CSPKJA3H.js.map +1 -0
  139. package/dist/GovernanceSubmissionConfigProposalFlowDetail-MZCPSZF2.js +111 -0
  140. package/dist/GovernanceSubmissionConfigProposalFlowDetail-MZCPSZF2.js.map +1 -0
  141. package/dist/GovernanceTransactionMintFlowDetail-Y2WRAODH.js +66 -0
  142. package/dist/GovernanceTransactionMintFlowDetail-Y2WRAODH.js.map +1 -0
  143. package/dist/GovernanceTransactionPerformTokenSwapFlowDetail-GEK6PMMI.js +133 -0
  144. package/dist/GovernanceTransactionPerformTokenSwapFlowDetail-GEK6PMMI.js.map +1 -0
  145. package/dist/GovernanceTransactionSendFundsConfig-VBKMLSF3.js +42 -0
  146. package/dist/GovernanceTransactionSendFundsConfig-VBKMLSF3.js.map +1 -0
  147. package/dist/GovernanceTransactionSendFundsFlowDetail-5TZB64VL.js +182 -0
  148. package/dist/GovernanceTransactionSendFundsFlowDetail-5TZB64VL.js.map +1 -0
  149. package/dist/GovernanceTransactionSendGroupTokenFlowDetail-EGOWVZM2.js +155 -0
  150. package/dist/GovernanceTransactionSendGroupTokenFlowDetail-EGOWVZM2.js.map +1 -0
  151. package/dist/GovernanceTransactionWithdrawTokenSwapFlowDetail-6XWVO5O6.js +56 -0
  152. package/dist/GovernanceTransactionWithdrawTokenSwapFlowDetail-6XWVO5O6.js.map +1 -0
  153. package/dist/GovernanceValidatorActionsFlowDetail-ZMLPAFUB.js +117 -0
  154. package/dist/GovernanceValidatorActionsFlowDetail-ZMLPAFUB.js.map +1 -0
  155. package/dist/HarvestConfig-AIGOGBFR.js +56 -0
  156. package/dist/HarvestConfig-AIGOGBFR.js.map +1 -0
  157. package/dist/HarvestFlowDetail-X3RUH3X3.js +131 -0
  158. package/dist/HarvestFlowDetail-X3RUH3X3.js.map +1 -0
  159. package/dist/HttpRequestConfig-OQEJIIJY.js +194 -0
  160. package/dist/HttpRequestConfig-OQEJIIJY.js.map +1 -0
  161. package/dist/HttpRequestFlowDetail-JVLV533Z.js +116 -0
  162. package/dist/HttpRequestFlowDetail-JVLV533Z.js.map +1 -0
  163. package/dist/IdentityCreateConfig-ZBUOJ6AL.js +94 -0
  164. package/dist/IdentityCreateConfig-ZBUOJ6AL.js.map +1 -0
  165. package/dist/IdentityCreateFlowDetail-4TE6UCEB.js +83 -0
  166. package/dist/IdentityCreateFlowDetail-4TE6UCEB.js.map +1 -0
  167. package/dist/IidCreateConfig-RRV2DYXI.js +75 -0
  168. package/dist/IidCreateConfig-RRV2DYXI.js.map +1 -0
  169. package/dist/IidCreateFlowDetail-HPVZAHVY.js +57 -0
  170. package/dist/IidCreateFlowDetail-HPVZAHVY.js.map +1 -0
  171. package/dist/KycVerifyConfig-VCG65K5K.js +65 -0
  172. package/dist/KycVerifyConfig-VCG65K5K.js.map +1 -0
  173. package/dist/KycVerifyFlowDetail-FEU43HML.js +421 -0
  174. package/dist/KycVerifyFlowDetail-FEU43HML.js.map +1 -0
  175. package/dist/ListDomainFlowsConfig-3JZEPTOJ.js +37 -0
  176. package/dist/ListDomainFlowsConfig-3JZEPTOJ.js.map +1 -0
  177. package/dist/ListDomainFlowsFlowDetail-XX5AXDZZ.js +257 -0
  178. package/dist/ListDomainFlowsFlowDetail-XX5AXDZZ.js.map +1 -0
  179. package/dist/LoadBatchesConfig-IMODIWRT.js +38 -0
  180. package/dist/LoadBatchesConfig-IMODIWRT.js.map +1 -0
  181. package/dist/LoadBatchesFlowDetail-GB24T76O.js +101 -0
  182. package/dist/LoadBatchesFlowDetail-GB24T76O.js.map +1 -0
  183. package/dist/MatrixDmConfig-NBII27CS.js +120 -0
  184. package/dist/MatrixDmConfig-NBII27CS.js.map +1 -0
  185. package/dist/MatrixRegisterConfig-N2U4FBYF.js +62 -0
  186. package/dist/MatrixRegisterConfig-N2U4FBYF.js.map +1 -0
  187. package/dist/MatrixRegisterFlowDetail-D5YNL5QX.js +86 -0
  188. package/dist/MatrixRegisterFlowDetail-D5YNL5QX.js.map +1 -0
  189. package/dist/MemberMultiSelectConfig-E7WUB2WD.js +30 -0
  190. package/dist/MemberMultiSelectConfig-E7WUB2WD.js.map +1 -0
  191. package/dist/MemberMultiSelectFlowDetail-6C4ZMSDR.js +392 -0
  192. package/dist/MemberMultiSelectFlowDetail-6C4ZMSDR.js.map +1 -0
  193. package/dist/OracleConfig-R7TDTTKN.js +56 -0
  194. package/dist/OracleConfig-R7TDTTKN.js.map +1 -0
  195. package/dist/OracleConfigureOracleConfig-QFF74X3N.js +198 -0
  196. package/dist/OracleConfigureOracleConfig-QFF74X3N.js.map +1 -0
  197. package/dist/OracleConfigureOracleFlowDetail-MIBXUEKC.js +255 -0
  198. package/dist/OracleConfigureOracleFlowDetail-MIBXUEKC.js.map +1 -0
  199. package/dist/OracleContractConfig-PHY5L7W2.js +38 -0
  200. package/dist/OracleContractConfig-PHY5L7W2.js.map +1 -0
  201. package/dist/OracleContractFlowDetail-M3PM4AU4.js +78 -0
  202. package/dist/OracleContractFlowDetail-M3PM4AU4.js.map +1 -0
  203. package/dist/OracleDeployConfig-QBG76ATZ.js +10 -0
  204. package/dist/OracleDeployConfig-QBG76ATZ.js.map +1 -0
  205. package/dist/OracleDeployFlowDetail-WKTMD2AD.js +231 -0
  206. package/dist/OracleDeployFlowDetail-WKTMD2AD.js.map +1 -0
  207. package/dist/OracleDeploySetupConfig-75XPGFJQ.js +10 -0
  208. package/dist/OracleDeploySetupConfig-75XPGFJQ.js.map +1 -0
  209. package/dist/OracleDeploySetupFlowDetail-R3BQ7EAU.js +165 -0
  210. package/dist/OracleDeploySetupFlowDetail-R3BQ7EAU.js.map +1 -0
  211. package/dist/OracleDeployStartConfig-NA6GZ4VQ.js +10 -0
  212. package/dist/OracleDeployStartConfig-NA6GZ4VQ.js.map +1 -0
  213. package/dist/OracleDeployStartFlowDetail-EL3CMDMG.js +89 -0
  214. package/dist/OracleDeployStartFlowDetail-EL3CMDMG.js.map +1 -0
  215. package/dist/OracleFlowDetail-5JCJK3GH.js +76 -0
  216. package/dist/OracleFlowDetail-5JCJK3GH.js.map +1 -0
  217. package/dist/OraclePromptConfig-YBRESISH.js +39 -0
  218. package/dist/OraclePromptConfig-YBRESISH.js.map +1 -0
  219. package/dist/OraclePromptFlowDetail-O3XNK7HY.js +112 -0
  220. package/dist/OraclePromptFlowDetail-O3XNK7HY.js.map +1 -0
  221. package/dist/OracleStoreConfigConfig-TUZWTJMA.js +134 -0
  222. package/dist/OracleStoreConfigConfig-TUZWTJMA.js.map +1 -0
  223. package/dist/OracleStoreConfigFlowDetail-Q6AUUSUL.js +99 -0
  224. package/dist/OracleStoreConfigFlowDetail-Q6AUUSUL.js.map +1 -0
  225. package/dist/OracleStoreSecretsAndConfigConfig-SZPYEK7U.js +198 -0
  226. package/dist/OracleStoreSecretsAndConfigConfig-SZPYEK7U.js.map +1 -0
  227. package/dist/OracleStoreSecretsAndConfigFlowDetail-HQU3UKEB.js +220 -0
  228. package/dist/OracleStoreSecretsAndConfigFlowDetail-HQU3UKEB.js.map +1 -0
  229. package/dist/OracleStoreSecretsConfig-PQMF7LFT.js +191 -0
  230. package/dist/OracleStoreSecretsConfig-PQMF7LFT.js.map +1 -0
  231. package/dist/OracleStoreSecretsFlowDetail-5RXWQ3KA.js +197 -0
  232. package/dist/OracleStoreSecretsFlowDetail-5RXWQ3KA.js.map +1 -0
  233. package/dist/ProposalCreateConfig-U5IHZNT7.js +161 -0
  234. package/dist/ProposalCreateConfig-U5IHZNT7.js.map +1 -0
  235. package/dist/ProposalCreateFlowDetail-2FCRCNYV.js +235 -0
  236. package/dist/ProposalCreateFlowDetail-2FCRCNYV.js.map +1 -0
  237. package/dist/ProposalVoteConfig-MH4MU7SL.js +150 -0
  238. package/dist/ProposalVoteConfig-MH4MU7SL.js.map +1 -0
  239. package/dist/ProposalVoteFlowDetail-IJJ3OHAB.js +280 -0
  240. package/dist/ProposalVoteFlowDetail-IJJ3OHAB.js.map +1 -0
  241. package/dist/ProtocolSelectConfig-S5U3P6K7.js +48 -0
  242. package/dist/ProtocolSelectConfig-S5U3P6K7.js.map +1 -0
  243. package/dist/ProtocolSelectFlowDetail-XBSJIEIH.js +116 -0
  244. package/dist/ProtocolSelectFlowDetail-XBSJIEIH.js.map +1 -0
  245. package/dist/RetireConfig-MV37WWZ6.js +59 -0
  246. package/dist/RetireConfig-MV37WWZ6.js.map +1 -0
  247. package/dist/RetireFlowDetail-VZ5O4SXI.js +147 -0
  248. package/dist/RetireFlowDetail-VZ5O4SXI.js.map +1 -0
  249. package/dist/SandboxProvisionConfig-ZGG4IRHM.js +46 -0
  250. package/dist/SandboxProvisionConfig-ZGG4IRHM.js.map +1 -0
  251. package/dist/SandboxProvisionFlowDetail-RUY64INV.js +79 -0
  252. package/dist/SandboxProvisionFlowDetail-RUY64INV.js.map +1 -0
  253. package/dist/WalletFundConfig-CMM3EP3B.js +117 -0
  254. package/dist/WalletFundConfig-CMM3EP3B.js.map +1 -0
  255. package/dist/WalletFundFlowDetail-TXWCZA4K.js +279 -0
  256. package/dist/WalletFundFlowDetail-TXWCZA4K.js.map +1 -0
  257. package/dist/WalletGenerateAndFundConfig-364RSEND.js +10 -0
  258. package/dist/WalletGenerateAndFundConfig-364RSEND.js.map +1 -0
  259. package/dist/WalletGenerateAndFundFlowDetail-C2LZW3NO.js +54 -0
  260. package/dist/WalletGenerateAndFundFlowDetail-C2LZW3NO.js.map +1 -0
  261. package/dist/WalletGenerateConfig-YYLCS65G.js +10 -0
  262. package/dist/WalletGenerateConfig-YYLCS65G.js.map +1 -0
  263. package/dist/WalletGenerateFlowDetail-CQCNDGJA.js +53 -0
  264. package/dist/WalletGenerateFlowDetail-CQCNDGJA.js.map +1 -0
  265. package/dist/XeroContactCreateConfig-OWG5PA3B.js +102 -0
  266. package/dist/XeroContactCreateConfig-OWG5PA3B.js.map +1 -0
  267. package/dist/XeroContactCreateFlowDetail-6MAINCF6.js +127 -0
  268. package/dist/XeroContactCreateFlowDetail-6MAINCF6.js.map +1 -0
  269. package/dist/XeroInvoiceCreateConfig-O74RUSZM.js +403 -0
  270. package/dist/XeroInvoiceCreateConfig-O74RUSZM.js.map +1 -0
  271. package/dist/XeroInvoiceCreateFlowDetail-UL7KS6CZ.js +631 -0
  272. package/dist/XeroInvoiceCreateFlowDetail-UL7KS6CZ.js.map +1 -0
  273. package/dist/XeroInvoiceListConfig-UR3GONBJ.js +113 -0
  274. package/dist/XeroInvoiceListConfig-UR3GONBJ.js.map +1 -0
  275. package/dist/XeroInvoiceListFlowDetail-LYHODWH6.js +58 -0
  276. package/dist/XeroInvoiceListFlowDetail-LYHODWH6.js.map +1 -0
  277. package/dist/XeroPaymentCreateConfig-RPMAIK6E.js +116 -0
  278. package/dist/XeroPaymentCreateConfig-RPMAIK6E.js.map +1 -0
  279. package/dist/XeroPaymentCreateFlowDetail-CF35MVIM.js +573 -0
  280. package/dist/XeroPaymentCreateFlowDetail-CF35MVIM.js.map +1 -0
  281. package/dist/action-manifest.json +2091 -393
  282. package/dist/chunk-2GAYKKTL.js +9 -0
  283. package/dist/chunk-2GAYKKTL.js.map +1 -0
  284. package/dist/chunk-3TUYY4HK.js +20 -0
  285. package/dist/chunk-3TUYY4HK.js.map +1 -0
  286. package/dist/chunk-4DGCCXD6.js +710 -0
  287. package/dist/chunk-4DGCCXD6.js.map +1 -0
  288. package/dist/chunk-4NAFQF6V.js +11 -0
  289. package/dist/chunk-4NAFQF6V.js.map +1 -0
  290. package/dist/chunk-4PONO4US.js +799 -0
  291. package/dist/chunk-4PONO4US.js.map +1 -0
  292. package/dist/chunk-4TMOIK5M.js +21 -0
  293. package/dist/chunk-4TMOIK5M.js.map +1 -0
  294. package/dist/chunk-5E6Z6JJN.js +4456 -0
  295. package/dist/chunk-5E6Z6JJN.js.map +1 -0
  296. package/dist/chunk-5IH3VC5I.js +102 -0
  297. package/dist/chunk-5IH3VC5I.js.map +1 -0
  298. package/dist/chunk-5NTKDOP6.js +89 -0
  299. package/dist/chunk-5NTKDOP6.js.map +1 -0
  300. package/dist/chunk-5O2SFRGU.js +18 -0
  301. package/dist/chunk-5O2SFRGU.js.map +1 -0
  302. package/dist/chunk-632JLECF.js +55 -0
  303. package/dist/chunk-632JLECF.js.map +1 -0
  304. package/dist/chunk-676HDB7K.js +95 -0
  305. package/dist/chunk-676HDB7K.js.map +1 -0
  306. package/dist/chunk-6ESTNTSH.js +223 -0
  307. package/dist/chunk-6ESTNTSH.js.map +1 -0
  308. package/dist/chunk-6GKJR52N.js +15 -0
  309. package/dist/chunk-6GKJR52N.js.map +1 -0
  310. package/dist/chunk-6L4ZIKYU.js +23 -0
  311. package/dist/chunk-6L4ZIKYU.js.map +1 -0
  312. package/dist/chunk-76YX5R4L.js +11 -0
  313. package/dist/chunk-76YX5R4L.js.map +1 -0
  314. package/dist/chunk-7J3GFMN3.js +32 -0
  315. package/dist/chunk-7J3GFMN3.js.map +1 -0
  316. package/dist/chunk-7LSARC2G.js +102 -0
  317. package/dist/chunk-7LSARC2G.js.map +1 -0
  318. package/dist/chunk-7W7UUUIE.js +609 -0
  319. package/dist/chunk-7W7UUUIE.js.map +1 -0
  320. package/dist/chunk-7ZLW7H37.js +21 -0
  321. package/dist/chunk-7ZLW7H37.js.map +1 -0
  322. package/dist/chunk-AAZHI22G.js +18 -0
  323. package/dist/chunk-AAZHI22G.js.map +1 -0
  324. package/dist/chunk-ACNE455I.js +76 -0
  325. package/dist/chunk-ACNE455I.js.map +1 -0
  326. package/dist/chunk-BKLSSLPZ.js +27 -0
  327. package/dist/chunk-BKLSSLPZ.js.map +1 -0
  328. package/dist/chunk-BZ7UPUTY.js +417 -0
  329. package/dist/chunk-BZ7UPUTY.js.map +1 -0
  330. package/dist/chunk-CGFAICUE.js +28 -0
  331. package/dist/chunk-CGFAICUE.js.map +1 -0
  332. package/dist/chunk-CMCEWQ3C.js +19 -0
  333. package/dist/chunk-CMCEWQ3C.js.map +1 -0
  334. package/dist/chunk-CP4UV436.js +41 -0
  335. package/dist/chunk-CP4UV436.js.map +1 -0
  336. package/dist/chunk-DIQRZP7Z.js +51 -0
  337. package/dist/chunk-DIQRZP7Z.js.map +1 -0
  338. package/dist/chunk-EBFFDDAS.js +13 -0
  339. package/dist/chunk-EBFFDDAS.js.map +1 -0
  340. package/dist/chunk-EGVS23DR.js +85 -0
  341. package/dist/chunk-EGVS23DR.js.map +1 -0
  342. package/dist/chunk-EKBQ7K4N.js +15 -0
  343. package/dist/chunk-EKBQ7K4N.js.map +1 -0
  344. package/dist/chunk-EKQCZRAN.js +24 -0
  345. package/dist/chunk-EKQCZRAN.js.map +1 -0
  346. package/dist/chunk-EYKZIZ5J.js +48 -0
  347. package/dist/chunk-EYKZIZ5J.js.map +1 -0
  348. package/dist/{chunk-NEOPTPDF.js → chunk-F4PTFXZH.js} +11554 -22046
  349. package/dist/chunk-F4PTFXZH.js.map +1 -0
  350. package/dist/chunk-F5GTFCYV.js +3333 -0
  351. package/dist/chunk-F5GTFCYV.js.map +1 -0
  352. package/dist/chunk-FFYZXA75.js +58 -0
  353. package/dist/chunk-FFYZXA75.js.map +1 -0
  354. package/dist/chunk-GFGDHPZ2.js +22 -0
  355. package/dist/chunk-GFGDHPZ2.js.map +1 -0
  356. package/dist/chunk-GR3CDFID.js +18 -0
  357. package/dist/chunk-GR3CDFID.js.map +1 -0
  358. package/dist/chunk-GR4SIU32.js +104 -0
  359. package/dist/chunk-GR4SIU32.js.map +1 -0
  360. package/dist/chunk-H5E46IIS.js +18 -0
  361. package/dist/chunk-H5E46IIS.js.map +1 -0
  362. package/dist/chunk-HFHVAMZL.js +22 -0
  363. package/dist/chunk-HFHVAMZL.js.map +1 -0
  364. package/dist/chunk-HT6L7A5M.js +12 -0
  365. package/dist/chunk-HT6L7A5M.js.map +1 -0
  366. package/dist/chunk-I2FPFISM.js +301 -0
  367. package/dist/chunk-I2FPFISM.js.map +1 -0
  368. package/dist/chunk-IADAQJDH.js +28 -0
  369. package/dist/chunk-IADAQJDH.js.map +1 -0
  370. package/dist/chunk-IBOBCMQQ.js +99 -0
  371. package/dist/chunk-IBOBCMQQ.js.map +1 -0
  372. package/dist/chunk-IFWKRCFF.js +56 -0
  373. package/dist/chunk-IFWKRCFF.js.map +1 -0
  374. package/dist/chunk-IH4T7V4C.js +40 -0
  375. package/dist/chunk-IH4T7V4C.js.map +1 -0
  376. package/dist/chunk-IIIZZ4E4.js +1679 -0
  377. package/dist/chunk-IIIZZ4E4.js.map +1 -0
  378. package/dist/chunk-ILSFU3WD.js +83 -0
  379. package/dist/chunk-ILSFU3WD.js.map +1 -0
  380. package/dist/chunk-IX3VBV3L.js +43 -0
  381. package/dist/chunk-IX3VBV3L.js.map +1 -0
  382. package/dist/chunk-JB6ASLUJ.js +315 -0
  383. package/dist/chunk-JB6ASLUJ.js.map +1 -0
  384. package/dist/chunk-JBBFSORW.js +846 -0
  385. package/dist/chunk-JBBFSORW.js.map +1 -0
  386. package/dist/chunk-JIDTNKKL.js +1183 -0
  387. package/dist/chunk-JIDTNKKL.js.map +1 -0
  388. package/dist/chunk-JSPE6NGZ.js +22 -0
  389. package/dist/chunk-JSPE6NGZ.js.map +1 -0
  390. package/dist/chunk-JVROGQ7Q.js +150 -0
  391. package/dist/chunk-JVROGQ7Q.js.map +1 -0
  392. package/dist/chunk-K4WUMWNJ.js +32 -0
  393. package/dist/chunk-K4WUMWNJ.js.map +1 -0
  394. package/dist/chunk-K74XQ4Q5.js +11 -0
  395. package/dist/chunk-K74XQ4Q5.js.map +1 -0
  396. package/dist/chunk-KLLMJ4U3.js +22 -0
  397. package/dist/chunk-KLLMJ4U3.js.map +1 -0
  398. package/dist/chunk-LTKVCJ2E.js +27 -0
  399. package/dist/chunk-LTKVCJ2E.js.map +1 -0
  400. package/dist/chunk-M36DJTFZ.js +34 -0
  401. package/dist/chunk-M36DJTFZ.js.map +1 -0
  402. package/dist/chunk-MHM52LCJ.js +154 -0
  403. package/dist/chunk-MHM52LCJ.js.map +1 -0
  404. package/dist/chunk-MQCDMHRZ.js +59 -0
  405. package/dist/chunk-MQCDMHRZ.js.map +1 -0
  406. package/dist/chunk-MZIBZ5FY.js +554 -0
  407. package/dist/chunk-MZIBZ5FY.js.map +1 -0
  408. package/dist/chunk-N3ORMGAI.js +348 -0
  409. package/dist/chunk-N3ORMGAI.js.map +1 -0
  410. package/dist/chunk-NCSGIRRQ.js +28 -0
  411. package/dist/chunk-NCSGIRRQ.js.map +1 -0
  412. package/dist/chunk-NIXT2SBH.js +1423 -0
  413. package/dist/chunk-NIXT2SBH.js.map +1 -0
  414. package/dist/chunk-NJAII6CO.js +148 -0
  415. package/dist/chunk-NJAII6CO.js.map +1 -0
  416. package/dist/chunk-NKE4TL43.js +92 -0
  417. package/dist/chunk-NKE4TL43.js.map +1 -0
  418. package/dist/chunk-NZ7AXA7B.js +1 -0
  419. package/dist/chunk-NZ7AXA7B.js.map +1 -0
  420. package/dist/chunk-OCAYEGI2.js +26 -0
  421. package/dist/chunk-OCAYEGI2.js.map +1 -0
  422. package/dist/chunk-OMLI45ER.js +90 -0
  423. package/dist/chunk-OMLI45ER.js.map +1 -0
  424. package/dist/chunk-P7OBLJAG.js +88 -0
  425. package/dist/chunk-P7OBLJAG.js.map +1 -0
  426. package/dist/chunk-PAY3CBWL.js +2321 -0
  427. package/dist/chunk-PAY3CBWL.js.map +1 -0
  428. package/dist/chunk-PFF6VY35.js +257 -0
  429. package/dist/chunk-PFF6VY35.js.map +1 -0
  430. package/dist/chunk-PYNDJDWZ.js +1758 -0
  431. package/dist/chunk-PYNDJDWZ.js.map +1 -0
  432. package/dist/chunk-QDQ6UMMN.js +53 -0
  433. package/dist/chunk-QDQ6UMMN.js.map +1 -0
  434. package/dist/chunk-QGT3G2XG.js +24 -0
  435. package/dist/chunk-QGT3G2XG.js.map +1 -0
  436. package/dist/chunk-QZYCJ2GZ.js +55 -0
  437. package/dist/chunk-QZYCJ2GZ.js.map +1 -0
  438. package/dist/chunk-REZ7RFSA.js +124 -0
  439. package/dist/chunk-REZ7RFSA.js.map +1 -0
  440. package/dist/chunk-RRYBAE6E.js +2449 -0
  441. package/dist/chunk-RRYBAE6E.js.map +1 -0
  442. package/dist/chunk-RWUZOB62.js +34 -0
  443. package/dist/chunk-RWUZOB62.js.map +1 -0
  444. package/dist/chunk-SB5UCPZH.js +116 -0
  445. package/dist/chunk-SB5UCPZH.js.map +1 -0
  446. package/dist/chunk-SEJJ7CRI.js +99 -0
  447. package/dist/chunk-SEJJ7CRI.js.map +1 -0
  448. package/dist/chunk-SHBFGRPV.js +45 -0
  449. package/dist/chunk-SHBFGRPV.js.map +1 -0
  450. package/dist/chunk-SOFJ4GC5.js +45 -0
  451. package/dist/chunk-SOFJ4GC5.js.map +1 -0
  452. package/dist/chunk-STH2HPZK.js +44 -0
  453. package/dist/chunk-STH2HPZK.js.map +1 -0
  454. package/dist/chunk-TK3JNKME.js +28 -0
  455. package/dist/chunk-TK3JNKME.js.map +1 -0
  456. package/dist/chunk-TMONHFE3.js +46 -0
  457. package/dist/chunk-TMONHFE3.js.map +1 -0
  458. package/dist/chunk-TR4KO3AG.js +44 -0
  459. package/dist/chunk-TR4KO3AG.js.map +1 -0
  460. package/dist/chunk-TS2LNBF2.js +68 -0
  461. package/dist/chunk-TS2LNBF2.js.map +1 -0
  462. package/dist/chunk-UZUMBFPP.js +26 -0
  463. package/dist/chunk-UZUMBFPP.js.map +1 -0
  464. package/dist/chunk-VRZ5LMOW.js +176 -0
  465. package/dist/chunk-VRZ5LMOW.js.map +1 -0
  466. package/dist/chunk-WLGGY6Z6.js +75 -0
  467. package/dist/chunk-WLGGY6Z6.js.map +1 -0
  468. package/dist/chunk-WO7V6ZNC.js +11 -0
  469. package/dist/chunk-WO7V6ZNC.js.map +1 -0
  470. package/dist/chunk-WXSENSRP.js +64 -0
  471. package/dist/chunk-WXSENSRP.js.map +1 -0
  472. package/dist/chunk-XEKBZ2SA.js +19 -0
  473. package/dist/chunk-XEKBZ2SA.js.map +1 -0
  474. package/dist/chunk-XPBKU3JX.js +61 -0
  475. package/dist/chunk-XPBKU3JX.js.map +1 -0
  476. package/dist/chunk-XRYXBXWH.js +24 -0
  477. package/dist/chunk-XRYXBXWH.js.map +1 -0
  478. package/dist/chunk-XVA7QRVH.js +22 -0
  479. package/dist/chunk-XVA7QRVH.js.map +1 -0
  480. package/dist/chunk-XYXDY72K.js +27508 -0
  481. package/dist/chunk-XYXDY72K.js.map +1 -0
  482. package/dist/chunk-YCTHHBSS.js +37 -0
  483. package/dist/chunk-YCTHHBSS.js.map +1 -0
  484. package/dist/chunk-YHPWD5NE.js +70 -0
  485. package/dist/chunk-YHPWD5NE.js.map +1 -0
  486. package/dist/chunk-YLNEKJQ5.js +126 -0
  487. package/dist/chunk-YLNEKJQ5.js.map +1 -0
  488. package/dist/chunk-YN4CEKCF.js +73 -0
  489. package/dist/chunk-YN4CEKCF.js.map +1 -0
  490. package/dist/chunk-YYNMESIF.js +17 -0
  491. package/dist/chunk-YYNMESIF.js.map +1 -0
  492. package/dist/chunk-Z6PRMCV6.js +1 -0
  493. package/dist/chunk-Z6PRMCV6.js.map +1 -0
  494. package/dist/chunk-ZDNW6VQG.js +11 -0
  495. package/dist/chunk-ZDNW6VQG.js.map +1 -0
  496. package/dist/chunk-ZP4D73DO.js +36 -0
  497. package/dist/chunk-ZP4D73DO.js.map +1 -0
  498. package/dist/chunk-ZUATADUV.js +26 -0
  499. package/dist/chunk-ZUATADUV.js.map +1 -0
  500. package/dist/{connections-1NtNQrsY.d.ts → connections-CEcurtWI.d.ts} +74 -9
  501. package/dist/core/index.cjs +14041 -6973
  502. package/dist/core/index.cjs.map +1 -1
  503. package/dist/core/index.d.ts +422 -138
  504. package/dist/core/index.js +425 -183
  505. package/dist/core/index.js.map +1 -1
  506. package/dist/flow-vnext/index.cjs +2842 -0
  507. package/dist/flow-vnext/index.cjs.map +1 -0
  508. package/dist/flow-vnext/index.d.ts +3 -0
  509. package/dist/flow-vnext/index.js +119 -0
  510. package/dist/flow-vnext/index.js.map +1 -0
  511. package/dist/{graphql-client-Bn0tN049.d.ts → graphql-client-B2tREsx6.d.ts} +3 -1
  512. package/dist/index-b9xxXGFs.d.ts +1230 -0
  513. package/dist/index.d.ts +5 -3
  514. package/dist/index.js +202 -37
  515. package/dist/index.js.map +1 -1
  516. package/dist/legacy-BpgIqaQ5.d.ts +14 -0
  517. package/dist/mantine/index.d.ts +7 -4
  518. package/dist/mantine/index.js +84 -30
  519. package/dist/mantine/index.js.map +1 -1
  520. package/dist/{runtime-BFwvCQDF.d.ts → types-Dqk5MTfW.d.ts} +6096 -5386
  521. package/package.json +12 -2
  522. package/dist/chunk-A4CWC4AG.js +0 -374
  523. package/dist/chunk-A4CWC4AG.js.map +0 -1
  524. package/dist/chunk-NEOPTPDF.js.map +0 -1
  525. package/dist/chunk-VRCRDKN5.js +0 -59694
  526. package/dist/chunk-VRCRDKN5.js.map +0 -1
@@ -0,0 +1,2449 @@
1
+ import {
2
+ verifyActionManifestV2
3
+ } from "./chunk-N3ORMGAI.js";
4
+ import {
5
+ isYMapLike
6
+ } from "./chunk-NCSGIRRQ.js";
7
+
8
+ // src/core/lib/flowEngine/vnext/legacy.ts
9
+ var LegacyFlowFrozenError = class extends Error {
10
+ constructor(operation) {
11
+ super(`Legacy Flow operation ${operation} is frozen; explicitly republish authored meaning as a new vNext revision`);
12
+ this.operation = operation;
13
+ this.name = "LegacyFlowFrozenError";
14
+ }
15
+ };
16
+ function assertLegacyFlowOperationAllowed(gate, operation) {
17
+ if (gate?.legacyMode === "read_only") throw new LegacyFlowFrozenError(operation);
18
+ }
19
+
20
+ // src/core/lib/flowEngine/vnext/canonical.ts
21
+ function deepFreezeJson(value) {
22
+ if (!value || typeof value !== "object") return value;
23
+ for (const nested of Object.values(value)) deepFreezeJson(nested);
24
+ return Object.freeze(value);
25
+ }
26
+ function isPlainObject(value) {
27
+ const prototype = Object.getPrototypeOf(value);
28
+ return prototype === Object.prototype || prototype === null;
29
+ }
30
+ function assertValidUnicode(value) {
31
+ for (let index = 0; index < value.length; index += 1) {
32
+ const codeUnit = value.charCodeAt(index);
33
+ if (codeUnit >= 55296 && codeUnit <= 56319) {
34
+ const next = value.charCodeAt(index + 1);
35
+ if (!(next >= 56320 && next <= 57343)) {
36
+ throw new TypeError("Canonical JSON contains an unpaired Unicode surrogate");
37
+ }
38
+ index += 1;
39
+ } else if (codeUnit >= 56320 && codeUnit <= 57343) {
40
+ throw new TypeError("Canonical JSON contains an unpaired Unicode surrogate");
41
+ }
42
+ }
43
+ }
44
+ function canonicalizeJson(value) {
45
+ const ancestors = /* @__PURE__ */ new Set();
46
+ const serialize = (candidate) => {
47
+ if (candidate === null || typeof candidate === "boolean") return JSON.stringify(candidate);
48
+ if (typeof candidate === "string") {
49
+ assertValidUnicode(candidate);
50
+ return JSON.stringify(candidate);
51
+ }
52
+ if (typeof candidate === "number") {
53
+ if (!Number.isFinite(candidate)) throw new TypeError("Canonical JSON numbers must be finite");
54
+ return JSON.stringify(candidate);
55
+ }
56
+ if (typeof candidate !== "object") {
57
+ throw new TypeError(`Canonical JSON contains a non-JSON value: ${typeof candidate}`);
58
+ }
59
+ if (ancestors.has(candidate)) throw new TypeError("Canonical JSON contains a circular reference");
60
+ ancestors.add(candidate);
61
+ try {
62
+ if (Array.isArray(candidate)) return `[${candidate.map((entry) => serialize(entry)).join(",")}]`;
63
+ if (!isPlainObject(candidate)) throw new TypeError("Canonical JSON contains a non-plain object");
64
+ return `{${Object.keys(candidate).sort().map((key) => {
65
+ assertValidUnicode(key);
66
+ return `${JSON.stringify(key)}:${serialize(candidate[key])}`;
67
+ }).join(",")}}`;
68
+ } finally {
69
+ ancestors.delete(candidate);
70
+ }
71
+ };
72
+ return serialize(value);
73
+ }
74
+ async function digestCanonicalJson(value) {
75
+ if (!globalThis.crypto?.subtle) throw new Error("Web Crypto is required to digest a Flow contract");
76
+ const bytes = new TextEncoder().encode(canonicalizeJson(value));
77
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
78
+ const hex = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
79
+ return `sha256:${hex}`;
80
+ }
81
+
82
+ // src/core/lib/flowEngine/vnext/contracts.ts
83
+ var FlowDefinitionVerificationError = class extends Error {
84
+ constructor(code, message) {
85
+ super(message);
86
+ this.code = code;
87
+ this.name = "FlowDefinitionVerificationError";
88
+ }
89
+ };
90
+ var DEFINITION_SIGNATURE_DOMAIN = "qi.flow.definition.v1\0";
91
+ var EXECUTION_POLICY_SIGNATURE_DOMAIN = "qi.flow.execution-policy.v1\0";
92
+ function asCanonical(value) {
93
+ return value;
94
+ }
95
+ function signatureInput(digest) {
96
+ return new TextEncoder().encode(`${DEFINITION_SIGNATURE_DOMAIN}${digest}`);
97
+ }
98
+ function policySignatureInput(digest) {
99
+ return new TextEncoder().encode(`${EXECUTION_POLICY_SIGNATURE_DOMAIN}${digest}`);
100
+ }
101
+ function assertExecutionPolicyPayload(payload) {
102
+ if (payload.kind !== "qi.flow.execution-policy" || payload.schemaVersion !== "1.0") throw new Error("Unsupported Flow execution policy");
103
+ if (payload.mode !== "enabled" && payload.mode !== "pause_new_effects") throw new Error("Unsupported Flow execution policy mode");
104
+ if (!payload.definition.digest || !payload.issuedBy || !payload.issuedAt) throw new Error("Execution policy identity, issuer, and timestamp are required");
105
+ if (payload.expiresAt && Date.parse(payload.expiresAt) <= Date.parse(payload.issuedAt)) throw new Error("Execution policy expiry must be after issuance");
106
+ }
107
+ async function computeExecutionPolicyDigest(payload) {
108
+ assertExecutionPolicyPayload(payload);
109
+ return await digestCanonicalJson(asCanonical(payload));
110
+ }
111
+ async function signExecutionPolicy(payload, signer) {
112
+ const snapshot = JSON.parse(canonicalizeJson(asCanonical(payload)));
113
+ assertExecutionPolicyPayload(snapshot);
114
+ if (signer.issuerDid !== snapshot.issuedBy || !signer.verificationMethod.startsWith(`${snapshot.issuedBy}#`)) {
115
+ throw new Error("Execution policy signer does not match the issuer");
116
+ }
117
+ const digest = await computeExecutionPolicyDigest(snapshot);
118
+ const signature = await signer.sign(policySignatureInput(digest));
119
+ if (!signature) throw new Error("Execution policy signer returned an empty signature");
120
+ return {
121
+ ...snapshot,
122
+ integrity: {
123
+ canonicalization: "RFC8785",
124
+ digest: { algorithm: "SHA-256", value: digest },
125
+ signature: { algorithm: signer.algorithm, verificationMethod: signer.verificationMethod, value: signature }
126
+ }
127
+ };
128
+ }
129
+ async function verifyExecutionPolicy(candidate, policy, now = /* @__PURE__ */ new Date()) {
130
+ const snapshot = JSON.parse(canonicalizeJson(asCanonical(candidate)));
131
+ const { integrity, ...payload } = snapshot;
132
+ assertExecutionPolicyPayload(payload);
133
+ const digest = await computeExecutionPolicyDigest(payload);
134
+ if (digest !== integrity.digest.value) throw new Error("Execution policy digest does not match its content");
135
+ if (!policy.trustedIssuerDids.includes(payload.issuedBy)) throw new Error(`Execution policy issuer is not trusted: ${payload.issuedBy}`);
136
+ if (policy.revokedIssuerDids?.includes(payload.issuedBy)) throw new Error(`Execution policy issuer is revoked: ${payload.issuedBy}`);
137
+ if (!policy.allowedSignatureAlgorithms.includes(integrity.signature.algorithm))
138
+ throw new Error(`Execution policy signature algorithm is not allowed: ${integrity.signature.algorithm}`);
139
+ if (!integrity.signature.verificationMethod.startsWith(`${payload.issuedBy}#`)) throw new Error("Execution policy verification method does not belong to the issuer");
140
+ if (payload.expiresAt && Date.parse(payload.expiresAt) <= now.getTime()) throw new Error("Execution policy is expired");
141
+ const valid = await policy.verifySignature({
142
+ issuerDid: payload.issuedBy,
143
+ verificationMethod: integrity.signature.verificationMethod,
144
+ algorithm: integrity.signature.algorithm,
145
+ data: policySignatureInput(digest),
146
+ signature: integrity.signature.value
147
+ });
148
+ if (!valid) throw new Error("Execution policy signature verification failed");
149
+ return deepFreezeJson(snapshot);
150
+ }
151
+ function assertDefinitionPayload(payload) {
152
+ if (payload.kind !== "qi.flow.definition-revision" || payload.schemaVersion !== "1.0") {
153
+ throw new FlowDefinitionVerificationError("INVALID_DEFINITION", "Unsupported Flow definition contract");
154
+ }
155
+ if (!payload.ref.flowId || !payload.ref.revision || !payload.publishedBy || payload.steps.length === 0) {
156
+ throw new FlowDefinitionVerificationError("INVALID_DEFINITION", "Flow definition identity, publisher, and steps are required");
157
+ }
158
+ const stepIds = /* @__PURE__ */ new Set();
159
+ for (const step of payload.steps) {
160
+ if (!step.stepId || !step.blockId || !step.action.contractDigest || !step.action.manifestDigest) {
161
+ throw new FlowDefinitionVerificationError("INVALID_DEFINITION", "Every Flow step must pin its identity and Action contract");
162
+ }
163
+ if (step.action.manifestDigest !== payload.actionManifestDigest) {
164
+ throw new FlowDefinitionVerificationError("INVALID_DEFINITION", `Flow step ${step.stepId} does not use the revision Action manifest`);
165
+ }
166
+ if (stepIds.has(step.stepId)) throw new FlowDefinitionVerificationError("INVALID_DEFINITION", `Duplicate Flow step id: ${step.stepId}`);
167
+ if (step.trigger.kind === "schedule") {
168
+ if (!step.trigger.scheduleRef || step.trigger.scheduleRevision !== void 0 && (!Number.isInteger(step.trigger.scheduleRevision) || step.trigger.scheduleRevision < 1)) {
169
+ throw new FlowDefinitionVerificationError("INVALID_DEFINITION", `Flow step ${step.stepId} has an invalid schedule binding`);
170
+ }
171
+ }
172
+ if (step.trigger.kind === "topic.request" && !step.trigger.requestKind.trim()) {
173
+ throw new FlowDefinitionVerificationError("INVALID_DEFINITION", `Flow step ${step.stepId} has an invalid Topic request kind`);
174
+ }
175
+ if (step.ttlMs !== void 0 && (!Number.isFinite(step.ttlMs) || step.ttlMs < 0)) {
176
+ throw new FlowDefinitionVerificationError("INVALID_DEFINITION", `Flow step ${step.stepId} has an invalid ttlMs`);
177
+ }
178
+ if (step.ttl?.absoluteDueDate && !Number.isFinite(Date.parse(step.ttl.absoluteDueDate))) {
179
+ throw new FlowDefinitionVerificationError("INVALID_DEFINITION", `Flow step ${step.stepId} has an invalid absolute TTL`);
180
+ }
181
+ for (const duration of [step.ttl?.fromEnablement, step.ttl?.fromCommitment]) {
182
+ const match = duration ? /^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?)?$/u.exec(duration) : void 0;
183
+ if (duration && (!match || !match.slice(1).some((part) => Number(part ?? 0) > 0))) {
184
+ throw new FlowDefinitionVerificationError("INVALID_DEFINITION", `Flow step ${step.stepId} has an invalid relative TTL`);
185
+ }
186
+ }
187
+ stepIds.add(step.stepId);
188
+ }
189
+ }
190
+ async function computeFlowDefinitionDigest(payload) {
191
+ assertDefinitionPayload(payload);
192
+ return await digestCanonicalJson(asCanonical(payload));
193
+ }
194
+ async function signFlowDefinitionRevision(payload, signer) {
195
+ const snapshot = JSON.parse(canonicalizeJson(asCanonical(payload)));
196
+ assertDefinitionPayload(snapshot);
197
+ if (signer.issuerDid !== snapshot.publishedBy || !signer.verificationMethod.startsWith(`${snapshot.publishedBy}#`)) {
198
+ throw new FlowDefinitionVerificationError("SIGNER_MISMATCH", "Flow definition signer does not match the publisher");
199
+ }
200
+ const digest = await computeFlowDefinitionDigest(snapshot);
201
+ const signature = await signer.sign(signatureInput(digest));
202
+ if (!signature) throw new FlowDefinitionVerificationError("INVALID_SIGNATURE", "Flow definition signer returned an empty signature");
203
+ return {
204
+ ...snapshot,
205
+ integrity: {
206
+ canonicalization: "RFC8785",
207
+ digest: { algorithm: "SHA-256", value: digest },
208
+ signature: { algorithm: signer.algorithm, verificationMethod: signer.verificationMethod, value: signature }
209
+ }
210
+ };
211
+ }
212
+ async function verifyFlowDefinitionRevision(candidate, policy) {
213
+ const snapshot = JSON.parse(canonicalizeJson(asCanonical(candidate)));
214
+ const { integrity, ...payload } = snapshot;
215
+ assertDefinitionPayload(payload);
216
+ const digest = await computeFlowDefinitionDigest(payload);
217
+ if (digest !== integrity.digest.value) throw new FlowDefinitionVerificationError("DIGEST_MISMATCH", "Flow definition digest does not match its content");
218
+ if (!policy.trustedIssuerDids.includes(payload.publishedBy)) {
219
+ throw new FlowDefinitionVerificationError("UNTRUSTED_ISSUER", `Flow definition issuer is not trusted: ${payload.publishedBy}`);
220
+ }
221
+ if (policy.revokedIssuerDids?.includes(payload.publishedBy)) {
222
+ throw new FlowDefinitionVerificationError("REVOKED_ISSUER", `Flow definition issuer is revoked: ${payload.publishedBy}`);
223
+ }
224
+ if (!policy.allowedSignatureAlgorithms.includes(integrity.signature.algorithm)) {
225
+ throw new FlowDefinitionVerificationError("DISALLOWED_SIGNATURE_ALGORITHM", `Flow definition signature algorithm is not allowed: ${integrity.signature.algorithm}`);
226
+ }
227
+ if (!integrity.signature.verificationMethod.startsWith(`${payload.publishedBy}#`)) {
228
+ throw new FlowDefinitionVerificationError("SIGNER_MISMATCH", "Flow definition verification method does not belong to the publisher");
229
+ }
230
+ const verified = await policy.verifySignature({
231
+ issuerDid: payload.publishedBy,
232
+ verificationMethod: integrity.signature.verificationMethod,
233
+ algorithm: integrity.signature.algorithm,
234
+ data: signatureInput(digest),
235
+ signature: integrity.signature.value
236
+ });
237
+ if (!verified) throw new FlowDefinitionVerificationError("INVALID_SIGNATURE", "Flow definition signature verification failed");
238
+ return deepFreezeJson(snapshot);
239
+ }
240
+ var FLOW_CAPABILITIES = {
241
+ definitionRead: "flow/definition.read",
242
+ definitionWrite: "flow/definition.write",
243
+ definitionPublish: "flow/definition.publish",
244
+ definitionClone: "flow/definition.clone",
245
+ runStart: "flow/run.start",
246
+ runClose: "flow/run.close",
247
+ runCancel: "flow/run.cancel",
248
+ actionExecute: "flow/action.execute",
249
+ topicBindFlow: "topic/bind-flow",
250
+ topicRequestAction: "topic/request-action",
251
+ topicRecordAction: "topic/record-action"
252
+ };
253
+ function segment(value) {
254
+ return encodeURIComponent(value);
255
+ }
256
+ function buildFlowResourceUri(definition, target) {
257
+ const root = `ixo:flow:${segment(definition.flowId)}@${segment(definition.revision)}`;
258
+ if (!target) return root;
259
+ if (target.kind === "run") return `${root}/runs/${segment(target.runId)}`;
260
+ const run = target.runId ? `/runs/${segment(target.runId)}` : "";
261
+ return `${root}${run}/steps/${segment(target.stepId)}`;
262
+ }
263
+
264
+ // src/core/lib/flowEngine/vnext/ids.ts
265
+ async function deriveId(namespace, parts) {
266
+ const digest = await digestCanonicalJson({ namespace, parts });
267
+ return `${namespace}:${digest.slice("sha256:".length)}`;
268
+ }
269
+ function deriveRunId(definition, launchKind, launchNonce) {
270
+ return deriveId("run", [definition.digest, launchKind, launchNonce]);
271
+ }
272
+ function deriveAttemptId(params) {
273
+ return deriveId("attempt", [params.runId, params.stepId, params.idempotencyKey, params.inputDigest]);
274
+ }
275
+ function deriveEventId(unsignedEvent) {
276
+ return deriveId("event", unsignedEvent);
277
+ }
278
+ function deriveReceiptId(params) {
279
+ return deriveId("receipt", [params.topicRequestId, params.attemptId, params.phase, params.eventId]);
280
+ }
281
+ function deriveEffectClaimKey(params) {
282
+ return digestCanonicalJson([
283
+ params.definition.digest,
284
+ params.runId,
285
+ params.stepId,
286
+ params.attemptId,
287
+ params.actorDid,
288
+ params.inputDigest,
289
+ params.action.contractDigest,
290
+ params.topicBindingId ?? null
291
+ ]);
292
+ }
293
+
294
+ // src/core/lib/flowEngine/vnext/events.ts
295
+ var EVENT_SIGNATURE_DOMAIN = "qi.flow.event.v1\0";
296
+ var FlowEventValidationError = class extends Error {
297
+ constructor(message) {
298
+ super(message);
299
+ this.name = "FlowEventValidationError";
300
+ }
301
+ };
302
+ function signatureInput2(eventId) {
303
+ return new TextEncoder().encode(`${EVENT_SIGNATURE_DOMAIN}${eventId}`);
304
+ }
305
+ function flowEventSnapshot(value) {
306
+ let snapshot;
307
+ try {
308
+ snapshot = JSON.parse(canonicalizeJson(value));
309
+ } catch {
310
+ throw new FlowEventValidationError("Flow event content cannot be canonicalized");
311
+ }
312
+ if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot)) throw new FlowEventValidationError("Flow event envelope is malformed");
313
+ return snapshot;
314
+ }
315
+ function isRecord(value) {
316
+ return value !== null && typeof value === "object" && !Array.isArray(value);
317
+ }
318
+ function isStringArray(value) {
319
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string");
320
+ }
321
+ function hasDefinitionRefShape(value) {
322
+ return isRecord(value) && typeof value.flowId === "string" && typeof value.revision === "string" && typeof value.digest === "string";
323
+ }
324
+ function hasAttemptShape(payload) {
325
+ return typeof payload.attemptId === "string" && typeof payload.stepId === "string";
326
+ }
327
+ function assertVerifiedEnvelopeShape(snapshot) {
328
+ if (snapshot.kind !== "qi.flow.event" || snapshot.schemaVersion !== "1.0" || typeof snapshot.eventId !== "string" || typeof snapshot.runId !== "string" || !hasDefinitionRefShape(snapshot.definition) || typeof snapshot.producer !== "string" || typeof snapshot.actor !== "string" || typeof snapshot.occurredAt !== "string" || !isStringArray(snapshot.parents) || snapshot.causationId !== void 0 && typeof snapshot.causationId !== "string" || typeof snapshot.correlationId !== "string" || typeof snapshot.idempotencyKey !== "string" || typeof snapshot.commandFingerprint !== "string" || !isStringArray(snapshot.proofReferences) || !isRecord(snapshot.signature) || typeof snapshot.signature.algorithm !== "string" || typeof snapshot.signature.verificationMethod !== "string" || typeof snapshot.signature.value !== "string" || !isRecord(snapshot.payload) || typeof snapshot.payload.kind !== "string") {
329
+ throw new FlowEventValidationError("Flow event envelope is malformed");
330
+ }
331
+ const payload = snapshot.payload;
332
+ switch (payload.kind) {
333
+ case "run.started": {
334
+ const genesis = payload.genesis;
335
+ if (!isRecord(genesis) || genesis.kind !== "qi.flow.run-genesis" || genesis.schemaVersion !== "1.0" || typeof genesis.runId !== "string" || !hasDefinitionRefShape(genesis.definition) || !["manual", "topic.request", "schedule", "event"].includes(String(genesis.launchKind)) || typeof genesis.launchNonce !== "string" || !isStringArray(genesis.requiredStepIds) || typeof genesis.startedBy !== "string" || typeof genesis.startedAt !== "string" || genesis.topicBindingId !== void 0 && typeof genesis.topicBindingId !== "string") {
336
+ throw new FlowEventValidationError("Flow run genesis is malformed");
337
+ }
338
+ break;
339
+ }
340
+ case "run.cancel_requested":
341
+ if (payload.reason !== void 0 && typeof payload.reason !== "string") throw new FlowEventValidationError("Flow cancellation reason is malformed");
342
+ break;
343
+ case "action.requested":
344
+ if (!hasAttemptShape(payload) || typeof payload.inputDigest !== "string") throw new FlowEventValidationError("Flow Action request is malformed");
345
+ break;
346
+ case "action.approval_proposed":
347
+ if (!hasAttemptShape(payload) || typeof payload.proposalDigest !== "string") throw new FlowEventValidationError("Flow Action approval proposal is malformed");
348
+ break;
349
+ case "action.started":
350
+ if (!hasAttemptShape(payload)) throw new FlowEventValidationError("Flow Action start is malformed");
351
+ break;
352
+ case "action.effect_armed":
353
+ if (!hasAttemptShape(payload) || typeof payload.claimKey !== "string" || !Number.isSafeInteger(payload.fencingEpoch) || Number(payload.fencingEpoch) < 1) {
354
+ throw new FlowEventValidationError("Flow Action fence is malformed");
355
+ }
356
+ break;
357
+ case "action.succeeded":
358
+ if (!hasAttemptShape(payload) || typeof payload.outputDigest !== "string" || payload.providerCorrelation !== void 0 && typeof payload.providerCorrelation !== "string" || payload.claimKey !== void 0 && typeof payload.claimKey !== "string" || payload.fencingEpoch !== void 0 && (!Number.isSafeInteger(payload.fencingEpoch) || Number(payload.fencingEpoch) < 1) || payload.outcomes !== void 0 && !Array.isArray(payload.outcomes)) {
359
+ throw new FlowEventValidationError("Flow Action success is malformed");
360
+ }
361
+ break;
362
+ case "action.outcome_emitted":
363
+ if (!hasAttemptShape(payload)) throw new FlowEventValidationError("Flow Action outcome is malformed");
364
+ break;
365
+ case "action.failed_before_effect":
366
+ if (!hasAttemptShape(payload) || !isRecord(payload.error)) throw new FlowEventValidationError("Flow Action failure is malformed");
367
+ break;
368
+ case "action.needs_verification":
369
+ if (!hasAttemptShape(payload) || typeof payload.reason !== "string" || payload.providerCorrelation !== void 0 && typeof payload.providerCorrelation !== "string") {
370
+ throw new FlowEventValidationError("Flow Action verification state is malformed");
371
+ }
372
+ break;
373
+ case "receipt.persisted":
374
+ if (typeof payload.attemptId !== "string" || typeof payload.receiptId !== "string" || typeof payload.receiptDigest !== "string") {
375
+ throw new FlowEventValidationError("Flow receipt evidence is malformed");
376
+ }
377
+ break;
378
+ case "run.finalized": {
379
+ const summary = payload.summary;
380
+ if (!["completed", "failed", "cancelled"].includes(String(payload.status)) || !isRecord(summary) || summary.kind !== "qi.flow.run-finalization-summary" || summary.schemaVersion !== "1.0" || summary.status !== payload.status || typeof summary.cancelRequested !== "boolean" || !isStringArray(summary.requiredStepIds) || !isStringArray(summary.frontierEventIds) || !Array.isArray(summary.attempts) || !summary.attempts.every(
381
+ (attempt) => isRecord(attempt) && typeof attempt.attemptId === "string" && typeof attempt.stepId === "string" && ["not_started", "armed", "succeeded", "failed_before_effect", "needs_verification"].includes(String(attempt.disposition)) && isStringArray(attempt.receiptIds)
382
+ ) || typeof payload.summaryDigest !== "string") {
383
+ throw new FlowEventValidationError("Flow run finalization is malformed");
384
+ }
385
+ break;
386
+ }
387
+ case "log":
388
+ if (!["debug", "info", "warn", "error"].includes(String(payload.level)) || typeof payload.message !== "string") {
389
+ throw new FlowEventValidationError("Flow log event is malformed");
390
+ }
391
+ break;
392
+ default:
393
+ throw new FlowEventValidationError(`Unsupported Flow event payload: ${String(payload.kind)}`);
394
+ }
395
+ }
396
+ async function signFlowEvent(unsigned, signer) {
397
+ const snapshot = flowEventSnapshot(unsigned);
398
+ const { eventId: _eventId, signature: _signature, ...unsignedSnapshot } = snapshot;
399
+ if (unsignedSnapshot.producer !== signer.producerDid || !signer.verificationMethod.startsWith(`${unsignedSnapshot.producer}#`)) {
400
+ throw new Error("Flow event signer does not match the producer");
401
+ }
402
+ const eventId = await deriveEventId(unsignedSnapshot);
403
+ const signature = await signer.sign(signatureInput2(eventId));
404
+ if (!signature) throw new Error("Flow event signer returned an empty signature");
405
+ return {
406
+ ...unsignedSnapshot,
407
+ eventId,
408
+ signature: { algorithm: signer.algorithm, verificationMethod: signer.verificationMethod, value: signature }
409
+ };
410
+ }
411
+ async function verifyFlowEvent(event, policy) {
412
+ const snapshot = flowEventSnapshot(event);
413
+ assertVerifiedEnvelopeShape(snapshot);
414
+ const { eventId, signature, ...unsigned } = snapshot;
415
+ const expectedId = await deriveEventId(unsigned);
416
+ if (expectedId !== eventId) throw new FlowEventValidationError("Flow event content does not match its event id");
417
+ const outcomes = snapshot.payload.kind === "action.succeeded" ? snapshot.payload.outcomes ?? [] : snapshot.payload.kind === "action.outcome_emitted" ? [snapshot.payload] : [];
418
+ const seenOutcomes = /* @__PURE__ */ new Set();
419
+ for (const outcome of outcomes) {
420
+ if (typeof outcome.name !== "string" || !outcome.name.trim()) throw new FlowEventValidationError("Flow event outcome name is required");
421
+ if (!outcome.payload || typeof outcome.payload !== "object" || Array.isArray(outcome.payload) || typeof outcome.payloadDigest !== "string") {
422
+ throw new FlowEventValidationError(`Flow event outcome payload is malformed: ${outcome.name}`);
423
+ }
424
+ const actualDigest = await digestCanonicalJson(outcome.payload);
425
+ if (actualDigest !== outcome.payloadDigest) throw new FlowEventValidationError(`Flow event outcome payload digest mismatch: ${outcome.name}`);
426
+ const identity = `${outcome.name}\0${outcome.payloadDigest}`;
427
+ if (seenOutcomes.has(identity)) throw new FlowEventValidationError(`Flow event contains a duplicate outcome: ${outcome.name}`);
428
+ seenOutcomes.add(identity);
429
+ }
430
+ if (snapshot.payload.kind === "run.finalized") {
431
+ if (!snapshot.payload.summary || typeof snapshot.payload.summary !== "object" || Array.isArray(snapshot.payload.summary)) {
432
+ throw new FlowEventValidationError("Flow run finalization summary is malformed");
433
+ }
434
+ const actualDigest = await digestCanonicalJson(snapshot.payload.summary);
435
+ if (actualDigest !== snapshot.payload.summaryDigest) throw new FlowEventValidationError("Flow run finalization summary digest mismatch");
436
+ }
437
+ if (!signature.verificationMethod.startsWith(`${snapshot.producer}#`)) throw new FlowEventValidationError("Flow event verification method does not belong to the producer");
438
+ if (!policy.allowedSignatureAlgorithms.includes(signature.algorithm)) {
439
+ throw new FlowEventValidationError(`Flow event signature algorithm is not allowed: ${signature.algorithm}`);
440
+ }
441
+ if (!await policy.isTrustedProducer(snapshot.producer, signature.verificationMethod)) {
442
+ throw new FlowEventValidationError(`Flow event producer is not trusted: ${snapshot.producer}`);
443
+ }
444
+ if (!await policy.verifySignature({
445
+ producerDid: snapshot.producer,
446
+ verificationMethod: signature.verificationMethod,
447
+ algorithm: signature.algorithm,
448
+ data: signatureInput2(eventId),
449
+ signature: signature.value
450
+ })) {
451
+ throw new FlowEventValidationError("Flow event signature verification failed");
452
+ }
453
+ return deepFreezeJson(snapshot);
454
+ }
455
+ function matrixFlowEventTransactionId(event) {
456
+ return `qi-flow-v1-${event.eventId}`;
457
+ }
458
+ function eventHasAncestor(event, ancestor, byId, seen = /* @__PURE__ */ new Set()) {
459
+ if (seen.has(event.eventId)) return false;
460
+ seen.add(event.eventId);
461
+ for (const parent of event.parents) {
462
+ if (parent === ancestor) return true;
463
+ const parentEvent = byId.get(parent);
464
+ if (parentEvent && eventHasAncestor(parentEvent, ancestor, byId, seen)) return true;
465
+ }
466
+ return false;
467
+ }
468
+ function causalOrder(events, byId) {
469
+ const indegree = new Map(events.map((event) => [event.eventId, 0]));
470
+ const children = /* @__PURE__ */ new Map();
471
+ for (const event of events) {
472
+ for (const parent of event.parents) {
473
+ if (!byId.has(parent)) continue;
474
+ indegree.set(event.eventId, (indegree.get(event.eventId) ?? 0) + 1);
475
+ children.set(parent, [...children.get(parent) ?? [], event.eventId]);
476
+ }
477
+ }
478
+ const ready = events.filter((event) => indegree.get(event.eventId) === 0).map((event) => event.eventId).sort();
479
+ const ordered = [];
480
+ while (ready.length > 0) {
481
+ const eventId = ready.shift();
482
+ const event = byId.get(eventId);
483
+ if (!event) continue;
484
+ ordered.push(event);
485
+ for (const childId of (children.get(eventId) ?? []).sort()) {
486
+ const next = (indegree.get(childId) ?? 0) - 1;
487
+ indegree.set(childId, next);
488
+ if (next === 0) {
489
+ ready.push(childId);
490
+ ready.sort();
491
+ }
492
+ }
493
+ }
494
+ const orderedIds = new Set(ordered.map((event) => event.eventId));
495
+ return { ordered, cyclic: new Set(events.filter((event) => !orderedIds.has(event.eventId)).map((event) => event.eventId)) };
496
+ }
497
+ function hasAcceptedAncestor(event, byId, accepted, predicate) {
498
+ const pending = [...event.parents];
499
+ const seen = /* @__PURE__ */ new Set();
500
+ while (pending.length > 0) {
501
+ const eventId = pending.pop();
502
+ if (seen.has(eventId)) continue;
503
+ seen.add(eventId);
504
+ const candidate = byId.get(eventId);
505
+ if (!candidate || !accepted.has(eventId)) continue;
506
+ if (predicate(candidate)) return true;
507
+ pending.push(...candidate.parents);
508
+ }
509
+ return false;
510
+ }
511
+ function attemptChainError(event, byId, accepted) {
512
+ const payload = event.payload;
513
+ if (!("attemptId" in payload) || payload.kind === "action.requested") return void 0;
514
+ if (payload.kind === "receipt.persisted") {
515
+ return hasAcceptedAncestor(event, byId, accepted, (candidate) => candidate.payload.kind === "action.succeeded" && candidate.payload.attemptId === payload.attemptId) ? void 0 : "missing_success_ancestor";
516
+ }
517
+ if (!("stepId" in payload)) return void 0;
518
+ const sameAttemptAndStep = (candidate) => {
519
+ const candidatePayload = candidate.payload;
520
+ return "attemptId" in candidatePayload && "stepId" in candidatePayload && candidatePayload.attemptId === payload.attemptId && candidatePayload.stepId === payload.stepId;
521
+ };
522
+ if (payload.kind === "action.outcome_emitted") {
523
+ return hasAcceptedAncestor(event, byId, accepted, (candidate) => {
524
+ if (!sameAttemptAndStep(candidate) || candidate.payload.kind !== "action.succeeded") return false;
525
+ return (candidate.payload.outcomes ?? []).some(
526
+ (outcome) => outcome.name === payload.name && outcome.payloadDigest === payload.payloadDigest && canonicalizeJson(outcome.payload) === canonicalizeJson(payload.payload)
527
+ );
528
+ }) ? void 0 : "missing_declaring_success_ancestor";
529
+ }
530
+ if (payload.kind === "action.started" || payload.kind === "action.effect_armed" || payload.kind === "action.approval_proposed") {
531
+ return hasAcceptedAncestor(event, byId, accepted, (candidate) => sameAttemptAndStep(candidate) && candidate.payload.kind === "action.requested") ? void 0 : "missing_request_ancestor";
532
+ }
533
+ if (payload.kind === "action.failed_before_effect") {
534
+ return hasAcceptedAncestor(event, byId, accepted, (candidate) => sameAttemptAndStep(candidate) && candidate.payload.kind === "action.started") ? void 0 : "missing_started_ancestor";
535
+ }
536
+ if (payload.kind === "action.succeeded") {
537
+ const hasStarted = hasAcceptedAncestor(event, byId, accepted, (candidate) => sameAttemptAndStep(candidate) && candidate.payload.kind === "action.started");
538
+ const hasArmed = hasAcceptedAncestor(event, byId, accepted, (candidate) => sameAttemptAndStep(candidate) && candidate.payload.kind === "action.effect_armed");
539
+ const hasClaimKey = payload.claimKey !== void 0;
540
+ const hasFencingEpoch = payload.fencingEpoch !== void 0;
541
+ if (hasClaimKey !== hasFencingEpoch) return "incomplete_fence_evidence";
542
+ if (hasClaimKey && hasFencingEpoch) {
543
+ return hasAcceptedAncestor(
544
+ event,
545
+ byId,
546
+ accepted,
547
+ (candidate) => sameAttemptAndStep(candidate) && candidate.payload.kind === "action.effect_armed" && candidate.payload.claimKey === payload.claimKey && candidate.payload.fencingEpoch === payload.fencingEpoch
548
+ ) ? void 0 : "missing_matching_fence_ancestor";
549
+ }
550
+ if (hasArmed && !hasStarted) return "missing_fence_evidence";
551
+ return hasStarted ? void 0 : "missing_execution_ancestor";
552
+ }
553
+ if (payload.kind === "action.needs_verification") {
554
+ return hasAcceptedAncestor(
555
+ event,
556
+ byId,
557
+ accepted,
558
+ (candidate) => sameAttemptAndStep(candidate) && (candidate.payload.kind === "action.started" || candidate.payload.kind === "action.effect_armed")
559
+ ) ? void 0 : "missing_execution_ancestor";
560
+ }
561
+ return void 0;
562
+ }
563
+ var DISPOSITION_RANK = {
564
+ not_started: 0,
565
+ armed: 1,
566
+ failed_before_effect: 2,
567
+ needs_verification: 3,
568
+ succeeded: 4
569
+ };
570
+ function compareCodeUnits(left, right) {
571
+ return left < right ? -1 : left > right ? 1 : 0;
572
+ }
573
+ function sortedUnique(values) {
574
+ return [...new Set(values)].sort(compareCodeUnits);
575
+ }
576
+ function sameStringSet(left, right) {
577
+ return canonicalizeJson(sortedUnique(left)) === canonicalizeJson(sortedUnique(right));
578
+ }
579
+ function acceptedFrontier(events, accepted) {
580
+ const acceptedEvents = events.filter((event) => accepted.has(event.eventId));
581
+ const referencedParents = new Set(acceptedEvents.flatMap((event) => event.parents.filter((parent) => accepted.has(parent))));
582
+ return acceptedEvents.map((event) => event.eventId).filter((eventId) => !referencedParents.has(eventId)).sort(compareCodeUnits);
583
+ }
584
+ function reduceFlowEvents(genesis, input) {
585
+ const unique = /* @__PURE__ */ new Map();
586
+ for (const event of input) if (!unique.has(event.eventId)) unique.set(event.eventId, event);
587
+ const events = [...unique.values()];
588
+ const canonicalDefinition = canonicalizeJson(genesis.definition);
589
+ const belongsToRun = (event) => event.runId === genesis.runId && canonicalizeJson(event.definition) === canonicalDefinition;
590
+ const runEvents = events.filter(belongsToRun);
591
+ const byId = new Map(events.map((event) => [event.eventId, event]));
592
+ const { ordered, cyclic } = causalOrder(events, byId);
593
+ const commandFingerprints = /* @__PURE__ */ new Map();
594
+ const attemptSteps = /* @__PURE__ */ new Map();
595
+ const runGenesisValues = new Set(
596
+ runEvents.filter((event) => event.payload.kind === "run.started").map((event) => event.payload.kind === "run.started" ? canonicalizeJson(event.payload.genesis) : "")
597
+ );
598
+ const canonicalGenesis = canonicalizeJson(genesis);
599
+ for (const event of runEvents) {
600
+ const fingerprints = commandFingerprints.get(event.idempotencyKey) ?? /* @__PURE__ */ new Set();
601
+ fingerprints.add(event.commandFingerprint);
602
+ commandFingerprints.set(event.idempotencyKey, fingerprints);
603
+ if ("attemptId" in event.payload && "stepId" in event.payload) {
604
+ const steps = attemptSteps.get(event.payload.attemptId) ?? /* @__PURE__ */ new Set();
605
+ steps.add(event.payload.stepId);
606
+ attemptSteps.set(event.payload.attemptId, steps);
607
+ }
608
+ }
609
+ const attempts = /* @__PURE__ */ new Map();
610
+ const accepted = [];
611
+ const acceptedSet = /* @__PURE__ */ new Set();
612
+ const invalid = [];
613
+ const invalidReasons = /* @__PURE__ */ new Map();
614
+ const cancelEvents = [];
615
+ const finalizationEvents = [];
616
+ const cycleEvents = events.filter((event) => cyclic.has(event.eventId)).sort((left, right) => compareCodeUnits(left.eventId, right.eventId));
617
+ for (const event of [...ordered, ...cycleEvents]) {
618
+ let reason;
619
+ if (!belongsToRun(event)) reason = "run_or_definition_mismatch";
620
+ if (!reason && event.payload.kind === "run.started" && runGenesisValues.size > 1) reason = "run_genesis_conflict";
621
+ if (!reason && event.payload.kind === "run.started" && canonicalizeJson(event.payload.genesis) !== canonicalGenesis) {
622
+ reason = "run_genesis_mismatch";
623
+ }
624
+ if (!reason && (commandFingerprints.get(event.idempotencyKey)?.size ?? 0) > 1) reason = "idempotency_fingerprint_conflict";
625
+ if (!reason && event.parents.some((parent) => !byId.has(parent))) reason = "missing_parent";
626
+ if (!reason && cyclic.has(event.eventId)) reason = "causal_cycle";
627
+ if (!reason && "attemptId" in event.payload && (attemptSteps.get(event.payload.attemptId)?.size ?? 0) > 1) reason = "attempt_step_conflict";
628
+ if (!reason && event.parents.some((parent) => invalidReasons.has(parent))) reason = "invalid_parent";
629
+ if (!reason) reason = attemptChainError(event, byId, acceptedSet);
630
+ if (!reason && event.payload.kind !== "log" && hasAcceptedAncestor(event, byId, acceptedSet, (candidate) => candidate.payload.kind === "run.finalized")) {
631
+ reason = "event_descends_from_finalization";
632
+ }
633
+ if (!reason && event.payload.kind === "action.requested") {
634
+ const causallyCancelled = cancelEvents.some((cancel) => eventHasAncestor(event, cancel.eventId, byId));
635
+ if (causallyCancelled) reason = "action_descends_from_cancellation";
636
+ }
637
+ if (reason) {
638
+ invalid.push({ eventId: event.eventId, reason });
639
+ invalidReasons.set(event.eventId, reason);
640
+ continue;
641
+ }
642
+ accepted.push(event.eventId);
643
+ acceptedSet.add(event.eventId);
644
+ const payload = event.payload;
645
+ if (payload.kind === "run.cancel_requested") cancelEvents.push(event);
646
+ if (payload.kind === "run.finalized") finalizationEvents.push(event);
647
+ if (!("attemptId" in payload)) continue;
648
+ const current = attempts.get(payload.attemptId) ?? {
649
+ attemptId: payload.attemptId,
650
+ stepId: "stepId" in payload ? payload.stepId : "",
651
+ disposition: "not_started",
652
+ receiptIds: [],
653
+ outcomes: []
654
+ };
655
+ let next = current;
656
+ if (payload.kind === "action.effect_armed" && DISPOSITION_RANK[current.disposition] < DISPOSITION_RANK.armed) {
657
+ next = { ...current, stepId: payload.stepId, disposition: "armed" };
658
+ }
659
+ if (payload.kind === "action.succeeded") {
660
+ next = { ...current, stepId: payload.stepId, disposition: "succeeded", outputDigest: payload.outputDigest, providerCorrelation: payload.providerCorrelation };
661
+ }
662
+ if (payload.kind === "action.failed_before_effect" && DISPOSITION_RANK[current.disposition] < DISPOSITION_RANK.failed_before_effect) {
663
+ next = { ...current, stepId: payload.stepId, disposition: "failed_before_effect" };
664
+ }
665
+ if (payload.kind === "action.needs_verification" && DISPOSITION_RANK[current.disposition] < DISPOSITION_RANK.needs_verification) {
666
+ next = { ...current, stepId: payload.stepId, disposition: "needs_verification", providerCorrelation: payload.providerCorrelation };
667
+ }
668
+ if (payload.kind === "receipt.persisted") {
669
+ next = { ...current, receiptIds: [.../* @__PURE__ */ new Set([...current.receiptIds, payload.receiptId])].sort() };
670
+ }
671
+ if (payload.kind === "action.outcome_emitted") {
672
+ const outcomes = [...current.outcomes, { name: payload.name, payload: payload.payload, payloadDigest: payload.payloadDigest }];
673
+ next = {
674
+ ...current,
675
+ outcomes: outcomes.filter((outcome, index) => outcomes.findIndex((candidate) => candidate.name === outcome.name && candidate.payloadDigest === outcome.payloadDigest) === index).sort((left, right) => compareCodeUnits(left.name, right.name) || compareCodeUnits(left.payloadDigest, right.payloadDigest))
676
+ };
677
+ }
678
+ attempts.set(payload.attemptId, next);
679
+ }
680
+ const values = [...attempts.values()];
681
+ const unresolved = values.some((attempt) => attempt.disposition === "armed" || attempt.disposition === "needs_verification");
682
+ const completedSteps = new Set(values.filter((attempt) => attempt.disposition === "succeeded").map((attempt) => attempt.stepId));
683
+ const completed = genesis.requiredStepIds.every((stepId) => completedSteps.has(stepId));
684
+ const failed = values.some((attempt) => attempt.disposition === "failed_before_effect");
685
+ const cancelRequested = cancelEvents.length > 0;
686
+ const active = values.some((attempt) => attempt.disposition === "not_started" || attempt.disposition === "armed");
687
+ const acceptedStateEvents = new Set(
688
+ accepted.filter((eventId) => {
689
+ const kind = byId.get(eventId)?.payload.kind;
690
+ return kind !== "run.finalized" && kind !== "log";
691
+ })
692
+ );
693
+ const frontierEventIds = acceptedFrontier(events, acceptedStateEvents);
694
+ const hasAcceptedStart = [...acceptedStateEvents].some((eventId) => byId.get(eventId)?.payload.kind === "run.started");
695
+ const missingTopicReceipt = genesis.topicBindingId !== void 0 && values.some((attempt) => attempt.disposition === "succeeded" && attempt.receiptIds.length === 0);
696
+ const missingDeclaredOutcome = accepted.some((eventId) => {
697
+ const success = byId.get(eventId);
698
+ if (success?.payload.kind !== "action.succeeded") return false;
699
+ const successPayload = success.payload;
700
+ return (successPayload.outcomes ?? []).some(
701
+ (declared) => !accepted.some((candidateId) => {
702
+ const candidate = byId.get(candidateId);
703
+ return candidate?.payload.kind === "action.outcome_emitted" && candidate.payload.attemptId === successPayload.attemptId && candidate.payload.stepId === successPayload.stepId && candidate.payload.name === declared.name && candidate.payload.payloadDigest === declared.payloadDigest && canonicalizeJson(candidate.payload.payload) === canonicalizeJson(declared.payload) && eventHasAncestor(candidate, success.eventId, byId);
704
+ })
705
+ );
706
+ });
707
+ let finalizableStatus;
708
+ if (hasAcceptedStart && !unresolved && !missingTopicReceipt && !missingDeclaredOutcome) {
709
+ if (completed) finalizableStatus = "completed";
710
+ else if (cancelRequested && !active) finalizableStatus = "cancelled";
711
+ else if (failed && !active) finalizableStatus = "failed";
712
+ }
713
+ const finalizationSummary = finalizableStatus ? {
714
+ kind: "qi.flow.run-finalization-summary",
715
+ schemaVersion: "1.0",
716
+ status: finalizableStatus,
717
+ cancelRequested,
718
+ requiredStepIds: sortedUnique(genesis.requiredStepIds),
719
+ frontierEventIds,
720
+ attempts: values.map((attempt) => ({
721
+ attemptId: attempt.attemptId,
722
+ stepId: attempt.stepId,
723
+ disposition: attempt.disposition,
724
+ receiptIds: sortedUnique(attempt.receiptIds)
725
+ })).sort((left, right) => compareCodeUnits(left.attemptId, right.attemptId))
726
+ } : void 0;
727
+ const validFinalizationIds = [];
728
+ for (const event of finalizationEvents) {
729
+ if (invalidReasons.has(event.eventId) || event.payload.kind !== "run.finalized") continue;
730
+ let reason;
731
+ if (!sameStringSet(event.parents, frontierEventIds)) reason = "incomplete_finalization_frontier";
732
+ else if (!finalizableStatus || !finalizationSummary) reason = "run_not_finalizable";
733
+ else if (event.payload.status !== finalizableStatus) reason = "finalization_status_mismatch";
734
+ else if (canonicalizeJson(event.payload.summary) !== canonicalizeJson(finalizationSummary)) {
735
+ reason = "finalization_summary_mismatch";
736
+ }
737
+ if (reason) {
738
+ invalid.push({ eventId: event.eventId, reason });
739
+ invalidReasons.set(event.eventId, reason);
740
+ } else {
741
+ validFinalizationIds.push(event.eventId);
742
+ }
743
+ }
744
+ let status = acceptedStateEvents.size === 0 ? "queued" : "running";
745
+ if (unresolved) status = "needs_verification";
746
+ else if (validFinalizationIds.length > 0 && finalizableStatus) status = finalizableStatus;
747
+ else if (cancelRequested) status = "cancelling";
748
+ const validAccepted = accepted.filter((eventId) => !invalidReasons.has(eventId));
749
+ return {
750
+ runId: genesis.runId,
751
+ definition: genesis.definition,
752
+ status,
753
+ attempts: Object.fromEntries([...attempts.entries()].sort(([left], [right]) => compareCodeUnits(left, right))),
754
+ cancelRequested,
755
+ frontierEventIds,
756
+ ...finalizableStatus && finalizationSummary ? { finalizationCandidate: { status: finalizableStatus, summary: finalizationSummary } } : {},
757
+ finalizedEventIds: validFinalizationIds.sort(compareCodeUnits),
758
+ acceptedEventIds: validAccepted.sort(compareCodeUnits),
759
+ invalidEvents: invalid.sort((left, right) => compareCodeUnits(left.eventId, right.eventId))
760
+ };
761
+ }
762
+ async function fingerprintFlowCommand(command) {
763
+ return await digestCanonicalJson(command);
764
+ }
765
+
766
+ // src/core/lib/flowEngine/vnext/effectClaims.ts
767
+ var EffectClaimTransitionError = class extends Error {
768
+ constructor(code, message) {
769
+ super(message);
770
+ this.code = code;
771
+ this.name = "EffectClaimTransitionError";
772
+ }
773
+ };
774
+ function claimEffect(existing, request, now) {
775
+ if (existing?.fingerprint !== void 0 && existing.fingerprint !== request.admission.commandFingerprint) {
776
+ return { outcome: "conflict", record: existing, reason: "Idempotency key already belongs to a different command fingerprint" };
777
+ }
778
+ if (existing && existing.providerIdempotencyKey !== request.providerIdempotencyKey) {
779
+ return { outcome: "conflict", record: existing, reason: "Effect claim already belongs to a different provider idempotency key" };
780
+ }
781
+ if (existing) {
782
+ const recovery = existing.status === "armed" || existing.status === "needs_verification" || existing.status === "success_prepared";
783
+ if (recovery) {
784
+ if (existing.leaseExpiresAt > now) return { outcome: "existing", record: existing };
785
+ return {
786
+ outcome: "claimed",
787
+ record: {
788
+ ...existing,
789
+ leaseOwner: request.leaseOwner,
790
+ // A prepared success has already consumed the effect fence. Recovery
791
+ // only drains its immutable result evidence into Matrix.
792
+ fencingEpoch: existing.status === "success_prepared" ? existing.fencingEpoch : existing.fencingEpoch + 1,
793
+ leaseExpiresAt: now + request.leaseTtlMs,
794
+ policyDigest: request.policyDigest,
795
+ updatedAt: now
796
+ }
797
+ };
798
+ }
799
+ if (existing.status !== "claimed") {
800
+ return { outcome: "existing", record: existing };
801
+ }
802
+ if (existing.leaseExpiresAt > now) return { outcome: "existing", record: existing };
803
+ if (request.admission.policy.mode !== "enabled") {
804
+ return {
805
+ outcome: "claimed",
806
+ record: {
807
+ ...existing,
808
+ leaseOwner: request.leaseOwner,
809
+ fencingEpoch: existing.fencingEpoch + 1,
810
+ leaseExpiresAt: now + request.leaseTtlMs,
811
+ policyDigest: request.policyDigest,
812
+ updatedAt: now
813
+ }
814
+ };
815
+ }
816
+ }
817
+ if (request.admission.policy.mode !== "enabled") return { outcome: "paused", record: existing ?? void 0, reason: "Execution policy pauses new effects" };
818
+ return {
819
+ outcome: "claimed",
820
+ record: {
821
+ kind: "qi.flow.effect-claim",
822
+ schemaVersion: "1.0",
823
+ claimKey: request.claimKey,
824
+ fingerprint: request.admission.commandFingerprint,
825
+ status: "claimed",
826
+ leaseOwner: request.leaseOwner,
827
+ fencingEpoch: (existing?.fencingEpoch ?? 0) + 1,
828
+ leaseExpiresAt: now + request.leaseTtlMs,
829
+ providerIdempotencyKey: request.providerIdempotencyKey,
830
+ policyDigest: request.policyDigest,
831
+ updatedAt: now
832
+ }
833
+ };
834
+ }
835
+ function assertFence(record, owner, epoch, now) {
836
+ if (record.leaseOwner !== owner || record.fencingEpoch !== epoch) {
837
+ throw new EffectClaimTransitionError("STALE_FENCE", "Effect claim owner or fencing epoch is stale");
838
+ }
839
+ if (record.leaseExpiresAt <= now) throw new EffectClaimTransitionError("STALE_FENCE", "Effect claim lease has expired");
840
+ }
841
+ function renewEffectClaim(record, owner, epoch, leaseTtlMs, now) {
842
+ assertFence(record, owner, epoch, now);
843
+ if (record.status !== "claimed") throw new EffectClaimTransitionError("INVALID_TRANSITION", "Only an unarmed claim can renew its lease");
844
+ return { ...record, leaseExpiresAt: now + leaseTtlMs, updatedAt: now };
845
+ }
846
+ function armEffectClaim(record, owner, epoch, now, providerCorrelation) {
847
+ assertFence(record, owner, epoch, now);
848
+ if (record.status === "armed" && record.providerCorrelation === providerCorrelation) return record;
849
+ if (record.status !== "claimed") throw new EffectClaimTransitionError("INVALID_TRANSITION", "Only a claimed effect can be armed");
850
+ return { ...record, status: "armed", ...providerCorrelation !== void 0 ? { providerCorrelation } : {}, updatedAt: now };
851
+ }
852
+ function prepareEffectSuccess(record, owner, epoch, outputDigest2, outcomesDigest, now, providerCorrelation) {
853
+ assertFence(record, owner, epoch, now);
854
+ if (record.status === "success_prepared") {
855
+ if (record.outputDigest !== outputDigest2 || record.outcomesDigest !== outcomesDigest) {
856
+ throw new EffectClaimTransitionError("INVALID_TRANSITION", "Prepared effect success has different result evidence");
857
+ }
858
+ return record;
859
+ }
860
+ if (record.status !== "armed" && record.status !== "needs_verification") {
861
+ throw new EffectClaimTransitionError("INVALID_TRANSITION", "Only an armed or verified effect can prepare success");
862
+ }
863
+ const nextCorrelation = providerCorrelation ?? record.providerCorrelation;
864
+ return {
865
+ ...record,
866
+ status: "success_prepared",
867
+ outputDigest: outputDigest2,
868
+ outcomesDigest,
869
+ ...nextCorrelation !== void 0 ? { providerCorrelation: nextCorrelation } : {},
870
+ updatedAt: now
871
+ };
872
+ }
873
+ function resolveEffectClaim(record, owner, epoch, outcome, now, providerCorrelation, successEventId) {
874
+ if (outcome === "failed_before_effect" && successEventId !== void 0) {
875
+ throw new EffectClaimTransitionError("INVALID_TRANSITION", "Failed-before-effect resolution cannot include success evidence");
876
+ }
877
+ if (record.status === outcome) {
878
+ const expectedCorrelation = providerCorrelation ?? record.providerCorrelation;
879
+ const sameCorrelation = record.providerCorrelation === expectedCorrelation;
880
+ const sameSuccess = outcome !== "succeeded" || record.successEventId === successEventId;
881
+ if (record.leaseOwner === owner && record.fencingEpoch === epoch && sameCorrelation && sameSuccess) return record;
882
+ throw new EffectClaimTransitionError("INVALID_TRANSITION", "Resolved effect evidence does not match the existing terminal record");
883
+ }
884
+ assertFence(record, owner, epoch, now);
885
+ if (outcome === "failed_before_effect" && record.status !== "claimed") {
886
+ throw new EffectClaimTransitionError("INVALID_TRANSITION", "An armed effect cannot be reported as failed before effect");
887
+ }
888
+ if (outcome === "succeeded" && (record.status !== "success_prepared" || !record.outputDigest || !record.outcomesDigest)) {
889
+ throw new EffectClaimTransitionError("INVALID_TRANSITION", "Effect success must be prepared before it can be finalized");
890
+ }
891
+ if (outcome === "succeeded" && !successEventId) {
892
+ throw new EffectClaimTransitionError("INVALID_TRANSITION", "Effect success requires its durable Matrix event id");
893
+ }
894
+ const nextCorrelation = providerCorrelation ?? record.providerCorrelation;
895
+ return {
896
+ ...record,
897
+ status: outcome,
898
+ ...nextCorrelation !== void 0 ? { providerCorrelation: nextCorrelation } : {},
899
+ ...successEventId ? { successEventId } : {},
900
+ updatedAt: now
901
+ };
902
+ }
903
+ function markEffectNeedsVerification(record, owner, epoch, now, providerCorrelation) {
904
+ assertFence(record, owner, epoch, now);
905
+ if (record.status === "needs_verification" && record.providerCorrelation === (providerCorrelation ?? record.providerCorrelation)) return record;
906
+ if (record.status !== "armed") throw new EffectClaimTransitionError("INVALID_TRANSITION", "Only an armed effect can become ambiguous");
907
+ const nextCorrelation = providerCorrelation ?? record.providerCorrelation;
908
+ return { ...record, status: "needs_verification", ...nextCorrelation !== void 0 ? { providerCorrelation: nextCorrelation } : {}, updatedAt: now };
909
+ }
910
+
911
+ // src/core/lib/flowEngine/vnext/actionContracts.ts
912
+ var ActionContractResolutionError = class extends Error {
913
+ constructor(code, message) {
914
+ super(message);
915
+ this.code = code;
916
+ this.name = "ActionContractResolutionError";
917
+ }
918
+ };
919
+ var SAFETY_CLASSES = /* @__PURE__ */ new Set(["pure", "provider_idempotent", "fenced", "approval_only"]);
920
+ var DATA_CLASSIFICATIONS = /* @__PURE__ */ new Set(["public", "shared", "confidential", "restricted"]);
921
+ var PROCEDURES = /* @__PURE__ */ new Set(["required", "supported", "unavailable"]);
922
+ function object(value, field) {
923
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
924
+ throw new ActionContractResolutionError("INVALID_ACTION_CONTRACT", `${field} must be a JSON object`);
925
+ }
926
+ return value;
927
+ }
928
+ function strings(value, field) {
929
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0)) {
930
+ throw new ActionContractResolutionError("INVALID_ACTION_CONTRACT", `${field} must be an array of non-empty strings`);
931
+ }
932
+ return [...value];
933
+ }
934
+ function requiredString(action, field) {
935
+ const value = action[field];
936
+ if (typeof value !== "string" || value.length === 0) {
937
+ throw new ActionContractResolutionError("INVALID_ACTION_CONTRACT", `${action.type}.${field} must be a non-empty string`);
938
+ }
939
+ return value;
940
+ }
941
+ function parseActionContract(action, manifestDigest) {
942
+ const can = requiredString(action, "can");
943
+ const safety = requiredString(action, "safety");
944
+ if (!SAFETY_CLASSES.has(safety)) {
945
+ throw new ActionContractResolutionError("INVALID_ACTION_CONTRACT", `${action.type}.safety is not a supported safety class`);
946
+ }
947
+ const dataClassification = requiredString(action, "dataClassification");
948
+ if (!DATA_CLASSIFICATIONS.has(dataClassification)) {
949
+ throw new ActionContractResolutionError("INVALID_ACTION_CONTRACT", `${action.type}.dataClassification is not supported`);
950
+ }
951
+ const providerIdempotency = object(action.providerIdempotency, `${action.type}.providerIdempotency`);
952
+ if (typeof providerIdempotency.supported !== "boolean") {
953
+ throw new ActionContractResolutionError("INVALID_ACTION_CONTRACT", `${action.type}.providerIdempotency.supported must be boolean`);
954
+ }
955
+ const readback = requiredString(action, "readbackProcedure");
956
+ const compensation = requiredString(action, "compensationProcedure");
957
+ if (!PROCEDURES.has(readback) || !PROCEDURES.has(compensation)) {
958
+ throw new ActionContractResolutionError("INVALID_ACTION_CONTRACT", `${action.type} readback and compensation procedures must be explicit`);
959
+ }
960
+ if ((safety === "provider_idempotent" || safety === "fenced") && readback === "unavailable") {
961
+ throw new ActionContractResolutionError("INVALID_ACTION_CONTRACT", `${action.type} cannot perform external effects without a readback procedure`);
962
+ }
963
+ if (safety === "provider_idempotent" && providerIdempotency.supported !== true) {
964
+ throw new ActionContractResolutionError("INVALID_ACTION_CONTRACT", `${action.type} declares provider idempotency without provider support`);
965
+ }
966
+ return {
967
+ kind: "qi.action.contract",
968
+ schemaVersion: "1.0",
969
+ type: action.type,
970
+ can,
971
+ contractVersion: action.contractVersion,
972
+ manifestDigest,
973
+ inputSchema: object(action.inputSchema, `${action.type}.inputSchema`),
974
+ outputSchema: object(action.outputSchema, `${action.type}.outputSchema`),
975
+ safety,
976
+ handlerVersion: requiredString(action, "handlerVersion"),
977
+ dataClassification,
978
+ requiredServices: strings(action.requiredServices, `${action.type}.requiredServices`),
979
+ idempotency: {
980
+ providerKey: providerIdempotency.supported,
981
+ readback,
982
+ compensation
983
+ }
984
+ };
985
+ }
986
+ async function computeActionContractDigest(contract) {
987
+ return await digestCanonicalJson(contract);
988
+ }
989
+ var HistoricalManifestActionContractResolver = class {
990
+ constructor(repository, trustPolicy) {
991
+ this.repository = repository;
992
+ this.trustPolicy = trustPolicy;
993
+ this.verifiedManifests = /* @__PURE__ */ new Map();
994
+ }
995
+ async resolve(ref) {
996
+ const manifest = await this.loadManifest(ref.manifestDigest);
997
+ const action = manifest.actions.find((candidate) => candidate.type === ref.type);
998
+ if (!action) throw new ActionContractResolutionError("ACTION_NOT_FOUND", `Action ${ref.type} is not present in ${ref.manifestDigest}`);
999
+ if (action.contractVersion !== ref.contractVersion) {
1000
+ throw new ActionContractResolutionError("ACTION_VERSION_MISMATCH", `Action ${ref.type} contract version does not match its Flow revision`);
1001
+ }
1002
+ const unsigned = parseActionContract(action, ref.manifestDigest);
1003
+ const contractDigest = await computeActionContractDigest(unsigned);
1004
+ if (contractDigest !== ref.contractDigest) {
1005
+ throw new ActionContractResolutionError("ACTION_CONTRACT_DIGEST_MISMATCH", `Action ${ref.type} contract bytes do not match the pinned digest`);
1006
+ }
1007
+ if (unsigned.can !== ref.can) {
1008
+ throw new ActionContractResolutionError("INVALID_ACTION_CONTRACT", `Action ${ref.type} capability does not match the Flow revision`);
1009
+ }
1010
+ return Object.freeze({ ...unsigned, contractDigest });
1011
+ }
1012
+ loadManifest(digest) {
1013
+ const cached = this.verifiedManifests.get(digest);
1014
+ if (cached) return cached;
1015
+ const pending = this.verifyManifest(digest);
1016
+ this.verifiedManifests.set(digest, pending);
1017
+ pending.catch(() => this.verifiedManifests.delete(digest));
1018
+ return pending;
1019
+ }
1020
+ async verifyManifest(digest) {
1021
+ const signed = await this.repository.getByDigest(digest);
1022
+ if (!signed) throw new ActionContractResolutionError("MANIFEST_NOT_FOUND", `Historical Action manifest is unavailable: ${digest}`);
1023
+ const verified = await verifyActionManifestV2(signed, this.trustPolicy);
1024
+ if (verified.integrity.digest.value !== digest) {
1025
+ throw new ActionContractResolutionError("MANIFEST_DIGEST_MISMATCH", `Historical manifest repository returned the wrong digest for ${digest}`);
1026
+ }
1027
+ return verified;
1028
+ }
1029
+ };
1030
+
1031
+ // src/core/lib/flowEngine/vnext/peerExecutor.ts
1032
+ import Ajv2020 from "ajv/dist/2020.js";
1033
+ var UNIVERSAL_ACTION_COMPLETED_OUTCOME = "step.completed";
1034
+ var PeerExecutionError = class extends Error {
1035
+ constructor(code, message) {
1036
+ super(message);
1037
+ this.code = code;
1038
+ this.name = "PeerExecutionError";
1039
+ }
1040
+ };
1041
+ function definitionRef(definition) {
1042
+ return { ...definition.ref, digest: definition.integrity.digest.value };
1043
+ }
1044
+ function proofReferences(authorization) {
1045
+ const invocations = "flow" in authorization ? [authorization.flow, authorization.action, authorization.topic, authorization.provider, authorization.effectClaim?.invocation] : [authorization];
1046
+ return [...new Set(invocations.flatMap((invocation) => invocation ? [invocation.cid, ...invocation.proofCids] : []))].sort();
1047
+ }
1048
+ function assertInvocation(invocation, expected) {
1049
+ if (invocation.audience !== expected.audience || invocation.can !== expected.can || invocation.with !== expected.with || invocation.definitionDigest !== expected.definitionDigest || invocation.actionContractDigest !== expected.actionContractDigest || invocation.idempotencyKey !== expected.idempotencyKey) {
1050
+ throw new PeerExecutionError("AUTHORIZATION_MISMATCH", `Verified invocation does not authorize ${expected.can} on ${expected.with}`);
1051
+ }
1052
+ }
1053
+ function outputDigest(output) {
1054
+ return digestCanonicalJson(output);
1055
+ }
1056
+ function compareCodeUnits2(left, right) {
1057
+ return left < right ? -1 : left > right ? 1 : 0;
1058
+ }
1059
+ async function actionOutcomes(output, provided = []) {
1060
+ const inputs = [
1061
+ { name: UNIVERSAL_ACTION_COMPLETED_OUTCOME, payload: { outputDigest: output } },
1062
+ ...provided.filter((outcome) => outcome.name.trim() !== UNIVERSAL_ACTION_COMPLETED_OUTCOME)
1063
+ ];
1064
+ const outcomes = await Promise.all(
1065
+ inputs.map(async ({ name, payload }) => {
1066
+ const normalizedName = name.trim();
1067
+ if (!normalizedName) throw new PeerExecutionError("EVENT_CONFLICT", "Action outcome name cannot be empty");
1068
+ const snapshot = JSON.parse(canonicalizeJson(payload));
1069
+ return { name: normalizedName, payload: snapshot, payloadDigest: await digestCanonicalJson(snapshot) };
1070
+ })
1071
+ );
1072
+ return outcomes.filter((outcome, index) => outcomes.findIndex((candidate) => candidate.name === outcome.name && candidate.payloadDigest === outcome.payloadDigest) === index).sort((left, right) => compareCodeUnits2(left.name, right.name) || compareCodeUnits2(left.payloadDigest, right.payloadDigest));
1073
+ }
1074
+ function actionOutcomesDigest(outcomes) {
1075
+ return digestCanonicalJson(outcomes);
1076
+ }
1077
+ function canonicalSnapshot(value) {
1078
+ return deepFreezeJson(JSON.parse(canonicalizeJson(value)));
1079
+ }
1080
+ function snapshotStartCommand(command) {
1081
+ return canonicalSnapshot({
1082
+ definition: command.definition,
1083
+ launchKind: command.launchKind,
1084
+ launchNonce: command.launchNonce,
1085
+ actor: command.actor,
1086
+ issuedAt: command.issuedAt,
1087
+ idempotencyKey: command.idempotencyKey,
1088
+ authorization: command.authorization,
1089
+ ...command.topicBindingId !== void 0 ? { topicBindingId: command.topicBindingId } : {}
1090
+ });
1091
+ }
1092
+ function snapshotAttemptCommand(command) {
1093
+ return canonicalSnapshot({
1094
+ definition: command.definition,
1095
+ genesis: command.genesis,
1096
+ stepId: command.stepId,
1097
+ actor: command.actor,
1098
+ issuedAt: command.issuedAt,
1099
+ idempotencyKey: command.idempotencyKey,
1100
+ inputs: command.inputs,
1101
+ authorization: command.authorization,
1102
+ policy: command.policy,
1103
+ ...command.topicBinding ? { topicBinding: command.topicBinding } : {},
1104
+ ...command.topicRequest ? { topicRequest: command.topicRequest } : {}
1105
+ });
1106
+ }
1107
+ function snapshotCancelCommand(command) {
1108
+ return canonicalSnapshot({
1109
+ definition: command.definition,
1110
+ genesis: command.genesis,
1111
+ actor: command.actor,
1112
+ issuedAt: command.issuedAt,
1113
+ idempotencyKey: command.idempotencyKey,
1114
+ authorization: command.authorization,
1115
+ ...command.reason !== void 0 ? { reason: command.reason } : {}
1116
+ });
1117
+ }
1118
+ function snapshotFinalizeCommand(command) {
1119
+ return canonicalSnapshot({
1120
+ definition: command.definition,
1121
+ genesis: command.genesis,
1122
+ actor: command.actor,
1123
+ issuedAt: command.issuedAt,
1124
+ idempotencyKey: command.idempotencyKey,
1125
+ authorization: command.authorization
1126
+ });
1127
+ }
1128
+ function durationMs(value) {
1129
+ const match = /^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?)?$/u.exec(value);
1130
+ if (!match) return void 0;
1131
+ const [, days, hours, minutes] = match;
1132
+ const total = Number(days ?? 0) * 864e5 + Number(hours ?? 0) * 36e5 + Number(minutes ?? 0) * 6e4;
1133
+ return total > 0 ? total : void 0;
1134
+ }
1135
+ function assertStepWithinTtl(step, genesis, now) {
1136
+ const startedAt = Date.parse(genesis.startedAt);
1137
+ const deadlines = [];
1138
+ if (step.ttlMs !== void 0) {
1139
+ if (!Number.isFinite(startedAt)) throw new PeerExecutionError("STEP_EXPIRED", "Run start time is unavailable for the signed step TTL");
1140
+ deadlines.push(startedAt + step.ttlMs);
1141
+ }
1142
+ if (step.ttl?.absoluteDueDate) deadlines.push(Date.parse(step.ttl.absoluteDueDate));
1143
+ for (const relative of [step.ttl?.fromEnablement, step.ttl?.fromCommitment]) {
1144
+ if (!relative) continue;
1145
+ const relativeMs = durationMs(relative);
1146
+ if (!Number.isFinite(startedAt) || relativeMs === void 0) {
1147
+ throw new PeerExecutionError("STEP_EXPIRED", "The signed relative step TTL cannot be proven unexpired");
1148
+ }
1149
+ deadlines.push(startedAt + relativeMs);
1150
+ }
1151
+ if (deadlines.some((deadline) => !Number.isFinite(deadline) || now >= deadline)) {
1152
+ throw new PeerExecutionError("STEP_EXPIRED", `Flow step ${step.stepId} is outside its signed execution window`);
1153
+ }
1154
+ }
1155
+ function assertCommandTime(issuedAtValue, executionNow) {
1156
+ const issuedAt = Date.parse(issuedAtValue);
1157
+ if (!Number.isFinite(issuedAt) || issuedAt > executionNow) {
1158
+ throw new PeerExecutionError("COMMAND_TIME_INVALID", "Command time must be valid and no later than executor time");
1159
+ }
1160
+ }
1161
+ async function assertRunGenesis(definitionRevision, genesis) {
1162
+ const definition = definitionRef(definitionRevision);
1163
+ const expectedRunId = await deriveRunId(definition, genesis.launchKind, genesis.launchNonce);
1164
+ const expectedStepIds = definitionRevision.steps.map((candidate) => candidate.stepId);
1165
+ if (genesis.runId !== expectedRunId || canonicalizeJson(genesis.definition) !== canonicalizeJson(definition) || canonicalizeJson(genesis.requiredStepIds) !== canonicalizeJson(expectedStepIds) || !Number.isFinite(Date.parse(genesis.startedAt))) {
1166
+ throw new PeerExecutionError("DEFINITION_MISMATCH", "Run genesis does not match the immutable Flow definition");
1167
+ }
1168
+ return definition;
1169
+ }
1170
+ function createPeerExecutor(options) {
1171
+ const schemaCompiler = new Ajv2020({ allErrors: true, strict: false });
1172
+ const validators = /* @__PURE__ */ new Map();
1173
+ function contractValidators(contract) {
1174
+ let resolved = validators.get(contract.contractDigest);
1175
+ if (!resolved) {
1176
+ try {
1177
+ const input = schemaCompiler.compile(contract.inputSchema);
1178
+ const output = schemaCompiler.compile(contract.outputSchema);
1179
+ if (input.$async || output.$async) {
1180
+ throw new Error("Asynchronous JSON Schema validation is not supported by the peer executor");
1181
+ }
1182
+ resolved = { input, output };
1183
+ } catch (error) {
1184
+ throw new PeerExecutionError("ACTION_CONTRACT_INVALID", `Pinned Action schema is invalid: ${error instanceof Error ? error.message : String(error)}`);
1185
+ }
1186
+ validators.set(contract.contractDigest, resolved);
1187
+ }
1188
+ return resolved;
1189
+ }
1190
+ function assertValidInputs(contract, inputs) {
1191
+ const validate = contractValidators(contract).input;
1192
+ if (!validate(inputs)) {
1193
+ throw new PeerExecutionError("INPUT_SCHEMA_INVALID", `Action inputs do not match the pinned schema: ${schemaCompiler.errorsText(validate.errors)}`);
1194
+ }
1195
+ }
1196
+ async function validatedOutputDigest(contract, candidate) {
1197
+ const output = canonicalSnapshot(candidate);
1198
+ const validate = contractValidators(contract).output;
1199
+ if (!validate(output)) {
1200
+ throw new PeerExecutionError("OUTPUT_SCHEMA_INVALID", `Action output does not match the pinned schema: ${schemaCompiler.errorsText(validate.errors)}`);
1201
+ }
1202
+ return outputDigest(output);
1203
+ }
1204
+ function assertExecutionWindow(command, step) {
1205
+ const executionNow = options.now?.() ?? Date.now();
1206
+ if (command.policy.expiresAt && (!Number.isFinite(Date.parse(command.policy.expiresAt)) || executionNow >= Date.parse(command.policy.expiresAt))) {
1207
+ throw new PeerExecutionError("POLICY_EXPIRED", "Signed execution policy has expired");
1208
+ }
1209
+ assertStepWithinTtl(step, command.genesis, executionNow);
1210
+ }
1211
+ const append = async (envelope) => {
1212
+ const event = await signFlowEvent(envelope, options.signer);
1213
+ try {
1214
+ const result = await options.events.append(event, matrixFlowEventTransactionId(event));
1215
+ if (result.outcome === "conflict") throw new PeerExecutionError("EVENT_CONFLICT", `Matrix transaction conflicts for ${event.eventId}`);
1216
+ } catch (error) {
1217
+ if (error instanceof PeerExecutionError) throw error;
1218
+ throw new PeerExecutionError("EVENT_UNAVAILABLE", `Matrix could not durably append ${event.payload.kind}: ${error instanceof Error ? error.message : String(error)}`);
1219
+ }
1220
+ return event;
1221
+ };
1222
+ const eventBase = (params) => ({
1223
+ kind: "qi.flow.event",
1224
+ schemaVersion: "1.0",
1225
+ runId: params.runId,
1226
+ definition: params.definition,
1227
+ producer: options.executorDid,
1228
+ actor: params.actor,
1229
+ occurredAt: params.issuedAt,
1230
+ parents: params.parents,
1231
+ correlationId: params.idempotencyKey,
1232
+ idempotencyKey: params.idempotencyKey,
1233
+ commandFingerprint: params.commandFingerprint,
1234
+ proofReferences: params.proofs
1235
+ });
1236
+ const readAnchoredRun = async (definition, genesis) => {
1237
+ let runEvents;
1238
+ try {
1239
+ runEvents = await options.events.read(genesis.runId);
1240
+ } catch (error) {
1241
+ throw new PeerExecutionError("EVENT_UNAVAILABLE", `Matrix could not inspect run state: ${error instanceof Error ? error.message : String(error)}`);
1242
+ }
1243
+ const reducedRun = reduceFlowEvents(genesis, runEvents);
1244
+ const acceptedEventIds = new Set(reducedRun.acceptedEventIds);
1245
+ const canonicalGenesis = canonicalizeJson(genesis);
1246
+ if (!runEvents.some(
1247
+ (event) => acceptedEventIds.has(event.eventId) && event.payload.kind === "run.started" && canonicalizeJson(event.payload.genesis) === canonicalGenesis
1248
+ )) {
1249
+ throw new PeerExecutionError("DEFINITION_MISMATCH", "Run genesis is not anchored by a verified run-start event");
1250
+ }
1251
+ if (canonicalizeJson(reducedRun.definition) !== canonicalizeJson(definition)) {
1252
+ throw new PeerExecutionError("DEFINITION_MISMATCH", "Reduced run definition does not match the immutable Flow definition");
1253
+ }
1254
+ return { runEvents, reducedRun, acceptedEventIds };
1255
+ };
1256
+ async function startRun(command) {
1257
+ command = snapshotStartCommand(command);
1258
+ const definition = definitionRef(command.definition);
1259
+ const runId = await deriveRunId(definition, command.launchKind, command.launchNonce);
1260
+ const executionNow = options.now?.() ?? Date.now();
1261
+ assertCommandTime(command.issuedAt, executionNow);
1262
+ if (command.launchKind === "topic.request" && !command.topicBindingId?.trim()) {
1263
+ throw new PeerExecutionError("TOPIC_BINDING_REQUIRED", "Topic run start requires a non-empty binding");
1264
+ }
1265
+ const genesis = {
1266
+ kind: "qi.flow.run-genesis",
1267
+ schemaVersion: "1.0",
1268
+ runId,
1269
+ definition,
1270
+ launchKind: command.launchKind,
1271
+ launchNonce: command.launchNonce,
1272
+ requiredStepIds: command.definition.steps.map((step) => step.stepId),
1273
+ startedBy: command.actor,
1274
+ startedAt: command.issuedAt,
1275
+ ...command.topicBindingId ? { topicBindingId: command.topicBindingId } : {}
1276
+ };
1277
+ let runEvents;
1278
+ try {
1279
+ runEvents = await options.events.read(runId);
1280
+ } catch (error) {
1281
+ throw new PeerExecutionError("EVENT_UNAVAILABLE", `Matrix could not inspect existing run starts: ${error instanceof Error ? error.message : String(error)}`);
1282
+ }
1283
+ const canonicalDefinition = canonicalizeJson(definition);
1284
+ const canonicalGenesis = canonicalizeJson(genesis);
1285
+ const existingStarts = runEvents.filter(
1286
+ (event) => event.runId === runId && canonicalizeJson(event.definition) === canonicalDefinition && event.payload.kind === "run.started"
1287
+ );
1288
+ if (existingStarts.some((event) => event.payload.kind === "run.started" && canonicalizeJson(event.payload.genesis) !== canonicalGenesis)) {
1289
+ throw new PeerExecutionError("EVENT_CONFLICT", `Run ${runId} already has different signed genesis evidence`);
1290
+ }
1291
+ if (existingStarts.length > 0) {
1292
+ const reducedRun = reduceFlowEvents(genesis, runEvents);
1293
+ const acceptedEventIds = new Set(reducedRun.acceptedEventIds);
1294
+ const acceptedStart = existingStarts.find((event) => acceptedEventIds.has(event.eventId));
1295
+ if (acceptedStart?.payload.kind === "run.started") return acceptedStart.payload.genesis;
1296
+ throw new PeerExecutionError("EVENT_CONFLICT", `Run ${runId} has invalid signed genesis evidence`);
1297
+ }
1298
+ const invocation = await options.authorizer.authorizeRunStart({
1299
+ authorization: command.authorization,
1300
+ executorDid: options.executorDid,
1301
+ definition,
1302
+ runId,
1303
+ actor: command.actor,
1304
+ issuedAt: command.issuedAt,
1305
+ idempotencyKey: command.idempotencyKey
1306
+ });
1307
+ assertInvocation(invocation, {
1308
+ audience: options.executorDid,
1309
+ can: FLOW_CAPABILITIES.runStart,
1310
+ with: buildFlowResourceUri(definition, { kind: "run", runId }),
1311
+ definitionDigest: definition.digest,
1312
+ idempotencyKey: command.idempotencyKey
1313
+ });
1314
+ const fingerprint = await fingerprintFlowCommand(genesis);
1315
+ await append({
1316
+ ...eventBase({
1317
+ runId,
1318
+ definition,
1319
+ actor: command.actor,
1320
+ issuedAt: command.issuedAt,
1321
+ idempotencyKey: command.idempotencyKey,
1322
+ commandFingerprint: fingerprint,
1323
+ parents: [],
1324
+ proofs: proofReferences(invocation)
1325
+ }),
1326
+ payload: { kind: "run.started", genesis }
1327
+ });
1328
+ return genesis;
1329
+ }
1330
+ async function cancelRun(command) {
1331
+ command = snapshotCancelCommand(command);
1332
+ const definition = await assertRunGenesis(command.definition, command.genesis);
1333
+ assertCommandTime(command.issuedAt, options.now?.() ?? Date.now());
1334
+ const { runEvents, reducedRun, acceptedEventIds } = await readAnchoredRun(definition, command.genesis);
1335
+ if (reducedRun.finalizedEventIds.length > 0) throw new PeerExecutionError("RUN_FINALIZED", `Run ${command.genesis.runId} is already finalized`);
1336
+ const commandFingerprint = await fingerprintFlowCommand({
1337
+ definitionDigest: definition.digest,
1338
+ runId: command.genesis.runId,
1339
+ kind: "run.cancel_requested",
1340
+ reason: command.reason ?? null
1341
+ });
1342
+ const sameKey = runEvents.filter((event) => event.idempotencyKey === command.idempotencyKey);
1343
+ const existing = sameKey.find(
1344
+ (event) => acceptedEventIds.has(event.eventId) && event.commandFingerprint === commandFingerprint && event.payload.kind === "run.cancel_requested" && event.payload.reason === command.reason
1345
+ );
1346
+ if (existing) return existing;
1347
+ if (sameKey.length > 0) throw new PeerExecutionError("EVENT_CONFLICT", "The cancellation command key is already bound to different evidence");
1348
+ const invocation = await options.authorizer.authorizeRunControl({
1349
+ authorization: command.authorization,
1350
+ executorDid: options.executorDid,
1351
+ definition,
1352
+ runId: command.genesis.runId,
1353
+ actor: command.actor,
1354
+ issuedAt: command.issuedAt,
1355
+ idempotencyKey: command.idempotencyKey,
1356
+ can: FLOW_CAPABILITIES.runCancel
1357
+ });
1358
+ assertInvocation(invocation, {
1359
+ audience: options.executorDid,
1360
+ can: FLOW_CAPABILITIES.runCancel,
1361
+ with: buildFlowResourceUri(definition, { kind: "run", runId: command.genesis.runId }),
1362
+ definitionDigest: definition.digest,
1363
+ idempotencyKey: command.idempotencyKey
1364
+ });
1365
+ return append({
1366
+ ...eventBase({
1367
+ runId: command.genesis.runId,
1368
+ definition,
1369
+ actor: command.actor,
1370
+ issuedAt: command.issuedAt,
1371
+ idempotencyKey: command.idempotencyKey,
1372
+ commandFingerprint,
1373
+ parents: reducedRun.frontierEventIds,
1374
+ proofs: proofReferences(invocation)
1375
+ }),
1376
+ payload: { kind: "run.cancel_requested", ...command.reason !== void 0 ? { reason: command.reason } : {} }
1377
+ });
1378
+ }
1379
+ async function finalizeRun(command) {
1380
+ command = snapshotFinalizeCommand(command);
1381
+ const definition = await assertRunGenesis(command.definition, command.genesis);
1382
+ assertCommandTime(command.issuedAt, options.now?.() ?? Date.now());
1383
+ const { runEvents, reducedRun, acceptedEventIds } = await readAnchoredRun(definition, command.genesis);
1384
+ const existingFinalization = runEvents.find(
1385
+ (event) => acceptedEventIds.has(event.eventId) && reducedRun.finalizedEventIds.includes(event.eventId) && event.payload.kind === "run.finalized"
1386
+ );
1387
+ if (existingFinalization) return existingFinalization;
1388
+ const candidate = reducedRun.finalizationCandidate;
1389
+ if (!candidate) throw new PeerExecutionError("RUN_NOT_FINALIZABLE", `Run ${command.genesis.runId} has no causally complete terminal state`);
1390
+ const summaryDigest = await digestCanonicalJson(candidate.summary);
1391
+ const commandFingerprint = await fingerprintFlowCommand({
1392
+ definitionDigest: definition.digest,
1393
+ runId: command.genesis.runId,
1394
+ kind: "run.finalized",
1395
+ status: candidate.status,
1396
+ summaryDigest
1397
+ });
1398
+ const sameKey = runEvents.filter((event) => event.idempotencyKey === command.idempotencyKey);
1399
+ if (sameKey.length > 0) throw new PeerExecutionError("EVENT_CONFLICT", "The finalization command key is already bound to stale or different evidence");
1400
+ const invocation = await options.authorizer.authorizeRunControl({
1401
+ authorization: command.authorization,
1402
+ executorDid: options.executorDid,
1403
+ definition,
1404
+ runId: command.genesis.runId,
1405
+ actor: command.actor,
1406
+ issuedAt: command.issuedAt,
1407
+ idempotencyKey: command.idempotencyKey,
1408
+ can: FLOW_CAPABILITIES.runClose
1409
+ });
1410
+ assertInvocation(invocation, {
1411
+ audience: options.executorDid,
1412
+ can: FLOW_CAPABILITIES.runClose,
1413
+ with: buildFlowResourceUri(definition, { kind: "run", runId: command.genesis.runId }),
1414
+ definitionDigest: definition.digest,
1415
+ idempotencyKey: command.idempotencyKey
1416
+ });
1417
+ return append({
1418
+ ...eventBase({
1419
+ runId: command.genesis.runId,
1420
+ definition,
1421
+ actor: command.actor,
1422
+ issuedAt: command.issuedAt,
1423
+ idempotencyKey: command.idempotencyKey,
1424
+ commandFingerprint,
1425
+ parents: candidate.summary.frontierEventIds,
1426
+ proofs: proofReferences(invocation)
1427
+ }),
1428
+ payload: { kind: "run.finalized", status: candidate.status, summary: candidate.summary, summaryDigest }
1429
+ });
1430
+ }
1431
+ async function executeAttempt(command) {
1432
+ command = snapshotAttemptCommand(command);
1433
+ const inputs = command.inputs;
1434
+ const definition = await assertRunGenesis(command.definition, command.genesis);
1435
+ const executionNow = options.now?.() ?? Date.now();
1436
+ assertCommandTime(command.issuedAt, executionNow);
1437
+ if (command.policy.definition.digest !== definition.digest) throw new PeerExecutionError("POLICY_MISMATCH", "Execution policy is for a different Flow definition");
1438
+ const { runEvents, reducedRun, acceptedEventIds } = await readAnchoredRun(definition, command.genesis);
1439
+ if (reducedRun.finalizedEventIds.length > 0) throw new PeerExecutionError("RUN_FINALIZED", `Run ${command.genesis.runId} is already finalized`);
1440
+ const step = command.definition.steps.find((candidate) => candidate.stepId === command.stepId);
1441
+ if (!step) throw new PeerExecutionError("STEP_NOT_FOUND", `Flow step is not in the immutable definition: ${command.stepId}`);
1442
+ if (step.trigger.kind !== "manual" && step.trigger.kind !== "topic.request" || step.conditions.length > 0) {
1443
+ throw new PeerExecutionError("ELIGIBILITY_EVIDENCE_REQUIRED", `Flow step ${step.stepId} requires signed eligibility evidence`);
1444
+ }
1445
+ const hasSignedTopicContext = step.trigger.kind === "topic.request" || command.genesis.launchKind === "topic.request" || command.genesis.topicBindingId !== void 0;
1446
+ if (hasSignedTopicContext && (!command.genesis.topicBindingId || !command.topicBinding || command.topicBinding.bindingId !== command.genesis.topicBindingId) || !hasSignedTopicContext && command.topicBinding) {
1447
+ throw new PeerExecutionError("AUTHORIZATION_MISMATCH", "Topic execution requires the exact binding recorded by the signed step and run genesis");
1448
+ }
1449
+ if (step.trigger.kind === "topic.request" && (!command.topicRequest || command.topicRequest.requestKind !== step.trigger.requestKind || !command.topicRequest.requestId.trim() || !/^sha256:[0-9a-f]{64}$/u.test(command.topicRequest.requestDigest)) || !hasSignedTopicContext && command.topicRequest) {
1450
+ throw new PeerExecutionError("AUTHORIZATION_MISMATCH", "Topic execution requires signed request evidence for the immutable request kind");
1451
+ }
1452
+ const contract = await options.contracts.resolve(step.action);
1453
+ assertValidInputs(contract, inputs);
1454
+ const inputDigest = await digestCanonicalJson(command.inputs);
1455
+ const attemptId = await deriveAttemptId({ runId: command.genesis.runId, stepId: command.stepId, idempotencyKey: command.idempotencyKey, inputDigest });
1456
+ const resource = buildFlowResourceUri(definition, { kind: "step", stepId: command.stepId, runId: command.genesis.runId });
1457
+ const authorization = await options.authorizer.authorizeAttempt({
1458
+ authorization: command.authorization,
1459
+ executorDid: options.executorDid,
1460
+ definition,
1461
+ runId: command.genesis.runId,
1462
+ stepId: command.stepId,
1463
+ action: contract,
1464
+ actor: command.actor,
1465
+ idempotencyKey: command.idempotencyKey,
1466
+ effectClaimAudience: options.effectClaimAudience,
1467
+ topicBinding: command.topicBinding,
1468
+ topicRequest: command.topicRequest
1469
+ });
1470
+ const invocationExpectation = {
1471
+ audience: options.executorDid,
1472
+ with: resource,
1473
+ definitionDigest: definition.digest,
1474
+ actionContractDigest: contract.contractDigest,
1475
+ idempotencyKey: command.idempotencyKey
1476
+ };
1477
+ assertInvocation(authorization.flow, { ...invocationExpectation, can: FLOW_CAPABILITIES.actionExecute });
1478
+ assertInvocation(authorization.action, { ...invocationExpectation, can: contract.can });
1479
+ if (hasSignedTopicContext) {
1480
+ if (!authorization.topic) throw new PeerExecutionError("AUTHORIZATION_MISMATCH", "Topic-bound execution requires a verified Topic invocation");
1481
+ assertInvocation(authorization.topic, {
1482
+ ...invocationExpectation,
1483
+ can: FLOW_CAPABILITIES.topicRequestAction,
1484
+ with: command.topicBinding.topicResource
1485
+ });
1486
+ if (command.topicRequest && (!authorization.topic.topicRequest || canonicalizeJson(authorization.topic.topicRequest) !== canonicalizeJson(command.topicRequest))) {
1487
+ throw new PeerExecutionError("AUTHORIZATION_MISMATCH", "Verified Topic invocation does not bind the requested Topic request evidence");
1488
+ }
1489
+ }
1490
+ const commandFingerprint = await fingerprintFlowCommand({
1491
+ definitionDigest: definition.digest,
1492
+ runId: command.genesis.runId,
1493
+ stepId: command.stepId,
1494
+ attemptId,
1495
+ actor: command.actor,
1496
+ inputDigest,
1497
+ actionContractDigest: contract.contractDigest,
1498
+ topicBindingId: command.topicBinding?.bindingId ?? null,
1499
+ topicRequest: command.topicRequest ?? null
1500
+ });
1501
+ const base = {
1502
+ runId: command.genesis.runId,
1503
+ definition,
1504
+ actor: command.actor,
1505
+ issuedAt: command.issuedAt,
1506
+ idempotencyKey: command.idempotencyKey,
1507
+ commandFingerprint,
1508
+ proofs: proofReferences(authorization)
1509
+ };
1510
+ let claimAdmission;
1511
+ if (contract.safety === "fenced") {
1512
+ if (!options.effectClaimAudience || !authorization.effectClaim) {
1513
+ throw new PeerExecutionError("AUTHORIZATION_MISMATCH", "Fenced execution requires a peer-issued invocation addressed to the effect claim ledger");
1514
+ }
1515
+ assertInvocation(authorization.effectClaim.invocation, {
1516
+ ...invocationExpectation,
1517
+ audience: options.effectClaimAudience,
1518
+ can: FLOW_CAPABILITIES.actionExecute
1519
+ });
1520
+ if (authorization.effectClaim.invocation.issuer !== options.executorDid) {
1521
+ throw new PeerExecutionError("AUTHORIZATION_MISMATCH", "Effect claim invocation must be issued by the peer that owns the lease");
1522
+ }
1523
+ claimAdmission = {
1524
+ authorization: authorization.effectClaim.authorization,
1525
+ invocation: authorization.effectClaim.invocation,
1526
+ policy: command.policy,
1527
+ commandFingerprint
1528
+ };
1529
+ }
1530
+ const existingRequest = runEvents.find(
1531
+ (event) => acceptedEventIds.has(event.eventId) && event.payload.kind === "action.requested" && event.payload.attemptId === attemptId && event.payload.stepId === command.stepId
1532
+ );
1533
+ if (existingRequest && (existingRequest.commandFingerprint !== commandFingerprint || existingRequest.payload.kind === "action.requested" && existingRequest.payload.inputDigest !== inputDigest)) {
1534
+ throw new PeerExecutionError("EVENT_CONFLICT", "The reserved attempt has different command evidence");
1535
+ }
1536
+ if (reducedRun.cancelRequested && !existingRequest) {
1537
+ throw new PeerExecutionError("RUN_CANCELLING", "Run cancellation was observed before this attempt was reserved");
1538
+ }
1539
+ const existingAttempt = reducedRun.attempts[attemptId];
1540
+ const existingSuccesses = runEvents.filter(
1541
+ (event) => acceptedEventIds.has(event.eventId) && event.payload.kind === "action.succeeded" && event.payload.attemptId === attemptId && event.payload.stepId === command.stepId
1542
+ );
1543
+ const acceptedEvents = runEvents.filter((event) => acceptedEventIds.has(event.eventId));
1544
+ if (existingRequest && contract.safety !== "fenced" && existingAttempt?.stepId === command.stepId) {
1545
+ if (existingAttempt.disposition === "succeeded") {
1546
+ if (!existingAttempt.outputDigest) throw new PeerExecutionError("EVENT_CONFLICT", "Accepted Action success is missing its output digest");
1547
+ if (existingSuccesses.length === 0) throw new PeerExecutionError("EVENT_CONFLICT", "Reduced Action success has no accepted event");
1548
+ for (const success of existingSuccesses) await persistActionOutcomeEvents(success, acceptedEvents);
1549
+ return {
1550
+ outcome: "succeeded",
1551
+ attemptId,
1552
+ outputDigest: existingAttempt.outputDigest,
1553
+ providerCorrelation: existingAttempt.providerCorrelation
1554
+ };
1555
+ }
1556
+ if (existingAttempt.disposition === "failed_before_effect") return { outcome: "failed_before_effect", attemptId };
1557
+ }
1558
+ const effectMayHaveStarted = runEvents.some(
1559
+ (event) => acceptedEventIds.has(event.eventId) && (event.payload.kind === "action.started" || event.payload.kind === "action.effect_armed") && event.payload.attemptId === attemptId && event.payload.stepId === command.stepId
1560
+ );
1561
+ if (!existingRequest && contract.safety !== "fenced") assertExecutionWindow(command, step);
1562
+ if (command.policy.mode === "pause_new_effects" && contract.safety === "provider_idempotent" && !effectMayHaveStarted) {
1563
+ throw new PeerExecutionError("POLICY_PAUSED", "Signed execution policy pauses new external effects");
1564
+ }
1565
+ const requested = existingRequest ?? await append({
1566
+ ...eventBase({ ...base, parents: reducedRun.frontierEventIds }),
1567
+ payload: { kind: "action.requested", attemptId, stepId: command.stepId, inputDigest }
1568
+ });
1569
+ if (contract.safety === "approval_only") {
1570
+ assertExecutionWindow(command, step);
1571
+ const proposalDigest = await digestCanonicalJson({ attemptId, inputs: command.inputs, action: contract.contractDigest });
1572
+ await append({
1573
+ ...eventBase({ ...base, parents: [requested.eventId] }),
1574
+ payload: { kind: "action.approval_proposed", attemptId, stepId: command.stepId, proposalDigest }
1575
+ });
1576
+ return { outcome: "approval_required", attemptId, proposalDigest };
1577
+ }
1578
+ const providerIdempotencyKey = `provider:${attemptId}`;
1579
+ let claim;
1580
+ let attemptParent = requested;
1581
+ if (contract.safety === "fenced") {
1582
+ if (!claimAdmission) throw new PeerExecutionError("AUTHORIZATION_MISMATCH", "Effect claim authorization is unavailable");
1583
+ const claimKey = await deriveEffectClaimKey({
1584
+ definition,
1585
+ runId: command.genesis.runId,
1586
+ stepId: command.stepId,
1587
+ attemptId,
1588
+ actorDid: command.actor,
1589
+ inputDigest,
1590
+ action: step.action,
1591
+ topicBindingId: command.topicBinding?.bindingId
1592
+ });
1593
+ const claimed = await options.effectClaims.claim({
1594
+ claimKey,
1595
+ leaseOwner: options.executorDid,
1596
+ leaseTtlMs: 3e4,
1597
+ providerIdempotencyKey,
1598
+ policyDigest: command.policy.integrity.digest.value,
1599
+ admission: claimAdmission
1600
+ });
1601
+ if (claimed.outcome === "paused") throw new PeerExecutionError("POLICY_PAUSED", claimed.reason);
1602
+ if (claimed.outcome === "conflict") throw new PeerExecutionError("CLAIM_CONFLICT", claimed.reason);
1603
+ if (!claimed.record) throw new PeerExecutionError("CLAIM_CONFLICT", "Effect claim ledger returned no claim record");
1604
+ const claimedRecord = claimed.record;
1605
+ claim = claimedRecord;
1606
+ const claimSuccess = claimedRecord.successEventId ? existingSuccesses.find((event) => event.eventId === claimedRecord.successEventId) : existingSuccesses.find(
1607
+ (event) => event.payload.kind === "action.succeeded" && event.payload.claimKey === claimedRecord.claimKey && event.payload.fencingEpoch === claimedRecord.fencingEpoch
1608
+ );
1609
+ if (claimedRecord.status === "succeeded") {
1610
+ return reconcileFenced(command, contract, authorization, attemptId, providerIdempotencyKey, claimedRecord, claimAdmission, base, requested, claimSuccess, acceptedEvents);
1611
+ }
1612
+ if (claimed.outcome === "existing" && claimedRecord.leaseOwner !== options.executorDid) {
1613
+ return { outcome: "deferred", attemptId, reason: `Effect claim is owned by ${claimedRecord.leaseOwner}` };
1614
+ }
1615
+ if (claimedRecord.status === "armed" || claimedRecord.status === "needs_verification" || claimedRecord.status === "success_prepared") {
1616
+ return reconcileFenced(command, contract, authorization, attemptId, providerIdempotencyKey, claimedRecord, claimAdmission, base, requested, claimSuccess, acceptedEvents);
1617
+ }
1618
+ claim = await options.effectClaims.arm(claimedRecord.claimKey, options.executorDid, claimedRecord.fencingEpoch, claimAdmission);
1619
+ try {
1620
+ attemptParent = await append({
1621
+ ...eventBase({ ...base, parents: [requested.eventId] }),
1622
+ payload: { kind: "action.effect_armed", attemptId, stepId: command.stepId, claimKey, fencingEpoch: claim.fencingEpoch }
1623
+ });
1624
+ } catch (error) {
1625
+ await options.effectClaims.markNeedsVerification(claim.claimKey, options.executorDid, claim.fencingEpoch, claimAdmission, claim.providerCorrelation);
1626
+ throw error;
1627
+ }
1628
+ } else {
1629
+ attemptParent = await append({
1630
+ ...eventBase({ ...base, parents: [requested.eventId] }),
1631
+ payload: { kind: "action.started", attemptId, stepId: command.stepId }
1632
+ });
1633
+ }
1634
+ if (!effectMayHaveStarted) {
1635
+ try {
1636
+ assertExecutionWindow(command, step);
1637
+ } catch (error) {
1638
+ if (!claim) throw error;
1639
+ if (!claimAdmission) throw new PeerExecutionError("AUTHORIZATION_MISMATCH", "Effect claim authorization is unavailable");
1640
+ const reason = error instanceof Error ? error.message : String(error);
1641
+ await options.effectClaims.markNeedsVerification(claim.claimKey, options.executorDid, claim.fencingEpoch, claimAdmission, claim.providerCorrelation);
1642
+ await append({
1643
+ ...eventBase({ ...base, parents: [attemptParent.eventId] }),
1644
+ payload: {
1645
+ kind: "action.needs_verification",
1646
+ attemptId,
1647
+ stepId: command.stepId,
1648
+ ...claim.providerCorrelation ? { providerCorrelation: claim.providerCorrelation } : {},
1649
+ reason
1650
+ }
1651
+ });
1652
+ return { outcome: "needs_verification", attemptId, providerCorrelation: claim.providerCorrelation };
1653
+ }
1654
+ }
1655
+ const provider = await options.actions.invoke({
1656
+ contract,
1657
+ inputs: command.inputs,
1658
+ providerIdempotencyKey,
1659
+ invocation: authorization,
1660
+ assertEffectAllowed: () => assertExecutionWindow(command, step)
1661
+ });
1662
+ if (provider.outcome === "succeeded") {
1663
+ const digest = await validatedOutputDigest(contract, provider.output);
1664
+ return persistSuccess(command, attemptId, digest, provider.outcomes, provider.providerCorrelation, claim, claimAdmission, base, attemptParent);
1665
+ }
1666
+ if (provider.outcome === "failed_before_effect" && !claim) {
1667
+ await append({
1668
+ ...eventBase({ ...base, parents: [attemptParent.eventId] }),
1669
+ payload: { kind: "action.failed_before_effect", attemptId, stepId: command.stepId, error: provider.error }
1670
+ });
1671
+ return { outcome: "failed_before_effect", attemptId };
1672
+ }
1673
+ const ambiguous = provider.outcome === "ambiguous" ? provider : { outcome: "ambiguous", reason: "Provider reported failure after the effect was armed; readback is required" };
1674
+ return reconcileAmbiguity(command, contract, authorization, attemptId, providerIdempotencyKey, claim, claimAdmission, base, attemptParent, ambiguous);
1675
+ }
1676
+ async function reconcileFenced(command, contract, authorization, attemptId, providerIdempotencyKey, claim, admission, base, requested, existingSuccess, existingEvents = []) {
1677
+ if (existingSuccess?.payload.kind === "action.succeeded") {
1678
+ const success = existingSuccess.payload;
1679
+ const outcomesMatch = claim.outcomesDigest === void 0 ? success.outcomes === void 0 : await actionOutcomesDigest(success.outcomes ?? []) === claim.outcomesDigest;
1680
+ if (success.claimKey !== claim.claimKey || success.fencingEpoch !== claim.fencingEpoch || success.outputDigest !== claim.outputDigest || !outcomesMatch) {
1681
+ throw new PeerExecutionError("EVENT_CONFLICT", "Accepted fenced success does not match the durable prepared evidence");
1682
+ }
1683
+ if (claim.status === "success_prepared") {
1684
+ await options.effectClaims.resolve(claim.claimKey, options.executorDid, claim.fencingEpoch, "succeeded", admission, success.providerCorrelation, existingSuccess.eventId);
1685
+ } else if (claim.status !== "succeeded" || claim.successEventId !== existingSuccess.eventId) {
1686
+ throw new PeerExecutionError("EVENT_CONFLICT", "Accepted fenced success has no prepared or finalized effect claim");
1687
+ }
1688
+ await persistActionOutcomeEvents(existingSuccess, existingEvents);
1689
+ return {
1690
+ outcome: "succeeded",
1691
+ attemptId,
1692
+ outputDigest: success.outputDigest,
1693
+ ...success.providerCorrelation !== void 0 ? { providerCorrelation: success.providerCorrelation } : {}
1694
+ };
1695
+ }
1696
+ if (claim.status === "succeeded") {
1697
+ throw new PeerExecutionError("EVENT_CONFLICT", "Finalized effect claim references a Matrix success event that is unavailable");
1698
+ }
1699
+ const armed = await append({
1700
+ ...eventBase({ ...base, parents: [requested.eventId] }),
1701
+ payload: {
1702
+ kind: "action.effect_armed",
1703
+ attemptId,
1704
+ stepId: command.stepId,
1705
+ claimKey: claim.claimKey,
1706
+ fencingEpoch: claim.fencingEpoch
1707
+ }
1708
+ });
1709
+ if (claim.status === "success_prepared" && claim.outputDigest && claim.outcomesDigest) {
1710
+ const readback = await options.actions.readback({
1711
+ contract,
1712
+ inputs: command.inputs,
1713
+ providerIdempotencyKey,
1714
+ providerCorrelation: claim.providerCorrelation,
1715
+ invocation: authorization
1716
+ });
1717
+ if (readback.outcome === "succeeded") {
1718
+ const digest = await validatedOutputDigest(contract, readback.output);
1719
+ const outcomes = await actionOutcomes(digest, readback.outcomes);
1720
+ if (digest === claim.outputDigest && await actionOutcomesDigest(outcomes) === claim.outcomesDigest) {
1721
+ return persistSuccess(command, attemptId, digest, readback.outcomes, readback.providerCorrelation, claim, admission, base, armed);
1722
+ }
1723
+ }
1724
+ const providerCorrelation = readback.outcome === "succeeded" || readback.outcome === "unknown" ? readback.providerCorrelation ?? claim.providerCorrelation : claim.providerCorrelation;
1725
+ await append({
1726
+ ...eventBase({ ...base, parents: [armed.eventId] }),
1727
+ payload: {
1728
+ kind: "action.needs_verification",
1729
+ attemptId,
1730
+ stepId: command.stepId,
1731
+ ...providerCorrelation !== void 0 ? { providerCorrelation } : {},
1732
+ reason: "Prepared provider result could not be reproduced with its complete outcome evidence"
1733
+ }
1734
+ });
1735
+ return { outcome: "needs_verification", attemptId, ...providerCorrelation !== void 0 ? { providerCorrelation } : {} };
1736
+ }
1737
+ return reconcileAmbiguity(command, contract, authorization, attemptId, providerIdempotencyKey, claim, admission, base, armed, {
1738
+ outcome: "ambiguous",
1739
+ providerCorrelation: claim.providerCorrelation,
1740
+ reason: "Recovered an armed effect claim"
1741
+ });
1742
+ }
1743
+ async function persistSuccess(command, attemptId, digest, providedOutcomes, providerCorrelation, claim, admission, base, attemptParent) {
1744
+ const outcomes = await actionOutcomes(digest, providedOutcomes);
1745
+ const outcomesDigest = await actionOutcomesDigest(outcomes);
1746
+ let durableClaim = claim;
1747
+ if (claim && !admission) throw new PeerExecutionError("AUTHORIZATION_MISMATCH", "Effect claim authorization is unavailable");
1748
+ if (claim && claim.status !== "success_prepared" && claim.status !== "succeeded") {
1749
+ durableClaim = await options.effectClaims.prepareSuccess(claim.claimKey, options.executorDid, claim.fencingEpoch, digest, outcomesDigest, admission, providerCorrelation);
1750
+ }
1751
+ if (durableClaim && (durableClaim.outputDigest !== digest || durableClaim.outcomesDigest !== outcomesDigest)) {
1752
+ throw new PeerExecutionError("EVENT_CONFLICT", "Prepared effect claim does not match the complete Action result evidence");
1753
+ }
1754
+ const success = await append({
1755
+ ...eventBase({ ...base, parents: [attemptParent.eventId] }),
1756
+ payload: {
1757
+ kind: "action.succeeded",
1758
+ attemptId,
1759
+ stepId: command.stepId,
1760
+ outputDigest: digest,
1761
+ outcomes,
1762
+ ...providerCorrelation !== void 0 ? { providerCorrelation } : {},
1763
+ ...durableClaim ? { claimKey: durableClaim.claimKey, fencingEpoch: durableClaim.fencingEpoch } : {}
1764
+ }
1765
+ });
1766
+ if (durableClaim?.status === "success_prepared") {
1767
+ await options.effectClaims.resolve(durableClaim.claimKey, options.executorDid, durableClaim.fencingEpoch, "succeeded", admission, providerCorrelation, success.eventId);
1768
+ }
1769
+ await persistActionOutcomeEvents(success);
1770
+ return { outcome: "succeeded", attemptId, outputDigest: digest, providerCorrelation };
1771
+ }
1772
+ async function persistActionOutcomeEvents(success, existingEvents = []) {
1773
+ if (success.payload.kind !== "action.succeeded") throw new PeerExecutionError("EVENT_CONFLICT", "Action outcomes require accepted success evidence");
1774
+ const successPayload = success.payload;
1775
+ for (const outcome of successPayload.outcomes ?? []) {
1776
+ const exists = existingEvents.some(
1777
+ (event) => event.payload.kind === "action.outcome_emitted" && event.payload.attemptId === successPayload.attemptId && event.payload.stepId === successPayload.stepId && event.payload.name === outcome.name && event.payload.payloadDigest === outcome.payloadDigest && event.parents.includes(success.eventId)
1778
+ );
1779
+ if (exists) continue;
1780
+ await append({
1781
+ ...eventBase({
1782
+ runId: success.runId,
1783
+ definition: success.definition,
1784
+ actor: success.actor,
1785
+ issuedAt: success.occurredAt,
1786
+ idempotencyKey: success.idempotencyKey,
1787
+ commandFingerprint: success.commandFingerprint,
1788
+ parents: [success.eventId],
1789
+ proofs: success.proofReferences
1790
+ }),
1791
+ causationId: success.eventId,
1792
+ payload: {
1793
+ kind: "action.outcome_emitted",
1794
+ attemptId: successPayload.attemptId,
1795
+ stepId: successPayload.stepId,
1796
+ ...outcome
1797
+ }
1798
+ });
1799
+ }
1800
+ }
1801
+ async function reconcileAmbiguity(command, contract, authorization, attemptId, providerIdempotencyKey, claim, admission, base, attemptParent, ambiguous) {
1802
+ const readback = await options.actions.readback({
1803
+ contract,
1804
+ inputs: command.inputs,
1805
+ providerIdempotencyKey,
1806
+ providerCorrelation: ambiguous.providerCorrelation,
1807
+ invocation: authorization
1808
+ });
1809
+ if (readback.outcome === "succeeded") {
1810
+ const digest = await validatedOutputDigest(contract, readback.output);
1811
+ return persistSuccess(command, attemptId, digest, readback.outcomes, readback.providerCorrelation, claim, admission, base, attemptParent);
1812
+ }
1813
+ if (readback.outcome === "not_found" && !claim) {
1814
+ await append({
1815
+ ...eventBase({ ...base, parents: [attemptParent.eventId] }),
1816
+ payload: { kind: "action.failed_before_effect", attemptId, stepId: command.stepId, error: { code: "PROVIDER_CONFIRMED_NOT_FOUND" } }
1817
+ });
1818
+ return { outcome: "failed_before_effect", attemptId };
1819
+ }
1820
+ const correlation = readback.outcome === "unknown" ? readback.providerCorrelation ?? ambiguous.providerCorrelation : ambiguous.providerCorrelation;
1821
+ if (claim && claim.status === "armed") {
1822
+ if (!admission) throw new PeerExecutionError("AUTHORIZATION_MISMATCH", "Effect claim authorization is unavailable");
1823
+ await options.effectClaims.markNeedsVerification(claim.claimKey, options.executorDid, claim.fencingEpoch, admission, correlation);
1824
+ }
1825
+ await append({
1826
+ ...eventBase({ ...base, parents: [attemptParent.eventId] }),
1827
+ payload: {
1828
+ kind: "action.needs_verification",
1829
+ attemptId,
1830
+ stepId: command.stepId,
1831
+ ...correlation !== void 0 ? { providerCorrelation: correlation } : {},
1832
+ reason: ambiguous.reason
1833
+ }
1834
+ });
1835
+ return { outcome: "needs_verification", attemptId, ...correlation !== void 0 ? { providerCorrelation: correlation } : {} };
1836
+ }
1837
+ return { startRun, cancelRun, finalizeRun, executeAttempt };
1838
+ }
1839
+
1840
+ // src/core/lib/flowEngine/vnext/topicReceipts.ts
1841
+ async function persistSignedTopicReceipt(params) {
1842
+ const outbox = params.outbox;
1843
+ const snapshot = JSON.parse(
1844
+ canonicalizeJson({
1845
+ topicRequestId: params.topicRequestId,
1846
+ attemptId: params.attemptId,
1847
+ phase: params.phase,
1848
+ eventId: params.eventId,
1849
+ signedReceipt: params.signedReceipt,
1850
+ persistedAt: params.persistedAt
1851
+ })
1852
+ );
1853
+ const canonicalReceipt = canonicalizeJson(snapshot.signedReceipt);
1854
+ const receiptDigest = await digestCanonicalJson(snapshot.signedReceipt);
1855
+ const receiptId = await deriveReceiptId({
1856
+ topicRequestId: snapshot.topicRequestId,
1857
+ attemptId: snapshot.attemptId,
1858
+ phase: snapshot.phase,
1859
+ eventId: snapshot.eventId
1860
+ });
1861
+ const record = {
1862
+ kind: "qi.flow.topic-receipt-outbox-record",
1863
+ schemaVersion: "1.0",
1864
+ receiptId,
1865
+ receiptDigest,
1866
+ topicRequestId: snapshot.topicRequestId,
1867
+ attemptId: snapshot.attemptId,
1868
+ phase: snapshot.phase,
1869
+ eventId: snapshot.eventId,
1870
+ canonicalReceipt,
1871
+ persistedAt: snapshot.persistedAt
1872
+ };
1873
+ const outcome = await outbox.persist(record);
1874
+ if (outcome === "conflict") throw new Error(`Topic receipt identity ${receiptId} is already bound to different signed bytes`);
1875
+ return record;
1876
+ }
1877
+ async function drainTopicReceiptOutbox(outbox, delivery, now = () => /* @__PURE__ */ new Date(), limit = 100) {
1878
+ const outcomes = [];
1879
+ for (const record of await outbox.pending(limit)) {
1880
+ try {
1881
+ const delivered = await delivery.deliver({
1882
+ receiptId: record.receiptId,
1883
+ receiptDigest: record.receiptDigest,
1884
+ canonicalReceipt: record.canonicalReceipt
1885
+ });
1886
+ await outbox.markDelivered(record.receiptId, record.receiptDigest, { ...delivered, deliveredAt: now().toISOString() });
1887
+ outcomes.push({ receiptId: record.receiptId, outcome: "delivered" });
1888
+ } catch (error) {
1889
+ outcomes.push({ receiptId: record.receiptId, outcome: "failed", error: error instanceof Error ? error.message : String(error) });
1890
+ }
1891
+ }
1892
+ return outcomes;
1893
+ }
1894
+
1895
+ // src/core/lib/flowEngine/vnext/matrixStores.ts
1896
+ var MATRIX_FLOW_EVENT_TYPE = "ixo.qi.flow.event.v1";
1897
+ var MATRIX_FLOW_DEFINITION_ANCHOR_TYPE = "ixo.qi.flow.definition-anchor.v1";
1898
+ var MatrixRoomFlowEventStore = class {
1899
+ constructor(roomId, transport, trust) {
1900
+ this.roomId = roomId;
1901
+ this.transport = transport;
1902
+ this.trust = trust;
1903
+ }
1904
+ async append(event, transactionId) {
1905
+ const verified = await verifyFlowEvent(event, this.trust);
1906
+ const expectedTransactionId = matrixFlowEventTransactionId(verified);
1907
+ if (transactionId !== expectedTransactionId) throw new Error(`Matrix Flow event append requires deterministic transaction ID ${expectedTransactionId}`);
1908
+ const result = await this.transport.append({ roomId: this.roomId, eventType: MATRIX_FLOW_EVENT_TYPE, transactionId, content: { event: verified } });
1909
+ if (result.outcome !== "conflict" && result.eventId !== verified.eventId) {
1910
+ throw new Error(`Matrix Flow event append acknowledged unexpected event ID ${result.eventId}`);
1911
+ }
1912
+ return result;
1913
+ }
1914
+ async inspect(runId, options = {}) {
1915
+ const acceptedEvents = [];
1916
+ const rejectedEvents = [];
1917
+ const seenCursors = /* @__PURE__ */ new Set();
1918
+ let cursor;
1919
+ do {
1920
+ const remaining = options.limit === void 0 ? void 0 : options.limit - acceptedEvents.length;
1921
+ if (remaining !== void 0 && remaining <= 0) break;
1922
+ const page = await this.transport.read({ roomId: this.roomId, runId, afterEventId: options.after, cursor, limit: remaining });
1923
+ for (const carrier of page.carriers) {
1924
+ if (options.limit !== void 0 && acceptedEvents.length >= options.limit) break;
1925
+ let eventSnapshot;
1926
+ try {
1927
+ eventSnapshot = deepFreezeJson(JSON.parse(canonicalizeJson(carrier.event)));
1928
+ } catch {
1929
+ eventSnapshot = deepFreezeJson(structuredClone(carrier.event));
1930
+ rejectedEvents.push({ carrierEventId: carrier.carrierEventId, event: eventSnapshot, reason: "Flow event content cannot be canonicalized" });
1931
+ continue;
1932
+ }
1933
+ try {
1934
+ acceptedEvents.push(await verifyFlowEvent(eventSnapshot, this.trust));
1935
+ } catch (error) {
1936
+ if (!(error instanceof FlowEventValidationError)) throw error;
1937
+ rejectedEvents.push({ carrierEventId: carrier.carrierEventId, event: eventSnapshot, reason: error.message });
1938
+ }
1939
+ }
1940
+ if (page.nextCursor === void 0) break;
1941
+ if (seenCursors.has(page.nextCursor)) throw new Error("Matrix Flow event transport returned a repeated cursor");
1942
+ seenCursors.add(page.nextCursor);
1943
+ cursor = page.nextCursor;
1944
+ } while (true);
1945
+ return { acceptedEvents, rejectedEvents };
1946
+ }
1947
+ async read(runId, options = {}) {
1948
+ return (await this.inspect(runId, options)).acceptedEvents;
1949
+ }
1950
+ };
1951
+ var ANCHOR_DOMAIN = "qi.flow.definition-anchor.v1\0";
1952
+ function anchorSignatureInput(digest) {
1953
+ return new TextEncoder().encode(`${ANCHOR_DOMAIN}${digest}`);
1954
+ }
1955
+ async function signMatrixDefinitionAnchor(payload, signer) {
1956
+ const snapshot = JSON.parse(canonicalizeJson(payload));
1957
+ if (snapshot.anchoredBy !== signer.issuerDid || !signer.verificationMethod.startsWith(`${snapshot.anchoredBy}#`)) {
1958
+ throw new Error("Matrix definition anchor signer does not match the issuer");
1959
+ }
1960
+ const digest = await digestCanonicalJson(snapshot);
1961
+ const signature = await signer.sign(anchorSignatureInput(digest));
1962
+ if (!signature) throw new Error("Matrix definition anchor signer returned an empty signature");
1963
+ return {
1964
+ ...snapshot,
1965
+ integrity: {
1966
+ canonicalization: "RFC8785",
1967
+ digest: { algorithm: "SHA-256", value: digest },
1968
+ signature: { algorithm: signer.algorithm, verificationMethod: signer.verificationMethod, value: signature }
1969
+ }
1970
+ };
1971
+ }
1972
+ async function verifyMatrixDefinitionAnchor(anchor, trust) {
1973
+ const snapshot = JSON.parse(canonicalizeJson(anchor));
1974
+ const { integrity, ...payload } = snapshot;
1975
+ const digest = await digestCanonicalJson(payload);
1976
+ if (digest !== integrity.digest.value) throw new Error("Matrix definition anchor digest mismatch");
1977
+ if (!trust.trustedIssuerDids.includes(payload.anchoredBy)) throw new Error(`Matrix definition anchor issuer is not trusted: ${payload.anchoredBy}`);
1978
+ if (!trust.allowedSignatureAlgorithms.includes(integrity.signature.algorithm)) throw new Error("Matrix definition anchor signature algorithm is not allowed");
1979
+ if (!integrity.signature.verificationMethod.startsWith(`${payload.anchoredBy}#`)) throw new Error("Matrix definition anchor verification method does not belong to the issuer");
1980
+ if (!await trust.verifySignature({
1981
+ issuerDid: payload.anchoredBy,
1982
+ verificationMethod: integrity.signature.verificationMethod,
1983
+ algorithm: integrity.signature.algorithm,
1984
+ data: anchorSignatureInput(digest),
1985
+ signature: integrity.signature.value
1986
+ })) {
1987
+ throw new Error("Matrix definition anchor signature is invalid");
1988
+ }
1989
+ return deepFreezeJson(snapshot);
1990
+ }
1991
+ var EncryptedMatrixFlowDefinitionRevisionRepository = class {
1992
+ constructor(roomId, transport, cipher, anchorSigner, anchorTrust, definitionTrust, now = () => /* @__PURE__ */ new Date()) {
1993
+ this.roomId = roomId;
1994
+ this.transport = transport;
1995
+ this.cipher = cipher;
1996
+ this.anchorSigner = anchorSigner;
1997
+ this.anchorTrust = anchorTrust;
1998
+ this.definitionTrust = definitionTrust;
1999
+ this.now = now;
2000
+ }
2001
+ async publish(revision, expectedParent) {
2002
+ const expectedParentSnapshot = expectedParent ? deepFreezeJson(JSON.parse(canonicalizeJson(expectedParent))) : void 0;
2003
+ const verified = await verifyFlowDefinitionRevision(revision, this.definitionTrust);
2004
+ if (canonicalizeJson(verified.parent ?? null) !== canonicalizeJson(expectedParentSnapshot ?? null)) {
2005
+ return "parent_conflict";
2006
+ }
2007
+ const definition = { ...verified.ref, digest: verified.integrity.digest.value };
2008
+ const plaintext = new TextEncoder().encode(canonicalizeJson(verified));
2009
+ const ciphertext = Uint8Array.from(await this.cipher.encrypt(plaintext));
2010
+ const ciphertextDigest = await digestCanonicalJson(Array.from(ciphertext));
2011
+ const mediaUri = await this.transport.putMedia({
2012
+ ciphertext,
2013
+ ciphertextDigest,
2014
+ contentType: "application/vnd.ixo.qi-flow-revision+json"
2015
+ });
2016
+ const anchor = await signMatrixDefinitionAnchor(
2017
+ {
2018
+ kind: "qi.flow.definition-anchor",
2019
+ schemaVersion: "1.0",
2020
+ definition,
2021
+ mediaUri,
2022
+ ciphertextDigest,
2023
+ encryption: { algorithm: this.cipher.algorithm, keyReference: this.cipher.keyReference },
2024
+ anchoredAt: this.now().toISOString(),
2025
+ anchoredBy: this.anchorSigner.issuerDid
2026
+ },
2027
+ this.anchorSigner
2028
+ );
2029
+ return this.transport.publishAnchor({
2030
+ roomId: this.roomId,
2031
+ eventType: MATRIX_FLOW_DEFINITION_ANCHOR_TYPE,
2032
+ transactionId: `qi-flow-definition-v1-${definition.digest.slice("sha256:".length)}`,
2033
+ anchor,
2034
+ expectedParent: expectedParentSnapshot
2035
+ });
2036
+ }
2037
+ async get(ref) {
2038
+ const candidate = await this.transport.getAnchor(this.roomId, ref.flowId, ref.revision);
2039
+ if (!candidate) return null;
2040
+ const anchor = await verifyMatrixDefinitionAnchor(candidate, this.anchorTrust);
2041
+ if (anchor.definition.digest !== ref.digest || anchor.definition.flowId !== ref.flowId || anchor.definition.revision !== ref.revision) {
2042
+ throw new Error("Matrix definition anchor does not match the requested revision");
2043
+ }
2044
+ if (anchor.encryption.algorithm !== this.cipher.algorithm || anchor.encryption.keyReference !== this.cipher.keyReference) {
2045
+ throw new Error("Matrix definition anchor encryption binding is unavailable");
2046
+ }
2047
+ const ciphertext = await this.transport.getMedia(anchor.mediaUri);
2048
+ const ciphertextDigest = await digestCanonicalJson(Array.from(ciphertext));
2049
+ if (ciphertextDigest !== anchor.ciphertextDigest) throw new Error("Encrypted Matrix revision media digest mismatch");
2050
+ const plaintext = await this.cipher.decrypt(ciphertext);
2051
+ const revision = JSON.parse(new TextDecoder().decode(plaintext));
2052
+ const verified = await verifyFlowDefinitionRevision(revision, this.definitionTrust);
2053
+ if (verified.ref.flowId !== anchor.definition.flowId || verified.ref.revision !== anchor.definition.revision || verified.integrity.digest.value !== anchor.definition.digest) {
2054
+ throw new Error("Decrypted Matrix revision does not match its signed anchor");
2055
+ }
2056
+ return verified;
2057
+ }
2058
+ };
2059
+
2060
+ // src/core/lib/flowEngine/vnext/composio.ts
2061
+ var ComposioContractMismatchError = class extends Error {
2062
+ constructor(reason) {
2063
+ super(`Composio Action is unavailable: ${reason}`);
2064
+ this.reason = reason;
2065
+ this.name = "ComposioContractMismatchError";
2066
+ }
2067
+ };
2068
+ var COMPOSIO_AVAILABILITY_SIGNATURE_DOMAIN = "qi.composio.action-availability.v1\0";
2069
+ function availabilitySignatureInput(digest) {
2070
+ return new TextEncoder().encode(`${COMPOSIO_AVAILABILITY_SIGNATURE_DOMAIN}${digest}`);
2071
+ }
2072
+ function assertAvailabilityPayload(payload) {
2073
+ if (payload.kind !== "qi.composio.action-availability" || payload.schemaVersion !== "1.0") throw new ComposioContractMismatchError("unsupported availability contract");
2074
+ if (!payload.issuedBy || !payload.actionContractDigest || !payload.handlerIdentity || !payload.toolSlug || !payload.accountBinding.bindingId || !payload.accountBinding.connectedAccountReference || !payload.ucanAudience) {
2075
+ throw new ComposioContractMismatchError("availability identity and execution binding are required");
2076
+ }
2077
+ if (payload.readback !== "unavailable" && !payload.readbackToolSlug?.trim()) {
2078
+ throw new ComposioContractMismatchError("required or supported readback must declare an explicit readback tool");
2079
+ }
2080
+ const checkedAt = Date.parse(payload.checkedAt);
2081
+ const expiresAt = Date.parse(payload.expiresAt);
2082
+ if (!Number.isFinite(checkedAt) || !Number.isFinite(expiresAt) || expiresAt <= checkedAt) {
2083
+ throw new ComposioContractMismatchError("availability timestamps are invalid");
2084
+ }
2085
+ }
2086
+ async function computeComposioAvailabilityDigest(payload) {
2087
+ assertAvailabilityPayload(payload);
2088
+ return await digestCanonicalJson(payload);
2089
+ }
2090
+ async function signComposioActionAvailability(payload, signer) {
2091
+ const snapshot = JSON.parse(canonicalizeJson(payload));
2092
+ assertAvailabilityPayload(snapshot);
2093
+ if (signer.issuerDid !== snapshot.issuedBy || !signer.verificationMethod.startsWith(`${snapshot.issuedBy}#`)) {
2094
+ throw new ComposioContractMismatchError("availability signer does not match the issuer");
2095
+ }
2096
+ const digest = await computeComposioAvailabilityDigest(snapshot);
2097
+ const signature = await signer.sign(availabilitySignatureInput(digest));
2098
+ if (!signature) throw new ComposioContractMismatchError("availability signer returned an empty signature");
2099
+ return {
2100
+ ...snapshot,
2101
+ integrity: {
2102
+ canonicalization: "RFC8785",
2103
+ digest: { algorithm: "SHA-256", value: digest },
2104
+ signature: { algorithm: signer.algorithm, verificationMethod: signer.verificationMethod, value: signature }
2105
+ }
2106
+ };
2107
+ }
2108
+ async function verifyComposioActionAvailability(candidate, policy, now = /* @__PURE__ */ new Date()) {
2109
+ const snapshot = JSON.parse(canonicalizeJson(candidate));
2110
+ const { integrity, ...payload } = snapshot;
2111
+ assertAvailabilityPayload(payload);
2112
+ const digest = await computeComposioAvailabilityDigest(payload);
2113
+ if (digest !== integrity.digest.value) throw new ComposioContractMismatchError("availability digest does not match its content");
2114
+ if (!policy.trustedIssuerDids.includes(payload.issuedBy)) throw new ComposioContractMismatchError("availability issuer is not trusted");
2115
+ if (policy.revokedIssuerDids?.includes(payload.issuedBy)) throw new ComposioContractMismatchError("availability issuer is revoked");
2116
+ if (!policy.allowedSignatureAlgorithms.includes(integrity.signature.algorithm)) throw new ComposioContractMismatchError("availability signature algorithm is not allowed");
2117
+ if (!integrity.signature.verificationMethod.startsWith(`${payload.issuedBy}#`)) {
2118
+ throw new ComposioContractMismatchError("availability verification method does not belong to the issuer");
2119
+ }
2120
+ if (Date.parse(payload.expiresAt) <= now.getTime()) throw new ComposioContractMismatchError("availability contract is expired");
2121
+ const valid = await policy.verifySignature({
2122
+ issuerDid: payload.issuedBy,
2123
+ verificationMethod: integrity.signature.verificationMethod,
2124
+ algorithm: integrity.signature.algorithm,
2125
+ data: availabilitySignatureInput(digest),
2126
+ signature: integrity.signature.value
2127
+ });
2128
+ if (!valid) throw new ComposioContractMismatchError("availability signature verification failed");
2129
+ return deepFreezeJson(snapshot);
2130
+ }
2131
+ async function assertAvailability(contract, availability, authorization, now) {
2132
+ if (Date.parse(availability.expiresAt) <= now.getTime()) throw new ComposioContractMismatchError("availability contract is expired");
2133
+ if (availability.status !== "available") throw new ComposioContractMismatchError(availability.unavailableReasons.join("; ") || "availability endpoint is unhealthy");
2134
+ if (availability.actionContractDigest !== contract.contractDigest) throw new ComposioContractMismatchError("Action contract digest mismatch");
2135
+ if (availability.handlerVersion !== contract.handlerVersion) throw new ComposioContractMismatchError("handler version mismatch");
2136
+ if (await digestCanonicalJson(contract.inputSchema) !== availability.inputSchemaDigest) throw new ComposioContractMismatchError("input schema digest mismatch");
2137
+ if (await digestCanonicalJson(contract.outputSchema) !== availability.outputSchemaDigest) throw new ComposioContractMismatchError("output schema digest mismatch");
2138
+ if (availability.providerIdempotency !== contract.idempotency.providerKey) throw new ComposioContractMismatchError("provider idempotency contract mismatch");
2139
+ if (availability.readback !== contract.idempotency.readback || availability.compensation !== contract.idempotency.compensation) {
2140
+ throw new ComposioContractMismatchError("recovery procedure mismatch");
2141
+ }
2142
+ if (availability.readback !== "unavailable" && !availability.readbackToolSlug?.trim()) {
2143
+ throw new ComposioContractMismatchError("required or supported readback must declare an explicit readback tool");
2144
+ }
2145
+ const provider = authorization.provider;
2146
+ if (!provider) throw new ComposioContractMismatchError("verified provider invocation is missing");
2147
+ if (provider.audience !== availability.ucanAudience || provider.can !== "composio/execute" || provider.with !== `ixo:composio:binding:${availability.accountBinding.bindingId}` || provider.actionContractDigest !== contract.contractDigest || provider.definitionDigest !== authorization.flow.definitionDigest || provider.idempotencyKey !== authorization.flow.idempotencyKey) {
2148
+ throw new ComposioContractMismatchError("provider UCAN does not authorize this Flow command and Action");
2149
+ }
2150
+ }
2151
+ var ManifestBoundComposioActionAdapter = class {
2152
+ constructor(availability, gateway, now = () => /* @__PURE__ */ new Date()) {
2153
+ this.availability = availability;
2154
+ this.gateway = gateway;
2155
+ this.now = now;
2156
+ }
2157
+ async invoke(request) {
2158
+ const available = await this.availability.resolve(request.contract.contractDigest);
2159
+ await assertAvailability(request.contract, available, request.invocation, this.now());
2160
+ request.assertEffectAllowed();
2161
+ return this.gateway.execute({
2162
+ toolSlug: available.toolSlug,
2163
+ bindingId: available.accountBinding.bindingId,
2164
+ connectedAccountReference: available.accountBinding.connectedAccountReference,
2165
+ arguments: request.inputs,
2166
+ providerIdempotencyKey: request.providerIdempotencyKey,
2167
+ providerInvocationReference: request.invocation.provider.cid
2168
+ });
2169
+ }
2170
+ async readback(request) {
2171
+ const available = await this.availability.resolve(request.contract.contractDigest);
2172
+ await assertAvailability(request.contract, available, request.invocation, this.now());
2173
+ if (!available.readbackToolSlug) return { outcome: "unknown", providerCorrelation: request.providerCorrelation, reason: "Manifest declares no explicit readback tool" };
2174
+ return this.gateway.readback({
2175
+ toolSlug: available.readbackToolSlug,
2176
+ bindingId: available.accountBinding.bindingId,
2177
+ connectedAccountReference: available.accountBinding.connectedAccountReference,
2178
+ arguments: request.inputs,
2179
+ providerIdempotencyKey: request.providerIdempotencyKey,
2180
+ providerCorrelation: request.providerCorrelation,
2181
+ providerInvocationReference: request.invocation.provider.cid
2182
+ });
2183
+ }
2184
+ };
2185
+
2186
+ // src/core/lib/flowEngine/vnext/runProjections.ts
2187
+ var FLOW_RUN_PROJECTIONS_MAP_KEY = "qi.flow.runProjections";
2188
+ var FLOW_RUN_PROJECTION_KEY_SEPARATOR = "::";
2189
+ var RUN_STATUSES = /* @__PURE__ */ new Set(["queued", "running", "cancelling", "needs_verification", "completed", "failed", "cancelled"]);
2190
+ var EFFECT_DISPOSITIONS = /* @__PURE__ */ new Set(["not_started", "armed", "succeeded", "failed_before_effect", "needs_verification"]);
2191
+ function isRecord2(value) {
2192
+ return value !== null && typeof value === "object" && !Array.isArray(value);
2193
+ }
2194
+ function isStringArray2(value) {
2195
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string");
2196
+ }
2197
+ function isDigest(value) {
2198
+ return typeof value === "string" && /^sha256:[0-9a-f]{64}$/u.test(value);
2199
+ }
2200
+ function hasValidProjectionShape(value) {
2201
+ if (!isRecord2(value)) return false;
2202
+ if (value.kind !== "qi.flow.run-projection" || value.schemaVersion !== "1.0" || typeof value.runId !== "string" || !isDigest(value.sourceEventSetDigest)) return false;
2203
+ if (!isRecord2(value.definition) || typeof value.definition.flowId !== "string" || typeof value.definition.revision !== "string" || !isDigest(value.definition.digest))
2204
+ return false;
2205
+ const sourceEventIds = value.sourceEventIds;
2206
+ if (!isStringArray2(sourceEventIds) || canonicalizeJson(sourceEventIds) !== canonicalizeJson([...new Set(sourceEventIds)].sort())) return false;
2207
+ const headEventIds = value.headEventIds;
2208
+ if (!isStringArray2(headEventIds) || canonicalizeJson(headEventIds) !== canonicalizeJson([...new Set(headEventIds)].sort()) || !headEventIds.every((eventId) => sourceEventIds.includes(eventId)))
2209
+ return false;
2210
+ if (typeof value.status !== "string" || !RUN_STATUSES.has(value.status) || typeof value.cancelRequested !== "boolean") return false;
2211
+ const timeline = value.timeline;
2212
+ if (!isRecord2(value.attempts) || !Array.isArray(timeline) || !Array.isArray(value.invalidEvents)) return false;
2213
+ for (const [attemptId, attempt] of Object.entries(value.attempts)) {
2214
+ if (!isRecord2(attempt) || attempt.attemptId !== attemptId || typeof attempt.stepId !== "string" || typeof attempt.disposition !== "string") return false;
2215
+ if (!EFFECT_DISPOSITIONS.has(attempt.disposition) || !isStringArray2(attempt.receiptIds) || !Array.isArray(attempt.outcomes)) return false;
2216
+ if (attempt.outputDigest !== void 0 && !isDigest(attempt.outputDigest)) return false;
2217
+ if (attempt.providerCorrelation !== void 0 && typeof attempt.providerCorrelation !== "string") return false;
2218
+ if (!attempt.outcomes.every((outcome) => isRecord2(outcome) && typeof outcome.name === "string" && isRecord2(outcome.payload) && isDigest(outcome.payloadDigest))) return false;
2219
+ }
2220
+ if (!timeline.every(
2221
+ (entry) => isRecord2(entry) && typeof entry.eventId === "string" && sourceEventIds.includes(entry.eventId) && typeof entry.kind === "string" && typeof entry.occurredAt === "string" && typeof entry.actor === "string" && typeof entry.producer === "string" && isStringArray2(entry.parents) && (entry.attemptId === void 0 || typeof entry.attemptId === "string") && (entry.stepId === void 0 || typeof entry.stepId === "string")
2222
+ ))
2223
+ return false;
2224
+ if (!headEventIds.every((eventId) => timeline.some((entry) => isRecord2(entry) && entry.eventId === eventId))) return false;
2225
+ return value.invalidEvents.every((entry) => isRecord2(entry) && typeof entry.eventId === "string" && sourceEventIds.includes(entry.eventId) && typeof entry.reason === "string");
2226
+ }
2227
+ function orderAcceptedEvents(events, acceptedEventIds) {
2228
+ const accepted = new Set(acceptedEventIds);
2229
+ const byId = /* @__PURE__ */ new Map();
2230
+ for (const event of events) if (accepted.has(event.eventId) && !byId.has(event.eventId)) byId.set(event.eventId, event);
2231
+ const indegree = new Map([...byId.keys()].map((eventId) => [eventId, 0]));
2232
+ const children = /* @__PURE__ */ new Map();
2233
+ for (const event of byId.values()) {
2234
+ for (const parent of event.parents) {
2235
+ if (!byId.has(parent)) continue;
2236
+ indegree.set(event.eventId, (indegree.get(event.eventId) ?? 0) + 1);
2237
+ children.set(parent, [...children.get(parent) ?? [], event.eventId]);
2238
+ }
2239
+ }
2240
+ const ready = [...byId.keys()].filter((eventId) => indegree.get(eventId) === 0).sort();
2241
+ const ordered = [];
2242
+ while (ready.length > 0) {
2243
+ const eventId = ready.shift();
2244
+ const event = byId.get(eventId);
2245
+ if (!event) continue;
2246
+ ordered.push(event);
2247
+ for (const childId of (children.get(eventId) ?? []).sort()) {
2248
+ const next = (indegree.get(childId) ?? 0) - 1;
2249
+ indegree.set(childId, next);
2250
+ if (next === 0) {
2251
+ ready.push(childId);
2252
+ ready.sort();
2253
+ }
2254
+ }
2255
+ }
2256
+ return ordered;
2257
+ }
2258
+ function projectAttempt(attempt) {
2259
+ return {
2260
+ attemptId: attempt.attemptId,
2261
+ stepId: attempt.stepId,
2262
+ disposition: attempt.disposition,
2263
+ receiptIds: [...attempt.receiptIds],
2264
+ outcomes: attempt.outcomes.map((outcome) => ({ ...outcome, payload: { ...outcome.payload } })),
2265
+ ...attempt.outputDigest !== void 0 ? { outputDigest: attempt.outputDigest } : {},
2266
+ ...attempt.providerCorrelation !== void 0 ? { providerCorrelation: attempt.providerCorrelation } : {}
2267
+ };
2268
+ }
2269
+ function projectTimelineEntry(event) {
2270
+ const payload = event.payload;
2271
+ return {
2272
+ eventId: event.eventId,
2273
+ kind: payload.kind,
2274
+ occurredAt: event.occurredAt,
2275
+ actor: event.actor,
2276
+ producer: event.producer,
2277
+ parents: [...event.parents],
2278
+ ..."attemptId" in payload ? { attemptId: payload.attemptId } : {},
2279
+ ..."stepId" in payload ? { stepId: payload.stepId } : {}
2280
+ };
2281
+ }
2282
+ async function projectFlowRun(genesis, events) {
2283
+ const genesisSnapshot = deepFreezeJson(JSON.parse(canonicalizeJson(genesis)));
2284
+ const eventSnapshot = deepFreezeJson(JSON.parse(canonicalizeJson(events)));
2285
+ const reduced = reduceFlowEvents(genesisSnapshot, eventSnapshot);
2286
+ const sourceEventIds = [...new Set(eventSnapshot.map((event) => event.eventId))].sort();
2287
+ const sourceEventSetDigest = await digestCanonicalJson(sourceEventIds);
2288
+ const ordered = orderAcceptedEvents(eventSnapshot, reduced.acceptedEventIds);
2289
+ const accepted = new Set(reduced.acceptedEventIds);
2290
+ const referencedParents = new Set(ordered.flatMap((event) => event.parents.filter((parent) => accepted.has(parent))));
2291
+ const headEventIds = ordered.map((event) => event.eventId).filter((eventId) => !referencedParents.has(eventId)).sort();
2292
+ const projection = {
2293
+ kind: "qi.flow.run-projection",
2294
+ schemaVersion: "1.0",
2295
+ runId: reduced.runId,
2296
+ definition: reduced.definition,
2297
+ sourceEventIds,
2298
+ sourceEventSetDigest,
2299
+ headEventIds,
2300
+ status: reduced.status,
2301
+ cancelRequested: reduced.cancelRequested,
2302
+ attempts: Object.fromEntries(Object.entries(reduced.attempts).map(([id, attempt]) => [id, projectAttempt(attempt)])),
2303
+ timeline: ordered.map(projectTimelineEntry),
2304
+ invalidEvents: reduced.invalidEvents.map((event) => ({ ...event }))
2305
+ };
2306
+ return deepFreezeJson(JSON.parse(canonicalizeJson(projection)));
2307
+ }
2308
+ async function snapshotProjection(value) {
2309
+ if (!value || typeof value !== "object") return null;
2310
+ let snapshot;
2311
+ try {
2312
+ snapshot = JSON.parse(canonicalizeJson(value));
2313
+ } catch {
2314
+ return null;
2315
+ }
2316
+ if (!hasValidProjectionShape(snapshot)) return null;
2317
+ if (await digestCanonicalJson(snapshot.sourceEventIds) !== snapshot.sourceEventSetDigest) return null;
2318
+ return deepFreezeJson(snapshot);
2319
+ }
2320
+ function canonicalStoredProjection(value) {
2321
+ try {
2322
+ return canonicalizeJson(value);
2323
+ } catch {
2324
+ return null;
2325
+ }
2326
+ }
2327
+ function flowRunProjectionStorageKey(runId, sourceEventSetDigest) {
2328
+ return `${encodeURIComponent(runId)}${FLOW_RUN_PROJECTION_KEY_SEPARATOR}${sourceEventSetDigest}`;
2329
+ }
2330
+ function projectionStoragePrefix(runId) {
2331
+ return `${encodeURIComponent(runId)}${FLOW_RUN_PROJECTION_KEY_SEPARATOR}`;
2332
+ }
2333
+ async function storedRunProjections(map, runId) {
2334
+ const projections = [];
2335
+ const pending = [];
2336
+ const prefix = projectionStoragePrefix(runId);
2337
+ map.forEach((value, key) => {
2338
+ if (!key.startsWith(prefix)) return;
2339
+ pending.push(
2340
+ snapshotProjection(value).then((projection) => {
2341
+ if (projection?.runId === runId && key === flowRunProjectionStorageKey(runId, projection.sourceEventSetDigest)) projections.push(projection);
2342
+ })
2343
+ );
2344
+ });
2345
+ await Promise.all(pending);
2346
+ return projections;
2347
+ }
2348
+ async function readFlowRunProjection(doc, genesis, events) {
2349
+ const map = doc.share.get(FLOW_RUN_PROJECTIONS_MAP_KEY);
2350
+ if (!isYMapLike(map)) return null;
2351
+ const expected = await projectFlowRun(genesis, events);
2352
+ const projection = await snapshotProjection(map.get(flowRunProjectionStorageKey(expected.runId, expected.sourceEventSetDigest)));
2353
+ if (!projection || projection.runId !== expected.runId) return null;
2354
+ return canonicalizeJson(projection) === canonicalizeJson(expected) ? projection : null;
2355
+ }
2356
+ async function repairFlowRunProjection(doc, genesis, events, verifiedEvidence = events) {
2357
+ const projection = await projectFlowRun(genesis, events);
2358
+ const canonicalProjection = canonicalizeJson(projection);
2359
+ const map = doc.getMap(FLOW_RUN_PROJECTIONS_MAP_KEY);
2360
+ const storageKey = flowRunProjectionStorageKey(projection.runId, projection.sourceEventSetDigest);
2361
+ while (true) {
2362
+ const observedValue = map.get(storageKey);
2363
+ const observedCanonical = canonicalStoredProjection(observedValue);
2364
+ const current = await snapshotProjection(observedValue);
2365
+ if (canonicalStoredProjection(map.get(storageKey)) !== observedCanonical) continue;
2366
+ const incomingIds = new Set(projection.sourceEventIds);
2367
+ const verifiedIds = new Set(verifiedEvidence.map((event) => event.eventId));
2368
+ const blocking = (await storedRunProjections(map, projection.runId)).filter((candidate) => candidate.sourceEventIds.every((eventId) => verifiedIds.has(eventId))).filter((candidate) => !candidate.sourceEventIds.every((eventId) => incomingIds.has(eventId))).sort((left, right) => left.sourceEventSetDigest.localeCompare(right.sourceEventSetDigest))[0];
2369
+ if (canonicalStoredProjection(map.get(storageKey)) !== observedCanonical) continue;
2370
+ if (blocking) {
2371
+ return { outcome: "stale", currentSourceEventSetDigest: blocking.sourceEventSetDigest };
2372
+ }
2373
+ if (current && canonicalizeJson(current) === canonicalProjection) return { outcome: "unchanged" };
2374
+ let changedWhileWriting = false;
2375
+ doc.transact(() => {
2376
+ if (canonicalStoredProjection(map.get(storageKey)) !== observedCanonical) {
2377
+ changedWhileWriting = true;
2378
+ return;
2379
+ }
2380
+ map.set(storageKey, JSON.parse(canonicalProjection));
2381
+ map.delete(projection.runId);
2382
+ }, "vnext-run-projection-repair");
2383
+ if (changedWhileWriting) continue;
2384
+ return {
2385
+ outcome: "repaired",
2386
+ ...current ? { previousSourceEventSetDigest: current.sourceEventSetDigest } : {}
2387
+ };
2388
+ }
2389
+ }
2390
+
2391
+ export {
2392
+ LegacyFlowFrozenError,
2393
+ assertLegacyFlowOperationAllowed,
2394
+ deepFreezeJson,
2395
+ canonicalizeJson,
2396
+ digestCanonicalJson,
2397
+ FlowDefinitionVerificationError,
2398
+ computeExecutionPolicyDigest,
2399
+ signExecutionPolicy,
2400
+ verifyExecutionPolicy,
2401
+ computeFlowDefinitionDigest,
2402
+ signFlowDefinitionRevision,
2403
+ verifyFlowDefinitionRevision,
2404
+ FLOW_CAPABILITIES,
2405
+ buildFlowResourceUri,
2406
+ deriveRunId,
2407
+ deriveAttemptId,
2408
+ deriveEventId,
2409
+ deriveReceiptId,
2410
+ deriveEffectClaimKey,
2411
+ FlowEventValidationError,
2412
+ signFlowEvent,
2413
+ verifyFlowEvent,
2414
+ matrixFlowEventTransactionId,
2415
+ reduceFlowEvents,
2416
+ fingerprintFlowCommand,
2417
+ EffectClaimTransitionError,
2418
+ claimEffect,
2419
+ renewEffectClaim,
2420
+ armEffectClaim,
2421
+ prepareEffectSuccess,
2422
+ resolveEffectClaim,
2423
+ markEffectNeedsVerification,
2424
+ ActionContractResolutionError,
2425
+ computeActionContractDigest,
2426
+ HistoricalManifestActionContractResolver,
2427
+ UNIVERSAL_ACTION_COMPLETED_OUTCOME,
2428
+ PeerExecutionError,
2429
+ createPeerExecutor,
2430
+ persistSignedTopicReceipt,
2431
+ drainTopicReceiptOutbox,
2432
+ MATRIX_FLOW_EVENT_TYPE,
2433
+ MATRIX_FLOW_DEFINITION_ANCHOR_TYPE,
2434
+ MatrixRoomFlowEventStore,
2435
+ signMatrixDefinitionAnchor,
2436
+ verifyMatrixDefinitionAnchor,
2437
+ EncryptedMatrixFlowDefinitionRevisionRepository,
2438
+ ComposioContractMismatchError,
2439
+ computeComposioAvailabilityDigest,
2440
+ signComposioActionAvailability,
2441
+ verifyComposioActionAvailability,
2442
+ ManifestBoundComposioActionAdapter,
2443
+ FLOW_RUN_PROJECTIONS_MAP_KEY,
2444
+ projectFlowRun,
2445
+ flowRunProjectionStorageKey,
2446
+ readFlowRunProjection,
2447
+ repairFlowRunProjection
2448
+ };
2449
+ //# sourceMappingURL=chunk-RRYBAE6E.js.map