@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,286 @@
1
+ export declare const EG1_VERSION = "EG-1";
2
+ /**
3
+ * Mint a GENUINE WebAuthn ECDSA-P256 device signoff over an authorization
4
+ * context — the same structure @emilia-protocol/verify verifyWebAuthnSignoff
5
+ * checks. This is what earns a receipt its class_a tier: a real per-signer
6
+ * assertion, not a self-asserted `outcome` string. Used to build the Class-A and
7
+ * quorum evidence the EG-1 harness embeds so the Gate can CRYPTOGRAPHICALLY
8
+ * credit the tier.
9
+ * @param {{ actionHash?: string, approver?: string, issuedAtMs?: number, nonce?: string, prevContextHash?: string }} [opts]
10
+ */
11
+ export declare function mintDeviceSignoff({ actionHash, approver, issuedAtMs, nonce, prevContextHash, }?: {
12
+ actionHash?: string;
13
+ approver?: string;
14
+ issuedAtMs?: number;
15
+ nonce?: string;
16
+ prevContextHash?: string;
17
+ }): {
18
+ signoff: {
19
+ '@type': string;
20
+ context: {
21
+ prev_context_hash?: string | undefined;
22
+ ep_version: string;
23
+ context_type: string;
24
+ action_hash: string | undefined;
25
+ policy: string;
26
+ nonce: string;
27
+ approver: string | undefined;
28
+ initiator: string;
29
+ issued_at: string;
30
+ expires_at: string;
31
+ };
32
+ webauthn: {
33
+ authenticator_data: string;
34
+ client_data_json: string;
35
+ signature: string;
36
+ };
37
+ approver_public_key: string;
38
+ };
39
+ approver_public_key: string;
40
+ context: {
41
+ prev_context_hash?: string | undefined;
42
+ ep_version: string;
43
+ context_type: string;
44
+ action_hash: string | undefined;
45
+ policy: string;
46
+ nonce: string;
47
+ approver: string | undefined;
48
+ initiator: string;
49
+ issued_at: string;
50
+ expires_at: string;
51
+ };
52
+ };
53
+ /**
54
+ * Mint a GENUINE EP-QUORUM-v1 evidence document: N distinct humans, each on a
55
+ * distinct device key, each with a real WebAuthn assertion bound to the SAME
56
+ * action_hash, within a window. verifyQuorum returns valid for it. This is what
57
+ * earns a receipt its `quorum` tier — never a bare {signers,threshold} block.
58
+ * @param {{ actionHash?: string, threshold?: number, approvers?: Array<{ role: string, approver: string }>, issuedAtMs?: number }} [opts]
59
+ */
60
+ export declare function mintQuorumEvidence({ actionHash, threshold, approvers, issuedAtMs, }?: {
61
+ actionHash?: string;
62
+ threshold?: number;
63
+ approvers?: Array<{
64
+ role: string;
65
+ approver: string;
66
+ }>;
67
+ issuedAtMs?: number;
68
+ }): {
69
+ '@type': string;
70
+ action_hash: string | undefined;
71
+ policy: {
72
+ mode: string;
73
+ required: number;
74
+ approvers: {
75
+ role: string;
76
+ approver: string;
77
+ }[];
78
+ distinct_humans: boolean;
79
+ window_sec: number;
80
+ };
81
+ members: {
82
+ role: string;
83
+ approver_public_key: string;
84
+ signoff: {
85
+ '@type': string;
86
+ context: {
87
+ prev_context_hash?: string | undefined;
88
+ ep_version: string;
89
+ context_type: string;
90
+ action_hash: string | undefined;
91
+ policy: string;
92
+ nonce: string;
93
+ approver: string | undefined;
94
+ initiator: string;
95
+ issued_at: string;
96
+ expires_at: string;
97
+ };
98
+ webauthn: {
99
+ authenticator_data: string;
100
+ client_data_json: string;
101
+ signature: string;
102
+ };
103
+ };
104
+ }[];
105
+ };
106
+ export declare const EG1_DEFAULT_SELECTOR: Readonly<{
107
+ protocol: "mcp";
108
+ tool: "release_payment";
109
+ }>;
110
+ export declare const EG1_DEFAULT_ACTION: Readonly<{
111
+ action_type: "payment.release";
112
+ amount_usd: 40000;
113
+ currency: "USD";
114
+ payment_instruction_id: "pi_eg1_40000";
115
+ beneficiary_account_hash: "sha256:eg1-beneficiary";
116
+ }>;
117
+ export declare const EG1_CHECKS: readonly {
118
+ id: string;
119
+ title: string;
120
+ }[];
121
+ /**
122
+ * Create an EG-1 harness: a throwaway issuer key + a receipt minter for the
123
+ * scenarios. Configure the subject's gate to trust `publicKey` for the run.
124
+ */
125
+ export declare function createEg1Harness({ now, action, idPrefix, }?: {
126
+ now?: () => number;
127
+ action?: Record<string, unknown>;
128
+ idPrefix?: string;
129
+ }): {
130
+ publicKey: string;
131
+ approverKeys: {
132
+ 'ep:key:eg1:class-a': {
133
+ approver_id: string;
134
+ public_key: string;
135
+ key_class: string;
136
+ };
137
+ 'ep:key:eg1:class-a-2': {
138
+ approver_id: string;
139
+ public_key: string;
140
+ key_class: string;
141
+ };
142
+ 'ep:key:eg1:controller': {
143
+ approver_id: string;
144
+ public_key: string;
145
+ key_class: string;
146
+ };
147
+ };
148
+ quorumPolicy: {
149
+ mode: string;
150
+ required: number;
151
+ distinct_humans: boolean;
152
+ window_sec: number;
153
+ approvers: {
154
+ role: string;
155
+ approver: string;
156
+ }[];
157
+ };
158
+ mint: ({ outcome, quorum, fakeQuorum, tamper, extra, }?: {
159
+ outcome?: "allow" | "allow_with_signoff";
160
+ quorum?: {
161
+ threshold?: number;
162
+ signers?: any[];
163
+ } | null;
164
+ fakeQuorum?: boolean;
165
+ tamper?: Record<string, any> | null;
166
+ extra?: Record<string, any>;
167
+ }) => {
168
+ '@version': string;
169
+ payload: {
170
+ receipt_id: string;
171
+ subject: string;
172
+ issuer: string;
173
+ created_at: string;
174
+ claim: Record<string, any>;
175
+ quorum?: any;
176
+ assurance_proof?: any;
177
+ signoff?: any;
178
+ approver_public_key?: string;
179
+ };
180
+ signature: {
181
+ algorithm: string;
182
+ value: string;
183
+ };
184
+ };
185
+ action: Record<string, unknown>;
186
+ actionHash: string;
187
+ now: () => number;
188
+ rpId: string;
189
+ allowedOrigins: string[];
190
+ };
191
+ /**
192
+ * Adapt an @emilia-protocol/gate instance into an EG-1 `invoke`. The gate must
193
+ * have been built trusting the harness public key. Uses gate.run() so the
194
+ * execution proof + reliance packet are produced on the allowed path.
195
+ */
196
+ export declare function makeGateInvoke(gate: any, { selector, action }?: {
197
+ selector?: Readonly<{
198
+ protocol: "mcp";
199
+ tool: "release_payment";
200
+ }> | undefined;
201
+ action?: Readonly<{
202
+ action_type: "payment.release";
203
+ amount_usd: 40000;
204
+ currency: "USD";
205
+ payment_instruction_id: "pi_eg1_40000";
206
+ beneficiary_account_hash: "sha256:eg1-beneficiary";
207
+ }> | undefined;
208
+ }): ({ receipt, observedAction }: {
209
+ receipt: any;
210
+ observedAction: any;
211
+ }) => Promise<{
212
+ allowed: boolean;
213
+ status: any;
214
+ reason: any;
215
+ decisionHash?: undefined;
216
+ execution?: undefined;
217
+ packet?: undefined;
218
+ } | {
219
+ allowed: boolean;
220
+ status: number;
221
+ reason: any;
222
+ decisionHash: any;
223
+ execution: any;
224
+ packet: any;
225
+ }>;
226
+ /**
227
+ * Drive a subject through the eight EG-1 checks and return a JSON report.
228
+ * @param {object} [o]
229
+ * @param {(scenario:object)=>Promise<object>} [o.invoke] the integration under test
230
+ * @param {object} [o.harness] from createEg1Harness()
231
+ * @param {object} [o.action] the high-risk action (defaults to the harness action)
232
+ */
233
+ export declare function runEg1({ invoke, harness, action, }?: {
234
+ invoke?: (scenario: {
235
+ receipt: any;
236
+ observedAction: any;
237
+ }) => Promise<{
238
+ allowed: boolean;
239
+ status?: number | null;
240
+ reason?: string | null;
241
+ decisionHash?: string | null;
242
+ execution?: {
243
+ authorizes_decision?: string | null;
244
+ } | null;
245
+ packet?: {
246
+ verdict?: string | null;
247
+ } | null;
248
+ }>;
249
+ harness?: ReturnType<typeof createEg1Harness>;
250
+ action?: Record<string, any>;
251
+ }): Promise<{
252
+ standard: string;
253
+ passed: boolean;
254
+ badge: string;
255
+ summary: {
256
+ passed: number;
257
+ total: number;
258
+ };
259
+ checks: any[];
260
+ generated_at: string;
261
+ }>;
262
+ declare const _default: {
263
+ EG1_VERSION: string;
264
+ EG1_CHECKS: readonly {
265
+ id: string;
266
+ title: string;
267
+ }[];
268
+ EG1_DEFAULT_ACTION: Readonly<{
269
+ action_type: "payment.release";
270
+ amount_usd: 40000;
271
+ currency: "USD";
272
+ payment_instruction_id: "pi_eg1_40000";
273
+ beneficiary_account_hash: "sha256:eg1-beneficiary";
274
+ }>;
275
+ EG1_DEFAULT_SELECTOR: Readonly<{
276
+ protocol: "mcp";
277
+ tool: "release_payment";
278
+ }>;
279
+ createEg1Harness: typeof createEg1Harness;
280
+ makeGateInvoke: typeof makeGateInvoke;
281
+ runEg1: typeof runEg1;
282
+ mintDeviceSignoff: typeof mintDeviceSignoff;
283
+ mintQuorumEvidence: typeof mintQuorumEvidence;
284
+ };
285
+ export default _default;
286
+ //# sourceMappingURL=eg1-conformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eg1-conformance.d.ts","sourceRoot":"","sources":["../src/eg1-conformance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,379 @@
1
+ // @ts-nocheck
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * EG-1 Conformance — the binary artifact that turns "we adopted EMILIA Gate"
5
+ * from a claim into a test result.
6
+ *
7
+ * The question EG-1 answers: *does your integration actually ENFORCE the gate,
8
+ * or are you only claiming it?* An integration earns EG-1 only if it
9
+ * demonstrably:
10
+ * 1. refuses a high-risk action with NO receipt (428);
11
+ * 2. refuses a software-tier receipt on a Class-A action;
12
+ * 3. refuses when the observed execution drifts from the authorized fields;
13
+ * 4. RUNS the action for a valid Class-A/quorum receipt;
14
+ * 5. refuses a replay of the same receipt;
15
+ * 6. refuses a tampered receipt;
16
+ * 7. emits an execution proof bound to the authorization decision;
17
+ * 8. produces a reliance packet whose verdict is "rely".
18
+ *
19
+ * This module is pure (no dependency on index.js, so no import cycle): it owns a
20
+ * throwaway issuer keypair, mints the scenario receipts, and drives any
21
+ * "subject" through the eight checks. A subject is an async `invoke` function
22
+ * representing one attempt at the guarded dangerous action:
23
+ *
24
+ * invoke({ receipt, observedAction }) -> {
25
+ * allowed: boolean, status: number, reason: string,
26
+ * // present only on an allowed run:
27
+ * decisionHash?: string, execution?: { authorizes_decision }, packet?: { verdict }
28
+ * }
29
+ *
30
+ * For integrations built on @emilia-protocol/gate, `makeGateInvoke(gate, ...)`
31
+ * produces a conformant `invoke` from `gate.run()`. Custom integrations (an HTTP
32
+ * service, a different language) implement `invoke` themselves and configure
33
+ * their gate to trust `harness.publicKey` for the run.
34
+ */
35
+ import crypto from 'node:crypto';
36
+ export const EG1_VERSION = 'EG-1';
37
+ // Same sorted-key canonical JSON the receipt signature is computed over.
38
+ const canon = (v) => (v == null ? JSON.stringify(v)
39
+ : Array.isArray(v) ? `[${v.map(canon).join(',')}]`
40
+ : typeof v === 'object' ? `{${Object.keys(v).sort().map((k) => JSON.stringify(k) + ':' + canon(v[k])).join(',')}}`
41
+ : JSON.stringify(v));
42
+ const sha256Hex = (v) => crypto.createHash('sha256').update(v, 'utf8').digest('hex');
43
+ const sha256Bytes = (v) => crypto.createHash('sha256').update(v).digest();
44
+ const RP_ID = 'emiliaprotocol.ai';
45
+ const RP_ORIGIN = `https://www.${RP_ID}`;
46
+ /**
47
+ * Mint a GENUINE WebAuthn ECDSA-P256 device signoff over an authorization
48
+ * context — the same structure @emilia-protocol/verify verifyWebAuthnSignoff
49
+ * checks. This is what earns a receipt its class_a tier: a real per-signer
50
+ * assertion, not a self-asserted `outcome` string. Used to build the Class-A and
51
+ * quorum evidence the EG-1 harness embeds so the Gate can CRYPTOGRAPHICALLY
52
+ * credit the tier.
53
+ * @param {{ actionHash?: string, approver?: string, issuedAtMs?: number, nonce?: string, prevContextHash?: string }} [opts]
54
+ */
55
+ export function mintDeviceSignoff({ actionHash, approver, issuedAtMs = Date.now(), nonce, prevContextHash = undefined, } = {}) {
56
+ const signer = crypto.generateKeyPairSync('ec', { namedCurve: 'P-256' });
57
+ const context = {
58
+ ep_version: '1.0', context_type: 'ep.signoff.v1',
59
+ action_hash: actionHash,
60
+ policy: 'policy_eg1',
61
+ nonce: nonce || ('sig_' + crypto.randomBytes(16).toString('hex')),
62
+ approver,
63
+ initiator: 'ent_agent_eg1',
64
+ issued_at: new Date(issuedAtMs).toISOString(),
65
+ expires_at: new Date(issuedAtMs + 5 * 60_000).toISOString(),
66
+ ...(prevContextHash !== undefined ? { prev_context_hash: prevContextHash } : {}),
67
+ };
68
+ const challenge = crypto.createHash('sha256').update(canon(context), 'utf8').digest().toString('base64url');
69
+ const clientData = Buffer.from(JSON.stringify({ type: 'webauthn.get', challenge, origin: `https://www.${RP_ID}` }), 'utf8');
70
+ const authData = Buffer.concat([
71
+ crypto.createHash('sha256').update(RP_ID, 'utf8').digest(),
72
+ Buffer.from([0x05]), // UP | UV
73
+ Buffer.from([0, 0, 0, 1]),
74
+ ]);
75
+ const signed = Buffer.concat([authData, crypto.createHash('sha256').update(clientData).digest()]);
76
+ const signature = crypto.sign('sha256', signed, signer.privateKey).toString('base64url');
77
+ return {
78
+ signoff: {
79
+ '@type': 'ep.signoff',
80
+ context,
81
+ webauthn: {
82
+ authenticator_data: authData.toString('base64url'),
83
+ client_data_json: clientData.toString('base64url'),
84
+ signature,
85
+ },
86
+ approver_public_key: signer.publicKey.export({ type: 'spki', format: 'der' }).toString('base64url'),
87
+ },
88
+ approver_public_key: signer.publicKey.export({ type: 'spki', format: 'der' }).toString('base64url'),
89
+ context,
90
+ };
91
+ }
92
+ /**
93
+ * Mint a GENUINE EP-QUORUM-v1 evidence document: N distinct humans, each on a
94
+ * distinct device key, each with a real WebAuthn assertion bound to the SAME
95
+ * action_hash, within a window. verifyQuorum returns valid for it. This is what
96
+ * earns a receipt its `quorum` tier — never a bare {signers,threshold} block.
97
+ * @param {{ actionHash?: string, threshold?: number, approvers?: Array<{ role: string, approver: string }>, issuedAtMs?: number }} [opts]
98
+ */
99
+ export function mintQuorumEvidence({ actionHash, threshold = 2, approvers, issuedAtMs = Date.now(), } = {}) {
100
+ const people = approvers || Array.from({ length: threshold }, (_, i) => ({ role: `approver_${i + 1}`, approver: `ep:approver:eg1_${i + 1}` }));
101
+ const members = people.map((p, i) => {
102
+ const s = mintDeviceSignoff({ actionHash, approver: p.approver, issuedAtMs: issuedAtMs + i * 1000 });
103
+ return { role: p.role, approver_public_key: s.approver_public_key, signoff: { '@type': s.signoff['@type'], context: s.signoff.context, webauthn: s.signoff.webauthn } };
104
+ });
105
+ return {
106
+ '@type': 'ep.quorum',
107
+ action_hash: actionHash,
108
+ policy: {
109
+ mode: 'threshold',
110
+ required: threshold,
111
+ approvers: people,
112
+ distinct_humans: true,
113
+ window_sec: 900,
114
+ },
115
+ members,
116
+ };
117
+ }
118
+ // The default high-risk action EG-1 exercises: a Class-A money movement, which
119
+ // the default gate manifest guards (selector { protocol:'mcp', tool:'release_payment' }).
120
+ export const EG1_DEFAULT_SELECTOR = Object.freeze({ protocol: 'mcp', tool: 'release_payment' });
121
+ export const EG1_DEFAULT_ACTION = Object.freeze({
122
+ action_type: 'payment.release',
123
+ amount_usd: 40000,
124
+ currency: 'USD',
125
+ payment_instruction_id: 'pi_eg1_40000',
126
+ beneficiary_account_hash: 'sha256:eg1-beneficiary',
127
+ });
128
+ export const EG1_CHECKS = Object.freeze([
129
+ { id: 'missing_receipt_refused', title: 'missing receipt → 428' },
130
+ { id: 'software_on_classA_refused', title: 'software receipt on Class-A action → refused' },
131
+ { id: 'execution_drift_refused', title: 'observed execution drift → refused' },
132
+ { id: 'valid_classA_runs', title: 'valid Class-A/quorum receipt → runs' },
133
+ { id: 'replay_refused', title: 'same receipt replay → refused' },
134
+ { id: 'tampered_refused', title: 'tampered receipt → refused' },
135
+ { id: 'execution_proof_binds', title: 'execution proof binds to authorization decision' },
136
+ { id: 'reliance_packet_rely', title: 'reliance packet returns verdict "rely"' },
137
+ ]);
138
+ /**
139
+ * Create an EG-1 harness: a throwaway issuer key + a receipt minter for the
140
+ * scenarios. Configure the subject's gate to trust `publicKey` for the run.
141
+ */
142
+ export function createEg1Harness({ now = Date.now, action = EG1_DEFAULT_ACTION, idPrefix = 'eg1', } = {}) {
143
+ const { publicKey, privateKey } = crypto.generateKeyPairSync('ed25519');
144
+ const pub = publicKey.export({ type: 'spki', format: 'der' }).toString('base64url');
145
+ const approverA = crypto.generateKeyPairSync('ec', { namedCurve: 'P-256' });
146
+ const approverA2 = crypto.generateKeyPairSync('ec', { namedCurve: 'P-256' });
147
+ const approverB = crypto.generateKeyPairSync('ed25519');
148
+ const approverKeys = {
149
+ 'ep:key:eg1:class-a': {
150
+ approver_id: 'ep:approver:eg1:cfo',
151
+ public_key: approverA.publicKey.export({ type: 'spki', format: 'der' }).toString('base64url'),
152
+ key_class: 'A',
153
+ },
154
+ 'ep:key:eg1:class-a-2': {
155
+ approver_id: 'ep:approver:eg1:security-officer',
156
+ public_key: approverA2.publicKey.export({ type: 'spki', format: 'der' }).toString('base64url'),
157
+ key_class: 'A',
158
+ },
159
+ 'ep:key:eg1:controller': {
160
+ approver_id: 'ep:approver:eg1:controller',
161
+ public_key: approverB.publicKey.export({ type: 'spki', format: 'der' }).toString('base64url'),
162
+ key_class: 'B',
163
+ },
164
+ };
165
+ const quorumPolicy = {
166
+ mode: 'threshold', required: 2, distinct_humans: true, window_sec: 900,
167
+ approvers: [
168
+ { role: 'cfo', approver: approverKeys['ep:key:eg1:class-a'].approver_id },
169
+ { role: 'security_officer', approver: approverKeys['ep:key:eg1:class-a-2'].approver_id },
170
+ ],
171
+ };
172
+ let counter = 0;
173
+ const nowMs = () => (typeof now === 'function' ? now() : now);
174
+ // The action_hash the self-contained human device assertions are bound to.
175
+ // Derived from the action so the signoff/quorum evidence is about THIS action.
176
+ const actionHash = crypto.createHash('sha256').update(canon(action), 'utf8').digest('hex');
177
+ function assuranceContext(payload) {
178
+ return {
179
+ '@version': 'EP-ASSURANCE-CONTEXT-v1',
180
+ receipt_id: payload.receipt_id,
181
+ claim_hash: `sha256:${sha256Hex(canon(payload.claim))}`,
182
+ };
183
+ }
184
+ function classASignoff(digest, { keyId = 'ep:key:eg1:class-a', keyPair = approverA, approver = 'ep:approver:eg1:cfo', } = {}) {
185
+ const challenge = Buffer.from(digest).toString('base64url');
186
+ const clientDataJSON = Buffer.from(JSON.stringify({ type: 'webauthn.get', challenge, origin: RP_ORIGIN }), 'utf8');
187
+ const rpIdHash = crypto.createHash('sha256').update(RP_ID).digest();
188
+ const authData = Buffer.concat([rpIdHash, Buffer.from([0x05]), Buffer.from([0, 0, 0, 0])]); // UP + UV
189
+ const signedData = Buffer.concat([authData, sha256Bytes(clientDataJSON)]);
190
+ return {
191
+ approver,
192
+ approver_key_id: keyId,
193
+ key_class: 'A',
194
+ webauthn: {
195
+ authenticator_data: authData.toString('base64url'),
196
+ client_data_json: clientDataJSON.toString('base64url'),
197
+ signature: crypto.sign('sha256', signedData, keyPair.privateKey).toString('base64url'),
198
+ },
199
+ };
200
+ }
201
+ function softwareSignoff(digest) {
202
+ return {
203
+ approver: 'ep:approver:eg1:controller',
204
+ approver_key_id: 'ep:key:eg1:controller',
205
+ key_class: 'B',
206
+ signature: crypto.sign(null, digest, approverB.privateKey).toString('base64url'),
207
+ };
208
+ }
209
+ function assuranceProof(payload, quorum) {
210
+ const context = assuranceContext(payload);
211
+ const contextHash = `sha256:${sha256Hex(canon(context))}`;
212
+ const digest = Buffer.from(contextHash.replace(/^sha256:/, ''), 'hex');
213
+ const threshold = Number(quorum?.threshold ?? quorum?.m ?? 1);
214
+ const signoffs = [classASignoff(digest)];
215
+ if (threshold >= 2) {
216
+ signoffs.push(classASignoff(digest, {
217
+ keyId: 'ep:key:eg1:class-a-2',
218
+ keyPair: approverA2,
219
+ approver: 'ep:approver:eg1:security-officer',
220
+ }));
221
+ }
222
+ return {
223
+ '@version': 'EP-ASSURANCE-PROOF-v1',
224
+ context_hash: contextHash,
225
+ threshold: threshold >= 2 ? threshold : 1,
226
+ signoffs,
227
+ };
228
+ }
229
+ /**
230
+ * Mint a scenario receipt.
231
+ * @param {object} o
232
+ * @param {'allow'|'allow_with_signoff'} [o.outcome] 'allow'=software; 'allow_with_signoff'
233
+ * embeds a REAL WebAuthn device signoff so the receipt cryptographically earns class_a.
234
+ * @param {object|boolean} [o.quorum] request quorum-tier evidence. Truthy -> a REAL
235
+ * EP-QUORUM-v1 doc (distinct humans + distinct keys + per-signer assertions). If an
236
+ * object with `threshold`/`signers`, its size sets the quorum size.
237
+ * @param {boolean} [o.fakeQuorum] embed an UNVERIFIABLE self-asserted quorum block
238
+ * ({signers,threshold}) with no per-signer signatures — used to prove the Gate
239
+ * REFUSES it (must NOT be credited quorum). For adversarial tests only.
240
+ * @param {object} [o.tamper] fields assigned to the claim AFTER signing (breaks the signature)
241
+ * @param {object} [o.extra] extra fields merged into the claim before signing
242
+ */
243
+ function mint({ outcome = 'allow_with_signoff', quorum = null, fakeQuorum = false, tamper = null, extra = {}, } = {}) {
244
+ const approver = outcome === 'allow'
245
+ ? 'ep:approver:eg1:controller'
246
+ : 'ep:approver:eg1:cfo';
247
+ const claim = { ...action, outcome, approver, ...extra };
248
+ const payload = {
249
+ receipt_id: `${idPrefix}_${++counter}`,
250
+ subject: 'agent:eg1-conformance',
251
+ issuer: 'ep:org:eg1',
252
+ created_at: new Date(nowMs()).toISOString(),
253
+ claim,
254
+ };
255
+ if (fakeQuorum) {
256
+ // Self-asserted ONLY — NO members / NO signatures / NO pinned proof. The
257
+ // Gate must refuse to credit this as quorum (assurance_too_low). For
258
+ // adversarial tests that prove payload claims are never trusted.
259
+ payload.quorum = { signers: ['ep:a', 'ep:b'], threshold: 2 };
260
+ }
261
+ else if (outcome === 'allow_with_signoff' || quorum) {
262
+ // Genuine, per-signer-verifiable evidence. The PRIMARY proof is the pinned
263
+ // EP-ASSURANCE-PROOF-v1 (verified against the harness's pinned approverKeys),
264
+ // which is what the EG-1 gate/custody path checks. We ALSO embed self-contained
265
+ // evidence (EP-QUORUM-v1 / WebAuthn device signoff) so a relying party that
266
+ // does NOT pin keys can still cryptographically credit the tier (DoD audit fix).
267
+ payload.assurance_proof = assuranceProof(payload, quorum);
268
+ if (quorum) {
269
+ const threshold = Number.isInteger(quorum.threshold) ? quorum.threshold
270
+ : (Array.isArray(quorum.signers) ? quorum.signers.length : 2);
271
+ payload.quorum = mintQuorumEvidence({
272
+ actionHash,
273
+ threshold,
274
+ approvers: quorumPolicy.approvers.slice(0, threshold),
275
+ issuedAtMs: nowMs(),
276
+ });
277
+ }
278
+ else {
279
+ const s = mintDeviceSignoff({ actionHash, approver, issuedAtMs: nowMs() });
280
+ payload.signoff = s.signoff;
281
+ payload.approver_public_key = s.approver_public_key;
282
+ }
283
+ }
284
+ const value = crypto.sign(null, Buffer.from(canon(payload), 'utf8'), privateKey).toString('base64url');
285
+ const receipt = { '@version': 'EP-RECEIPT-v1', payload, signature: { algorithm: 'Ed25519', value } };
286
+ if (tamper)
287
+ Object.assign(receipt.payload.claim, tamper); // tamper AFTER signing -> signature no longer binds
288
+ return receipt;
289
+ }
290
+ return { publicKey: pub, approverKeys, quorumPolicy, mint, action, actionHash, now: nowMs, rpId: RP_ID, allowedOrigins: [RP_ORIGIN] };
291
+ }
292
+ /**
293
+ * Adapt an @emilia-protocol/gate instance into an EG-1 `invoke`. The gate must
294
+ * have been built trusting the harness public key. Uses gate.run() so the
295
+ * execution proof + reliance packet are produced on the allowed path.
296
+ */
297
+ export function makeGateInvoke(gate, { selector = EG1_DEFAULT_SELECTOR, action = EG1_DEFAULT_ACTION } = {}) {
298
+ if (!gate || typeof gate.run !== 'function') {
299
+ throw new Error('makeGateInvoke requires an EMILIA Gate instance (with .run)');
300
+ }
301
+ return async ({ receipt, observedAction }) => {
302
+ const out = await gate.run({ selector, receipt, observedAction: observedAction ?? action }, async () => ({ eg1: 'side-effect-ran' }));
303
+ if (!out.ok) {
304
+ return { allowed: false, status: out.status, reason: out.authorization?.reason ?? 'refused' };
305
+ }
306
+ return {
307
+ allowed: true,
308
+ status: 200,
309
+ reason: out.authorization?.reason ?? 'allow',
310
+ decisionHash: out.authorization?.evidence?.hash ?? null,
311
+ execution: out.execution ?? null,
312
+ packet: out.packet ?? null,
313
+ };
314
+ };
315
+ }
316
+ const pick = (r) => ({ allowed: !!r.allowed, status: r.status ?? null, reason: r.reason ?? null });
317
+ /**
318
+ * Drive a subject through the eight EG-1 checks and return a JSON report.
319
+ * @param {object} [o]
320
+ * @param {(scenario:object)=>Promise<object>} [o.invoke] the integration under test
321
+ * @param {object} [o.harness] from createEg1Harness()
322
+ * @param {object} [o.action] the high-risk action (defaults to the harness action)
323
+ */
324
+ export async function runEg1({ invoke, harness, action, } = {}) {
325
+ if (typeof invoke !== 'function')
326
+ throw new Error('runEg1 requires an invoke(scenario) function');
327
+ if (!harness || typeof harness.mint !== 'function')
328
+ throw new Error('runEg1 requires a harness from createEg1Harness()');
329
+ const act = action || harness.action || EG1_DEFAULT_ACTION;
330
+ const observed = act;
331
+ const drift = { ...act, amount_usd: Number(act.amount_usd ?? 0) + 1 };
332
+ const results = {};
333
+ const set = (id, pass, observed_) => { results[id] = { pass: !!pass, observed: observed_ }; };
334
+ // 1. missing receipt → 428
335
+ let r = await invoke({ receipt: null, observedAction: observed });
336
+ set('missing_receipt_refused', !r.allowed && r.status === 428, pick(r));
337
+ // 2. software receipt on a Class-A action → refused
338
+ r = await invoke({ receipt: harness.mint({ outcome: 'allow' }), observedAction: observed });
339
+ set('software_on_classA_refused', !r.allowed && /assurance/i.test(r.reason || ''), pick(r));
340
+ // 3. observed execution drift → refused
341
+ r = await invoke({ receipt: harness.mint({ outcome: 'allow_with_signoff' }), observedAction: drift });
342
+ set('execution_drift_refused', !r.allowed && /binding/i.test(r.reason || ''), pick(r));
343
+ // 4. valid Class-A receipt → runs (capture for 5/7/8)
344
+ const valid = harness.mint({ outcome: 'allow_with_signoff' });
345
+ r = await invoke({ receipt: valid, observedAction: observed });
346
+ const validAllowed = r.allowed === true;
347
+ set('valid_classA_runs', validAllowed, pick(r));
348
+ // 7. execution proof binds to the authorization decision
349
+ const boundOk = validAllowed
350
+ && !!r.execution && !!r.execution.authorizes_decision
351
+ && !!r.decisionHash && r.execution.authorizes_decision === r.decisionHash;
352
+ set('execution_proof_binds', boundOk, {
353
+ authorizes_decision: r.execution?.authorizes_decision ?? null,
354
+ decision_hash: r.decisionHash ?? null,
355
+ });
356
+ // 8. reliance packet verdict "rely"
357
+ set('reliance_packet_rely', validAllowed && String(r.packet?.verdict || '').toLowerCase() === 'rely', {
358
+ verdict: r.packet?.verdict ?? null,
359
+ });
360
+ // 5. same receipt replay → refused
361
+ r = await invoke({ receipt: valid, observedAction: observed });
362
+ set('replay_refused', !r.allowed && /replay/i.test(r.reason || ''), pick(r));
363
+ // 6. tampered receipt → refused
364
+ r = await invoke({ receipt: harness.mint({ outcome: 'allow_with_signoff', tamper: { amount_usd: 9_999_999 } }), observedAction: observed });
365
+ set('tampered_refused', !r.allowed && r.status === 428, pick(r));
366
+ const checks = EG1_CHECKS.map((c) => ({ id: c.id, title: c.title, ...results[c.id] }));
367
+ const passedCount = checks.filter((c) => c.pass).length;
368
+ const passed = passedCount === checks.length;
369
+ return {
370
+ standard: EG1_VERSION,
371
+ passed,
372
+ badge: passed ? 'EG-1 Enforced' : 'EG-1 not earned',
373
+ summary: { passed: passedCount, total: checks.length },
374
+ checks,
375
+ generated_at: new Date(harness.now ? harness.now() : Date.now()).toISOString(),
376
+ };
377
+ }
378
+ export default { EG1_VERSION, EG1_CHECKS, EG1_DEFAULT_ACTION, EG1_DEFAULT_SELECTOR, createEg1Harness, makeGateInvoke, runEg1, mintDeviceSignoff, mintQuorumEvidence };
379
+ //# sourceMappingURL=eg1-conformance.js.map