@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
package/CHANGELOG.md CHANGED
@@ -4,6 +4,64 @@
4
4
  All notable changes to `@emilia-protocol/gate` are documented here.
5
5
  This package follows [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## 0.13.0 (2026-07-20)
8
+
9
+ ### Added
10
+
11
+ - A receipt-program execution kernel that composes CAID matching, Gate
12
+ authorization, bounded capability reservation, provider execution,
13
+ execution evidence, and an operator-signed content-addressed certificate.
14
+ - Offline certificate verification under a separately pinned operator key,
15
+ context, and evidence record, including CAID re-performance, exact schemas and
16
+ instruction sequencing, result digest, action/operation binding, and Gate
17
+ evidence-record references.
18
+ - A tenant-bound Trust Program kernel for staged, ordered or threshold
19
+ authorization ceremonies, with durable Postgres state, revocation handling,
20
+ exact predecessor/evidence bindings, and tenant-wide replay refusal.
21
+ - Explicit `executed`, `refused`, and `indeterminate` terminal states. Provider
22
+ timeout and non-canonical provider output halt the operation without restoring
23
+ replay authority.
24
+
25
+ ### Security
26
+
27
+ - Production construction requires both a durable atomic evidence log and a
28
+ durable capability store, an external KMS/HSM signer, pinned certificate
29
+ context, pinned result projector, and finite provider deadline. Process-local
30
+ state and keys are available only behind an explicit test/demo opt-in.
31
+ - CAID resolution, operation-id field selection, certificate signing and
32
+ context, result projection, deadline, clock, and Gate trust are
33
+ constructor-pinned; runtime requests cannot replace them.
34
+ - Provider code receives deep-frozen snapshots rather than Gate's live
35
+ authorization objects. Complete certificates are appended to the atomic
36
+ evidence log, and signer/persistence failures preserve Gate's terminal state
37
+ without issuing contradictory proof.
38
+ - The certificate is an operator-signed integrity and binding artifact. It is
39
+ not a zero-knowledge proof and does not attest that an external provider's
40
+ statement is truthful.
41
+
42
+ ## 0.12.0 (2026-07-18)
43
+
44
+ ### Added
45
+
46
+ - A distinct contractor release-template profile that requires a signed
47
+ `project_record_snapshot_digest` while preserving the closed legacy profile.
48
+ - A contractor evidence-package profile that carries and re-verifies the exact
49
+ project-record sidecar bytes under a relying-party-owned verifier.
50
+ - A read-only Procore change-order source adapter with complete pagination and
51
+ stable double-fetch snapshots.
52
+
53
+ ### Security
54
+
55
+ - A project-system source record cannot become agreement acceptance or release
56
+ authority. Replacing its committed snapshot changes the action digest and
57
+ fails closed.
58
+ - Existing Action Escrow templates without a project source remain valid under
59
+ their original closed profile; new contractor artifacts use an explicit
60
+ version boundary and cannot be silently downgraded.
61
+ - Unmarked project-bound artifacts from the unreleased `0.11.1` preview remain
62
+ readable only through the contractor package path, which requires the exact
63
+ project-record sidecar and a relying-party-owned source verifier.
64
+
7
65
  ## 0.11.0 (2026-07-17)
8
66
 
9
67
  ### Added
package/README.md CHANGED
@@ -295,6 +295,245 @@ challenge. The Gate composes that and adds the lifecycle controls a firewall nee
295
295
  can establish a declared surface as `gated`; a passive network witness alone is always
296
296
  `witness_only`. Inventory completeness remains an explicit relying-party assumption.
297
297
 
298
+ ## Formal-to-runtime bridge
299
+
300
+ Every Gate has an explicit runtime lifecycle monitor. It mirrors the load-bearing
301
+ state ordering behind the formal model: authorization must precede the effect,
302
+ consumption is one-way, and execution evidence follows the effect attempt. A
303
+ divergence emits a bounded `SPEC_DIVERGENCE` event and moves the Gate into
304
+ fail-closed safe mode. In safe mode, pass-through is disabled and a receipt must
305
+ earn at least Class-A assurance before execution.
306
+
307
+ ```js
308
+ import { createRuntimeMonitor, createTrustedActionFirewall } from '@emilia-protocol/gate';
309
+
310
+ const monitor = createRuntimeMonitor({
311
+ onDivergence: (event) => siem.append(event),
312
+ authorizeRecovery: (request) => operatorApproval.verify(request),
313
+ });
314
+ const gate = createTrustedActionFirewall({ runtimeMonitor: monitor, /* ... */ });
315
+ ```
316
+
317
+ Recovery is explicit and operator-authorized; it never re-authorizes a prior
318
+ receipt. The repository's `check:runtime-bridge` gate binds each monitor
319
+ theorem to an invariant declared in `formal/ep_handshake.cfg`, so a renamed or
320
+ removed formal source cannot silently leave the runtime map stale. This is a
321
+ machine-checked coverage binding, not a claim that TLA+ is automatically
322
+ compiled into JavaScript: the formal specifications remain the source of the
323
+ invariants and the monitor's transition table is covered by its own tests.
324
+
325
+ ## Capability receipts
326
+
327
+ `capability-receipt.js` adds an issuer-signed capability envelope around an
328
+ ordinary EP receipt. The envelope binds a secret preimage, an integer budget,
329
+ currency, expiry, a signed delegation chain, and an optional `m-of-n` Shamir
330
+ threshold. The envelope's `consumed` field is only an issuance invariant; spend
331
+ state lives in an atomic capability store and is never trusted from the bearer
332
+ object.
333
+
334
+ ```js
335
+ import {
336
+ createMemoryCapabilityStore,
337
+ executeWithCapability,
338
+ mintCapabilityReceipt,
339
+ } from '@emilia-protocol/gate/capability-receipt';
340
+
341
+ const minted = mintCapabilityReceipt(baseReceipt, {
342
+ issuerPrivateKey,
343
+ budget: { amount: 1_000_000, currency: 'USD' },
344
+ expiry: '2026-12-31T00:00:00.000Z',
345
+ scope: {
346
+ profile: CAPABILITY_SCOPE_PROFILE,
347
+ operation_id_field: 'payment_instruction_id',
348
+ action_digests: allowedPaymentActions.map(capabilityActionDigest),
349
+ },
350
+ });
351
+ const store = createMemoryCapabilityStore(); // tests only; use Postgres in production
352
+ store.registerCapability(minted.capabilityReceipt);
353
+ await executeWithCapability({
354
+ capabilityReceipt: minted.capabilityReceipt,
355
+ secret: minted.secret,
356
+ action: { amount: 10_000, currency: 'USD' },
357
+ observedAction: actionFromTheSystemOfRecord,
358
+ store,
359
+ gate,
360
+ trustedIssuerKeys: [capabilityIssuerPublicKey],
361
+ operationId: 'provider-idempotency-key',
362
+ executeAction: sendPayment,
363
+ });
364
+ ```
365
+
366
+ The production adapter requires a transaction callback and locks the capability
367
+ state row before reserving budget. If the external effect throws, the reserved
368
+ amount is committed as indeterminate; it is never silently reopened. The
369
+ capability path is separate from ordinary receipt consumption: the capability
370
+ store owns replay and budget state for each explicitly supplied operation ID.
371
+ The verifier requires a pinned capability issuer key. Every operation must
372
+ match one exact signed action digest, and the caller's stable operation ID must
373
+ equal the signed scope's field in the executor-observed action. The same digest
374
+ is persisted with the reservation. The separate budget projection must match
375
+ the amount and currency in that verified action, and the effect callback
376
+ receives a clone of the verified action—not the projection. A new operation ID
377
+ therefore cannot relabel the same payment instruction after a timeout.
378
+
379
+ The built-in `urn:emilia:scope:action-digest-set-v1` profile is exact-byte
380
+ scope. `urn:emilia:scope:caid-set-v1` is also supported for interoperable
381
+ material-action scope, but only when the deployment supplies its pinned CAID
382
+ resolver as `capabilityCaidResolver`; a missing, unknown, or non-matching CAID
383
+ fails closed. CAID correlates content here—it does not replace issuer trust,
384
+ human authorization, holder proof, or durable budget state.
385
+
386
+ ### Gate-integrated capability enforcement
387
+
388
+ For an action that must be both human-authorized and budget-limited, pass the
389
+ capability store when constructing the Gate and supply a capability to `run()`
390
+ or `guard()`:
391
+
392
+ ```js
393
+ const gate = createTrustedActionFirewall({
394
+ capabilityStore: postgresCapabilityStore,
395
+ capabilityTrustedIssuerKeys: [capabilityIssuerPublicKey],
396
+ capabilityCaidResolver: resolveWithPinnedCaidRegistry, // for caid-set scopes
397
+ // ...the ordinary Gate trust and durable evidence configuration
398
+ });
399
+
400
+ const result = await gate.run({
401
+ selector: { protocol: 'mcp', tool: 'release_payment' },
402
+ observedAction: actionFromTheSystemOfRecord,
403
+ capability: {
404
+ capabilityReceipt,
405
+ secret,
406
+ action: { amount: 10_000, currency: 'USD' },
407
+ operationId: 'provider-idempotency-key',
408
+ },
409
+ }, (authorization, operation) => sendPayment(actionFromTheSystemOfRecord, {
410
+ idempotencyKey: operation.providerIdempotencyKey,
411
+ authorization,
412
+ }));
413
+ ```
414
+
415
+ The Gate verifies the ordinary receipt first without consuming it, requires the
416
+ capability amount and currency to equal the observed action's `amount` or
417
+ `amount_usd` and `currency`, checks the signed exact-action scope, reserves the
418
+ budget and action digest before calling `sendPayment`, and passes the stable
419
+ operation ID to the provider adapter as its idempotency key. A replay,
420
+ out-of-scope action, operation relabel, overspend, missing registration, or
421
+ envelope mismatch never enters the effect. An exception after the effect begins
422
+ commits the amount as `indeterminate` and keeps the operation closed for
423
+ authenticated reconciliation. Capability issuer keys are pinned separately
424
+ from the ordinary receipt trust list.
425
+
426
+ Delegation is issuer-authorized and budget-backed: `delegateCapabilityReceipt`
427
+ atomically reserves and commits the child budget against the parent before the
428
+ child is registered. A failed child registration is reported for
429
+ reconciliation; it never creates spendable budget out of thin air. A holder
430
+ cannot edit `delegation_chain` or enlarge a child because the issuer signs the
431
+ entire envelope.
432
+
433
+ ## Receipt programs
434
+
435
+ `createReceiptProgramKernel()` composes CAID, the Gate capability path, and the
436
+ evidence log into one bounded instruction surface. The instruction descriptor
437
+ and certificate encoding are deterministic; external effects are not. It does not create a
438
+ second ledger or bypass Gate. A successful run emits an Ed25519-signed
439
+ certificate over the exact program, provider result projection, execution
440
+ steps, and compact Gate evidence references.
441
+
442
+ ```js
443
+ import {
444
+ createReceiptProgramKernel,
445
+ verifyReceiptProgramCertificate,
446
+ } from '@emilia-protocol/gate/receipt-program';
447
+
448
+ const certificateContext = {
449
+ issuer: 'emilia-operator',
450
+ tenant: 'acme',
451
+ environment: 'production',
452
+ audience: 'acme-audit',
453
+ key_id: 'kms://receipt-program-1',
454
+ };
455
+
456
+ const kernel = createReceiptProgramKernel({
457
+ gate, // already configured production Gate
458
+ resolveCaid, // relying-party-pinned synchronous resolver
459
+ operationIdField: 'payment_instruction_id',
460
+ certificateSigner: {
461
+ keyId: 'kms://receipt-program-1',
462
+ custody: 'kms',
463
+ publicKey: operatorPublicKey,
464
+ sign: (bytes) => signWithKms(bytes),
465
+ },
466
+ certificateContext,
467
+ projectResult: (raw) => ({
468
+ provider: raw.provider,
469
+ provider_operation_id: raw.provider_operation_id,
470
+ status: raw.status,
471
+ }),
472
+ effectTimeoutMs: 15_000,
473
+ });
474
+
475
+ const run = await kernel.run({
476
+ programId: 'delegated-payment-v1',
477
+ instructionId: 'release-milestone-1',
478
+ caid,
479
+ selector: { protocol: 'mcp', tool: 'release_payment' },
480
+ observedAction: actionFromTheSystemOfRecord,
481
+ capability: {
482
+ capabilityReceipt,
483
+ secret,
484
+ action: { amount: 50, currency: 'USD' },
485
+ operationId: actionFromTheSystemOfRecord.payment_instruction_id,
486
+ },
487
+ }, async (_authorization, operation) => ({
488
+ provider: 'licensed-custodian',
489
+ provider_operation_id: operation.providerIdempotencyKey,
490
+ status: await releaseWithIdempotency(operation.providerIdempotencyKey),
491
+ }));
492
+
493
+ const checked = verifyReceiptProgramCertificate(run.certificate, {
494
+ trustedCertificateKeys: {
495
+ 'kms://receipt-program-1': operatorPublicKey,
496
+ },
497
+ resolveCaid,
498
+ expectedContext: certificateContext,
499
+ certificateEvidence: run.certificate_evidence,
500
+ // Must check this exact record against the relying party's pinned stream,
501
+ // authenticated snapshot, or inclusion proof. Rehashing the object is not enough.
502
+ verifyCertificateInclusion: verifyInPinnedEvidenceStream,
503
+ requireAtomicCertificateEvidence: true,
504
+ });
505
+ ```
506
+
507
+ Production construction requires a durable atomic evidence log and durable
508
+ capability store, external KMS/HSM signing custody, an exact certificate
509
+ context, and a pinned disclosure projector. Provider code receives only frozen
510
+ copies of authorization and operation data. A provider exception, real deadline
511
+ expiry, or invalid result projection after invocation becomes `indeterminate`
512
+ and leaves the operation closed to blind replay. A certificate is returned as
513
+ durable proof only after signing and complete-certificate evidence append
514
+ succeed; typed signer/persistence failures preserve Gate's terminal outcome.
515
+ `checked.ok` means certificate validity, not provider success—inspect
516
+ `checked.outcome` and `checked.execution_succeeded`. The certificate proves
517
+ operator-signed integrity and binding; it is not a zero-knowledge proof or
518
+ independent proof of provider truth. See the runnable `examples/receipt-program/` reference and the
519
+ [architecture profile](../../docs/architecture/RECEIPT-PROGRAM-EXECUTION-KERNEL.md).
520
+
521
+ ## Zero-knowledge range receipts
522
+
523
+ `zk-range-proof.js` provides `EP-ZK-RANGE-RECEIPT-v1`. It uses Bulletproofs over
524
+ Ristretto255 to prove a hidden integer `v` satisfies `0 <= v <= max` without
525
+ revealing `v` or its blinding factor. The second commitment proves the upper
526
+ bound relation `max - v` without relying on a mutable claim. The envelope
527
+ binds a public policy hash, predicate, base-receipt digest, issuer key, and
528
+ nonce. The ordinary EP receipt signature must still be verified separately.
529
+
530
+ The cryptographic engine is an explicit optional backend:
531
+ `@aptos-labs/confidential-asset-bindings@1.1.2`. It is not pulled into the
532
+ default Gate install because its WASM/mobile distribution is large. A
533
+ deployment enabling ZK receipts must pin, audit, and pass the backend's own
534
+ proof tests. This v1 is a genuine hidden-range proof; it is not a claim that
535
+ the repository automatically compiles all TLA+ invariants into R1CS.
536
+
298
537
  ## Action Escrow
299
538
 
300
539
  Action Escrow is the Gate profile for a two-party agreement whose downstream
@@ -315,6 +554,19 @@ adjudicate disputes, or make an agreement legally enforceable. An ambiguous
315
554
  provider outcome enters reconciliation and is never retried as though nothing
316
555
  happened.
317
556
 
557
+ Construction and contractor integrations use the explicit
558
+ `EP-ACTION-ESCROW-CONTRACTOR-TEMPLATE-v1` profile. Build its DAB verifier with
559
+ `createActionEscrowContractorDocumentBindingVerifier()` and its portable
560
+ six-row package with `assembleActionEscrowContractorEvidencePackage()`. The
561
+ package carries the exact project-system sidecar bytes beside the PDF and
562
+ re-performs both under relying-party-owned verifiers. A project record is
563
+ source evidence only: it cannot fill agreement-acceptance, release-approval,
564
+ or custodian-effect rows. The legacy template and package APIs refuse the
565
+ contractor profile instead of silently ignoring its project-source binding.
566
+ Unmarked project-bound artifacts from the unreleased `0.11.1` preview remain
567
+ verifiable only through the contractor package path, including its exact
568
+ sidecar and relying-party-owned project-source verifier.
569
+
318
570
  ## Production custody
319
571
 
320
572
  The three things a serious buyer (CISO, auditor, insurer) asks after the demo:
@@ -1,269 +1,4 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
- //
3
- // EP Action Control Manifest: the missing control-plane waist between agent
4
- // runtimes, receipt formats, transparency logs, and system-of-record adapters.
5
- //
6
- // A receipt proves an authorization event. This manifest tells an executor
7
- // when a receipt is required, what assurance tier is required, which material
8
- // fields must be observed from the system of record, and what evidence must be
9
- // emitted after the effect boundary.
10
-
11
- import { HIGH_RISK_ACTION_PACKS, DEFAULT_PASS_THROUGH_ACTIONS } from './action-packs.js';
12
-
13
- export const ACTION_CONTROL_MANIFEST_VERSION = 'EP-ACTION-CONTROL-MANIFEST-v0.2';
14
- export const ACTION_CONTROL_SCHEMA_URL = 'https://www.emiliaprotocol.ai/docs/schemas/agent-action-control-manifest-v0.2.schema.json';
15
- export const ACTION_CONTROL_CONFORMANCE_LEVEL = 'EG-1';
16
-
17
- const RISK_LEVELS = new Set(['low', 'medium', 'high', 'critical']);
18
- const ASSURANCE_CLASSES = new Set(['software', 'class_a', 'quorum']);
19
- const ENFORCEMENT_POINTS = new Set(['pre_execution', 'pre_effect_commit']);
20
-
21
- export const ACTION_CONTROL_DEFAULTS = Object.freeze({
22
- decision_point: 'pre_effect_commit',
23
- missing_receipt: 'refuse',
24
- invalid_receipt: 'refuse',
25
- stale_receipt: 'refuse',
26
- replay: 'one_time_consumption',
27
- evidence_log: 'strict',
28
- });
29
-
30
- export const ACTION_CONTROL_EVIDENCE_PROFILES = Object.freeze({
31
- authorization_receipt: 'EP-RECEIPT-v1',
32
- execution_attestation: 'EP-EXECUTION-ATTESTATION-v1',
33
- reliance_packet: 'EP-RELIANCE-PACKET-v1',
34
- transparency: 'SCITT-compatible Signed Statement',
35
- });
36
-
37
- export const ACTION_CONTROL_CONFORMANCE_CHECKS = Object.freeze([
38
- 'missing_receipt_refused',
39
- 'software_on_classA_refused',
40
- 'execution_drift_refused',
41
- 'valid_classA_runs',
42
- 'replay_refused',
43
- 'tampered_refused',
44
- 'execution_proof_binds',
45
- 'reliance_packet_rely',
46
- ]);
47
-
48
- function cloneJson(value) {
49
- return value == null ? value : JSON.parse(JSON.stringify(value));
50
- }
51
-
52
- function normalizeRisk(risk) {
53
- return RISK_LEVELS.has(risk) ? risk : 'high';
54
- }
55
-
56
- function normalizeAssurance(value) {
57
- return ASSURANCE_CLASSES.has(value) ? value : 'software';
58
- }
59
-
60
- function defaultControlForAction(action) {
61
- const requiredFields = action.execution_binding?.required_fields || [];
62
- if (!action.receipt_required) {
63
- return {
64
- enforcement_point: 'none',
65
- authorization_receipt: { required: false },
66
- evidence_output: { audit_event: true },
67
- };
68
- }
69
- return {
70
- enforcement_point: 'pre_effect_commit',
71
- status: 428,
72
- challenge_header: 'Receipt-Required',
73
- proof_header: 'X-EMILIA-Receipt',
74
- authorization_receipt: {
75
- required: true,
76
- profile: 'EP-RECEIPT-v1',
77
- signature: 'Ed25519 over RFC 8785 canonical JSON',
78
- verifier: 'offline',
79
- },
80
- replay: {
81
- mode: 'one_time_consumption',
82
- receipt_id_required: true,
83
- },
84
- execution_binding: {
85
- required: true,
86
- source: 'system_of_record',
87
- required_fields: [...requiredFields],
88
- },
89
- transparency: {
90
- mode: 'registerable',
91
- profile: 'SCITT Signed Statement',
92
- required: false,
93
- },
94
- evidence_output: {
95
- audit_event: true,
96
- execution_attestation: true,
97
- reliance_packet: true,
98
- blocked_attempts: true,
99
- },
100
- };
101
- }
102
-
103
- export function toActionControl(action) {
104
- const out = {
105
- id: action.id,
106
- label: action.label || action.description || action.id,
107
- action_type: action.action_type,
108
- risk: normalizeRisk(action.risk || (action.receipt_required ? 'high' : 'low')),
109
- receipt_required: !!action.receipt_required,
110
- assurance_class: normalizeAssurance(action.assurance_class),
111
- max_age_sec: action.max_age_sec || 900,
112
- match: cloneJson(action.match || {}),
113
- why: action.why || action.description || null,
114
- control: cloneJson(action.control || defaultControlForAction(action)),
115
- conformance: {
116
- level: ACTION_CONTROL_CONFORMANCE_LEVEL,
117
- checks: [...ACTION_CONTROL_CONFORMANCE_CHECKS],
118
- ...(action.conformance || {}),
119
- },
120
- };
121
- if (action.quorum) out.quorum = cloneJson(action.quorum);
122
- if (action.business_authorization || action.businessAuthorization) {
123
- out.business_authorization = cloneJson(action.business_authorization || action.businessAuthorization);
124
- }
125
- return out;
126
- }
127
-
128
- export function createDefaultActionControlManifest({
129
- service = {},
130
- includePassThrough = true,
131
- extraActions = [],
132
- } = {}) {
133
- const actions = [
134
- ...HIGH_RISK_ACTION_PACKS.map(toActionControl),
135
- ...(includePassThrough ? DEFAULT_PASS_THROUGH_ACTIONS.map(toActionControl) : []),
136
- ...extraActions.map(toActionControl),
137
- ];
138
- return {
139
- '@version': ACTION_CONTROL_MANIFEST_VERSION,
140
- '$schema': ACTION_CONTROL_SCHEMA_URL,
141
- profile: 'agent-action-control',
142
- service: {
143
- name: service.name || 'EMILIA Gate default action controls',
144
- issuer: service.issuer || 'https://www.emiliaprotocol.ai',
145
- manifest_url: service.manifest_url || 'https://www.emiliaprotocol.ai/.well-known/agent-action-control.json',
146
- ...service,
147
- },
148
- defaults: { ...ACTION_CONTROL_DEFAULTS },
149
- evidence_profiles: { ...ACTION_CONTROL_EVIDENCE_PROFILES },
150
- actions,
151
- };
152
- }
153
-
154
- function selectorMatches(match = {}, selector = {}) {
155
- if (!match || typeof match !== 'object') return false;
156
- return Object.entries(match).every(([k, v]) => selector[k] === v);
157
- }
158
-
159
- export function findActionControl(manifest, selector = {}) {
160
- if (!manifest || !Array.isArray(manifest.actions)) return null;
161
- return manifest.actions.find((action) => {
162
- if (selector.action_type && action.action_type === selector.action_type) return true;
163
- return selectorMatches(action.match, selector);
164
- }) || null;
165
- }
166
-
167
- export function validateActionControlManifest(manifest) {
168
- const errors = [];
169
- if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest)) {
170
- return { ok: false, errors: ['manifest must be an object'] };
171
- }
172
- if (manifest['@version'] !== ACTION_CONTROL_MANIFEST_VERSION) {
173
- errors.push(`@version must be ${ACTION_CONTROL_MANIFEST_VERSION}`);
174
- }
175
- if (manifest.profile !== 'agent-action-control' && manifest.profile !== 'emilia.action-control') {
176
- errors.push('profile must be agent-action-control (or the deployed alias emilia.action-control)');
177
- }
178
- if (!manifest.service || typeof manifest.service !== 'object') {
179
- errors.push('service object is required');
180
- }
181
- if (!manifest.defaults || typeof manifest.defaults !== 'object') {
182
- errors.push('defaults object is required');
183
- }
184
- if (!Array.isArray(manifest.actions) || manifest.actions.length === 0) {
185
- errors.push('actions must be a non-empty array');
186
- }
187
- for (const [idx, action] of (manifest.actions || []).entries()) {
188
- const prefix = `actions[${idx}]`;
189
- if (!action || typeof action !== 'object') {
190
- errors.push(`${prefix} must be an object`);
191
- continue;
192
- }
193
- if (!action.id || typeof action.id !== 'string') errors.push(`${prefix}.id is required`);
194
- if (!action.action_type || typeof action.action_type !== 'string') errors.push(`${prefix}.action_type is required`);
195
- if (!action.match || typeof action.match !== 'object') errors.push(`${prefix}.match is required`);
196
- if (typeof action.receipt_required !== 'boolean') errors.push(`${prefix}.receipt_required must be boolean`);
197
- if (!RISK_LEVELS.has(action.risk)) errors.push(`${prefix}.risk must be low|medium|high|critical`);
198
- if (!ASSURANCE_CLASSES.has(action.assurance_class)) errors.push(`${prefix}.assurance_class must be software|class_a|quorum`);
199
- // Key-class floor: a critical action must be bound to a human key. normalizeAssurance()
200
- // defaults a missing or unrecognized tier to the weakest 'software', so this also fails
201
- // closed on a critical action whose tier was omitted rather than silently downgrading it.
202
- if (action.receipt_required && action.risk === 'critical' && action.assurance_class === 'software') {
203
- errors.push(`${prefix}.assurance_class must be class_a or quorum when risk is critical`);
204
- }
205
- if (action.receipt_required) {
206
- if (!Number.isFinite(action.max_age_sec) || action.max_age_sec <= 0) errors.push(`${prefix}.max_age_sec must be positive`);
207
- const control = action.control;
208
- if (!control || typeof control !== 'object') {
209
- errors.push(`${prefix}.control is required when receipt_required=true`);
210
- continue;
211
- }
212
- if (!ENFORCEMENT_POINTS.has(control.enforcement_point)) {
213
- errors.push(`${prefix}.control.enforcement_point must be pre_execution or pre_effect_commit`);
214
- }
215
- if (control.status !== 428) errors.push(`${prefix}.control.status must be 428`);
216
- if (control.authorization_receipt?.required !== true) errors.push(`${prefix}.control.authorization_receipt.required must be true`);
217
- if (control.authorization_receipt?.profile !== 'EP-RECEIPT-v1') errors.push(`${prefix}.control.authorization_receipt.profile must be EP-RECEIPT-v1`);
218
- if (control.authorization_receipt?.verifier !== 'offline') errors.push(`${prefix}.control.authorization_receipt.verifier must be offline`);
219
- if (control.replay?.mode !== 'one_time_consumption') errors.push(`${prefix}.control.replay.mode must be one_time_consumption`);
220
- if (control.replay?.receipt_id_required !== true) errors.push(`${prefix}.control.replay.receipt_id_required must be true`);
221
- const fields = control.execution_binding?.required_fields;
222
- if (control.execution_binding?.required !== true) errors.push(`${prefix}.control.execution_binding.required must be true`);
223
- if (control.execution_binding?.source !== 'system_of_record') errors.push(`${prefix}.control.execution_binding.source must be system_of_record`);
224
- if (!Array.isArray(fields) || fields.length === 0 || fields.some((f) => typeof f !== 'string' || !f)) {
225
- errors.push(`${prefix}.control.execution_binding.required_fields must be a non-empty string array`);
226
- }
227
- if (control.evidence_output?.execution_attestation !== true) errors.push(`${prefix}.control.evidence_output.execution_attestation must be true`);
228
- if (control.evidence_output?.reliance_packet !== true) errors.push(`${prefix}.control.evidence_output.reliance_packet must be true`);
229
- if (action.conformance?.level !== ACTION_CONTROL_CONFORMANCE_LEVEL) errors.push(`${prefix}.conformance.level must be ${ACTION_CONTROL_CONFORMANCE_LEVEL}`);
230
- if (action.business_authorization !== undefined) {
231
- const business = action.business_authorization;
232
- const policy = business?.policy;
233
- const approvers = business?.allowed_approvers;
234
- if (!business || typeof business !== 'object' || Array.isArray(business)) {
235
- errors.push(`${prefix}.business_authorization must be an object`);
236
- } else {
237
- if (!policy || typeof policy !== 'object' || Array.isArray(policy)
238
- || typeof policy.id !== 'string' || !policy.id
239
- || typeof policy.hash !== 'string' || !policy.hash) {
240
- errors.push(`${prefix}.business_authorization.policy must pin non-empty id and hash`);
241
- }
242
- if (typeof business.tenant_id !== 'string' || !business.tenant_id) {
243
- errors.push(`${prefix}.business_authorization.tenant_id must be a non-empty string`);
244
- }
245
- if (!Array.isArray(approvers) || approvers.length === 0
246
- || approvers.some((entry) => !entry || typeof entry !== 'object'
247
- || typeof entry.subject !== 'string' || !entry.subject
248
- || typeof entry.role !== 'string' || !entry.role)) {
249
- errors.push(`${prefix}.business_authorization.allowed_approvers must name subject and role`);
250
- }
251
- }
252
- }
253
- }
254
- }
255
- return { ok: errors.length === 0, errors };
256
- }
257
-
258
- export default {
259
- ACTION_CONTROL_MANIFEST_VERSION,
260
- ACTION_CONTROL_SCHEMA_URL,
261
- ACTION_CONTROL_CONFORMANCE_LEVEL,
262
- ACTION_CONTROL_DEFAULTS,
263
- ACTION_CONTROL_EVIDENCE_PROFILES,
264
- ACTION_CONTROL_CONFORMANCE_CHECKS,
265
- toActionControl,
266
- createDefaultActionControlManifest,
267
- findActionControl,
268
- validateActionControlManifest,
269
- };
2
+ // Compatibility entry point for the TypeScript action-control manifest.
3
+ export * from './dist/action-control-manifest.js';
4
+ export { default } from './dist/action-control-manifest.js';