@emilia-protocol/gate 0.10.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 +91 -0
  2. package/README.md +272 -0
  3. package/action-control-manifest.js +3 -268
  4. package/action-escrow-custodian.js +4 -0
  5. package/action-escrow-evidence.js +4 -0
  6. package/action-escrow-package.js +4 -0
  7. package/action-escrow-postgres.js +4 -0
  8. package/action-escrow-state.js +4 -0
  9. package/action-escrow-verifiers.js +4 -0
  10. package/action-escrow.js +4 -0
  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 +47 -4
  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 -85
  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,85 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * EMILIA Gate — Vercel System-of-Record adapter.
4
+ * Guards promote-to-production, project delete, and env/secret changes so they
5
+ * never reach Vercel without a receipt bound to THIS project. Client injected
6
+ * (the Vercel REST client or a thin wrapper).
7
+ */
8
+ import { createAdapter, manifestFromPack, hashCanonical } from './_kit.js';
9
+
10
+ export const SECRET_VALUE_BINDING_VERSION = 'EP-VERCEL-SECRET-VALUE-v1';
11
+
12
+ /** Digest an exact secret value for receipt binding; callers must never log it. */
13
+ export function secretValueDigest(value) {
14
+ return hashCanonical({
15
+ version: SECRET_VALUE_BINDING_VERSION,
16
+ value,
17
+ });
18
+ }
19
+
20
+ export const VERCEL_ACTION_PACK = Object.freeze([
21
+ Object.freeze({
22
+ id: 'vercel.deploy.promote', label: 'Promote to production', action_type: 'vercel.deploy.promote',
23
+ risk: 'critical', receipt_required: true, assurance_class: 'quorum',
24
+ match: { protocol: 'vercel', tool: 'promote_deployment' },
25
+ why: 'Changes live production. Quorum for the prod cutover.',
26
+ execution_binding: { required_fields: ['action_type', 'project', 'deployment_id'] },
27
+ }),
28
+ Object.freeze({
29
+ id: 'vercel.project.delete', label: 'Delete project', action_type: 'vercel.project.delete',
30
+ risk: 'critical', receipt_required: true, assurance_class: 'class_a',
31
+ match: { protocol: 'vercel', tool: 'delete_project' },
32
+ why: 'Destroys a project and its deployments. Bind the project.',
33
+ execution_binding: { required_fields: ['action_type', 'project'] },
34
+ }),
35
+ Object.freeze({
36
+ id: 'vercel.env.set', label: 'Set env / secret', action_type: 'vercel.env.set',
37
+ risk: 'high', receipt_required: true, assurance_class: 'class_a',
38
+ match: { protocol: 'vercel', tool: 'upsert_env' },
39
+ why: 'Changes production secrets/config. Bind project+key+target.',
40
+ execution_binding: {
41
+ required_fields: [
42
+ 'action_type', 'project', 'key', 'target', 'secret_value_digest', 'secret_value_version',
43
+ ],
44
+ },
45
+ }),
46
+ ]);
47
+
48
+ const OPS = {
49
+ 'deploy.promote': {
50
+ selector: { protocol: 'vercel', tool: 'promote_deployment' },
51
+ observed: (p) => ({ action_type: 'vercel.deploy.promote', project: p.project, deployment_id: p.deployment_id }),
52
+ perform: (c, p) => c.promoteDeployment({ project: p.project, deploymentId: p.deployment_id }),
53
+ },
54
+ 'project.delete': {
55
+ selector: { protocol: 'vercel', tool: 'delete_project' },
56
+ observed: (p) => ({ action_type: 'vercel.project.delete', project: p.project }),
57
+ perform: (c, p) => c.deleteProject({ project: p.project }),
58
+ },
59
+ 'env.set': {
60
+ selector: { protocol: 'vercel', tool: 'upsert_env' },
61
+ observed: (p) => ({
62
+ action_type: 'vercel.env.set',
63
+ project: p.project,
64
+ key: p.key,
65
+ target: p.target,
66
+ secret_value_digest: secretValueDigest(p.value),
67
+ secret_value_version: SECRET_VALUE_BINDING_VERSION,
68
+ }),
69
+ actuator: (p, observed) => ({ ...observed, value: p.value }),
70
+ perform: (c, p) => c.upsertEnv({ project: p.project, key: p.key, value: p.value, target: p.target }),
71
+ },
72
+ };
73
+
74
+ const adapter = createAdapter({ system: 'vercel', ops: OPS });
75
+ export const VERCEL_OPS = adapter.OPS;
76
+ export function createVercelManifest(extra = []) { return manifestFromPack(VERCEL_ACTION_PACK, extra); }
77
+ export function guardVercelMutation(gate, client, args) { return adapter.guard(gate, client, args); }
78
+ export default {
79
+ VERCEL_ACTION_PACK,
80
+ VERCEL_OPS,
81
+ SECRET_VALUE_BINDING_VERSION,
82
+ secretValueDigest,
83
+ createVercelManifest,
84
+ guardVercelMutation,
85
+ };
@@ -0,0 +1,354 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * Stateful execution boundary for EP-AEC.
4
+ *
5
+ * verifyAuthorizationChain is a pure evidence-composition decision. This
6
+ * wrapper adds the stateful properties an executor needs: independently bound
7
+ * action bytes, a mandatory human-assurance floor, atomic one-time reservation,
8
+ * tamper-evident decision records, and conservative crash semantics.
9
+ */
10
+ import { createEvidenceLog, verifyEvidenceRecord } from './evidence.js';
11
+ import { MemoryConsumptionStore } from './store.js';
12
+ import { verifyAuthorizationChain } from '@emilia-protocol/verify/evidence-chain';
13
+
14
+ type Obj = Record<string, any>;
15
+
16
+ type ConsumptionStore = {
17
+ durable?: boolean;
18
+ ownershipFenced?: boolean;
19
+ permanentConsumption?: boolean;
20
+ reserve?: (key: string) => Promise<boolean> | boolean;
21
+ commit?: (key: string) => Promise<boolean> | boolean;
22
+ release?: (key: string) => Promise<void> | void;
23
+ };
24
+
25
+ type ExecutionEvidenceLog = {
26
+ durable?: boolean;
27
+ strict?: boolean;
28
+ forkAware?: boolean;
29
+ atomicAppend?: boolean;
30
+ record?: (entry: Obj) => Promise<Obj> | Obj;
31
+ };
32
+
33
+ const HUMAN_FLOORS: Set<string | undefined> = new Set(['class_a', 'quorum', 'class_a_or_quorum']);
34
+ const HEX_256 = /^[0-9a-f]{64}$/;
35
+ const COMPONENT_TYPE = /^[A-Za-z0-9_.:-]+$/;
36
+ const RESERVED_COMPONENT_TYPES = new Set(['ep-receipt', 'ep-quorum']);
37
+ const own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
38
+
39
+ function deepFreeze(value) {
40
+ if (!value || typeof value !== 'object') return value;
41
+ const stack = [value];
42
+ const seen = new WeakSet();
43
+ while (stack.length) {
44
+ const current = stack.pop();
45
+ if (!current || typeof current !== 'object' || seen.has(current)) continue;
46
+ seen.add(current);
47
+ for (const child of Object.values(current)) stack.push(child);
48
+ Object.freeze(current);
49
+ }
50
+ return value;
51
+ }
52
+
53
+ function validLogRecord(record, atomicRequired, expectedEntry) {
54
+ return verifyEvidenceRecord(record, { atomicRequired, expectedEntry });
55
+ }
56
+
57
+ function validComponent(result, type) {
58
+ return Array.isArray(result?.components)
59
+ && result.components.some((component) => component.type === type && component.valid === true && component.bound === true);
60
+ }
61
+
62
+ function humanFloorSatisfied(result, floor) {
63
+ const classA = validComponent(result, 'ep-receipt');
64
+ const quorum = validComponent(result, 'ep-quorum');
65
+ if (floor === 'class_a') return classA;
66
+ if (floor === 'quorum') return quorum;
67
+ return classA || quorum;
68
+ }
69
+
70
+ function evidenceSatisfied(result) {
71
+ try {
72
+ if (!result || typeof result !== 'object') return false;
73
+ // New verifiers expose the evidence-layer term. Older supported 3.x
74
+ // verifiers expose the equivalent `allow` result only. If `satisfied` is
75
+ // present, it is authoritative so a conflicting compatibility alias can
76
+ // never upgrade a refusal.
77
+ return own(result, 'satisfied') ? result.satisfied === true : result.allow === true;
78
+ } catch {
79
+ return false;
80
+ }
81
+ }
82
+
83
+ function consumptionKey(result) {
84
+ // Consume the executor-owned action instance, not a presenter-selected
85
+ // component identifier. Otherwise an invalid decoy component or an alternate
86
+ // valid human proof can create a fresh key for the same physical effect.
87
+ // Repeated intended effects therefore need a unique nonce/id inside the
88
+ // canonical action before authorization is collected.
89
+ return HEX_256.test(result?.action_digest)
90
+ ? `aec:action:${result.action_digest}`
91
+ : null;
92
+ }
93
+
94
+ function instant(now) {
95
+ try {
96
+ const value = typeof now === 'function' ? now() : now;
97
+ const date = value instanceof Date ? value : new Date(value);
98
+ return Number.isFinite(date.getTime()) ? date.toISOString() : null;
99
+ } catch {
100
+ return null;
101
+ }
102
+ }
103
+
104
+ /**
105
+ * @param {object} [config]
106
+ * @param {string} [config.requirement] relying-party AEC requirement (required at runtime)
107
+ * @param {object} [config.policiesByType] relying-party human acceptance profiles (required at runtime)
108
+ * @param {object} [config.verifiers] relying-party-pinned custom component verifiers
109
+ * @param {object} [config.keysByType] relying-party-pinned custom verifier keys
110
+ * @param {'class_a'|'quorum'|'class_a_or_quorum'} [config.humanFloor] (required at runtime)
111
+ * @param {object} [config.store] ownership-fenced consumption store
112
+ * @param {object} [config.log] tamper-evident evidence log
113
+ * @param {boolean} [config.allowEphemeralState=false] test/demo opt-in only
114
+ * @param {Function|number|Date} [config.now=Date.now]
115
+ */
116
+ export function createAECExecutionGate({
117
+ requirement,
118
+ policiesByType,
119
+ verifiers = {},
120
+ keysByType = {},
121
+ humanFloor,
122
+ store,
123
+ log,
124
+ allowEphemeralState = false,
125
+ now = Date.now,
126
+ }: {
127
+ requirement?: string;
128
+ policiesByType?: Obj;
129
+ verifiers?: Record<string, Function>;
130
+ keysByType?: Obj;
131
+ humanFloor?: 'class_a' | 'quorum' | 'class_a_or_quorum';
132
+ store?: ConsumptionStore;
133
+ log?: ExecutionEvidenceLog;
134
+ allowEphemeralState?: boolean;
135
+ now?: (() => number) | number | Date;
136
+ } = {}) {
137
+ if (typeof requirement !== 'string' || !requirement.trim()) {
138
+ throw new Error('AEC execution gate requires a relying-party requirement');
139
+ }
140
+ if (!policiesByType || typeof policiesByType !== 'object' || Array.isArray(policiesByType)) {
141
+ throw new Error('AEC execution gate requires relying-party policiesByType');
142
+ }
143
+ let pinnedPolicies;
144
+ try { pinnedPolicies = deepFreeze(structuredClone(policiesByType)); }
145
+ catch { throw new Error('AEC execution gate policiesByType must be cloneable canonical data'); }
146
+ if (!verifiers || typeof verifiers !== 'object' || Array.isArray(verifiers)) {
147
+ throw new Error('AEC execution gate verifiers must be a relying-party-owned object');
148
+ }
149
+ const pinnedVerifiers = Object.create(null);
150
+ try {
151
+ for (const [type, verifier] of Object.entries(verifiers)) {
152
+ if (!COMPONENT_TYPE.test(type) || type.length > 128 || RESERVED_COMPONENT_TYPES.has(type)
153
+ || typeof verifier !== 'function') {
154
+ throw new Error('invalid verifier registry member');
155
+ }
156
+ pinnedVerifiers[type] = verifier;
157
+ }
158
+ Object.freeze(pinnedVerifiers);
159
+ } catch {
160
+ throw new Error('AEC execution gate verifiers must contain only named custom verifier functions');
161
+ }
162
+ if (!keysByType || typeof keysByType !== 'object' || Array.isArray(keysByType)) {
163
+ throw new Error('AEC execution gate keysByType must be a relying-party-owned object');
164
+ }
165
+ let pinnedKeysByType;
166
+ try { pinnedKeysByType = deepFreeze(structuredClone(keysByType)); }
167
+ catch { throw new Error('AEC execution gate keysByType must be cloneable canonical data'); }
168
+ if (!HUMAN_FLOORS.has(humanFloor)) {
169
+ throw new Error('AEC execution gate requires humanFloor class_a, quorum, or class_a_or_quorum');
170
+ }
171
+ if (!store && !allowEphemeralState) {
172
+ throw new Error('AEC execution gate requires a durable consumption store');
173
+ }
174
+ if (!log && !allowEphemeralState) {
175
+ throw new Error('AEC execution gate requires a durable strict evidence log');
176
+ }
177
+
178
+ const consumption = store || new MemoryConsumptionStore();
179
+ const evidence = log || createEvidenceLog({ strict: true });
180
+ if (!allowEphemeralState && (consumption.durable !== true || consumption.ownershipFenced !== true
181
+ || consumption.permanentConsumption !== true)) {
182
+ throw new Error('AEC execution gate requires a capability-marked, ownership-fenced durable store with non-expiring committed keys');
183
+ }
184
+ if (!allowEphemeralState && (evidence.durable !== true || evidence.strict !== true
185
+ || evidence.forkAware !== true || evidence.atomicAppend !== true)) {
186
+ throw new Error('AEC execution gate requires a durable strict evidence log with atomic shared-head append and fork detection');
187
+ }
188
+ for (const method of ['reserve', 'commit']) {
189
+ if (typeof consumption?.[method] !== 'function') {
190
+ throw new Error(`AEC execution gate consumption store requires ${method}()`);
191
+ }
192
+ }
193
+ if (typeof evidence?.record !== 'function') {
194
+ throw new Error('AEC execution gate evidence log requires record()');
195
+ }
196
+ // Capture the methods that passed construction checks. Callers may retain the
197
+ // objects for observability, but replacing a method later must not rewrite the
198
+ // gate's replay or evidence semantics.
199
+ // The loop above already proves reserve/commit are functions; TS can't track
200
+ // narrowing through a dynamic (computed) property key, hence the assertions.
201
+ const reserveConsumption = consumption.reserve!.bind(consumption);
202
+ const commitConsumption = consumption.commit!.bind(consumption);
203
+ const releaseConsumption = typeof consumption.release === 'function'
204
+ ? consumption.release.bind(consumption) : null;
205
+ const recordEvidence = evidence.record.bind(evidence);
206
+
207
+ async function deny(
208
+ reason: string,
209
+ result: Obj | null = null,
210
+ extra: Obj = {},
211
+ ): Promise<{ ok: false; allow: false; reason: string; result: Obj | null; decision: any; value?: undefined; authorization?: undefined; execution?: undefined }> {
212
+ let decision = null;
213
+ try {
214
+ const entry = {
215
+ type: 'aec.execution.decision',
216
+ at: instant(now),
217
+ allow: false,
218
+ reason,
219
+ action_digest: result?.action_digest ?? null,
220
+ requirement,
221
+ human_floor: humanFloor,
222
+ ...extra,
223
+ };
224
+ decision = await recordEvidence(entry);
225
+ if (!validLogRecord(decision, !allowEphemeralState, entry)) throw new Error('malformed evidence record');
226
+ } catch {
227
+ return { ok: false, allow: false, reason: 'evidence_log_failed', result, decision: null };
228
+ }
229
+ return { ok: false, allow: false, reason, result, decision };
230
+ }
231
+
232
+ async function run(
233
+ request: Obj = {},
234
+ effect: (input: { action: any; result: any; authorization: any }) => any,
235
+ ): Promise<
236
+ | { ok: false; allow: false; reason: string; result: Obj | null; decision: any; value?: undefined; authorization?: undefined; execution?: undefined }
237
+ | { ok: true; allow: true; value: any; result: any; authorization: any; execution: any; reason?: undefined }
238
+ > {
239
+ if (typeof effect !== 'function') throw new Error('AEC execution gate run() requires an effect function');
240
+ let chain;
241
+ let expectedAction;
242
+ try {
243
+ if (!request || typeof request !== 'object' || Array.isArray(request)) {
244
+ return deny('invalid_execution_request');
245
+ }
246
+ // Trust configuration belongs to the relying party at gate construction.
247
+ // Accepting verifier code or trust keys beside presenter evidence lets the
248
+ // presenter define the proof that its own evidence must pass.
249
+ if (own(request, 'verifiers') || own(request, 'keysByType') || own(request, 'policiesByType')) {
250
+ return deny('runtime_trust_configuration_refused');
251
+ }
252
+ chain = request.chain;
253
+ expectedAction = request.expectedAction;
254
+ } catch {
255
+ return deny('invalid_execution_request');
256
+ }
257
+ const verificationTime = instant(now);
258
+ if (!verificationTime) return deny('invalid_verification_time');
259
+ let actionSnapshot;
260
+ try { actionSnapshot = deepFreeze(structuredClone(expectedAction)); }
261
+ catch { return deny('invalid_expected_action'); }
262
+
263
+ const result = verifyAuthorizationChain(chain, {
264
+ verifiers: pinnedVerifiers,
265
+ keysByType: pinnedKeysByType,
266
+ policiesByType: pinnedPolicies,
267
+ requirement,
268
+ expectedAction: actionSnapshot,
269
+ verificationTime,
270
+ });
271
+ if (!evidenceSatisfied(result)) return deny('aec_refused', result, { reasons: result.reasons });
272
+ if (!humanFloorSatisfied(result, humanFloor)) return deny('human_floor_unsatisfied', result);
273
+
274
+ const key = consumptionKey(result);
275
+ if (!key) return deny('missing_stable_consumption_key', result);
276
+
277
+ let reserved;
278
+ try { reserved = (await reserveConsumption(key)) === true; }
279
+ catch { return deny('consumption_store_unavailable', result, { consumption_key: key }); }
280
+ if (!reserved) return deny('replay_refused', result, { consumption_key: key });
281
+
282
+ let authorization;
283
+ try {
284
+ const entry = {
285
+ type: 'aec.execution.decision',
286
+ at: verificationTime,
287
+ allow: true,
288
+ reason: 'allow',
289
+ action_digest: result.action_digest,
290
+ requirement,
291
+ human_floor: humanFloor,
292
+ consumption_key: key,
293
+ };
294
+ authorization = await recordEvidence(entry);
295
+ if (!validLogRecord(authorization, !allowEphemeralState, entry)) throw new Error('malformed evidence record');
296
+ } catch {
297
+ try { if (releaseConsumption) await releaseConsumption(key); } catch { /* frozen is safe */ }
298
+ return { ok: false, allow: false, reason: 'evidence_log_failed', result, decision: null };
299
+ }
300
+
301
+ let effectStarted = false;
302
+ let committed = false;
303
+ try {
304
+ effectStarted = true;
305
+ const value = await effect({ action: actionSnapshot, result, authorization });
306
+ if ((await commitConsumption(key)) !== true) throw new Error('consumption_store_commit_refused');
307
+ committed = true;
308
+ const executionEntry = {
309
+ type: 'aec.execution.outcome',
310
+ at: instant(now),
311
+ outcome: 'executed',
312
+ authorizes_decision: authorization.hash,
313
+ action_digest: result.action_digest,
314
+ consumption_key: key,
315
+ };
316
+ const execution = await recordEvidence(executionEntry);
317
+ if (!validLogRecord(execution, !allowEphemeralState, executionEntry)) throw new Error('malformed evidence record');
318
+ return { ok: true, allow: true, value, result, authorization, execution };
319
+ } catch (error) {
320
+ if (effectStarted && !committed) {
321
+ try { committed = (await commitConsumption(key)) === true; } catch { /* reservation remains fail-closed */ }
322
+ }
323
+ try {
324
+ const indeterminateEntry = {
325
+ type: 'aec.execution.outcome',
326
+ at: instant(now),
327
+ outcome: 'indeterminate',
328
+ authorizes_decision: authorization.hash,
329
+ action_digest: result.action_digest,
330
+ consumption_key: key,
331
+ };
332
+ const indeterminate = await recordEvidence(indeterminateEntry);
333
+ if (!validLogRecord(indeterminate, !allowEphemeralState, indeterminateEntry)) {
334
+ throw new Error('malformed evidence record');
335
+ }
336
+ } catch { /* the original failure remains primary; replay is still blocked */ }
337
+ throw error;
338
+ }
339
+ }
340
+
341
+ return { run, evidence, store: consumption };
342
+ }
343
+
344
+ export const __aecExecutionSecurityInternals = Object.freeze({
345
+ deepFreeze,
346
+ validLogRecord,
347
+ validComponent,
348
+ humanFloorSatisfied,
349
+ evidenceSatisfied,
350
+ consumptionKey,
351
+ instant,
352
+ });
353
+
354
+ export default { createAECExecutionGate };