@emilia-protocol/gate 0.11.0 → 0.14.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 (425) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +310 -0
  3. package/action-control-manifest.js +3 -268
  4. package/action-escrow-custodian.js +3 -394
  5. package/action-escrow-evidence.js +3 -858
  6. package/action-escrow-package.js +3 -1668
  7. package/action-escrow-postgres.js +3 -337
  8. package/action-escrow-state.js +3 -396
  9. package/action-escrow-verifiers.js +3 -331
  10. package/action-escrow.js +3 -2447
  11. package/action-packs.js +3 -140
  12. package/adapters/_kit.js +3 -104
  13. package/adapters/aws.js +3 -108
  14. package/adapters/cloudflare.js +3 -54
  15. package/adapters/gcp.js +3 -70
  16. package/adapters/github.js +3 -109
  17. package/adapters/jira.js +3 -55
  18. package/adapters/k8s.js +3 -70
  19. package/adapters/linear.js +3 -55
  20. package/adapters/salesforce.js +3 -55
  21. package/adapters/stripe.js +3 -81
  22. package/adapters/supabase.js +3 -121
  23. package/adapters/terraform.js +3 -59
  24. package/adapters/vercel.js +3 -84
  25. package/aec-execution.js +3 -312
  26. package/breakglass.js +3 -582
  27. package/capability-receipt.js +4 -0
  28. package/cf1-conformance.js +3 -106
  29. package/challenge-store.js +3 -69
  30. package/control-plane.js +3 -340
  31. package/coverage.js +3 -721
  32. package/demo.mjs +1 -1
  33. package/deployment-attestation.js +3 -247
  34. package/dist/action-control-manifest.d.ts +82 -0
  35. package/dist/action-control-manifest.d.ts.map +1 -0
  36. package/dist/action-control-manifest.js +422 -0
  37. package/dist/action-control-manifest.js.map +1 -0
  38. package/dist/action-escrow-custodian.d.ts +74 -0
  39. package/dist/action-escrow-custodian.d.ts.map +1 -0
  40. package/dist/action-escrow-custodian.js +363 -0
  41. package/dist/action-escrow-custodian.js.map +1 -0
  42. package/dist/action-escrow-evidence.d.ts +130 -0
  43. package/dist/action-escrow-evidence.d.ts.map +1 -0
  44. package/dist/action-escrow-evidence.js +1012 -0
  45. package/dist/action-escrow-evidence.js.map +1 -0
  46. package/dist/action-escrow-package.d.ts +10 -0
  47. package/dist/action-escrow-package.d.ts.map +1 -0
  48. package/dist/action-escrow-package.js +1583 -0
  49. package/dist/action-escrow-package.js.map +1 -0
  50. package/dist/action-escrow-postgres.d.ts +62 -0
  51. package/dist/action-escrow-postgres.d.ts.map +1 -0
  52. package/dist/action-escrow-postgres.js +339 -0
  53. package/dist/action-escrow-postgres.js.map +1 -0
  54. package/dist/action-escrow-state.d.ts +141 -0
  55. package/dist/action-escrow-state.d.ts.map +1 -0
  56. package/dist/action-escrow-state.js +413 -0
  57. package/dist/action-escrow-state.js.map +1 -0
  58. package/dist/action-escrow-verifiers.d.ts +65 -0
  59. package/dist/action-escrow-verifiers.d.ts.map +1 -0
  60. package/dist/action-escrow-verifiers.js +421 -0
  61. package/dist/action-escrow-verifiers.js.map +1 -0
  62. package/dist/action-escrow.d.ts +112 -0
  63. package/dist/action-escrow.d.ts.map +1 -0
  64. package/dist/action-escrow.js +2661 -0
  65. package/dist/action-escrow.js.map +1 -0
  66. package/dist/action-packs.d.ts +54 -0
  67. package/dist/action-packs.d.ts.map +1 -0
  68. package/dist/action-packs.js +143 -0
  69. package/dist/action-packs.js.map +1 -0
  70. package/dist/adapters/_kit.d.ts +50 -0
  71. package/dist/adapters/_kit.d.ts.map +1 -0
  72. package/dist/adapters/_kit.js +98 -0
  73. package/dist/adapters/_kit.js.map +1 -0
  74. package/dist/adapters/aws.d.ts +158 -0
  75. package/dist/adapters/aws.d.ts.map +1 -0
  76. package/dist/adapters/aws.js +136 -0
  77. package/dist/adapters/aws.js.map +1 -0
  78. package/dist/adapters/cloudflare.d.ts +116 -0
  79. package/dist/adapters/cloudflare.d.ts.map +1 -0
  80. package/dist/adapters/cloudflare.js +75 -0
  81. package/dist/adapters/cloudflare.js.map +1 -0
  82. package/dist/adapters/gcp.d.ts +139 -0
  83. package/dist/adapters/gcp.d.ts.map +1 -0
  84. package/dist/adapters/gcp.js +69 -0
  85. package/dist/adapters/gcp.js.map +1 -0
  86. package/dist/adapters/github.d.ts +123 -0
  87. package/dist/adapters/github.d.ts.map +1 -0
  88. package/dist/adapters/github.js +105 -0
  89. package/dist/adapters/github.js.map +1 -0
  90. package/dist/adapters/jira.d.ts +109 -0
  91. package/dist/adapters/jira.d.ts.map +1 -0
  92. package/dist/adapters/jira.js +54 -0
  93. package/dist/adapters/jira.js.map +1 -0
  94. package/dist/adapters/k8s.d.ts +139 -0
  95. package/dist/adapters/k8s.d.ts.map +1 -0
  96. package/dist/adapters/k8s.js +69 -0
  97. package/dist/adapters/k8s.js.map +1 -0
  98. package/dist/adapters/linear.d.ts +109 -0
  99. package/dist/adapters/linear.d.ts.map +1 -0
  100. package/dist/adapters/linear.js +54 -0
  101. package/dist/adapters/linear.js.map +1 -0
  102. package/dist/adapters/salesforce.d.ts +109 -0
  103. package/dist/adapters/salesforce.d.ts.map +1 -0
  104. package/dist/adapters/salesforce.js +54 -0
  105. package/dist/adapters/salesforce.js.map +1 -0
  106. package/dist/adapters/stripe.d.ts +116 -0
  107. package/dist/adapters/stripe.d.ts.map +1 -0
  108. package/dist/adapters/stripe.js +77 -0
  109. package/dist/adapters/stripe.js.map +1 -0
  110. package/dist/adapters/supabase.d.ts +127 -0
  111. package/dist/adapters/supabase.d.ts.map +1 -0
  112. package/dist/adapters/supabase.js +112 -0
  113. package/dist/adapters/supabase.js.map +1 -0
  114. package/dist/adapters/terraform.d.ts +109 -0
  115. package/dist/adapters/terraform.d.ts.map +1 -0
  116. package/dist/adapters/terraform.js +58 -0
  117. package/dist/adapters/terraform.js.map +1 -0
  118. package/dist/adapters/vercel.d.ts +114 -0
  119. package/dist/adapters/vercel.d.ts.map +1 -0
  120. package/dist/adapters/vercel.js +81 -0
  121. package/dist/adapters/vercel.js.map +1 -0
  122. package/dist/aec-execution.d.ts +107 -0
  123. package/dist/aec-execution.d.ts.map +1 -0
  124. package/dist/aec-execution.js +334 -0
  125. package/dist/aec-execution.js.map +1 -0
  126. package/dist/breakglass.d.ts +205 -0
  127. package/dist/breakglass.d.ts.map +1 -0
  128. package/dist/breakglass.js +627 -0
  129. package/dist/breakglass.js.map +1 -0
  130. package/dist/capability-receipt.d.ts +601 -0
  131. package/dist/capability-receipt.d.ts.map +1 -0
  132. package/dist/capability-receipt.js +1177 -0
  133. package/dist/capability-receipt.js.map +1 -0
  134. package/dist/cf1-conformance.d.ts +83 -0
  135. package/dist/cf1-conformance.d.ts.map +1 -0
  136. package/dist/cf1-conformance.js +94 -0
  137. package/dist/cf1-conformance.js.map +1 -0
  138. package/dist/challenge-store.d.ts +20 -0
  139. package/dist/challenge-store.d.ts.map +1 -0
  140. package/dist/challenge-store.js +62 -0
  141. package/dist/challenge-store.js.map +1 -0
  142. package/dist/control-plane.d.ts +136 -0
  143. package/dist/control-plane.d.ts.map +1 -0
  144. package/dist/control-plane.js +349 -0
  145. package/dist/control-plane.js.map +1 -0
  146. package/dist/coverage.d.ts +156 -0
  147. package/dist/coverage.d.ts.map +1 -0
  148. package/dist/coverage.js +768 -0
  149. package/dist/coverage.js.map +1 -0
  150. package/dist/deployment-attestation.d.ts +93 -0
  151. package/dist/deployment-attestation.d.ts.map +1 -0
  152. package/dist/deployment-attestation.js +262 -0
  153. package/dist/deployment-attestation.js.map +1 -0
  154. package/dist/eg1-conformance.d.ts +286 -0
  155. package/dist/eg1-conformance.d.ts.map +1 -0
  156. package/dist/eg1-conformance.js +379 -0
  157. package/dist/eg1-conformance.js.map +1 -0
  158. package/dist/enterprise.d.ts +88 -0
  159. package/dist/enterprise.d.ts.map +1 -0
  160. package/dist/enterprise.js +194 -0
  161. package/dist/enterprise.js.map +1 -0
  162. package/dist/evidence-postgres.d.ts +123 -0
  163. package/dist/evidence-postgres.d.ts.map +1 -0
  164. package/dist/evidence-postgres.js +343 -0
  165. package/dist/evidence-postgres.js.map +1 -0
  166. package/dist/evidence.d.ts +113 -0
  167. package/dist/evidence.d.ts.map +1 -0
  168. package/dist/evidence.js +369 -0
  169. package/dist/evidence.js.map +1 -0
  170. package/dist/execution-binding.d.ts +49 -0
  171. package/dist/execution-binding.d.ts.map +1 -0
  172. package/dist/execution-binding.js +243 -0
  173. package/dist/execution-binding.js.map +1 -0
  174. package/dist/formal-runtime-map.d.ts +42 -0
  175. package/dist/formal-runtime-map.d.ts.map +1 -0
  176. package/dist/formal-runtime-map.js +23 -0
  177. package/dist/formal-runtime-map.js.map +1 -0
  178. package/dist/index.d.ts +1003 -0
  179. package/dist/index.d.ts.map +1 -0
  180. package/dist/index.js +1737 -0
  181. package/dist/index.js.map +1 -0
  182. package/dist/key-registry.d.ts +60 -0
  183. package/dist/key-registry.d.ts.map +1 -0
  184. package/dist/key-registry.js +144 -0
  185. package/dist/key-registry.js.map +1 -0
  186. package/dist/mcp.d.ts +53 -0
  187. package/dist/mcp.d.ts.map +1 -0
  188. package/dist/mcp.js +112 -0
  189. package/dist/mcp.js.map +1 -0
  190. package/dist/metering.d.ts +80 -0
  191. package/dist/metering.d.ts.map +1 -0
  192. package/dist/metering.js +227 -0
  193. package/dist/metering.js.map +1 -0
  194. package/dist/metrics.d.ts +68 -0
  195. package/dist/metrics.d.ts.map +1 -0
  196. package/dist/metrics.js +242 -0
  197. package/dist/metrics.js.map +1 -0
  198. package/dist/network-witness.d.ts +167 -0
  199. package/dist/network-witness.d.ts.map +1 -0
  200. package/dist/network-witness.js +520 -0
  201. package/dist/network-witness.js.map +1 -0
  202. package/dist/proposal-to-effect.d.ts +146 -0
  203. package/dist/proposal-to-effect.d.ts.map +1 -0
  204. package/dist/proposal-to-effect.js +427 -0
  205. package/dist/proposal-to-effect.js.map +1 -0
  206. package/dist/protocol-state.d.ts +141 -0
  207. package/dist/protocol-state.d.ts.map +1 -0
  208. package/dist/protocol-state.js +106 -0
  209. package/dist/protocol-state.js.map +1 -0
  210. package/dist/receipt-program.d.ts +59 -0
  211. package/dist/receipt-program.d.ts.map +1 -0
  212. package/dist/receipt-program.js +1053 -0
  213. package/dist/receipt-program.js.map +1 -0
  214. package/dist/reliance-kernel.d.ts +66 -0
  215. package/dist/reliance-kernel.d.ts.map +1 -0
  216. package/dist/reliance-kernel.js +103 -0
  217. package/dist/reliance-kernel.js.map +1 -0
  218. package/dist/reliance-packet.d.ts +67 -0
  219. package/dist/reliance-packet.d.ts.map +1 -0
  220. package/dist/reliance-packet.js +176 -0
  221. package/dist/reliance-packet.js.map +1 -0
  222. package/dist/remedy-program-postgres.d.ts +37 -0
  223. package/dist/remedy-program-postgres.d.ts.map +1 -0
  224. package/dist/remedy-program-postgres.js +291 -0
  225. package/dist/remedy-program-postgres.js.map +1 -0
  226. package/dist/remedy-program-receipt.d.ts +97 -0
  227. package/dist/remedy-program-receipt.d.ts.map +1 -0
  228. package/dist/remedy-program-receipt.js +817 -0
  229. package/dist/remedy-program-receipt.js.map +1 -0
  230. package/dist/remedy-program.d.ts +76 -0
  231. package/dist/remedy-program.d.ts.map +1 -0
  232. package/dist/remedy-program.js +1346 -0
  233. package/dist/remedy-program.js.map +1 -0
  234. package/dist/reports/art14.d.ts +101 -0
  235. package/dist/reports/art14.d.ts.map +1 -0
  236. package/dist/reports/art14.js +340 -0
  237. package/dist/reports/art14.js.map +1 -0
  238. package/dist/reports/assurance-package.d.ts +197 -0
  239. package/dist/reports/assurance-package.d.ts.map +1 -0
  240. package/dist/reports/assurance-package.js +313 -0
  241. package/dist/reports/assurance-package.js.map +1 -0
  242. package/dist/reports/auditor-workpaper.d.ts +194 -0
  243. package/dist/reports/auditor-workpaper.d.ts.map +1 -0
  244. package/dist/reports/auditor-workpaper.js +545 -0
  245. package/dist/reports/auditor-workpaper.js.map +1 -0
  246. package/dist/reports/external-verification.d.ts +76 -0
  247. package/dist/reports/external-verification.d.ts.map +1 -0
  248. package/dist/reports/external-verification.js +209 -0
  249. package/dist/reports/external-verification.js.map +1 -0
  250. package/dist/reports/reperform.d.ts +122 -0
  251. package/dist/reports/reperform.d.ts.map +1 -0
  252. package/dist/reports/reperform.js +432 -0
  253. package/dist/reports/reperform.js.map +1 -0
  254. package/dist/reports/underwriter.d.ts +127 -0
  255. package/dist/reports/underwriter.d.ts.map +1 -0
  256. package/dist/reports/underwriter.js +348 -0
  257. package/dist/reports/underwriter.js.map +1 -0
  258. package/dist/retention.d.ts +88 -0
  259. package/dist/retention.d.ts.map +1 -0
  260. package/dist/retention.js +90 -0
  261. package/dist/retention.js.map +1 -0
  262. package/dist/roster.d.ts +113 -0
  263. package/dist/roster.d.ts.map +1 -0
  264. package/dist/roster.js +261 -0
  265. package/dist/roster.js.map +1 -0
  266. package/dist/runtime-monitor.d.ts +132 -0
  267. package/dist/runtime-monitor.d.ts.map +1 -0
  268. package/dist/runtime-monitor.js +197 -0
  269. package/dist/runtime-monitor.js.map +1 -0
  270. package/dist/settlement.d.ts +68 -0
  271. package/dist/settlement.d.ts.map +1 -0
  272. package/dist/settlement.js +306 -0
  273. package/dist/settlement.js.map +1 -0
  274. package/dist/siem.d.ts +261 -0
  275. package/dist/siem.d.ts.map +1 -0
  276. package/dist/siem.js +247 -0
  277. package/dist/siem.js.map +1 -0
  278. package/dist/store-postgres.d.ts +107 -0
  279. package/dist/store-postgres.d.ts.map +1 -0
  280. package/dist/store-postgres.js +152 -0
  281. package/dist/store-postgres.js.map +1 -0
  282. package/dist/store.d.ts +95 -0
  283. package/dist/store.d.ts.map +1 -0
  284. package/dist/store.js +202 -0
  285. package/dist/store.js.map +1 -0
  286. package/dist/strict-json.d.ts +14 -0
  287. package/dist/strict-json.d.ts.map +1 -0
  288. package/dist/strict-json.js +132 -0
  289. package/dist/strict-json.js.map +1 -0
  290. package/dist/trust-program-adapters.d.ts +122 -0
  291. package/dist/trust-program-adapters.d.ts.map +1 -0
  292. package/dist/trust-program-adapters.js +802 -0
  293. package/dist/trust-program-adapters.js.map +1 -0
  294. package/dist/trust-program-postgres.d.ts +41 -0
  295. package/dist/trust-program-postgres.d.ts.map +1 -0
  296. package/dist/trust-program-postgres.js +346 -0
  297. package/dist/trust-program-postgres.js.map +1 -0
  298. package/dist/trust-program-revocation.d.ts +206 -0
  299. package/dist/trust-program-revocation.d.ts.map +1 -0
  300. package/dist/trust-program-revocation.js +600 -0
  301. package/dist/trust-program-revocation.js.map +1 -0
  302. package/dist/trust-program.d.ts +197 -0
  303. package/dist/trust-program.d.ts.map +1 -0
  304. package/dist/trust-program.js +1351 -0
  305. package/dist/trust-program.js.map +1 -0
  306. package/dist/witness-postgres.d.ts +43 -0
  307. package/dist/witness-postgres.d.ts.map +1 -0
  308. package/dist/witness-postgres.js +92 -0
  309. package/dist/witness-postgres.js.map +1 -0
  310. package/dist/zk-range-proof.d.ts +78 -0
  311. package/dist/zk-range-proof.d.ts.map +1 -0
  312. package/dist/zk-range-proof.js +228 -0
  313. package/dist/zk-range-proof.js.map +1 -0
  314. package/eg1-conformance.js +3 -404
  315. package/enterprise.js +3 -180
  316. package/ep-assure.mjs +1 -0
  317. package/evidence-postgres.js +3 -356
  318. package/evidence.js +4 -360
  319. package/execution-binding.js +3 -212
  320. package/formal-runtime-map.js +4 -0
  321. package/index.js +4 -1249
  322. package/key-registry.js +3 -134
  323. package/mcp.js +3 -109
  324. package/metering.js +3 -226
  325. package/metrics.js +3 -231
  326. package/network-witness.js +3 -499
  327. package/package.json +35 -4
  328. package/proposal-to-effect.js +4 -0
  329. package/receipt-program.js +4 -0
  330. package/reliance-kernel.js +3 -112
  331. package/reliance-packet.js +3 -175
  332. package/remedy-program-postgres.js +4 -0
  333. package/remedy-program-receipt.js +4 -0
  334. package/remedy-program.js +4 -0
  335. package/reports/art14.js +0 -0
  336. package/reports/assurance-package.js +2 -312
  337. package/reports/auditor-workpaper.js +3 -537
  338. package/reports/external-verification.js +3 -222
  339. package/reports/reperform.js +3 -424
  340. package/reports/underwriter.js +3 -339
  341. package/retention.js +3 -84
  342. package/roster.js +3 -264
  343. package/runtime-monitor.js +4 -0
  344. package/settlement.js +3 -299
  345. package/siem.js +3 -235
  346. package/src/action-control-manifest.ts +424 -0
  347. package/src/action-escrow-custodian.ts +427 -0
  348. package/src/action-escrow-evidence.ts +1178 -0
  349. package/src/action-escrow-package.ts +1821 -0
  350. package/src/action-escrow-postgres.ts +366 -0
  351. package/src/action-escrow-state.ts +498 -0
  352. package/src/action-escrow-verifiers.ts +484 -0
  353. package/src/action-escrow.ts +3039 -0
  354. package/src/action-packs.ts +170 -0
  355. package/src/adapters/_kit.ts +117 -0
  356. package/src/adapters/aws.ts +142 -0
  357. package/src/adapters/cloudflare.ts +78 -0
  358. package/src/adapters/gcp.ts +71 -0
  359. package/src/adapters/github.ts +110 -0
  360. package/src/adapters/jira.ts +56 -0
  361. package/src/adapters/k8s.ts +71 -0
  362. package/src/adapters/linear.ts +56 -0
  363. package/src/adapters/salesforce.ts +56 -0
  364. package/src/adapters/stripe.ts +82 -0
  365. package/src/adapters/supabase.ts +122 -0
  366. package/src/adapters/terraform.ts +60 -0
  367. package/src/adapters/vercel.ts +85 -0
  368. package/src/aec-execution.ts +354 -0
  369. package/src/breakglass.ts +647 -0
  370. package/src/capability-receipt.ts +1258 -0
  371. package/src/cf1-conformance.ts +120 -0
  372. package/src/challenge-store.ts +70 -0
  373. package/src/control-plane.ts +374 -0
  374. package/src/coverage.ts +832 -0
  375. package/src/deployment-attestation.ts +259 -0
  376. package/src/eg1-conformance.ts +471 -0
  377. package/src/enterprise.ts +195 -0
  378. package/src/evidence-postgres.ts +374 -0
  379. package/src/evidence.ts +367 -0
  380. package/src/execution-binding.ts +236 -0
  381. package/src/formal-runtime-map.ts +24 -0
  382. package/src/index.ts +2127 -0
  383. package/src/key-registry.ts +150 -0
  384. package/src/mcp.ts +120 -0
  385. package/src/metering.ts +237 -0
  386. package/src/metrics.ts +232 -0
  387. package/src/network-witness.ts +585 -0
  388. package/src/proposal-to-effect.ts +571 -0
  389. package/src/protocol-state.ts +143 -0
  390. package/src/protocol-state.typecheck.ts +94 -0
  391. package/src/receipt-program.ts +1105 -0
  392. package/src/reliance-kernel.ts +119 -0
  393. package/src/reliance-packet.ts +206 -0
  394. package/src/remedy-program-postgres.ts +367 -0
  395. package/src/remedy-program-receipt.ts +891 -0
  396. package/src/remedy-program.ts +1388 -0
  397. package/src/reports/art14.ts +361 -0
  398. package/src/reports/assurance-package.ts +330 -0
  399. package/src/reports/auditor-workpaper.ts +558 -0
  400. package/src/reports/external-verification.ts +232 -0
  401. package/src/reports/reperform.ts +441 -0
  402. package/src/reports/underwriter.ts +356 -0
  403. package/src/retention.ts +100 -0
  404. package/src/roster.ts +273 -0
  405. package/src/runtime-monitor.ts +217 -0
  406. package/src/settlement.ts +313 -0
  407. package/src/siem.ts +247 -0
  408. package/src/store-postgres.ts +167 -0
  409. package/src/store.ts +214 -0
  410. package/src/strict-json.ts +115 -0
  411. package/src/trust-program-adapters.ts +847 -0
  412. package/src/trust-program-postgres.ts +429 -0
  413. package/src/trust-program-revocation.ts +751 -0
  414. package/src/trust-program.ts +1460 -0
  415. package/src/witness-postgres.ts +106 -0
  416. package/src/zk-range-proof.ts +250 -0
  417. package/store-postgres.js +3 -161
  418. package/store.js +4 -198
  419. package/strict-json.js +3 -102
  420. package/trust-program-adapters.js +4 -0
  421. package/trust-program-postgres.js +4 -0
  422. package/trust-program-revocation.js +4 -0
  423. package/trust-program.js +4 -0
  424. package/witness-postgres.js +3 -96
  425. package/zk-range-proof.js +4 -0
@@ -0,0 +1,1583 @@
1
+ // @ts-nocheck
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Strict adapter from one exact Action Escrow kernel snapshot to the portable
5
+ * Action Escrow evidence-package profile.
6
+ *
7
+ * This module does not accept package-field overrides. Every package field is
8
+ * either derived from the durable record or occupies one of the four external
9
+ * artifact slots that the kernel intentionally does not own.
10
+ */
11
+ import crypto from 'node:crypto';
12
+ import { ACTION_ESCROW_PROFILE_VERSION, ACTION_ESCROW_STATE_VERSION, ACTION_ESCROW_STATES, ACTION_ESCROW_TRANSITIONS, computeActionEscrowReleaseBindingMomentDigest, computeActionEscrowResolutionNonce, } from './action-escrow.js';
13
+ import { buildActionEscrowEvidencePackage } from './action-escrow-evidence.js';
14
+ import { ACTION_ESCROW_STATE_STATEMENT_DOMAIN, ACTION_ESCROW_STATE_STATEMENT_VERSION, } from './action-escrow-state.js';
15
+ import { ACTION_ESCROW_CONTRACTOR_TEMPLATE_VERSION, computeActionEscrowAgreementDigest, validateActionEscrowReleaseTemplate, } from './action-escrow-verifiers.js';
16
+ import { canonicalize, hashCanonical } from './execution-binding.js';
17
+ import { computeDocumentActionBindingDigest, computeDocumentSha256, computeReleaseActionDigest, } from '@emilia-protocol/verify/document-action-binding';
18
+ const HASH = /^sha256:[0-9a-f]{64}$/;
19
+ const ID = /^[A-Za-z0-9][A-Za-z0-9._:/#@+-]{0,255}$/;
20
+ const BASE64URL = /^[A-Za-z0-9_-]+$/;
21
+ const MAX_RECORD_NODES = 50_000;
22
+ const MAX_RECORD_DEPTH = 64;
23
+ const MAX_STRING_BYTES = 4 * 1024 * 1024;
24
+ const DEFAULT_MAX_DOCUMENT_BYTES = 50 * 1024 * 1024;
25
+ const INPUT_KEYS = new Set([
26
+ 'kernelRecord',
27
+ 'finalPdfBytes',
28
+ 'documentFileName',
29
+ 'documentExecution',
30
+ 'operatorStateStatement',
31
+ 'verificationProfile',
32
+ ]);
33
+ const CONTRACTOR_INPUT_KEYS = new Set([
34
+ ...INPUT_KEYS,
35
+ 'projectRecordBytes',
36
+ 'projectRecordFileName',
37
+ 'projectRecordProvider',
38
+ 'projectRecordSnapshotDigest',
39
+ ]);
40
+ const OPTION_KEYS = new Set(['now', 'maxDocumentBytes']);
41
+ const CONTRACTOR_OPTION_KEYS = new Set([
42
+ ...OPTION_KEYS,
43
+ 'maxProjectRecordBytes',
44
+ ]);
45
+ const RECORD_KEYS = new Set([
46
+ '@version',
47
+ 'escrow_key',
48
+ 'revision',
49
+ 'state',
50
+ 'agreement_digest',
51
+ 'document_action_binding_digest',
52
+ 'milestone_id',
53
+ 'release_action_digest',
54
+ 'parties',
55
+ 'parties_digest',
56
+ 'profile',
57
+ 'profile_digest',
58
+ 'document_action_binding',
59
+ 'agreement_acceptances',
60
+ 'funding',
61
+ 'milestone_evidence',
62
+ 'release_approvals',
63
+ 'release',
64
+ 'dispute',
65
+ 'cancellation',
66
+ 'completion',
67
+ 'pending_amendment',
68
+ 'superseded_bindings',
69
+ 'operations',
70
+ 'history',
71
+ 'created_at',
72
+ 'updated_at',
73
+ ]);
74
+ const PROFILE_KEYS = new Set([
75
+ '@version',
76
+ 'profile_id',
77
+ 'provider_id',
78
+ 'required_acceptance_party_ids',
79
+ 'required_release_approver_party_ids',
80
+ 'prohibit_self_approval',
81
+ ]);
82
+ const PARTY_KEYS = new Set(['party_id', 'role']);
83
+ const CONTAINER_KEYS = new Set(['artifact', 'verification']);
84
+ const ACCEPTANCE_KEYS = new Set(['party_id', 'artifact', 'verification']);
85
+ const RELEASE_APPROVAL_KEYS = new Set(['party_id', 'resolution', 'verification']);
86
+ const CORE_VERIFICATION_KEYS = [
87
+ 'valid',
88
+ 'agreement_digest',
89
+ 'document_action_binding_digest',
90
+ 'milestone_id',
91
+ 'release_action_digest',
92
+ 'parties_digest',
93
+ 'profile_digest',
94
+ ];
95
+ const BINDING_VERIFICATION_KEYS = new Set([
96
+ ...CORE_VERIFICATION_KEYS,
97
+ 'verification_digest',
98
+ 'document_digest',
99
+ 'agreement_id',
100
+ 'binding_id',
101
+ 'release_action_template',
102
+ 'supersedes_document_action_binding_digest',
103
+ ]);
104
+ const ACCEPTANCE_VERIFICATION_KEYS = new Set([
105
+ ...CORE_VERIFICATION_KEYS,
106
+ 'party_id',
107
+ 'principal_key_id',
108
+ 'acceptance_digest',
109
+ ]);
110
+ const FUNDING_VERIFICATION_KEYS = new Set([
111
+ ...CORE_VERIFICATION_KEYS,
112
+ 'authenticated',
113
+ 'provider_id',
114
+ 'statement_type',
115
+ 'status',
116
+ 'provider_transaction_id',
117
+ 'provider_milestone_id',
118
+ 'amount',
119
+ 'currency',
120
+ 'destination_id',
121
+ 'statement_digest',
122
+ ]);
123
+ const MILESTONE_VERIFICATION_KEYS = new Set([
124
+ ...CORE_VERIFICATION_KEYS,
125
+ 'evidence_digest',
126
+ 'submitter_party_id',
127
+ 'observed_at',
128
+ ]);
129
+ const RELEASE_APPROVAL_VERIFICATION_KEYS = new Set([
130
+ ...CORE_VERIFICATION_KEYS,
131
+ 'authorizes_action',
132
+ 'outcome',
133
+ 'party_role',
134
+ 'principal_key_id',
135
+ 'nonce',
136
+ 'issued_at',
137
+ 'expires_at',
138
+ 'resolution_digest',
139
+ 'evidence_digest',
140
+ ]);
141
+ const PROVIDER_VERIFICATION_KEYS = new Set([
142
+ ...CORE_VERIFICATION_KEYS,
143
+ 'authenticated',
144
+ 'provider_id',
145
+ 'provider_idempotency_key',
146
+ 'provider_request_digest',
147
+ 'provider_transaction_id',
148
+ 'provider_milestone_id',
149
+ 'amount',
150
+ 'currency',
151
+ 'destination_id',
152
+ 'statement_type',
153
+ 'status',
154
+ 'statement_digest',
155
+ ]);
156
+ const COMMAND_VERIFICATION_KEYS = new Set([
157
+ ...CORE_VERIFICATION_KEYS,
158
+ 'authorizes_command',
159
+ 'command',
160
+ 'party_id',
161
+ 'details_digest',
162
+ 'command_digest',
163
+ ]);
164
+ const OPERATION_KEYS = new Set([
165
+ 'idempotency_key',
166
+ 'operation',
167
+ 'request_digest',
168
+ 'code',
169
+ 'ok',
170
+ 'outcome',
171
+ 'state',
172
+ 'at',
173
+ ]);
174
+ const HISTORY_KEYS = new Set([
175
+ 'from',
176
+ 'to',
177
+ 'operation',
178
+ 'idempotency_key',
179
+ 'at',
180
+ ]);
181
+ const SUPERSESSION_KEYS = new Set([
182
+ 'document_action_binding_digest',
183
+ 'release_action_digest',
184
+ 'superseded_by_binding_digest',
185
+ 'superseded_at',
186
+ ]);
187
+ const RELEASE_KEYS = new Set([
188
+ 'release_key',
189
+ 'provider_idempotency_key',
190
+ 'operation_idempotency_key',
191
+ 'status',
192
+ 'reserved_at',
193
+ 'reconciled_at',
194
+ 'provider_request',
195
+ 'provider_statement',
196
+ 'provider_verification',
197
+ ]);
198
+ const PROVIDER_REQUEST_KEYS = new Set([
199
+ 'method',
200
+ 'provider_id',
201
+ 'agreement_digest',
202
+ 'document_action_binding_digest',
203
+ 'milestone_id',
204
+ 'release_action_digest',
205
+ 'parties',
206
+ 'parties_digest',
207
+ 'profile',
208
+ 'profile_digest',
209
+ 'agreement_id',
210
+ 'binding_id',
211
+ 'document_digest',
212
+ 'release_action_template',
213
+ 'release_key',
214
+ 'idempotency_key',
215
+ 'request_digest',
216
+ ]);
217
+ const PENDING_AMENDMENT_KEYS = new Set([
218
+ 'from_state',
219
+ 'document_action_binding_digest',
220
+ 'release_action_digest',
221
+ 'document_action_binding',
222
+ 'agreement_acceptances',
223
+ 'proposer_party_id',
224
+ 'proposal_authorization',
225
+ 'proposed_at',
226
+ ]);
227
+ const COMMAND_CONTAINER_KEYS = new Set(['artifact', 'verification']);
228
+ const DISPUTE_KEYS = new Set(['party_id', 'reason', 'authorization', 'opened_at']);
229
+ const CANCELLATION_KEYS = new Set([
230
+ 'party_id',
231
+ 'reason',
232
+ 'authorization',
233
+ 'cancelled_at',
234
+ ]);
235
+ const COMPLETION_KEYS = new Set([
236
+ 'party_id',
237
+ 'meaning',
238
+ 'authorization',
239
+ 'completed_at',
240
+ ]);
241
+ const STATE_STATEMENT_KEYS = new Set([
242
+ 'version',
243
+ 'issuer',
244
+ 'payload',
245
+ 'statement_digest',
246
+ 'signature',
247
+ ]);
248
+ const STATE_ISSUER_KEYS = new Set(['operator_id', 'key_id']);
249
+ const STATE_PAYLOAD_KEYS = new Set([
250
+ 'statement_id',
251
+ 'agreement_id',
252
+ 'binding_digest',
253
+ 'action_digest',
254
+ 'profile_digest',
255
+ 'state',
256
+ 'revision',
257
+ 'amendment_digests',
258
+ 'state_record_digest',
259
+ 'previous_statement_digest',
260
+ 'occurred_at',
261
+ ]);
262
+ const STATE_SIGNATURE_KEYS = new Set(['algorithm', 'signature_b64u']);
263
+ const PROFILE_REFERENCE_KEYS = new Set(['id', 'digest']);
264
+ const EXECUTED_AGREEMENT_STATES = new Set([
265
+ 'effective',
266
+ 'awaiting_funding',
267
+ 'funded',
268
+ 'milestone_submitted',
269
+ 'release_reserved',
270
+ 'released',
271
+ 'disputed',
272
+ 'amendment_pending',
273
+ 'completed',
274
+ 'release_indeterminate',
275
+ ]);
276
+ const FUNDING_STATES = new Set([
277
+ 'funded',
278
+ 'milestone_submitted',
279
+ 'release_reserved',
280
+ 'released',
281
+ 'disputed',
282
+ 'completed',
283
+ 'release_indeterminate',
284
+ ]);
285
+ const MILESTONE_STATES = new Set([
286
+ 'milestone_submitted',
287
+ 'release_reserved',
288
+ 'released',
289
+ 'disputed',
290
+ 'completed',
291
+ 'release_indeterminate',
292
+ ]);
293
+ const RELEASE_APPROVAL_STATES = new Set([
294
+ 'milestone_submitted',
295
+ 'release_reserved',
296
+ 'released',
297
+ 'disputed',
298
+ 'completed',
299
+ 'release_indeterminate',
300
+ ]);
301
+ const COMPLETE_RELEASE_APPROVAL_STATES = new Set([
302
+ 'release_reserved',
303
+ 'released',
304
+ 'completed',
305
+ 'release_indeterminate',
306
+ ]);
307
+ const REQUIRED_RELEASE_STATES = new Set([
308
+ 'release_reserved',
309
+ 'released',
310
+ 'completed',
311
+ 'release_indeterminate',
312
+ ]);
313
+ const OPTIONAL_RELEASE_STATES = new Set([
314
+ 'milestone_submitted',
315
+ 'disputed',
316
+ ]);
317
+ const KERNEL_OPERATIONS = new Set([
318
+ 'create',
319
+ 'begin_acceptance',
320
+ 'accept_agreement',
321
+ 'request_funding',
322
+ 'record_funding',
323
+ 'submit_milestone',
324
+ 'approve_release',
325
+ 'release',
326
+ 'reconcile_release',
327
+ 'open_dispute',
328
+ 'propose_amendment',
329
+ 'accept_amendment',
330
+ 'cancel',
331
+ 'complete',
332
+ ]);
333
+ const SECRET_FIELD_NAMES = new Set([
334
+ 'api_key',
335
+ 'api_token',
336
+ 'api_secret',
337
+ 'access_key',
338
+ 'access_key_id',
339
+ 'access_token',
340
+ 'refresh_token',
341
+ 'session_token',
342
+ 'oauth_token',
343
+ 'bearer_token',
344
+ 'client_secret',
345
+ 'client_password',
346
+ 'password',
347
+ 'passwd',
348
+ 'private_key',
349
+ 'private_key_pem',
350
+ 'secret',
351
+ 'secret_key',
352
+ 'secret_access_key',
353
+ 'signing_secret',
354
+ 'webhook_secret',
355
+ 'credential',
356
+ 'credentials',
357
+ 'provider_credentials',
358
+ 'authorization_header',
359
+ 'cookie',
360
+ 'set_cookie',
361
+ 'request_headers',
362
+ 'http_headers',
363
+ 'headers',
364
+ 'connection_string',
365
+ 'database_url',
366
+ ]);
367
+ function fail(reason) {
368
+ throw new TypeError(`action-escrow package: ${reason}`);
369
+ }
370
+ function isRecord(value) {
371
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
372
+ return false;
373
+ const prototype = Object.getPrototypeOf(value);
374
+ return prototype === Object.prototype || prototype === null;
375
+ }
376
+ function exactKeys(value, allowed, required = allowed) {
377
+ if (!isRecord(value))
378
+ return false;
379
+ const keys = Object.keys(value);
380
+ return keys.every((key) => allowed.has(key))
381
+ && [...required].every((key) => Object.hasOwn(value, key));
382
+ }
383
+ function validString(value, max = 512) {
384
+ return typeof value === 'string'
385
+ && value.length > 0
386
+ && value.length <= max
387
+ && !/[\u0000-\u001f\u007f]/.test(value);
388
+ }
389
+ function validDigest(value) {
390
+ return typeof value === 'string' && HASH.test(value);
391
+ }
392
+ function validInstant(value) {
393
+ if (typeof value !== 'string')
394
+ return false;
395
+ const parsed = Date.parse(value);
396
+ return Number.isFinite(parsed) && new Date(parsed).toISOString() === value;
397
+ }
398
+ function canonicalCopy(value, label) {
399
+ let nodes = 0;
400
+ let stringBytes = 0;
401
+ const seen = new WeakSet();
402
+ function copy(current, depth) {
403
+ nodes += 1;
404
+ if (nodes > MAX_RECORD_NODES || depth > MAX_RECORD_DEPTH) {
405
+ fail(`${label} exceeds resource limits`);
406
+ }
407
+ if (current === null || typeof current === 'boolean')
408
+ return current;
409
+ if (typeof current === 'string') {
410
+ stringBytes += Buffer.byteLength(current, 'utf8');
411
+ if (stringBytes > MAX_STRING_BYTES)
412
+ fail(`${label} exceeds string limits`);
413
+ return current;
414
+ }
415
+ if (typeof current === 'number') {
416
+ if (!Number.isSafeInteger(current) || Object.is(current, -0)) {
417
+ fail(`${label} contains a non-canonical number`);
418
+ }
419
+ return current;
420
+ }
421
+ if (!isRecord(current) && !Array.isArray(current)) {
422
+ fail(`${label} is not canonical JSON`);
423
+ }
424
+ if (seen.has(current))
425
+ fail(`${label} contains an alias or cycle`);
426
+ seen.add(current);
427
+ if (Array.isArray(current)) {
428
+ return current.map((entry) => copy(entry, depth + 1));
429
+ }
430
+ return Object.fromEntries(Object.entries(current).map(([key, entry]) => [key, copy(entry, depth + 1)]));
431
+ }
432
+ return copy(value, 0);
433
+ }
434
+ function canonicalDigest(value) {
435
+ return `sha256:${hashCanonical(value)}`;
436
+ }
437
+ function sameCanonical(left, right) {
438
+ try {
439
+ return canonicalize(left) === canonicalize(right);
440
+ }
441
+ catch {
442
+ return false;
443
+ }
444
+ }
445
+ function normalizeFieldName(value) {
446
+ return value
447
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
448
+ .replace(/[^A-Za-z0-9]+/g, '_')
449
+ .replace(/^_+|_+$/g, '')
450
+ .toLowerCase();
451
+ }
452
+ function assertNoSecrets(value, label) {
453
+ const stack = [{ value, path: label }];
454
+ while (stack.length > 0) {
455
+ const current = stack.pop();
456
+ // stack.length > 0 guarantees pop() returns an entry; TS can't see that.
457
+ if (!current)
458
+ break;
459
+ if (typeof current.value === 'string') {
460
+ if (/-----BEGIN (?:ENCRYPTED )?PRIVATE KEY-----/.test(current.value)
461
+ || /^\s*Bearer\s+\S+/i.test(current.value)
462
+ || /^[a-z][a-z0-9+.-]*:\/\/[^/\s]*@/i.test(current.value)) {
463
+ fail(`${current.path} contains provider credentials or secrets`);
464
+ }
465
+ continue;
466
+ }
467
+ if (current.value === null || typeof current.value !== 'object')
468
+ continue;
469
+ for (const [key, child] of Object.entries(current.value)) {
470
+ const normalized = normalizeFieldName(key);
471
+ if (SECRET_FIELD_NAMES.has(normalized)
472
+ || normalized.endsWith('_client_secret')
473
+ || normalized.endsWith('_private_key')
474
+ || normalized.endsWith('_access_token')
475
+ || normalized.endsWith('_refresh_token')
476
+ || normalized.endsWith('_password')) {
477
+ fail(`${current.path}.${key} contains provider credentials or secrets`);
478
+ }
479
+ stack.push({ value: child, path: `${current.path}.${key}` });
480
+ }
481
+ }
482
+ }
483
+ function expectedCore(record, overrides = {}) {
484
+ return {
485
+ agreement_digest: record.agreement_digest,
486
+ document_action_binding_digest: overrides.document_action_binding_digest ?? record.document_action_binding_digest,
487
+ milestone_id: record.milestone_id,
488
+ release_action_digest: overrides.release_action_digest ?? record.release_action_digest,
489
+ parties_digest: record.parties_digest,
490
+ profile_digest: record.profile_digest,
491
+ };
492
+ }
493
+ function verificationMatchesCore(value, expected) {
494
+ return isRecord(value)
495
+ && value.valid === true
496
+ && Object.entries(expected).every(([key, entry]) => value[key] === entry);
497
+ }
498
+ function validateStringArray(value, allowed, label) {
499
+ if (!Array.isArray(value)
500
+ || value.length === 0
501
+ || value.some((entry) => !validString(entry, 256))
502
+ || new Set(value).size !== value.length
503
+ || value.some((entry) => !allowed.has(entry))) {
504
+ fail(`${label} is invalid`);
505
+ }
506
+ }
507
+ function partyIdentity(party) {
508
+ return `${party.role}\u0000${party.party_id}`;
509
+ }
510
+ function sameParties(left, right) {
511
+ if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length)
512
+ return false;
513
+ const expected = new Set(left.map(partyIdentity));
514
+ return expected.size === left.length && right.every((party) => (exactKeys(party, PARTY_KEYS) && expected.has(partyIdentity(party))));
515
+ }
516
+ function validatePartiesAndProfile(record) {
517
+ if (!Array.isArray(record.parties)
518
+ || record.parties.length < 2
519
+ || record.parties.length > 16) {
520
+ fail('kernel record parties are invalid');
521
+ }
522
+ const ids = new Set();
523
+ for (const party of record.parties) {
524
+ if (!exactKeys(party, PARTY_KEYS)
525
+ || !validString(party.party_id, 256)
526
+ || !validString(party.role, 128)
527
+ || ids.has(party.party_id)) {
528
+ fail('kernel record party is malformed or duplicated');
529
+ }
530
+ ids.add(party.party_id);
531
+ }
532
+ if (record.parties_digest !== canonicalDigest(record.parties)) {
533
+ fail('kernel record parties digest mismatch');
534
+ }
535
+ if (!exactKeys(record.profile, PROFILE_KEYS)
536
+ || record.profile['@version'] !== ACTION_ESCROW_PROFILE_VERSION
537
+ || !validString(record.profile.profile_id, 256)
538
+ || !validString(record.profile.provider_id, 256)
539
+ || typeof record.profile.prohibit_self_approval !== 'boolean') {
540
+ fail('kernel record profile is malformed');
541
+ }
542
+ validateStringArray(record.profile.required_acceptance_party_ids, ids, 'required acceptance party roster');
543
+ validateStringArray(record.profile.required_release_approver_party_ids, ids, 'required release party roster');
544
+ if (record.profile.required_acceptance_party_ids.length !== record.parties.length) {
545
+ fail('required acceptance party roster does not cover the exact parties');
546
+ }
547
+ if (record.profile_digest !== canonicalDigest(record.profile)) {
548
+ fail('kernel record profile digest mismatch');
549
+ }
550
+ }
551
+ function validateHistory(record) {
552
+ if (!Array.isArray(record.operations)
553
+ || record.operations.length === 0
554
+ || !Array.isArray(record.history)
555
+ || record.history.length === 0) {
556
+ fail('kernel operation or state history is malformed');
557
+ }
558
+ const operationIds = new Set();
559
+ const operationsById = new Map();
560
+ let previousOperationTime = Number.NEGATIVE_INFINITY;
561
+ for (const operation of record.operations) {
562
+ if (!exactKeys(operation, OPERATION_KEYS)
563
+ || !validString(operation.idempotency_key, 512)
564
+ || operationIds.has(operation.idempotency_key)
565
+ || !validString(operation.operation, 128)
566
+ || !KERNEL_OPERATIONS.has(operation.operation)
567
+ || !validDigest(operation.request_digest)
568
+ || !validString(operation.code, 256)
569
+ || typeof operation.ok !== 'boolean'
570
+ || !validString(operation.outcome, 128)
571
+ || !ACTION_ESCROW_STATES.includes(operation.state)
572
+ || !validInstant(operation.at)) {
573
+ fail('kernel operation history is malformed');
574
+ }
575
+ const operationTime = Date.parse(operation.at);
576
+ if (operationTime < previousOperationTime) {
577
+ fail('kernel operation history is not time-monotonic');
578
+ }
579
+ operationIds.add(operation.idempotency_key);
580
+ operationsById.set(operation.idempotency_key, operation);
581
+ previousOperationTime = operationTime;
582
+ }
583
+ const firstOperation = record.operations[0];
584
+ if (firstOperation.operation !== 'create'
585
+ || firstOperation.state !== 'draft'
586
+ || firstOperation.code !== 'escrow_created'
587
+ || firstOperation.ok !== true) {
588
+ fail('kernel operation history has no valid creation root');
589
+ }
590
+ let previous = null;
591
+ let previousHistoryTime = Number.NEGATIVE_INFINITY;
592
+ const releaseHistoryCounts = new Map();
593
+ for (const [index, entry] of record.history.entries()) {
594
+ if (!exactKeys(entry, HISTORY_KEYS)
595
+ || entry.from !== previous
596
+ || !ACTION_ESCROW_STATES.includes(entry.to)
597
+ || !validString(entry.operation, 128)
598
+ || !validString(entry.idempotency_key, 512)
599
+ || !validInstant(entry.at)) {
600
+ fail('kernel state history is malformed');
601
+ }
602
+ const linkedOperation = operationsById.get(entry.idempotency_key);
603
+ const historyTime = Date.parse(entry.at);
604
+ if (!linkedOperation
605
+ || linkedOperation.operation !== entry.operation
606
+ || historyTime < previousHistoryTime) {
607
+ fail('kernel state history is not bound to its operation log');
608
+ }
609
+ if (entry.operation === 'release') {
610
+ if (historyTime < Date.parse(linkedOperation.at)) {
611
+ fail('kernel release history predates its reservation');
612
+ }
613
+ releaseHistoryCounts.set(entry.idempotency_key, (releaseHistoryCounts.get(entry.idempotency_key) ?? 0) + 1);
614
+ }
615
+ else if (entry.at !== linkedOperation.at || entry.to !== linkedOperation.state) {
616
+ fail('kernel state history is inconsistent with its operation');
617
+ }
618
+ if (index === 0) {
619
+ if (entry.from !== null || entry.to !== 'draft' || entry.operation !== 'create') {
620
+ fail('kernel state history has no valid creation root');
621
+ }
622
+ }
623
+ else if (!ACTION_ESCROW_TRANSITIONS[entry.from]?.includes(entry.to)) {
624
+ fail('kernel state history contains an invalid transition');
625
+ }
626
+ previous = entry.to;
627
+ previousHistoryTime = historyTime;
628
+ }
629
+ if (previous !== record.state)
630
+ fail('kernel state does not match its history');
631
+ const internalReleaseTransitions = [...releaseHistoryCounts.values()]
632
+ .reduce((total, count) => total + Math.max(0, count - 1), 0);
633
+ if (record.revision !== record.operations.length - 1 + internalReleaseTransitions) {
634
+ fail('kernel revision does not match its complete operation history');
635
+ }
636
+ const eventTimes = [
637
+ ...record.operations.map((entry) => entry.at),
638
+ ...record.history.map((entry) => entry.at),
639
+ ];
640
+ if (record.created_at !== record.operations[0].at
641
+ || Date.parse(record.created_at) > Date.parse(record.updated_at)
642
+ || eventTimes.some((instant) => Date.parse(instant) > Date.parse(record.updated_at))
643
+ || Math.max(...eventTimes.map((instant) => Date.parse(instant)))
644
+ !== Date.parse(record.updated_at)) {
645
+ fail('kernel record timestamps do not match its history');
646
+ }
647
+ }
648
+ /**
649
+ * @param {any} container
650
+ * @param {any} record
651
+ * @param {{
652
+ * bindingDigest?: any,
653
+ * actionDigest?: any,
654
+ * supersedesDigest?: string|null,
655
+ * documentDigest?: string|null,
656
+ * documentLength?: number|null,
657
+ * }} [options]
658
+ */
659
+ function validateBindingContainer(container, record, { bindingDigest = record.document_action_binding_digest, actionDigest = record.release_action_digest, supersedesDigest = null, documentDigest = null, documentLength = null, } = {}) {
660
+ if (!exactKeys(container, CONTAINER_KEYS)
661
+ || !isRecord(container.artifact)
662
+ || !isRecord(container.verification)) {
663
+ fail('document-action binding container is malformed');
664
+ }
665
+ const binding = container.artifact;
666
+ const verification = container.verification;
667
+ const computedBindingDigest = computeDocumentActionBindingDigest(binding);
668
+ const computedActionDigest = computeReleaseActionDigest(binding.release_action?.template);
669
+ const bindingDocumentDigest = binding.document?.digest;
670
+ const currentContractorProfile = binding.release_action?.template?.action_escrow_template_profile
671
+ === ACTION_ESCROW_CONTRACTOR_TEMPLATE_VERSION;
672
+ const projectRecordBound = validDigest(binding.release_action?.template?.project_record_snapshot_digest);
673
+ // `validateActionEscrowReleaseTemplate` (action-escrow-verifiers.ts, outside
674
+ // this file's scope) still infers its options parameter type from only the
675
+ // one destructured property that carries a default value, so a fresh object
676
+ // literal here trips the excess-property check. Routing through a locally
677
+ // typed variable avoids that without changing what gets passed at runtime.
678
+ const releaseTemplateOptions = {
679
+ profileDigest: record.profile_digest,
680
+ agreementId: binding.agreement_id,
681
+ agreementDigest: record.agreement_digest,
682
+ milestoneId: record.milestone_id,
683
+ documentDigest: bindingDocumentDigest,
684
+ materialTerms: binding.material_terms,
685
+ contractorProjectSource: currentContractorProfile,
686
+ };
687
+ const releaseActionTemplate = validateActionEscrowReleaseTemplate(binding.release_action?.template, releaseTemplateOptions);
688
+ const requiredVerification = new Set(BINDING_VERIFICATION_KEYS);
689
+ if (supersedesDigest === null) {
690
+ requiredVerification.delete('supersedes_document_action_binding_digest');
691
+ }
692
+ if (!exactKeys(verification, BINDING_VERIFICATION_KEYS, requiredVerification)
693
+ || !verificationMatchesCore(verification, expectedCore(record, {
694
+ document_action_binding_digest: bindingDigest,
695
+ release_action_digest: actionDigest,
696
+ }))
697
+ || computedBindingDigest !== bindingDigest
698
+ || binding.binding_digest !== bindingDigest
699
+ || verification.verification_digest !== bindingDigest
700
+ || computedActionDigest !== actionDigest
701
+ || binding.release_action?.digest !== actionDigest
702
+ || !validDigest(bindingDocumentDigest)
703
+ || verification.document_digest !== bindingDocumentDigest
704
+ || verification.agreement_id !== binding.agreement_id
705
+ || verification.binding_id !== binding.binding_id
706
+ || computeActionEscrowAgreementDigest(binding.agreement_id) !== record.agreement_digest
707
+ || releaseActionTemplate === null
708
+ || !sameCanonical(verification.release_action_template, releaseActionTemplate)
709
+ || !sameParties(record.parties, binding.parties)
710
+ || !sameParties(record.parties, binding.required_parties)
711
+ || (binding.supersedes_digest ?? null) !== supersedesDigest
712
+ || (verification.supersedes_document_action_binding_digest ?? null)
713
+ !== supersedesDigest) {
714
+ fail('document-action binding is inconsistent with the kernel record');
715
+ }
716
+ if (documentDigest !== null
717
+ && (bindingDocumentDigest !== documentDigest
718
+ || releaseActionTemplate.document_sha256 !== documentDigest)) {
719
+ fail('final PDF does not match the kernel document binding');
720
+ }
721
+ if (documentLength !== null && binding.document?.byte_length !== documentLength) {
722
+ fail('final PDF byte length does not match the kernel document binding');
723
+ }
724
+ return {
725
+ agreementId: binding.agreement_id,
726
+ binding,
727
+ contractorProjectSource: projectRecordBound,
728
+ documentDigest: bindingDocumentDigest,
729
+ projectRecordSnapshotDigest: releaseActionTemplate.project_record_snapshot_digest ?? null,
730
+ };
731
+ }
732
+ function validateAcceptances(entries, record, core, { requireComplete, requireIncomplete = false, } = {}) {
733
+ if (!Array.isArray(entries))
734
+ fail('agreement acceptances are malformed');
735
+ const parties = new Map(record.parties.map((party) => [party.party_id, party]));
736
+ const required = new Set(record.profile.required_acceptance_party_ids);
737
+ const seenParties = new Set();
738
+ const seenKeys = new Set();
739
+ const result = [];
740
+ for (const entry of entries) {
741
+ const verification = entry?.verification;
742
+ const party = parties.get(entry?.party_id);
743
+ if (!exactKeys(entry, ACCEPTANCE_KEYS)
744
+ || !party
745
+ || !required.has(entry.party_id)
746
+ || seenParties.has(entry.party_id)
747
+ || !isRecord(entry.artifact)
748
+ || !exactKeys(verification, ACCEPTANCE_VERIFICATION_KEYS)
749
+ || !verificationMatchesCore(verification, core)
750
+ || verification.party_id !== entry.party_id
751
+ || !validString(verification.principal_key_id, 512)
752
+ || seenKeys.has(verification.principal_key_id)
753
+ || verification.acceptance_digest !== canonicalDigest(entry.artifact)) {
754
+ fail('agreement acceptance is malformed or inconsistent');
755
+ }
756
+ seenParties.add(entry.party_id);
757
+ seenKeys.add(verification.principal_key_id);
758
+ result.push({
759
+ party_id: entry.party_id,
760
+ role: party.role,
761
+ evidence: entry.artifact,
762
+ });
763
+ }
764
+ if (requireComplete && seenParties.size !== required.size) {
765
+ fail('required agreement acceptance is missing');
766
+ }
767
+ if (requireIncomplete && seenParties.size >= required.size) {
768
+ fail('agreement acceptance count is inconsistent with the stage');
769
+ }
770
+ return result;
771
+ }
772
+ function validateFunding(record) {
773
+ const template = record.document_action_binding.verification.release_action_template;
774
+ if (!exactKeys(record.funding, new Set(['statement', 'verification']))
775
+ || !isRecord(record.funding.statement)
776
+ || !exactKeys(record.funding.verification, FUNDING_VERIFICATION_KEYS)
777
+ || !verificationMatchesCore(record.funding.verification, expectedCore(record))
778
+ || record.funding.verification.authenticated !== true
779
+ || record.funding.verification.provider_id !== record.profile.provider_id
780
+ || record.funding.verification.statement_type !== 'funding'
781
+ || record.funding.verification.status !== 'funded'
782
+ || record.funding.verification.provider_transaction_id
783
+ !== template.custodian_transaction_id
784
+ || record.funding.verification.provider_milestone_id
785
+ !== template.custodian_milestone_id
786
+ || record.funding.verification.amount !== template.amount
787
+ || record.funding.verification.currency !== template.currency
788
+ || record.funding.verification.destination_id !== template.destination_id
789
+ || record.funding.verification.statement_digest
790
+ !== canonicalDigest(record.funding.statement)) {
791
+ fail('funding statement is malformed or inconsistent');
792
+ }
793
+ return record.funding.statement;
794
+ }
795
+ function validateMilestone(record) {
796
+ if (!exactKeys(record.milestone_evidence, CONTAINER_KEYS)
797
+ || !isRecord(record.milestone_evidence.artifact)
798
+ || !exactKeys(record.milestone_evidence.verification, MILESTONE_VERIFICATION_KEYS)
799
+ || !verificationMatchesCore(record.milestone_evidence.verification, expectedCore(record))
800
+ || !validDigest(record.milestone_evidence.verification.evidence_digest)
801
+ || !record.parties.some((party) => party.party_id
802
+ === record.milestone_evidence.verification.submitter_party_id)
803
+ || !validInstant(record.milestone_evidence.verification.observed_at)) {
804
+ fail('milestone evidence is malformed or inconsistent');
805
+ }
806
+ const artifact = record.milestone_evidence.artifact;
807
+ const claimedDigest = artifact.evidence_digest
808
+ ?? artifact.payload?.claim?.evidence_manifest_digest;
809
+ if (claimedDigest !== undefined
810
+ && claimedDigest !== record.milestone_evidence.verification.evidence_digest) {
811
+ fail('milestone artifact digest does not match its kernel verification');
812
+ }
813
+ const submission = record.operations.find((operation) => operation.operation === 'submit_milestone');
814
+ if (!submission
815
+ || Date.parse(record.milestone_evidence.verification.observed_at)
816
+ > Date.parse(submission.at)) {
817
+ fail('milestone evidence was not valid at its submission operation');
818
+ }
819
+ return {
820
+ milestone_id: record.milestone_id,
821
+ evidence: artifact,
822
+ resolution: null,
823
+ };
824
+ }
825
+ function validateReleaseApprovals(record, milestoneVerification) {
826
+ if (!Array.isArray(record.release_approvals))
827
+ fail('release approvals are malformed');
828
+ const parties = new Map(record.parties.map((party) => [party.party_id, party]));
829
+ const required = new Set(record.profile.required_release_approver_party_ids);
830
+ const bindingInput = {
831
+ agreement_digest: record.agreement_digest,
832
+ document_action_binding_digest: record.document_action_binding_digest,
833
+ milestone_id: record.milestone_id,
834
+ release_action_digest: record.release_action_digest,
835
+ profile_digest: record.profile_digest,
836
+ evidence_digest: milestoneVerification.evidence_digest,
837
+ release_action_template: record.document_action_binding.verification.release_action_template,
838
+ };
839
+ const bindingMomentDigest = computeActionEscrowReleaseBindingMomentDigest(bindingInput);
840
+ const expectedInitiator = milestoneVerification.submitter_party_id;
841
+ if (!validDigest(bindingMomentDigest) || !validString(expectedInitiator, 256)) {
842
+ fail('release approval binding context is malformed');
843
+ }
844
+ const seenParties = new Set();
845
+ const seenKeys = new Set();
846
+ const result = [];
847
+ const approvalOperations = record.operations.filter((operation) => operation.operation === 'approve_release');
848
+ for (const [index, entry] of record.release_approvals.entries()) {
849
+ const party = parties.get(entry?.party_id);
850
+ const verification = entry?.verification;
851
+ const context = entry?.resolution?.signoff?.context;
852
+ if (!exactKeys(entry, RELEASE_APPROVAL_KEYS)
853
+ || !party
854
+ || !required.has(entry.party_id)
855
+ || seenParties.has(entry.party_id)
856
+ || !isRecord(entry.resolution)
857
+ || entry.resolution.profile !== 'EP-RESOLUTION-v1'
858
+ || !isRecord(context)
859
+ || !exactKeys(verification, RELEASE_APPROVAL_VERIFICATION_KEYS)
860
+ || !verificationMatchesCore(verification, expectedCore(record))
861
+ || verification.authorizes_action !== true
862
+ || verification.outcome !== 'approved'
863
+ || verification.party_role !== party.role
864
+ || !validString(verification.principal_key_id, 512)
865
+ || seenKeys.has(verification.principal_key_id)
866
+ || !validString(verification.nonce, 512)
867
+ || !validInstant(verification.issued_at)
868
+ || !validInstant(verification.expires_at)
869
+ || Date.parse(verification.issued_at) < Date.parse(milestoneVerification.observed_at)
870
+ || Date.parse(verification.expires_at) <= Date.parse(verification.issued_at)
871
+ || verification.resolution_digest !== canonicalDigest(entry.resolution)
872
+ || verification.evidence_digest !== milestoneVerification.evidence_digest
873
+ || context.principal !== entry.party_id
874
+ || context.principal_key_id !== verification.principal_key_id
875
+ || context.envelope_hash !== bindingMomentDigest
876
+ || context.action_hash !== record.release_action_digest
877
+ || context.initiator !== expectedInitiator
878
+ || context.nonce !== computeActionEscrowResolutionNonce(bindingInput, entry.party_id)
879
+ || context.nonce !== verification.nonce
880
+ || context.issued_at !== verification.issued_at
881
+ || context.expires_at !== verification.expires_at
882
+ || context.resolution?.outcome !== 'approved'
883
+ || context.resolution?.selected_option !== 0) {
884
+ fail('release approval is malformed or inconsistent');
885
+ }
886
+ const approvalOperation = approvalOperations[index];
887
+ if (!approvalOperation
888
+ || Date.parse(verification.issued_at) > Date.parse(approvalOperation.at)
889
+ || Date.parse(verification.expires_at) <= Date.parse(approvalOperation.at)
890
+ || (record.release !== null
891
+ && (Date.parse(verification.issued_at) > Date.parse(record.release.reserved_at)
892
+ || Date.parse(verification.expires_at) <= Date.parse(record.release.reserved_at)))) {
893
+ fail('release approval was not valid at its operation');
894
+ }
895
+ seenParties.add(entry.party_id);
896
+ seenKeys.add(verification.principal_key_id);
897
+ result.push({
898
+ party_id: entry.party_id,
899
+ role: party.role,
900
+ evidence: entry.resolution,
901
+ });
902
+ }
903
+ return { approvals: result, approvedPartyIds: seenParties };
904
+ }
905
+ function validateProviderVerification(value, record, release) {
906
+ const template = record.document_action_binding.verification.release_action_template;
907
+ if (!exactKeys(value, PROVIDER_VERIFICATION_KEYS)
908
+ || !verificationMatchesCore(value, expectedCore(record))
909
+ || value.authenticated !== true
910
+ || value.provider_id !== record.profile.provider_id
911
+ || value.provider_idempotency_key !== release.provider_idempotency_key
912
+ || value.provider_request_digest !== release.provider_request.request_digest
913
+ || value.provider_transaction_id !== template.custodian_transaction_id
914
+ || value.provider_milestone_id !== template.custodian_milestone_id
915
+ || value.amount !== template.amount
916
+ || value.currency !== template.currency
917
+ || value.destination_id !== template.destination_id
918
+ || value.statement_type !== 'release'
919
+ || !['released', 'not_released', 'pending'].includes(value.status)
920
+ || !validDigest(value.statement_digest)
921
+ || value.statement_digest !== canonicalDigest(release.provider_statement)) {
922
+ fail('provider release statement is malformed or inconsistent');
923
+ }
924
+ }
925
+ function validateRelease(record) {
926
+ const release = record.release;
927
+ if (!exactKeys(release, RELEASE_KEYS)
928
+ || !validString(release.release_key, 256)
929
+ || !validString(release.provider_idempotency_key, 256)
930
+ || !validString(release.operation_idempotency_key, 512)
931
+ || !['reserved', 'released', 'not_released', 'indeterminate'].includes(release.status)
932
+ || !validInstant(release.reserved_at)
933
+ || (release.reconciled_at !== null && !validInstant(release.reconciled_at))
934
+ || !exactKeys(release.provider_request, PROVIDER_REQUEST_KEYS)) {
935
+ fail('release record is malformed');
936
+ }
937
+ const expectedReleaseKey = `ep-ae-reservation:${hashCanonical({
938
+ '@version': 'EP-ACTION-ESCROW-RELEASE-KEY-v1',
939
+ agreement_digest: record.agreement_digest,
940
+ document_action_binding_digest: record.document_action_binding_digest,
941
+ milestone_id: record.milestone_id,
942
+ release_action_digest: record.release_action_digest,
943
+ profile_digest: record.profile_digest,
944
+ })}`;
945
+ const expectedProviderKey = `ep-ae-release:${hashCanonical({
946
+ '@version': 'EP-ACTION-ESCROW-PROVIDER-IDEMPOTENCY-v1',
947
+ agreement_digest: record.agreement_digest,
948
+ document_action_binding_digest: record.document_action_binding_digest,
949
+ milestone_id: record.milestone_id,
950
+ release_action_digest: record.release_action_digest,
951
+ profile_digest: record.profile_digest,
952
+ })}`;
953
+ if (release.release_key !== expectedReleaseKey
954
+ || release.provider_idempotency_key !== expectedProviderKey) {
955
+ fail('release reservation key mismatch');
956
+ }
957
+ const request = release.provider_request;
958
+ const { request_digest: requestDigest, ...requestScope } = request;
959
+ if (request.method !== 'POST'
960
+ || request.provider_id !== record.profile.provider_id
961
+ || request.agreement_digest !== record.agreement_digest
962
+ || request.document_action_binding_digest
963
+ !== record.document_action_binding_digest
964
+ || request.milestone_id !== record.milestone_id
965
+ || request.release_action_digest !== record.release_action_digest
966
+ || !sameCanonical(request.parties, record.parties)
967
+ || request.parties_digest !== record.parties_digest
968
+ || !sameCanonical(request.profile, record.profile)
969
+ || request.profile_digest !== record.profile_digest
970
+ || request.agreement_id
971
+ !== record.document_action_binding.verification.agreement_id
972
+ || request.binding_id !== record.document_action_binding.verification.binding_id
973
+ || request.document_digest
974
+ !== record.document_action_binding.verification.document_digest
975
+ || !sameCanonical(request.release_action_template, record.document_action_binding.verification.release_action_template)
976
+ || request.release_key !== release.release_key
977
+ || request.idempotency_key !== release.provider_idempotency_key
978
+ || requestDigest !== canonicalDigest({
979
+ '@version': 'EP-ACTION-ESCROW-PROVIDER-REQUEST-v1',
980
+ ...requestScope,
981
+ })) {
982
+ fail('provider release request is inconsistent with the kernel record');
983
+ }
984
+ const execution = record.operations.find((entry) => (entry.operation === 'release'
985
+ && entry.idempotency_key === release.operation_idempotency_key));
986
+ if (!execution)
987
+ fail('release execution record is missing');
988
+ if (release.reserved_at !== execution.at
989
+ || (release.reconciled_at !== null
990
+ && Date.parse(release.reconciled_at) < Date.parse(release.reserved_at))) {
991
+ fail('release timestamps are inconsistent with the execution operation');
992
+ }
993
+ const expectedExecution = {
994
+ reserved: {
995
+ states: new Set(['release_reserved']),
996
+ operationStates: new Set(['release_reserved']),
997
+ codes: new Set(['release_reserved']),
998
+ ok: false,
999
+ outcomes: new Set(['reserved']),
1000
+ },
1001
+ released: {
1002
+ states: new Set(['released', 'completed']),
1003
+ operationStates: new Set(['released']),
1004
+ codes: new Set(['release_committed', 'release_reconciled_released']),
1005
+ ok: true,
1006
+ outcomes: new Set(['applied']),
1007
+ },
1008
+ not_released: {
1009
+ states: new Set(['milestone_submitted', 'disputed', 'amendment_pending']),
1010
+ operationStates: new Set(['milestone_submitted', 'amendment_pending']),
1011
+ codes: new Set([
1012
+ 'provider_release_not_released',
1013
+ 'release_reconciled_not_released',
1014
+ ]),
1015
+ ok: false,
1016
+ outcomes: new Set(['refused']),
1017
+ },
1018
+ indeterminate: {
1019
+ states: new Set(['release_indeterminate']),
1020
+ operationStates: new Set(['release_indeterminate']),
1021
+ codes: new Set([
1022
+ 'release_effect_indeterminate',
1023
+ 'release_commit_indeterminate',
1024
+ 'release_still_indeterminate',
1025
+ ]),
1026
+ ok: false,
1027
+ outcomes: new Set(['indeterminate']),
1028
+ },
1029
+ }[release.status];
1030
+ if (!expectedExecution.states.has(record.state)
1031
+ || !expectedExecution.operationStates.has(execution.state)
1032
+ || !expectedExecution.codes.has(execution.code)
1033
+ || execution.ok !== expectedExecution.ok
1034
+ || !expectedExecution.outcomes.has(execution.outcome)) {
1035
+ fail('release execution record is inconsistent with the release state');
1036
+ }
1037
+ if (release.status === 'reserved') {
1038
+ if (release.reconciled_at !== null
1039
+ || release.provider_statement !== null
1040
+ || release.provider_verification !== null) {
1041
+ fail('reserved release carries premature provider evidence');
1042
+ }
1043
+ }
1044
+ else {
1045
+ if (release.reconciled_at === null)
1046
+ fail('reconciled release is missing its instant');
1047
+ const hasStatement = release.provider_statement !== null;
1048
+ const hasVerification = release.provider_verification !== null;
1049
+ if (hasStatement !== hasVerification) {
1050
+ fail('provider release statement and verification must be paired');
1051
+ }
1052
+ if (release.status !== 'indeterminate' && !hasStatement) {
1053
+ fail('authoritative provider release statement is missing');
1054
+ }
1055
+ if (hasStatement) {
1056
+ if (!isRecord(release.provider_statement)) {
1057
+ fail('provider release statement is malformed');
1058
+ }
1059
+ validateProviderVerification(release.provider_verification, record, release);
1060
+ if (release.status !== 'indeterminate'
1061
+ && release.provider_verification.status !== release.status) {
1062
+ fail('provider release status mismatch');
1063
+ }
1064
+ }
1065
+ }
1066
+ return {
1067
+ reservation: {
1068
+ release_key: release.release_key,
1069
+ provider_idempotency_key: release.provider_idempotency_key,
1070
+ reserved_at: release.reserved_at,
1071
+ },
1072
+ provider_request: request,
1073
+ provider_statement: release.provider_statement,
1074
+ execution_record: execution,
1075
+ };
1076
+ }
1077
+ function validateCommandAuthorization(container, record, command, partyId, details) {
1078
+ if (!exactKeys(container, COMMAND_CONTAINER_KEYS)
1079
+ || !isRecord(container.artifact)
1080
+ || !exactKeys(container.verification, COMMAND_VERIFICATION_KEYS)
1081
+ || !verificationMatchesCore(container.verification, expectedCore(record))) {
1082
+ fail(`${command} authorization is malformed`);
1083
+ }
1084
+ const detailsDigest = canonicalDigest(details);
1085
+ const commandDigest = canonicalDigest({
1086
+ '@version': 'EP-ACTION-ESCROW-COMMAND-v1',
1087
+ ...expectedCore(record),
1088
+ command,
1089
+ party_id: partyId,
1090
+ details_digest: detailsDigest,
1091
+ });
1092
+ if (container.verification.authorizes_command !== true
1093
+ || container.verification.command !== command
1094
+ || container.verification.party_id !== partyId
1095
+ || container.verification.details_digest !== detailsDigest
1096
+ || container.verification.command_digest !== commandDigest) {
1097
+ fail(`${command} authorization does not match the state change`);
1098
+ }
1099
+ }
1100
+ function validateAncillaryState(record) {
1101
+ if (record.state === 'disputed') {
1102
+ if (!exactKeys(record.dispute, DISPUTE_KEYS)
1103
+ || !record.parties.some((party) => party.party_id === record.dispute.party_id)
1104
+ || !validString(record.dispute.reason, 2048)
1105
+ || !validInstant(record.dispute.opened_at)) {
1106
+ fail('dispute state is malformed');
1107
+ }
1108
+ validateCommandAuthorization(record.dispute.authorization, record, 'open_dispute', record.dispute.party_id, { reason: record.dispute.reason });
1109
+ }
1110
+ else if (record.dispute !== null) {
1111
+ fail('non-disputed stage carries a dispute');
1112
+ }
1113
+ if (record.state === 'cancelled') {
1114
+ if (!exactKeys(record.cancellation, CANCELLATION_KEYS)
1115
+ || !record.parties.some((party) => party.party_id === record.cancellation.party_id)
1116
+ || (record.cancellation.reason !== null
1117
+ && !validString(record.cancellation.reason, 2048))
1118
+ || !validInstant(record.cancellation.cancelled_at)) {
1119
+ fail('cancellation state is malformed');
1120
+ }
1121
+ validateCommandAuthorization(record.cancellation.authorization, record, 'cancel', record.cancellation.party_id, { reason: record.cancellation.reason });
1122
+ }
1123
+ else if (record.cancellation !== null) {
1124
+ fail('non-cancelled stage carries a cancellation');
1125
+ }
1126
+ if (record.state === 'completed') {
1127
+ if (!exactKeys(record.completion, COMPLETION_KEYS)
1128
+ || !record.parties.some((party) => party.party_id === record.completion.party_id)
1129
+ || record.completion.meaning !== 'administrative_archive_only'
1130
+ || !validInstant(record.completion.completed_at)) {
1131
+ fail('completion state is malformed');
1132
+ }
1133
+ validateCommandAuthorization(record.completion.authorization, record, 'complete', record.completion.party_id, { meaning: 'administrative_archive_only' });
1134
+ }
1135
+ else if (record.completion !== null) {
1136
+ fail('non-completed stage carries a completion record');
1137
+ }
1138
+ }
1139
+ /** @param {any} record */
1140
+ function validateSupersessions(record) {
1141
+ if (!Array.isArray(record.superseded_bindings)) {
1142
+ fail('superseded binding history is malformed');
1143
+ }
1144
+ const amendments = [];
1145
+ const amendmentDigests = [];
1146
+ let previousNext = null;
1147
+ const seen = new Set();
1148
+ for (const entry of record.superseded_bindings) {
1149
+ if (!exactKeys(entry, SUPERSESSION_KEYS)
1150
+ || !validDigest(entry.document_action_binding_digest)
1151
+ || !validDigest(entry.release_action_digest)
1152
+ || !validDigest(entry.superseded_by_binding_digest)
1153
+ || !validInstant(entry.superseded_at)
1154
+ || entry.document_action_binding_digest === entry.superseded_by_binding_digest
1155
+ || seen.has(entry.document_action_binding_digest)
1156
+ || (previousNext !== null
1157
+ && entry.document_action_binding_digest !== previousNext)) {
1158
+ fail('superseded binding history is inconsistent');
1159
+ }
1160
+ seen.add(entry.document_action_binding_digest);
1161
+ previousNext = entry.superseded_by_binding_digest;
1162
+ amendments.push(entry);
1163
+ amendmentDigests.push(canonicalDigest(entry));
1164
+ }
1165
+ if (previousNext !== null && previousNext !== record.document_action_binding_digest) {
1166
+ fail('superseded binding history does not terminate at the current binding');
1167
+ }
1168
+ return {
1169
+ amendments,
1170
+ amendmentDigests,
1171
+ currentSupersedes: amendments.at(-1)?.document_action_binding_digest ?? null,
1172
+ };
1173
+ }
1174
+ /** @param {any} record */
1175
+ function validatePendingAmendment(record) {
1176
+ const pendingAllowed = record.state === 'amendment_pending'
1177
+ || record.state === 'release_indeterminate'
1178
+ || record.state === 'cancelled';
1179
+ if (record.pending_amendment === null) {
1180
+ if (record.state === 'amendment_pending')
1181
+ fail('pending amendment is missing');
1182
+ return;
1183
+ }
1184
+ if (!pendingAllowed
1185
+ || !exactKeys(record.pending_amendment, PENDING_AMENDMENT_KEYS)
1186
+ || ![
1187
+ 'effective',
1188
+ 'awaiting_funding',
1189
+ 'funded',
1190
+ 'milestone_submitted',
1191
+ 'disputed',
1192
+ 'release_reserved',
1193
+ 'release_indeterminate',
1194
+ ].includes(record.pending_amendment.from_state)
1195
+ || !validDigest(record.pending_amendment.document_action_binding_digest)
1196
+ || !validDigest(record.pending_amendment.release_action_digest)
1197
+ || record.pending_amendment.document_action_binding_digest
1198
+ === record.document_action_binding_digest
1199
+ || !record.parties.some((/** @type {{party_id: string}} */ party) => party.party_id
1200
+ === record.pending_amendment.proposer_party_id)
1201
+ || !validInstant(record.pending_amendment.proposed_at)) {
1202
+ fail('pending amendment is malformed');
1203
+ }
1204
+ if (record.state === 'amendment_pending'
1205
+ && ['release_reserved', 'release_indeterminate'].includes(record.pending_amendment.from_state)) {
1206
+ fail('pending amendment stage is inconsistent with release reconciliation');
1207
+ }
1208
+ if (record.state === 'release_indeterminate'
1209
+ && !['release_reserved', 'release_indeterminate'].includes(record.pending_amendment.from_state)) {
1210
+ fail('indeterminate amendment does not originate from an uncertain release');
1211
+ }
1212
+ validateBindingContainer(record.pending_amendment.document_action_binding, record, {
1213
+ bindingDigest: record.pending_amendment.document_action_binding_digest,
1214
+ actionDigest: record.pending_amendment.release_action_digest,
1215
+ supersedesDigest: record.document_action_binding_digest,
1216
+ });
1217
+ const pendingCore = expectedCore(record, {
1218
+ document_action_binding_digest: record.pending_amendment.document_action_binding_digest,
1219
+ release_action_digest: record.pending_amendment.release_action_digest,
1220
+ });
1221
+ validateAcceptances(record.pending_amendment.agreement_acceptances, record, pendingCore, { requireComplete: false, requireIncomplete: true });
1222
+ validateCommandAuthorization(record.pending_amendment.proposal_authorization, record, 'propose_amendment', record.pending_amendment.proposer_party_id, {
1223
+ next_document_action_binding_digest: record.pending_amendment.document_action_binding_digest,
1224
+ next_release_action_digest: record.pending_amendment.release_action_digest,
1225
+ });
1226
+ }
1227
+ /** @param {any} record */
1228
+ function validateLifecycle(record) {
1229
+ const requiresExecutedAgreement = EXECUTED_AGREEMENT_STATES.has(record.state);
1230
+ const agreementAcceptances = validateAcceptances(record.agreement_acceptances, record, expectedCore(record), {
1231
+ requireComplete: requiresExecutedAgreement,
1232
+ requireIncomplete: record.state === 'awaiting_acceptance',
1233
+ });
1234
+ if (record.state === 'draft' && agreementAcceptances.length !== 0) {
1235
+ fail('draft stage carries agreement acceptances');
1236
+ }
1237
+ const requiresFunding = FUNDING_STATES.has(record.state);
1238
+ if (requiresFunding !== (record.funding !== null)) {
1239
+ fail(requiresFunding
1240
+ ? 'required funding statement is missing'
1241
+ : 'stage carries an unexpected funding statement');
1242
+ }
1243
+ const fundingStatement = record.funding === null ? null : validateFunding(record);
1244
+ const requiresMilestone = MILESTONE_STATES.has(record.state);
1245
+ if (requiresMilestone !== (record.milestone_evidence !== null)) {
1246
+ fail(requiresMilestone
1247
+ ? 'required milestone evidence is missing'
1248
+ : 'stage carries unexpected milestone evidence');
1249
+ }
1250
+ const milestone = record.milestone_evidence === null ? null : validateMilestone(record);
1251
+ validateLifecycleOperationCoverage(record);
1252
+ if (!RELEASE_APPROVAL_STATES.has(record.state)
1253
+ && record.release_approvals.length !== 0) {
1254
+ fail('stage carries unexpected release approvals');
1255
+ }
1256
+ if (record.release_approvals.length > 0 && milestone === null) {
1257
+ fail('release approval has no milestone evidence');
1258
+ }
1259
+ const releaseApprovalResult = milestone === null
1260
+ ? { approvals: [], approvedPartyIds: new Set() }
1261
+ : validateReleaseApprovals(record, record.milestone_evidence.verification);
1262
+ if (COMPLETE_RELEASE_APPROVAL_STATES.has(record.state)
1263
+ && releaseApprovalResult.approvedPartyIds.size
1264
+ !== record.profile.required_release_approver_party_ids.length) {
1265
+ fail('required release approval is missing');
1266
+ }
1267
+ const hasRelease = record.release !== null;
1268
+ if (REQUIRED_RELEASE_STATES.has(record.state) && !hasRelease) {
1269
+ fail('required release artifacts are missing');
1270
+ }
1271
+ if (!REQUIRED_RELEASE_STATES.has(record.state)
1272
+ && !OPTIONAL_RELEASE_STATES.has(record.state)
1273
+ && hasRelease) {
1274
+ fail('stage carries unexpected release artifacts');
1275
+ }
1276
+ const release = hasRelease ? validateRelease(record) : null;
1277
+ validateAncillaryState(record);
1278
+ validatePendingAmendment(record);
1279
+ return {
1280
+ requiresExecutedAgreement,
1281
+ agreementAcceptances,
1282
+ fundingStatement,
1283
+ milestones: milestone === null ? [] : [milestone],
1284
+ releaseApprovals: releaseApprovalResult.approvals,
1285
+ release,
1286
+ };
1287
+ }
1288
+ /** @param {any} record */
1289
+ function validateLifecycleOperationCoverage(record) {
1290
+ /** @param {string} name */
1291
+ const count = (name) => record.operations
1292
+ .filter((/** @type {{operation: string}} */ operation) => operation.operation === name)
1293
+ .length;
1294
+ /**
1295
+ * @param {string} name
1296
+ * @param {number} expected
1297
+ */
1298
+ const requireExact = (name, expected) => {
1299
+ if (count(name) !== expected) {
1300
+ fail(`kernel ${name} operation coverage does not match its artifacts`);
1301
+ }
1302
+ };
1303
+ const acceptanceCount = record.profile.required_acceptance_party_ids.length;
1304
+ const expectedInitialAcceptances = record.superseded_bindings.length > 0
1305
+ ? acceptanceCount
1306
+ : record.agreement_acceptances.length;
1307
+ const expectedAmendmentAcceptances = record.superseded_bindings.length * acceptanceCount
1308
+ + (Array.isArray(record.pending_amendment?.agreement_acceptances)
1309
+ ? record.pending_amendment.agreement_acceptances.length
1310
+ : 0);
1311
+ requireExact('create', 1);
1312
+ requireExact('begin_acceptance', record.history.some((/** @type {{to: string}} */ entry) => entry.to === 'awaiting_acceptance')
1313
+ ? 1 : 0);
1314
+ requireExact('accept_agreement', expectedInitialAcceptances);
1315
+ requireExact('request_funding', record.history.some((/** @type {{to: string}} */ entry) => entry.to === 'awaiting_funding')
1316
+ ? 1 : 0);
1317
+ requireExact('record_funding', record.funding === null ? 0 : 1);
1318
+ requireExact('submit_milestone', record.milestone_evidence === null ? 0 : 1);
1319
+ requireExact('approve_release', record.release_approvals.length);
1320
+ requireExact('propose_amendment', record.superseded_bindings.length + (record.pending_amendment === null ? 0 : 1));
1321
+ requireExact('accept_amendment', expectedAmendmentAcceptances);
1322
+ requireExact('open_dispute', record.dispute === null ? 0 : 1);
1323
+ requireExact('cancel', record.cancellation === null ? 0 : 1);
1324
+ requireExact('complete', record.completion === null ? 0 : 1);
1325
+ if ((record.release === null) !== (count('release') === 0)) {
1326
+ fail('kernel release operation coverage does not match its artifacts');
1327
+ }
1328
+ if (record.release === null && count('reconcile_release') !== 0) {
1329
+ fail('kernel reconciliation operation has no release artifact');
1330
+ }
1331
+ }
1332
+ /** @param {any} record */
1333
+ function validateKernelRecord(record) {
1334
+ if (!exactKeys(record, RECORD_KEYS)
1335
+ || record['@version'] !== ACTION_ESCROW_STATE_VERSION
1336
+ || !Number.isSafeInteger(record.revision)
1337
+ || record.revision < 0
1338
+ || !ACTION_ESCROW_STATES.includes(record.state)
1339
+ || !validString(record.escrow_key, 256)
1340
+ || !validDigest(record.agreement_digest)
1341
+ || !validDigest(record.document_action_binding_digest)
1342
+ || !validString(record.milestone_id, 256)
1343
+ || !validDigest(record.release_action_digest)
1344
+ || !validDigest(record.parties_digest)
1345
+ || !validDigest(record.profile_digest)
1346
+ || !validInstant(record.created_at)
1347
+ || !validInstant(record.updated_at)) {
1348
+ fail('kernel record is malformed');
1349
+ }
1350
+ const expectedEscrowKey = `ep-action-escrow:${hashCanonical({
1351
+ '@version': 'EP-ACTION-ESCROW-KEY-v1',
1352
+ agreement_digest: record.agreement_digest,
1353
+ milestone_id: record.milestone_id,
1354
+ })}`;
1355
+ if (record.escrow_key !== expectedEscrowKey)
1356
+ fail('kernel escrow key mismatch');
1357
+ validatePartiesAndProfile(record);
1358
+ validateHistory(record);
1359
+ }
1360
+ /**
1361
+ * @param {any} value
1362
+ * @param {{agreementId: string, bindingDigest: string | null, documentDigest: string | null}} expected
1363
+ * @param {boolean} required
1364
+ */
1365
+ function validateDocumentExecution(value, expected, required) {
1366
+ if (value === null) {
1367
+ if (required)
1368
+ fail('required document-execution artifact is missing');
1369
+ return null;
1370
+ }
1371
+ if (!isRecord(value)
1372
+ || value.agreement_id !== expected.agreementId
1373
+ || value.binding_digest !== expected.bindingDigest
1374
+ || value.document_digest !== expected.documentDigest
1375
+ || value.authorizes_action !== false
1376
+ || (value.state !== undefined && value.state !== 'executed')) {
1377
+ fail('document-execution artifact does not match the kernel record');
1378
+ }
1379
+ return value;
1380
+ }
1381
+ /**
1382
+ * @param {any} value
1383
+ * @param {any} record
1384
+ */
1385
+ function validateProfileReference(value, record) {
1386
+ if (!exactKeys(value, PROFILE_REFERENCE_KEYS)
1387
+ || value.id !== record.profile.profile_id
1388
+ || value.digest !== record.profile_digest) {
1389
+ fail('verification-profile reference mismatch');
1390
+ }
1391
+ }
1392
+ /** @param {any} statement */
1393
+ function stateStatementDigest(statement) {
1394
+ const body = {
1395
+ version: statement.version,
1396
+ issuer: statement.issuer,
1397
+ payload: statement.payload,
1398
+ };
1399
+ const bytes = Buffer.from(ACTION_ESCROW_STATE_STATEMENT_DOMAIN + canonicalize(body), 'utf8');
1400
+ return `sha256:${crypto.createHash('sha256').update(bytes).digest('hex')}`;
1401
+ }
1402
+ /**
1403
+ * @param {any} statement
1404
+ * @param {any} record
1405
+ * @param {string} agreementId
1406
+ * @param {string[]} amendmentDigests
1407
+ * @param {number} assembledAt
1408
+ */
1409
+ function validateStateStatement(statement, record, agreementId, amendmentDigests, assembledAt) {
1410
+ if (!exactKeys(statement, STATE_STATEMENT_KEYS)
1411
+ || statement.version !== ACTION_ESCROW_STATE_STATEMENT_VERSION
1412
+ || !exactKeys(statement.issuer, STATE_ISSUER_KEYS)
1413
+ || !validString(statement.issuer.operator_id, 256)
1414
+ || !validString(statement.issuer.key_id, 256)
1415
+ || !exactKeys(statement.payload, STATE_PAYLOAD_KEYS)
1416
+ || !validString(statement.payload.statement_id, 256)
1417
+ || statement.payload.agreement_id !== agreementId
1418
+ || statement.payload.binding_digest !== record.document_action_binding_digest
1419
+ || statement.payload.action_digest !== record.release_action_digest
1420
+ || statement.payload.profile_digest !== record.profile_digest
1421
+ || statement.payload.state !== record.state
1422
+ || statement.payload.revision !== record.revision
1423
+ || !Array.isArray(statement.payload.amendment_digests)
1424
+ || statement.payload.amendment_digests.length !== amendmentDigests.length
1425
+ || statement.payload.amendment_digests.some((/** @type {string} */ digest, /** @type {number} */ index) => digest
1426
+ !== amendmentDigests[index])
1427
+ || statement.payload.state_record_digest !== canonicalDigest(record)
1428
+ || (statement.payload.previous_statement_digest !== null
1429
+ && !validDigest(statement.payload.previous_statement_digest))
1430
+ || !validInstant(statement.payload.occurred_at)
1431
+ || Date.parse(statement.payload.occurred_at) > assembledAt
1432
+ || !exactKeys(statement.signature, STATE_SIGNATURE_KEYS)
1433
+ || statement.signature.algorithm !== 'Ed25519'
1434
+ || typeof statement.signature.signature_b64u !== 'string'
1435
+ || !BASE64URL.test(statement.signature.signature_b64u)
1436
+ || statement.signature.signature_b64u.length % 4 === 1
1437
+ || !validDigest(statement.statement_digest)
1438
+ || statement.statement_digest !== stateStatementDigest(statement)) {
1439
+ fail('operator state statement mismatch');
1440
+ }
1441
+ }
1442
+ /**
1443
+ * @param {Buffer|Uint8Array} value
1444
+ * @param {number} maxDocumentBytes
1445
+ */
1446
+ function finalPdfBytes(value, maxDocumentBytes) {
1447
+ if (!(Buffer.isBuffer(value) || value instanceof Uint8Array)) {
1448
+ fail('finalPdfBytes must be bytes');
1449
+ }
1450
+ const bytes = Buffer.from(value);
1451
+ if (bytes.length === 0 || bytes.length > maxDocumentBytes) {
1452
+ fail(`finalPdfBytes must be between 1 and ${maxDocumentBytes} bytes`);
1453
+ }
1454
+ if (!bytes.subarray(0, 5).equals(Buffer.from('%PDF-', 'ascii'))
1455
+ || !bytes.subarray(Math.max(0, bytes.length - 1024)).includes(Buffer.from('%%EOF'))) {
1456
+ fail('finalPdfBytes is not a final PDF');
1457
+ }
1458
+ return bytes;
1459
+ }
1460
+ /** @param {number|string|Date|(() => (number|string|Date))} value */
1461
+ function evaluationInstant(value) {
1462
+ const candidate = typeof value === 'function' ? value() : value;
1463
+ const parsed = candidate instanceof Date
1464
+ ? candidate.getTime()
1465
+ : typeof candidate === 'number'
1466
+ ? candidate
1467
+ : Date.parse(candidate);
1468
+ if (!Number.isFinite(parsed))
1469
+ fail('now must be a valid instant');
1470
+ return parsed;
1471
+ }
1472
+ /**
1473
+ * Assemble an EP-ACTION-ESCROW-EVIDENCE-PACKAGE-v1 from one exact durable
1474
+ * kernel record and the external artifacts the kernel deliberately does not
1475
+ * retain. Invalid local assembly input throws before a package is produced.
1476
+ */
1477
+ function assembleEvidencePackage(input, options, { contractorProjectSource }) {
1478
+ const inputKeys = contractorProjectSource ? CONTRACTOR_INPUT_KEYS : INPUT_KEYS;
1479
+ const optionKeys = contractorProjectSource
1480
+ ? CONTRACTOR_OPTION_KEYS
1481
+ : OPTION_KEYS;
1482
+ if (!exactKeys(input, inputKeys)) {
1483
+ fail('caller overrides are not accepted; use the closed assembler input');
1484
+ }
1485
+ if (!exactKeys(options, optionKeys, new Set())) {
1486
+ fail('caller overrides are not accepted in assembler options');
1487
+ }
1488
+ const maxDocumentBytes = options.maxDocumentBytes ?? DEFAULT_MAX_DOCUMENT_BYTES;
1489
+ if (!Number.isSafeInteger(maxDocumentBytes) || maxDocumentBytes <= 0) {
1490
+ fail('maxDocumentBytes must be a positive safe integer');
1491
+ }
1492
+ const assembledAt = evaluationInstant(options.now ?? Date.now);
1493
+ const bytes = finalPdfBytes(input.finalPdfBytes, maxDocumentBytes);
1494
+ const record = canonicalCopy(input.kernelRecord, 'kernelRecord');
1495
+ const documentExecution = input.documentExecution === null
1496
+ ? null
1497
+ : canonicalCopy(input.documentExecution, 'documentExecution');
1498
+ const stateStatement = canonicalCopy(input.operatorStateStatement, 'operatorStateStatement');
1499
+ const verificationProfile = canonicalCopy(input.verificationProfile, 'verificationProfile');
1500
+ assertNoSecrets(record, 'kernelRecord');
1501
+ assertNoSecrets(documentExecution, 'documentExecution');
1502
+ assertNoSecrets(stateStatement, 'operatorStateStatement');
1503
+ assertNoSecrets(verificationProfile, 'verificationProfile');
1504
+ validateKernelRecord(record);
1505
+ if (Date.parse(record.updated_at) > assembledAt) {
1506
+ fail('kernel record is from the future');
1507
+ }
1508
+ const supersessions = validateSupersessions(record);
1509
+ const documentDigest = computeDocumentSha256(bytes);
1510
+ const binding = validateBindingContainer(record.document_action_binding, record, {
1511
+ supersedesDigest: supersessions.currentSupersedes,
1512
+ documentDigest,
1513
+ documentLength: bytes.length,
1514
+ });
1515
+ if (binding.contractorProjectSource !== contractorProjectSource) {
1516
+ fail(contractorProjectSource
1517
+ ? 'contractor evidence package requires the contractor binding profile'
1518
+ : 'contractor binding requires the contractor evidence-package assembler');
1519
+ }
1520
+ if (contractorProjectSource
1521
+ && input.projectRecordSnapshotDigest
1522
+ !== binding.projectRecordSnapshotDigest) {
1523
+ fail('project-record snapshot digest does not match the document binding');
1524
+ }
1525
+ const lifecycle = validateLifecycle(record);
1526
+ const execution = validateDocumentExecution(documentExecution, {
1527
+ agreementId: binding.agreementId,
1528
+ bindingDigest: record.document_action_binding_digest,
1529
+ documentDigest,
1530
+ }, lifecycle.requiresExecutedAgreement);
1531
+ validateProfileReference(verificationProfile, record);
1532
+ validateStateStatement(stateStatement, record, binding.agreementId, supersessions.amendmentDigests, assembledAt);
1533
+ return buildActionEscrowEvidencePackage(/** @type {any} */ ({
1534
+ agreementId: binding.agreementId,
1535
+ stage: record.state,
1536
+ binding: binding.binding,
1537
+ documentBytes: bytes,
1538
+ documentFileName: input.documentFileName,
1539
+ documentExecution: execution,
1540
+ agreementAcceptances: lifecycle.agreementAcceptances,
1541
+ releaseApprovals: lifecycle.releaseApprovals,
1542
+ fundingStatement: lifecycle.fundingStatement,
1543
+ milestones: lifecycle.milestones,
1544
+ release: lifecycle.release,
1545
+ stateRecord: {
1546
+ snapshot: record,
1547
+ statement: stateStatement,
1548
+ },
1549
+ amendments: supersessions.amendments,
1550
+ verificationProfile,
1551
+ ...(contractorProjectSource
1552
+ ? {
1553
+ projectRecordBytes: input.projectRecordBytes,
1554
+ projectRecordFileName: input.projectRecordFileName,
1555
+ projectRecordProvider: input.projectRecordProvider,
1556
+ projectRecordSnapshotDigest: input.projectRecordSnapshotDigest,
1557
+ }
1558
+ : {}),
1559
+ }), {
1560
+ now: assembledAt,
1561
+ maxDocumentBytes,
1562
+ ...(contractorProjectSource
1563
+ ? { maxProjectRecordBytes: options.maxProjectRecordBytes }
1564
+ : {}),
1565
+ });
1566
+ }
1567
+ export function assembleActionEscrowEvidencePackage(input = {}, options = {}) {
1568
+ return assembleEvidencePackage(input, options, {
1569
+ contractorProjectSource: false,
1570
+ });
1571
+ }
1572
+ export function assembleActionEscrowContractorEvidencePackage(input = {}, options = {}) {
1573
+ return assembleEvidencePackage(input, options, {
1574
+ contractorProjectSource: true,
1575
+ });
1576
+ }
1577
+ export const buildActionEscrowEvidencePackageFromKernel = assembleActionEscrowEvidencePackage;
1578
+ export default {
1579
+ assembleActionEscrowContractorEvidencePackage,
1580
+ assembleActionEscrowEvidencePackage,
1581
+ buildActionEscrowEvidencePackageFromKernel,
1582
+ };
1583
+ //# sourceMappingURL=action-escrow-package.js.map