@emilia-protocol/gate 0.11.0 → 0.13.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 (419) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +252 -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 +1002 -0
  179. package/dist/index.d.ts.map +1 -0
  180. package/dist/index.js +1736 -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/protocol-state.d.ts +141 -0
  203. package/dist/protocol-state.d.ts.map +1 -0
  204. package/dist/protocol-state.js +106 -0
  205. package/dist/protocol-state.js.map +1 -0
  206. package/dist/receipt-program.d.ts +59 -0
  207. package/dist/receipt-program.d.ts.map +1 -0
  208. package/dist/receipt-program.js +1053 -0
  209. package/dist/receipt-program.js.map +1 -0
  210. package/dist/reliance-kernel.d.ts +66 -0
  211. package/dist/reliance-kernel.d.ts.map +1 -0
  212. package/dist/reliance-kernel.js +103 -0
  213. package/dist/reliance-kernel.js.map +1 -0
  214. package/dist/reliance-packet.d.ts +67 -0
  215. package/dist/reliance-packet.d.ts.map +1 -0
  216. package/dist/reliance-packet.js +176 -0
  217. package/dist/reliance-packet.js.map +1 -0
  218. package/dist/remedy-program-postgres.d.ts +37 -0
  219. package/dist/remedy-program-postgres.d.ts.map +1 -0
  220. package/dist/remedy-program-postgres.js +291 -0
  221. package/dist/remedy-program-postgres.js.map +1 -0
  222. package/dist/remedy-program-receipt.d.ts +97 -0
  223. package/dist/remedy-program-receipt.d.ts.map +1 -0
  224. package/dist/remedy-program-receipt.js +817 -0
  225. package/dist/remedy-program-receipt.js.map +1 -0
  226. package/dist/remedy-program.d.ts +76 -0
  227. package/dist/remedy-program.d.ts.map +1 -0
  228. package/dist/remedy-program.js +1346 -0
  229. package/dist/remedy-program.js.map +1 -0
  230. package/dist/reports/art14.d.ts +101 -0
  231. package/dist/reports/art14.d.ts.map +1 -0
  232. package/dist/reports/art14.js +340 -0
  233. package/dist/reports/art14.js.map +1 -0
  234. package/dist/reports/assurance-package.d.ts +197 -0
  235. package/dist/reports/assurance-package.d.ts.map +1 -0
  236. package/dist/reports/assurance-package.js +313 -0
  237. package/dist/reports/assurance-package.js.map +1 -0
  238. package/dist/reports/auditor-workpaper.d.ts +194 -0
  239. package/dist/reports/auditor-workpaper.d.ts.map +1 -0
  240. package/dist/reports/auditor-workpaper.js +545 -0
  241. package/dist/reports/auditor-workpaper.js.map +1 -0
  242. package/dist/reports/external-verification.d.ts +76 -0
  243. package/dist/reports/external-verification.d.ts.map +1 -0
  244. package/dist/reports/external-verification.js +209 -0
  245. package/dist/reports/external-verification.js.map +1 -0
  246. package/dist/reports/reperform.d.ts +122 -0
  247. package/dist/reports/reperform.d.ts.map +1 -0
  248. package/dist/reports/reperform.js +432 -0
  249. package/dist/reports/reperform.js.map +1 -0
  250. package/dist/reports/underwriter.d.ts +127 -0
  251. package/dist/reports/underwriter.d.ts.map +1 -0
  252. package/dist/reports/underwriter.js +348 -0
  253. package/dist/reports/underwriter.js.map +1 -0
  254. package/dist/retention.d.ts +88 -0
  255. package/dist/retention.d.ts.map +1 -0
  256. package/dist/retention.js +90 -0
  257. package/dist/retention.js.map +1 -0
  258. package/dist/roster.d.ts +113 -0
  259. package/dist/roster.d.ts.map +1 -0
  260. package/dist/roster.js +261 -0
  261. package/dist/roster.js.map +1 -0
  262. package/dist/runtime-monitor.d.ts +132 -0
  263. package/dist/runtime-monitor.d.ts.map +1 -0
  264. package/dist/runtime-monitor.js +197 -0
  265. package/dist/runtime-monitor.js.map +1 -0
  266. package/dist/settlement.d.ts +68 -0
  267. package/dist/settlement.d.ts.map +1 -0
  268. package/dist/settlement.js +306 -0
  269. package/dist/settlement.js.map +1 -0
  270. package/dist/siem.d.ts +261 -0
  271. package/dist/siem.d.ts.map +1 -0
  272. package/dist/siem.js +247 -0
  273. package/dist/siem.js.map +1 -0
  274. package/dist/store-postgres.d.ts +107 -0
  275. package/dist/store-postgres.d.ts.map +1 -0
  276. package/dist/store-postgres.js +152 -0
  277. package/dist/store-postgres.js.map +1 -0
  278. package/dist/store.d.ts +95 -0
  279. package/dist/store.d.ts.map +1 -0
  280. package/dist/store.js +202 -0
  281. package/dist/store.js.map +1 -0
  282. package/dist/strict-json.d.ts +14 -0
  283. package/dist/strict-json.d.ts.map +1 -0
  284. package/dist/strict-json.js +132 -0
  285. package/dist/strict-json.js.map +1 -0
  286. package/dist/trust-program-adapters.d.ts +122 -0
  287. package/dist/trust-program-adapters.d.ts.map +1 -0
  288. package/dist/trust-program-adapters.js +802 -0
  289. package/dist/trust-program-adapters.js.map +1 -0
  290. package/dist/trust-program-postgres.d.ts +41 -0
  291. package/dist/trust-program-postgres.d.ts.map +1 -0
  292. package/dist/trust-program-postgres.js +346 -0
  293. package/dist/trust-program-postgres.js.map +1 -0
  294. package/dist/trust-program-revocation.d.ts +206 -0
  295. package/dist/trust-program-revocation.d.ts.map +1 -0
  296. package/dist/trust-program-revocation.js +600 -0
  297. package/dist/trust-program-revocation.js.map +1 -0
  298. package/dist/trust-program.d.ts +197 -0
  299. package/dist/trust-program.d.ts.map +1 -0
  300. package/dist/trust-program.js +1351 -0
  301. package/dist/trust-program.js.map +1 -0
  302. package/dist/witness-postgres.d.ts +43 -0
  303. package/dist/witness-postgres.d.ts.map +1 -0
  304. package/dist/witness-postgres.js +92 -0
  305. package/dist/witness-postgres.js.map +1 -0
  306. package/dist/zk-range-proof.d.ts +78 -0
  307. package/dist/zk-range-proof.d.ts.map +1 -0
  308. package/dist/zk-range-proof.js +228 -0
  309. package/dist/zk-range-proof.js.map +1 -0
  310. package/eg1-conformance.js +3 -404
  311. package/enterprise.js +3 -180
  312. package/ep-assure.mjs +1 -0
  313. package/evidence-postgres.js +3 -356
  314. package/evidence.js +4 -360
  315. package/execution-binding.js +3 -212
  316. package/formal-runtime-map.js +4 -0
  317. package/index.js +4 -1249
  318. package/key-registry.js +3 -134
  319. package/mcp.js +3 -109
  320. package/metering.js +3 -226
  321. package/metrics.js +3 -231
  322. package/network-witness.js +3 -499
  323. package/package.json +31 -2
  324. package/receipt-program.js +4 -0
  325. package/reliance-kernel.js +3 -112
  326. package/reliance-packet.js +3 -175
  327. package/remedy-program-postgres.js +4 -0
  328. package/remedy-program-receipt.js +4 -0
  329. package/remedy-program.js +4 -0
  330. package/reports/art14.js +0 -0
  331. package/reports/assurance-package.js +2 -312
  332. package/reports/auditor-workpaper.js +3 -537
  333. package/reports/external-verification.js +3 -222
  334. package/reports/reperform.js +3 -424
  335. package/reports/underwriter.js +3 -339
  336. package/retention.js +3 -84
  337. package/roster.js +3 -264
  338. package/runtime-monitor.js +4 -0
  339. package/settlement.js +3 -299
  340. package/siem.js +3 -235
  341. package/src/action-control-manifest.ts +424 -0
  342. package/src/action-escrow-custodian.ts +427 -0
  343. package/src/action-escrow-evidence.ts +1178 -0
  344. package/src/action-escrow-package.ts +1821 -0
  345. package/src/action-escrow-postgres.ts +366 -0
  346. package/src/action-escrow-state.ts +498 -0
  347. package/src/action-escrow-verifiers.ts +484 -0
  348. package/src/action-escrow.ts +3039 -0
  349. package/src/action-packs.ts +170 -0
  350. package/src/adapters/_kit.ts +117 -0
  351. package/src/adapters/aws.ts +142 -0
  352. package/src/adapters/cloudflare.ts +78 -0
  353. package/src/adapters/gcp.ts +71 -0
  354. package/src/adapters/github.ts +110 -0
  355. package/src/adapters/jira.ts +56 -0
  356. package/src/adapters/k8s.ts +71 -0
  357. package/src/adapters/linear.ts +56 -0
  358. package/src/adapters/salesforce.ts +56 -0
  359. package/src/adapters/stripe.ts +82 -0
  360. package/src/adapters/supabase.ts +122 -0
  361. package/src/adapters/terraform.ts +60 -0
  362. package/src/adapters/vercel.ts +85 -0
  363. package/src/aec-execution.ts +354 -0
  364. package/src/breakglass.ts +647 -0
  365. package/src/capability-receipt.ts +1258 -0
  366. package/src/cf1-conformance.ts +120 -0
  367. package/src/challenge-store.ts +70 -0
  368. package/src/control-plane.ts +374 -0
  369. package/src/coverage.ts +832 -0
  370. package/src/deployment-attestation.ts +259 -0
  371. package/src/eg1-conformance.ts +471 -0
  372. package/src/enterprise.ts +195 -0
  373. package/src/evidence-postgres.ts +374 -0
  374. package/src/evidence.ts +367 -0
  375. package/src/execution-binding.ts +236 -0
  376. package/src/formal-runtime-map.ts +24 -0
  377. package/src/index.ts +2122 -0
  378. package/src/key-registry.ts +150 -0
  379. package/src/mcp.ts +120 -0
  380. package/src/metering.ts +237 -0
  381. package/src/metrics.ts +232 -0
  382. package/src/network-witness.ts +585 -0
  383. package/src/protocol-state.ts +143 -0
  384. package/src/protocol-state.typecheck.ts +94 -0
  385. package/src/receipt-program.ts +1105 -0
  386. package/src/reliance-kernel.ts +119 -0
  387. package/src/reliance-packet.ts +206 -0
  388. package/src/remedy-program-postgres.ts +367 -0
  389. package/src/remedy-program-receipt.ts +891 -0
  390. package/src/remedy-program.ts +1388 -0
  391. package/src/reports/art14.ts +361 -0
  392. package/src/reports/assurance-package.ts +330 -0
  393. package/src/reports/auditor-workpaper.ts +558 -0
  394. package/src/reports/external-verification.ts +232 -0
  395. package/src/reports/reperform.ts +441 -0
  396. package/src/reports/underwriter.ts +356 -0
  397. package/src/retention.ts +100 -0
  398. package/src/roster.ts +273 -0
  399. package/src/runtime-monitor.ts +217 -0
  400. package/src/settlement.ts +313 -0
  401. package/src/siem.ts +247 -0
  402. package/src/store-postgres.ts +167 -0
  403. package/src/store.ts +214 -0
  404. package/src/strict-json.ts +115 -0
  405. package/src/trust-program-adapters.ts +847 -0
  406. package/src/trust-program-postgres.ts +429 -0
  407. package/src/trust-program-revocation.ts +751 -0
  408. package/src/trust-program.ts +1460 -0
  409. package/src/witness-postgres.ts +106 -0
  410. package/src/zk-range-proof.ts +250 -0
  411. package/store-postgres.js +3 -161
  412. package/store.js +4 -198
  413. package/strict-json.js +3 -102
  414. package/trust-program-adapters.js +4 -0
  415. package/trust-program-postgres.js +4 -0
  416. package/trust-program-revocation.js +4 -0
  417. package/trust-program.js +4 -0
  418. package/witness-postgres.js +3 -96
  419. package/zk-range-proof.js +4 -0
@@ -0,0 +1,484 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * Adapters that turn independently verified protocol artifacts into the exact
4
+ * result contract consumed by the Action Escrow state kernel.
5
+ */
6
+ import {
7
+ verifyDocumentActionBinding,
8
+ } from '@emilia-protocol/verify/document-action-binding';
9
+ import type { DocumentActionMaterialTerm } from '@emilia-protocol/verify/document-action-binding';
10
+ import { canonicalize, hashCanonical } from './execution-binding.js';
11
+
12
+ /**
13
+ * Validated, sorted shape of the caller-supplied expected-binding context
14
+ * returned by {@link exactExpected}.
15
+ * @typedef {Object} ExpectedActionBindingContext
16
+ * @property {string} agreement_digest
17
+ * @property {string} document_action_binding_digest
18
+ * @property {string} release_action_digest
19
+ * @property {string} milestone_id
20
+ * @property {Array<{party_id: string, role: string}>} parties
21
+ * @property {string} parties_digest
22
+ * @property {string} profile_digest
23
+ * @property {string|null} supersedes_document_action_binding_digest
24
+ */
25
+
26
+ /**
27
+ * Validated release-action template shape produced by
28
+ * {@link validateActionEscrowReleaseTemplate}.
29
+ * @typedef {Object} ActionEscrowReleaseTemplate
30
+ * @property {string} action_type
31
+ * @property {string} action_escrow_profile_digest
32
+ * @property {string} agreement_id
33
+ * @property {string} agreement_digest
34
+ * @property {string} milestone_id
35
+ * @property {string} amount
36
+ * @property {string} currency
37
+ * @property {string} destination_id
38
+ * @property {string} payee_id
39
+ * @property {string} custodian_provider
40
+ * @property {'sandbox'|'production'} custodian_environment
41
+ * @property {string} custodian_transaction_id
42
+ * @property {string} custodian_milestone_id
43
+ * @property {string} document_sha256
44
+ * @property {string} material_terms_sha256
45
+ * @property {string} completion_evidence_sha256
46
+ * @property {number} amendment_version
47
+ * @property {string} [project_record_snapshot_digest]
48
+ * @property {string} [action_escrow_template_profile]
49
+ */
50
+
51
+ export const ACTION_ESCROW_AGREEMENT_DIGEST_VERSION =
52
+ 'EP-ACTION-ESCROW-AGREEMENT-DIGEST-v1';
53
+ export const ACTION_ESCROW_CONTRACTOR_TEMPLATE_VERSION =
54
+ 'EP-ACTION-ESCROW-CONTRACTOR-TEMPLATE-v1';
55
+
56
+ const HASH = /^sha256:[0-9a-f]{64}$/;
57
+ const AMOUNT = /^(?:0|[1-9][0-9]*)(?:\.[0-9]+)?$/;
58
+ const CURRENCY = /^[A-Z]{3}$/;
59
+ export const ACTION_ESCROW_REQUIRED_MATERIAL_TERM_IDS = Object.freeze([
60
+ 'amendment_version',
61
+ 'completion_requirements_digest',
62
+ 'document_authorizes_payment',
63
+ 'milestone_name',
64
+ 'payee_id',
65
+ 'release.amount',
66
+ 'release.destination_id',
67
+ 'release.milestone_id',
68
+ 'release_requires_mutual_approval',
69
+ 'retainage_amount',
70
+ ]);
71
+ export const ACTION_ESCROW_CONTRACTOR_REQUIRED_MATERIAL_TERM_IDS = Object.freeze([
72
+ ...ACTION_ESCROW_REQUIRED_MATERIAL_TERM_IDS,
73
+ 'project_record_snapshot_digest',
74
+ ]);
75
+ const LEGACY_RELEASE_TEMPLATE_KEYS = new Set([
76
+ 'action_type',
77
+ 'action_escrow_profile_digest',
78
+ 'agreement_id',
79
+ 'agreement_digest',
80
+ 'milestone_id',
81
+ 'amount',
82
+ 'currency',
83
+ 'destination_id',
84
+ 'payee_id',
85
+ 'custodian_provider',
86
+ 'custodian_environment',
87
+ 'custodian_transaction_id',
88
+ 'custodian_milestone_id',
89
+ 'document_sha256',
90
+ 'material_terms_sha256',
91
+ 'completion_evidence_sha256',
92
+ 'amendment_version',
93
+ ]);
94
+ const UNMARKED_PROJECT_RELEASE_TEMPLATE_KEYS = new Set([
95
+ ...LEGACY_RELEASE_TEMPLATE_KEYS,
96
+ 'project_record_snapshot_digest',
97
+ ]);
98
+ const CONTRACTOR_RELEASE_TEMPLATE_KEYS = new Set([
99
+ ...LEGACY_RELEASE_TEMPLATE_KEYS,
100
+ 'action_escrow_template_profile',
101
+ 'project_record_snapshot_digest',
102
+ ]);
103
+
104
+ function isRecord(value: any): value is Record<string, any> {
105
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;
106
+ const prototype = Object.getPrototypeOf(value);
107
+ return prototype === Object.prototype || prototype === null;
108
+ }
109
+
110
+ /** @param {*} value */
111
+ function canonicalCopy(value) {
112
+ return JSON.parse(canonicalize(value));
113
+ }
114
+
115
+ /** @param {*} value */
116
+ function deepFreeze(value) {
117
+ if (!value || typeof value !== 'object' || Object.isFrozen(value)) return value;
118
+ Object.freeze(value);
119
+ for (const child of Object.values(value)) deepFreeze(child);
120
+ return value;
121
+ }
122
+
123
+ /** @param {*} value */
124
+ function validString(value, max = 256) {
125
+ return typeof value === 'string'
126
+ && value.length > 0
127
+ && value.length <= max
128
+ && !/[\u0000-\u001f\u007f]/.test(value);
129
+ }
130
+
131
+ /** @param {*} parties */
132
+ function sortedParties(parties) {
133
+ if (!Array.isArray(parties)) return null;
134
+ try {
135
+ return canonicalCopy(parties).sort(
136
+ /**
137
+ * @param {{party_id: string, role: string}} left
138
+ * @param {{party_id: string, role: string}} right
139
+ */
140
+ (left, right) => {
141
+ const leftKey = `${left.role}\u0000${left.party_id}`;
142
+ const rightKey = `${right.role}\u0000${right.party_id}`;
143
+ return leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0;
144
+ },
145
+ );
146
+ } catch {
147
+ return null;
148
+ }
149
+ }
150
+
151
+ /** @param {*} value */
152
+ function bytesCopy(value) {
153
+ if (Buffer.isBuffer(value) || value instanceof Uint8Array) {
154
+ return Uint8Array.from(value);
155
+ }
156
+ if (value instanceof ArrayBuffer) return new Uint8Array(value.slice(0));
157
+ return null;
158
+ }
159
+
160
+ /** @param {string} reason */
161
+ function refusal(reason) {
162
+ return Object.freeze({
163
+ valid: false,
164
+ reason,
165
+ });
166
+ }
167
+
168
+ export function computeActionEscrowAgreementDigest(agreementId) {
169
+ if (!validString(agreementId)) return null;
170
+ try {
171
+ return `sha256:${hashCanonical({
172
+ '@version': ACTION_ESCROW_AGREEMENT_DIGEST_VERSION,
173
+ agreement_id: agreementId,
174
+ })}`;
175
+ } catch {
176
+ return null;
177
+ }
178
+ }
179
+
180
+ /**
181
+ * @param {*} value
182
+ * @returns {ExpectedActionBindingContext|null}
183
+ */
184
+ function exactExpected(value) {
185
+ if (!isRecord(value)
186
+ || !HASH.test(value.agreement_digest)
187
+ || !HASH.test(value.document_action_binding_digest)
188
+ || !HASH.test(value.release_action_digest)
189
+ || !HASH.test(value.parties_digest)
190
+ || !HASH.test(value.profile_digest)
191
+ || !validString(value.milestone_id)
192
+ || !Array.isArray(value.parties)) {
193
+ return null;
194
+ }
195
+ const parties = sortedParties(value.parties);
196
+ if (!parties || parties.length < 2) return null;
197
+ return {
198
+ agreement_digest: value.agreement_digest,
199
+ document_action_binding_digest: value.document_action_binding_digest,
200
+ release_action_digest: value.release_action_digest,
201
+ milestone_id: value.milestone_id,
202
+ parties,
203
+ parties_digest: value.parties_digest,
204
+ profile_digest: value.profile_digest,
205
+ supersedes_document_action_binding_digest:
206
+ value.supersedes_document_action_binding_digest ?? null,
207
+ };
208
+ }
209
+
210
+ export function validateActionEscrowReleaseTemplate(template: any, {
211
+ profileDigest,
212
+ agreementId,
213
+ agreementDigest,
214
+ milestoneId,
215
+ documentDigest,
216
+ materialTerms,
217
+ contractorProjectSource = false,
218
+ }: {
219
+ profileDigest?: any;
220
+ agreementId?: any;
221
+ agreementDigest?: any;
222
+ milestoneId?: any;
223
+ documentDigest?: any;
224
+ materialTerms?: any;
225
+ contractorProjectSource?: boolean;
226
+ } = {}) {
227
+ const templateKeys = isRecord(template) ? Object.keys(template) : [];
228
+ const allowedKeys = contractorProjectSource
229
+ ? CONTRACTOR_RELEASE_TEMPLATE_KEYS
230
+ : UNMARKED_PROJECT_RELEASE_TEMPLATE_KEYS;
231
+ const requiredKeys = contractorProjectSource
232
+ ? CONTRACTOR_RELEASE_TEMPLATE_KEYS
233
+ : LEGACY_RELEASE_TEMPLATE_KEYS;
234
+ if (!isRecord(template)
235
+ || templateKeys.some((key) => !allowedKeys.has(key))
236
+ || [...requiredKeys].some((key) => !Object.hasOwn(template, key))
237
+ || (contractorProjectSource
238
+ && template.action_escrow_template_profile
239
+ !== ACTION_ESCROW_CONTRACTOR_TEMPLATE_VERSION)
240
+ || template.action_type !== 'escrow.milestone.release'
241
+ || template.action_escrow_profile_digest !== profileDigest
242
+ || template.agreement_id !== agreementId
243
+ || template.agreement_digest !== agreementDigest
244
+ || template.milestone_id !== milestoneId
245
+ || typeof template.amount !== 'string'
246
+ || !AMOUNT.test(template.amount)
247
+ || typeof template.currency !== 'string'
248
+ || !CURRENCY.test(template.currency)
249
+ || !validString(template.destination_id, 512)
250
+ || !validString(template.payee_id, 512)
251
+ || !validString(template.custodian_provider, 128)
252
+ || !['sandbox', 'production'].includes(template.custodian_environment)
253
+ || !validString(template.custodian_transaction_id, 256)
254
+ || !validString(template.custodian_milestone_id, 256)
255
+ || template.document_sha256 !== documentDigest
256
+ || !HASH.test(template.material_terms_sha256)
257
+ || (materialTerms !== undefined
258
+ && template.material_terms_sha256 !== `sha256:${hashCanonical(materialTerms)}`)
259
+ || (contractorProjectSource
260
+ && !HASH.test(template.project_record_snapshot_digest))
261
+ || (Object.hasOwn(template, 'project_record_snapshot_digest')
262
+ && !HASH.test(template.project_record_snapshot_digest))
263
+ || !HASH.test(template.completion_evidence_sha256)
264
+ || !Number.isSafeInteger(template.amendment_version)
265
+ || template.amendment_version < 1) {
266
+ return null;
267
+ }
268
+ try {
269
+ const copy = canonicalCopy(template);
270
+ return Buffer.byteLength(canonicalize(copy), 'utf8') <= 64 * 1024 ? copy : null;
271
+ } catch {
272
+ return null;
273
+ }
274
+ }
275
+
276
+ function exactActionTemplate(binding, expected, contractorProjectSource) {
277
+ return validateActionEscrowReleaseTemplate(binding?.release_action?.template, {
278
+ profileDigest: expected.profile_digest,
279
+ agreementId: binding?.agreement_id,
280
+ agreementDigest: expected.agreement_digest,
281
+ milestoneId: expected.milestone_id,
282
+ documentDigest: binding?.document?.digest,
283
+ materialTerms: binding?.material_terms,
284
+ contractorProjectSource,
285
+ });
286
+ }
287
+
288
+ function materialTermsMatchAction(binding, template) {
289
+ if (!Array.isArray(binding?.material_terms)) return false;
290
+ const terms = new Map<string, DocumentActionMaterialTerm>(
291
+ binding.material_terms.map(
292
+ (term: DocumentActionMaterialTerm): [string, DocumentActionMaterialTerm] => [term.term_id, term],
293
+ ),
294
+ );
295
+ const amount = terms.get('release.amount');
296
+ const destination = terms.get('release.destination_id');
297
+ const milestone = terms.get('release.milestone_id');
298
+ const amendment = terms.get('amendment_version');
299
+ const completionRequirements = terms.get('completion_requirements_digest');
300
+ const documentAuthorizesPayment = terms.get('document_authorizes_payment');
301
+ const milestoneName = terms.get('milestone_name');
302
+ const payee = terms.get('payee_id');
303
+ const releaseRequiresMutualApproval = terms.get('release_requires_mutual_approval');
304
+ const retainage = terms.get('retainage_amount');
305
+ const projectRecord = terms.get('project_record_snapshot_digest');
306
+ const projectRecordBound = Object.hasOwn(
307
+ template,
308
+ 'project_record_snapshot_digest',
309
+ );
310
+ return amount?.type === 'amount'
311
+ && amount.value === template.amount
312
+ && amount.currency === template.currency
313
+ // `.includes()` is not a type guard, but it can only be true here when
314
+ // `destination` is defined (undefined never matches either literal).
315
+ && ['identifier', 'string'].includes(destination?.type as string)
316
+ && destination!.value === template.destination_id
317
+ && ['identifier', 'string'].includes(milestone?.type as string)
318
+ && milestone!.value === template.milestone_id
319
+ && amendment?.type === 'integer'
320
+ && amendment.value === template.amendment_version
321
+ && completionRequirements?.type === 'digest'
322
+ && HASH.test(completionRequirements.value)
323
+ && documentAuthorizesPayment?.type === 'boolean'
324
+ && documentAuthorizesPayment.value === false
325
+ && milestoneName?.type === 'string'
326
+ && validString(milestoneName.value, 2048)
327
+ && payee?.type === 'identifier'
328
+ && payee.value === template.payee_id
329
+ && releaseRequiresMutualApproval?.type === 'boolean'
330
+ && releaseRequiresMutualApproval.value === true
331
+ && retainage?.type === 'amount'
332
+ && retainage.currency === template.currency
333
+ && (!projectRecordBound
334
+ || (
335
+ projectRecord?.type === 'digest'
336
+ && projectRecord.value === template.project_record_snapshot_digest
337
+ ));
338
+ }
339
+
340
+ /**
341
+ * Create a kernel verifier backed by the public DAB verifier.
342
+ *
343
+ * The document resolver is mandatory: mapping authenticity without checking
344
+ * the final bytes is insufficient for a release decision.
345
+ */
346
+ function createDocumentBindingVerifier({
347
+ issuerKeys,
348
+ resolveDocumentBytes,
349
+ allowedMediaTypes = ['application/pdf'],
350
+ allowedPartyRoles = ['client', 'contractor'],
351
+ now = Date.now,
352
+ }: {
353
+ issuerKeys?: Record<string, any>;
354
+ resolveDocumentBytes?: (info: Record<string, any>) => any;
355
+ allowedMediaTypes?: string[];
356
+ allowedPartyRoles?: string[];
357
+ now?: () => number;
358
+ } = {}, {
359
+ contractorProjectSource,
360
+ }: {
361
+ contractorProjectSource: boolean;
362
+ }) {
363
+ if (!isRecord(issuerKeys)
364
+ || Object.keys(issuerKeys).length === 0
365
+ || typeof resolveDocumentBytes !== 'function'
366
+ || typeof now !== 'function') {
367
+ throw new TypeError('pinned DAB keys, document resolver, and clock are required');
368
+ }
369
+ const pinnedIssuerKeys = deepFreeze(canonicalCopy(issuerKeys));
370
+ const mediaTypes = deepFreeze(canonicalCopy(allowedMediaTypes));
371
+ const partyRoles = deepFreeze(canonicalCopy(allowedPartyRoles));
372
+
373
+ return async function verifyForKernel(binding, untrustedExpected) {
374
+ try {
375
+ const expected = exactExpected(untrustedExpected);
376
+ if (!expected) return refusal('invalid_expected_binding_context');
377
+ const evaluationTime = now();
378
+ const options = {
379
+ issuerKeys: pinnedIssuerKeys,
380
+ now: evaluationTime,
381
+ allowedMediaTypes: mediaTypes,
382
+ allowedPartyRoles: partyRoles,
383
+ allowedActionTypes: ['escrow.milestone.release'],
384
+ requiredMaterialTermIds: (contractorProjectSource
385
+ ? ACTION_ESCROW_CONTRACTOR_REQUIRED_MATERIAL_TERM_IDS
386
+ : ACTION_ESCROW_REQUIRED_MATERIAL_TERM_IDS) as string[],
387
+ expectedRequiredParties: expected.parties,
388
+ expectedSupersedesDigest:
389
+ expected.supersedes_document_action_binding_digest,
390
+ };
391
+ const authenticated = verifyDocumentActionBinding(binding, options);
392
+ if (!authenticated.valid) return refusal(authenticated.reason);
393
+ if (authenticated.binding_digest !== expected.document_action_binding_digest
394
+ || authenticated.action_digest !== expected.release_action_digest
395
+ || computeActionEscrowAgreementDigest(authenticated.agreement_id)
396
+ !== expected.agreement_digest) {
397
+ return refusal('kernel_binding_context_mismatch');
398
+ }
399
+
400
+ const actionTemplate = exactActionTemplate(
401
+ binding,
402
+ expected,
403
+ contractorProjectSource,
404
+ );
405
+ if (!actionTemplate
406
+ || !materialTermsMatchAction(
407
+ binding,
408
+ actionTemplate,
409
+ )) {
410
+ return refusal('material_action_mapping_mismatch');
411
+ }
412
+ const resolved = await resolveDocumentBytes(deepFreeze({
413
+ agreement_id: authenticated.agreement_id,
414
+ binding_id: authenticated.binding_id,
415
+ binding_digest: authenticated.binding_digest,
416
+ document_digest: authenticated.document_digest,
417
+ document_media_type: binding.document.media_type,
418
+ document_byte_length: binding.document.byte_length,
419
+ }));
420
+ const documentBytes = bytesCopy(resolved);
421
+ if (!documentBytes) return refusal('document_bytes_unavailable');
422
+ const verified = verifyDocumentActionBinding(binding, {
423
+ ...options,
424
+ documentBytes,
425
+ documentMediaType: binding.document.media_type,
426
+ releaseActionTemplate: actionTemplate,
427
+ });
428
+ if (!verified.valid) return refusal(verified.reason);
429
+
430
+ return deepFreeze({
431
+ valid: true,
432
+ reason: 'valid',
433
+ verification_digest: verified.binding_digest,
434
+ document_digest: verified.document_digest,
435
+ agreement_id: verified.agreement_id,
436
+ binding_id: verified.binding_id,
437
+ release_action_template: actionTemplate,
438
+ agreement_digest: expected.agreement_digest,
439
+ document_action_binding_digest: verified.binding_digest,
440
+ milestone_id: expected.milestone_id,
441
+ release_action_digest: verified.action_digest,
442
+ parties_digest: expected.parties_digest,
443
+ profile_digest: expected.profile_digest,
444
+ ...(HASH.test(actionTemplate.project_record_snapshot_digest)
445
+ ? {
446
+ project_record_snapshot_digest:
447
+ actionTemplate.project_record_snapshot_digest,
448
+ }
449
+ : {}),
450
+ ...(verified.supersedes_digest === null
451
+ ? {}
452
+ : {
453
+ supersedes_document_action_binding_digest:
454
+ verified.supersedes_digest,
455
+ }),
456
+ });
457
+ } catch {
458
+ return refusal('document_action_binding_verifier_failed');
459
+ }
460
+ };
461
+ }
462
+
463
+ export function createActionEscrowDocumentBindingVerifier(options = {}) {
464
+ return createDocumentBindingVerifier(options, {
465
+ contractorProjectSource: false,
466
+ });
467
+ }
468
+
469
+ export function createActionEscrowContractorDocumentBindingVerifier(options = {}) {
470
+ return createDocumentBindingVerifier(options, {
471
+ contractorProjectSource: true,
472
+ });
473
+ }
474
+
475
+ export default Object.freeze({
476
+ ACTION_ESCROW_AGREEMENT_DIGEST_VERSION,
477
+ ACTION_ESCROW_CONTRACTOR_TEMPLATE_VERSION,
478
+ ACTION_ESCROW_CONTRACTOR_REQUIRED_MATERIAL_TERM_IDS,
479
+ ACTION_ESCROW_REQUIRED_MATERIAL_TERM_IDS,
480
+ computeActionEscrowAgreementDigest,
481
+ createActionEscrowContractorDocumentBindingVerifier,
482
+ createActionEscrowDocumentBindingVerifier,
483
+ validateActionEscrowReleaseTemplate,
484
+ });