@suveren/gateway 0.18.0 → 0.18.1

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 (763) hide show
  1. package/bin/suveren-gateway.js +26 -1
  2. package/content/guides/3-mandates.md +1 -0
  3. package/dist/control-plane/index.mjs +132 -12
  4. package/dist/mcp-server/chunk-JUFH4SKS.mjs +639 -0
  5. package/dist/mcp-server/http.mjs +1592 -190
  6. package/dist/mcp-server/report-verify-cli.mjs +171 -0
  7. package/dist/ui/assets/index-78vuGrVE.js +111 -0
  8. package/dist/ui/assets/{index-y1OFeYnS.css → index-Dfh38n-b.css} +1 -1
  9. package/dist/ui/index.html +2 -2
  10. package/node_modules/dayjs/.editorconfig +7 -0
  11. package/node_modules/dayjs/CHANGELOG.md +1022 -0
  12. package/node_modules/dayjs/LICENSE +21 -0
  13. package/node_modules/dayjs/README.md +186 -0
  14. package/node_modules/dayjs/dayjs.min.js +1 -0
  15. package/node_modules/dayjs/esm/constant.js +25 -0
  16. package/node_modules/dayjs/esm/index.d.ts +429 -0
  17. package/node_modules/dayjs/esm/index.js +541 -0
  18. package/node_modules/dayjs/esm/locale/af.js +39 -0
  19. package/node_modules/dayjs/esm/locale/am.js +40 -0
  20. package/node_modules/dayjs/esm/locale/ar-dz.js +41 -0
  21. package/node_modules/dayjs/esm/locale/ar-iq.js +42 -0
  22. package/node_modules/dayjs/esm/locale/ar-kw.js +41 -0
  23. package/node_modules/dayjs/esm/locale/ar-ly.js +27 -0
  24. package/node_modules/dayjs/esm/locale/ar-ma.js +42 -0
  25. package/node_modules/dayjs/esm/locale/ar-sa.js +41 -0
  26. package/node_modules/dayjs/esm/locale/ar-tn.js +42 -0
  27. package/node_modules/dayjs/esm/locale/ar.js +81 -0
  28. package/node_modules/dayjs/esm/locale/az.js +39 -0
  29. package/node_modules/dayjs/esm/locale/be.js +102 -0
  30. package/node_modules/dayjs/esm/locale/bg.js +55 -0
  31. package/node_modules/dayjs/esm/locale/bi.js +39 -0
  32. package/node_modules/dayjs/esm/locale/bm.js +39 -0
  33. package/node_modules/dayjs/esm/locale/bn-bd.js +81 -0
  34. package/node_modules/dayjs/esm/locale/bn.js +72 -0
  35. package/node_modules/dayjs/esm/locale/bo.js +38 -0
  36. package/node_modules/dayjs/esm/locale/br.js +93 -0
  37. package/node_modules/dayjs/esm/locale/bs.js +24 -0
  38. package/node_modules/dayjs/esm/locale/ca.js +44 -0
  39. package/node_modules/dayjs/esm/locale/cs.js +120 -0
  40. package/node_modules/dayjs/esm/locale/cv.js +24 -0
  41. package/node_modules/dayjs/esm/locale/cy.js +39 -0
  42. package/node_modules/dayjs/esm/locale/da.js +40 -0
  43. package/node_modules/dayjs/esm/locale/de-at.js +63 -0
  44. package/node_modules/dayjs/esm/locale/de-ch.js +63 -0
  45. package/node_modules/dayjs/esm/locale/de.js +64 -0
  46. package/node_modules/dayjs/esm/locale/dv.js +39 -0
  47. package/node_modules/dayjs/esm/locale/el.js +39 -0
  48. package/node_modules/dayjs/esm/locale/en-au.js +41 -0
  49. package/node_modules/dayjs/esm/locale/en-ca.js +38 -0
  50. package/node_modules/dayjs/esm/locale/en-gb.js +42 -0
  51. package/node_modules/dayjs/esm/locale/en-ie.js +39 -0
  52. package/node_modules/dayjs/esm/locale/en-il.js +38 -0
  53. package/node_modules/dayjs/esm/locale/en-in.js +42 -0
  54. package/node_modules/dayjs/esm/locale/en-nz.js +41 -0
  55. package/node_modules/dayjs/esm/locale/en-sg.js +39 -0
  56. package/node_modules/dayjs/esm/locale/en-tt.js +42 -0
  57. package/node_modules/dayjs/esm/locale/en.js +12 -0
  58. package/node_modules/dayjs/esm/locale/eo.js +39 -0
  59. package/node_modules/dayjs/esm/locale/es-do.js +39 -0
  60. package/node_modules/dayjs/esm/locale/es-mx.js +38 -0
  61. package/node_modules/dayjs/esm/locale/es-pr.js +39 -0
  62. package/node_modules/dayjs/esm/locale/es-us.js +38 -0
  63. package/node_modules/dayjs/esm/locale/es.js +39 -0
  64. package/node_modules/dayjs/esm/locale/et.js +65 -0
  65. package/node_modules/dayjs/esm/locale/eu.js +43 -0
  66. package/node_modules/dayjs/esm/locale/fa.js +39 -0
  67. package/node_modules/dayjs/esm/locale/fi.js +88 -0
  68. package/node_modules/dayjs/esm/locale/fo.js +39 -0
  69. package/node_modules/dayjs/esm/locale/fr-ca.js +38 -0
  70. package/node_modules/dayjs/esm/locale/fr-ch.js +39 -0
  71. package/node_modules/dayjs/esm/locale/fr.js +41 -0
  72. package/node_modules/dayjs/esm/locale/fy.js +39 -0
  73. package/node_modules/dayjs/esm/locale/ga.js +39 -0
  74. package/node_modules/dayjs/esm/locale/gd.js +39 -0
  75. package/node_modules/dayjs/esm/locale/gl.js +39 -0
  76. package/node_modules/dayjs/esm/locale/gom-latn.js +25 -0
  77. package/node_modules/dayjs/esm/locale/gu.js +38 -0
  78. package/node_modules/dayjs/esm/locale/he.js +78 -0
  79. package/node_modules/dayjs/esm/locale/hi.js +38 -0
  80. package/node_modules/dayjs/esm/locale/hr.js +53 -0
  81. package/node_modules/dayjs/esm/locale/ht.js +38 -0
  82. package/node_modules/dayjs/esm/locale/hu.js +61 -0
  83. package/node_modules/dayjs/esm/locale/hy-am.js +39 -0
  84. package/node_modules/dayjs/esm/locale/id.js +39 -0
  85. package/node_modules/dayjs/esm/locale/index.d.ts +11 -0
  86. package/node_modules/dayjs/esm/locale/is.js +68 -0
  87. package/node_modules/dayjs/esm/locale/it-ch.js +39 -0
  88. package/node_modules/dayjs/esm/locale/it.js +39 -0
  89. package/node_modules/dayjs/esm/locale/ja.js +45 -0
  90. package/node_modules/dayjs/esm/locale/jv.js +39 -0
  91. package/node_modules/dayjs/esm/locale/ka.js +39 -0
  92. package/node_modules/dayjs/esm/locale/kk.js +39 -0
  93. package/node_modules/dayjs/esm/locale/km.js +42 -0
  94. package/node_modules/dayjs/esm/locale/kn.js +38 -0
  95. package/node_modules/dayjs/esm/locale/ko.js +45 -0
  96. package/node_modules/dayjs/esm/locale/ku.js +77 -0
  97. package/node_modules/dayjs/esm/locale/ky.js +39 -0
  98. package/node_modules/dayjs/esm/locale/lb.js +24 -0
  99. package/node_modules/dayjs/esm/locale/lo.js +38 -0
  100. package/node_modules/dayjs/esm/locale/lt.js +70 -0
  101. package/node_modules/dayjs/esm/locale/lv.js +39 -0
  102. package/node_modules/dayjs/esm/locale/me.js +24 -0
  103. package/node_modules/dayjs/esm/locale/mi.js +39 -0
  104. package/node_modules/dayjs/esm/locale/mk.js +39 -0
  105. package/node_modules/dayjs/esm/locale/ml.js +38 -0
  106. package/node_modules/dayjs/esm/locale/mn.js +38 -0
  107. package/node_modules/dayjs/esm/locale/mr.js +23 -0
  108. package/node_modules/dayjs/esm/locale/ms-my.js +39 -0
  109. package/node_modules/dayjs/esm/locale/ms.js +39 -0
  110. package/node_modules/dayjs/esm/locale/mt.js +39 -0
  111. package/node_modules/dayjs/esm/locale/my.js +39 -0
  112. package/node_modules/dayjs/esm/locale/nb.js +40 -0
  113. package/node_modules/dayjs/esm/locale/ne.js +40 -0
  114. package/node_modules/dayjs/esm/locale/nl-be.js +39 -0
  115. package/node_modules/dayjs/esm/locale/nl.js +40 -0
  116. package/node_modules/dayjs/esm/locale/nn.js +39 -0
  117. package/node_modules/dayjs/esm/locale/oc-lnc.js +39 -0
  118. package/node_modules/dayjs/esm/locale/pa-in.js +38 -0
  119. package/node_modules/dayjs/esm/locale/pl.js +87 -0
  120. package/node_modules/dayjs/esm/locale/pt-br.js +38 -0
  121. package/node_modules/dayjs/esm/locale/pt.js +40 -0
  122. package/node_modules/dayjs/esm/locale/rn.js +39 -0
  123. package/node_modules/dayjs/esm/locale/ro.js +39 -0
  124. package/node_modules/dayjs/esm/locale/ru.js +99 -0
  125. package/node_modules/dayjs/esm/locale/rw.js +35 -0
  126. package/node_modules/dayjs/esm/locale/sd.js +39 -0
  127. package/node_modules/dayjs/esm/locale/se.js +39 -0
  128. package/node_modules/dayjs/esm/locale/si.js +38 -0
  129. package/node_modules/dayjs/esm/locale/sk.js +121 -0
  130. package/node_modules/dayjs/esm/locale/sl.js +141 -0
  131. package/node_modules/dayjs/esm/locale/sq.js +39 -0
  132. package/node_modules/dayjs/esm/locale/sr-cyrl.js +74 -0
  133. package/node_modules/dayjs/esm/locale/sr.js +74 -0
  134. package/node_modules/dayjs/esm/locale/ss.js +39 -0
  135. package/node_modules/dayjs/esm/locale/sv-fi.js +46 -0
  136. package/node_modules/dayjs/esm/locale/sv.js +44 -0
  137. package/node_modules/dayjs/esm/locale/sw.js +39 -0
  138. package/node_modules/dayjs/esm/locale/ta.js +38 -0
  139. package/node_modules/dayjs/esm/locale/te.js +38 -0
  140. package/node_modules/dayjs/esm/locale/tet.js +39 -0
  141. package/node_modules/dayjs/esm/locale/tg.js +39 -0
  142. package/node_modules/dayjs/esm/locale/th.js +38 -0
  143. package/node_modules/dayjs/esm/locale/tk.js +39 -0
  144. package/node_modules/dayjs/esm/locale/tl-ph.js +39 -0
  145. package/node_modules/dayjs/esm/locale/tlh.js +24 -0
  146. package/node_modules/dayjs/esm/locale/tr.js +39 -0
  147. package/node_modules/dayjs/esm/locale/types.d.ts +33 -0
  148. package/node_modules/dayjs/esm/locale/tzl.js +24 -0
  149. package/node_modules/dayjs/esm/locale/tzm-latn.js +39 -0
  150. package/node_modules/dayjs/esm/locale/tzm.js +39 -0
  151. package/node_modules/dayjs/esm/locale/ug-cn.js +39 -0
  152. package/node_modules/dayjs/esm/locale/uk.js +77 -0
  153. package/node_modules/dayjs/esm/locale/ur.js +39 -0
  154. package/node_modules/dayjs/esm/locale/uz-latn.js +39 -0
  155. package/node_modules/dayjs/esm/locale/uz.js +39 -0
  156. package/node_modules/dayjs/esm/locale/vi.js +43 -0
  157. package/node_modules/dayjs/esm/locale/x-pseudo.js +39 -0
  158. package/node_modules/dayjs/esm/locale/yo.js +39 -0
  159. package/node_modules/dayjs/esm/locale/zh-cn.js +67 -0
  160. package/node_modules/dayjs/esm/locale/zh-hk.js +65 -0
  161. package/node_modules/dayjs/esm/locale/zh-tw.js +65 -0
  162. package/node_modules/dayjs/esm/locale/zh.js +67 -0
  163. package/node_modules/dayjs/esm/plugin/advancedFormat/index.d.ts +4 -0
  164. package/node_modules/dayjs/esm/plugin/advancedFormat/index.js +66 -0
  165. package/node_modules/dayjs/esm/plugin/arraySupport/index.d.ts +10 -0
  166. package/node_modules/dayjs/esm/plugin/arraySupport/index.js +33 -0
  167. package/node_modules/dayjs/esm/plugin/badMutable/index.d.ts +4 -0
  168. package/node_modules/dayjs/esm/plugin/badMutable/index.js +61 -0
  169. package/node_modules/dayjs/esm/plugin/bigIntSupport/index.d.ts +11 -0
  170. package/node_modules/dayjs/esm/plugin/bigIntSupport/index.js +32 -0
  171. package/node_modules/dayjs/esm/plugin/buddhistEra/index.d.ts +4 -0
  172. package/node_modules/dayjs/esm/plugin/buddhistEra/index.js +21 -0
  173. package/node_modules/dayjs/esm/plugin/calendar/index.d.ts +10 -0
  174. package/node_modules/dayjs/esm/plugin/calendar/index.js +32 -0
  175. package/node_modules/dayjs/esm/plugin/customParseFormat/index.d.ts +8 -0
  176. package/node_modules/dayjs/esm/plugin/customParseFormat/index.js +333 -0
  177. package/node_modules/dayjs/esm/plugin/dayOfYear/index.d.ts +11 -0
  178. package/node_modules/dayjs/esm/plugin/dayOfYear/index.js +9 -0
  179. package/node_modules/dayjs/esm/plugin/devHelper/index.d.ts +4 -0
  180. package/node_modules/dayjs/esm/plugin/devHelper/index.js +50 -0
  181. package/node_modules/dayjs/esm/plugin/duration/index.d.ts +88 -0
  182. package/node_modules/dayjs/esm/plugin/duration/index.js +357 -0
  183. package/node_modules/dayjs/esm/plugin/isBetween/index.d.ts +10 -0
  184. package/node_modules/dayjs/esm/plugin/isBetween/index.js +10 -0
  185. package/node_modules/dayjs/esm/plugin/isLeapYear/index.d.ts +10 -0
  186. package/node_modules/dayjs/esm/plugin/isLeapYear/index.js +7 -0
  187. package/node_modules/dayjs/esm/plugin/isMoment/index.d.ts +10 -0
  188. package/node_modules/dayjs/esm/plugin/isMoment/index.js +5 -0
  189. package/node_modules/dayjs/esm/plugin/isSameOrAfter/index.d.ts +10 -0
  190. package/node_modules/dayjs/esm/plugin/isSameOrAfter/index.js +5 -0
  191. package/node_modules/dayjs/esm/plugin/isSameOrBefore/index.d.ts +10 -0
  192. package/node_modules/dayjs/esm/plugin/isSameOrBefore/index.js +5 -0
  193. package/node_modules/dayjs/esm/plugin/isToday/index.d.ts +10 -0
  194. package/node_modules/dayjs/esm/plugin/isToday/index.js +9 -0
  195. package/node_modules/dayjs/esm/plugin/isTomorrow/index.d.ts +10 -0
  196. package/node_modules/dayjs/esm/plugin/isTomorrow/index.js +9 -0
  197. package/node_modules/dayjs/esm/plugin/isYesterday/index.d.ts +10 -0
  198. package/node_modules/dayjs/esm/plugin/isYesterday/index.js +9 -0
  199. package/node_modules/dayjs/esm/plugin/isoWeek/index.d.ts +27 -0
  200. package/node_modules/dayjs/esm/plugin/isoWeek/index.js +57 -0
  201. package/node_modules/dayjs/esm/plugin/isoWeeksInYear/index.d.ts +10 -0
  202. package/node_modules/dayjs/esm/plugin/isoWeeksInYear/index.js +15 -0
  203. package/node_modules/dayjs/esm/plugin/localeData/index.d.ts +44 -0
  204. package/node_modules/dayjs/esm/plugin/localeData/index.js +114 -0
  205. package/node_modules/dayjs/esm/plugin/localizedFormat/index.d.ts +4 -0
  206. package/node_modules/dayjs/esm/plugin/localizedFormat/index.js +20 -0
  207. package/node_modules/dayjs/esm/plugin/localizedFormat/utils.js +20 -0
  208. package/node_modules/dayjs/esm/plugin/minMax/index.d.ts +22 -0
  209. package/node_modules/dayjs/esm/plugin/minMax/index.js +39 -0
  210. package/node_modules/dayjs/esm/plugin/negativeYear/index.d.ts +4 -0
  211. package/node_modules/dayjs/esm/plugin/negativeYear/index.js +36 -0
  212. package/node_modules/dayjs/esm/plugin/objectSupport/index.d.ts +48 -0
  213. package/node_modules/dayjs/esm/plugin/objectSupport/index.js +97 -0
  214. package/node_modules/dayjs/esm/plugin/pluralGetSet/index.d.ts +44 -0
  215. package/node_modules/dayjs/esm/plugin/pluralGetSet/index.js +7 -0
  216. package/node_modules/dayjs/esm/plugin/preParsePostFormat/index.d.ts +4 -0
  217. package/node_modules/dayjs/esm/plugin/preParsePostFormat/index.js +40 -0
  218. package/node_modules/dayjs/esm/plugin/quarterOfYear/index.d.ts +26 -0
  219. package/node_modules/dayjs/esm/plugin/quarterOfYear/index.js +41 -0
  220. package/node_modules/dayjs/esm/plugin/relativeTime/index.d.ts +24 -0
  221. package/node_modules/dayjs/esm/plugin/relativeTime/index.js +130 -0
  222. package/node_modules/dayjs/esm/plugin/timezone/index.d.ts +20 -0
  223. package/node_modules/dayjs/esm/plugin/timezone/index.js +205 -0
  224. package/node_modules/dayjs/esm/plugin/toArray/index.d.ts +10 -0
  225. package/node_modules/dayjs/esm/plugin/toArray/index.js +7 -0
  226. package/node_modules/dayjs/esm/plugin/toObject/index.d.ts +20 -0
  227. package/node_modules/dayjs/esm/plugin/toObject/index.js +15 -0
  228. package/node_modules/dayjs/esm/plugin/updateLocale/index.d.ts +8 -0
  229. package/node_modules/dayjs/esm/plugin/updateLocale/index.js +18 -0
  230. package/node_modules/dayjs/esm/plugin/utc/index.d.ts +19 -0
  231. package/node_modules/dayjs/esm/plugin/utc/index.js +188 -0
  232. package/node_modules/dayjs/esm/plugin/weekOfYear/index.d.ts +12 -0
  233. package/node_modules/dayjs/esm/plugin/weekOfYear/index.js +44 -0
  234. package/node_modules/dayjs/esm/plugin/weekYear/index.d.ts +10 -0
  235. package/node_modules/dayjs/esm/plugin/weekYear/index.js +19 -0
  236. package/node_modules/dayjs/esm/plugin/weekday/index.d.ts +12 -0
  237. package/node_modules/dayjs/esm/plugin/weekday/index.js +15 -0
  238. package/node_modules/dayjs/esm/utils.js +58 -0
  239. package/node_modules/dayjs/index.d.ts +429 -0
  240. package/node_modules/dayjs/locale/af.js +1 -0
  241. package/node_modules/dayjs/locale/am.js +1 -0
  242. package/node_modules/dayjs/locale/ar-dz.js +1 -0
  243. package/node_modules/dayjs/locale/ar-iq.js +1 -0
  244. package/node_modules/dayjs/locale/ar-kw.js +1 -0
  245. package/node_modules/dayjs/locale/ar-ly.js +1 -0
  246. package/node_modules/dayjs/locale/ar-ma.js +1 -0
  247. package/node_modules/dayjs/locale/ar-sa.js +1 -0
  248. package/node_modules/dayjs/locale/ar-tn.js +1 -0
  249. package/node_modules/dayjs/locale/ar.js +1 -0
  250. package/node_modules/dayjs/locale/az.js +1 -0
  251. package/node_modules/dayjs/locale/be.js +1 -0
  252. package/node_modules/dayjs/locale/bg.js +1 -0
  253. package/node_modules/dayjs/locale/bi.js +1 -0
  254. package/node_modules/dayjs/locale/bm.js +1 -0
  255. package/node_modules/dayjs/locale/bn-bd.js +1 -0
  256. package/node_modules/dayjs/locale/bn.js +1 -0
  257. package/node_modules/dayjs/locale/bo.js +1 -0
  258. package/node_modules/dayjs/locale/br.js +1 -0
  259. package/node_modules/dayjs/locale/bs.js +1 -0
  260. package/node_modules/dayjs/locale/ca.js +1 -0
  261. package/node_modules/dayjs/locale/cs.js +1 -0
  262. package/node_modules/dayjs/locale/cv.js +1 -0
  263. package/node_modules/dayjs/locale/cy.js +1 -0
  264. package/node_modules/dayjs/locale/da.js +1 -0
  265. package/node_modules/dayjs/locale/de-at.js +1 -0
  266. package/node_modules/dayjs/locale/de-ch.js +1 -0
  267. package/node_modules/dayjs/locale/de.js +1 -0
  268. package/node_modules/dayjs/locale/dv.js +1 -0
  269. package/node_modules/dayjs/locale/el.js +1 -0
  270. package/node_modules/dayjs/locale/en-au.js +1 -0
  271. package/node_modules/dayjs/locale/en-ca.js +1 -0
  272. package/node_modules/dayjs/locale/en-gb.js +1 -0
  273. package/node_modules/dayjs/locale/en-ie.js +1 -0
  274. package/node_modules/dayjs/locale/en-il.js +1 -0
  275. package/node_modules/dayjs/locale/en-in.js +1 -0
  276. package/node_modules/dayjs/locale/en-nz.js +1 -0
  277. package/node_modules/dayjs/locale/en-sg.js +1 -0
  278. package/node_modules/dayjs/locale/en-tt.js +1 -0
  279. package/node_modules/dayjs/locale/en.js +1 -0
  280. package/node_modules/dayjs/locale/eo.js +1 -0
  281. package/node_modules/dayjs/locale/es-do.js +1 -0
  282. package/node_modules/dayjs/locale/es-mx.js +1 -0
  283. package/node_modules/dayjs/locale/es-pr.js +1 -0
  284. package/node_modules/dayjs/locale/es-us.js +1 -0
  285. package/node_modules/dayjs/locale/es.js +1 -0
  286. package/node_modules/dayjs/locale/et.js +1 -0
  287. package/node_modules/dayjs/locale/eu.js +1 -0
  288. package/node_modules/dayjs/locale/fa.js +1 -0
  289. package/node_modules/dayjs/locale/fi.js +1 -0
  290. package/node_modules/dayjs/locale/fo.js +1 -0
  291. package/node_modules/dayjs/locale/fr-ca.js +1 -0
  292. package/node_modules/dayjs/locale/fr-ch.js +1 -0
  293. package/node_modules/dayjs/locale/fr.js +1 -0
  294. package/node_modules/dayjs/locale/fy.js +1 -0
  295. package/node_modules/dayjs/locale/ga.js +1 -0
  296. package/node_modules/dayjs/locale/gd.js +1 -0
  297. package/node_modules/dayjs/locale/gl.js +1 -0
  298. package/node_modules/dayjs/locale/gom-latn.js +1 -0
  299. package/node_modules/dayjs/locale/gu.js +1 -0
  300. package/node_modules/dayjs/locale/he.js +1 -0
  301. package/node_modules/dayjs/locale/hi.js +1 -0
  302. package/node_modules/dayjs/locale/hr.js +1 -0
  303. package/node_modules/dayjs/locale/ht.js +1 -0
  304. package/node_modules/dayjs/locale/hu.js +1 -0
  305. package/node_modules/dayjs/locale/hy-am.js +1 -0
  306. package/node_modules/dayjs/locale/id.js +1 -0
  307. package/node_modules/dayjs/locale/index.d.ts +11 -0
  308. package/node_modules/dayjs/locale/is.js +1 -0
  309. package/node_modules/dayjs/locale/it-ch.js +1 -0
  310. package/node_modules/dayjs/locale/it.js +1 -0
  311. package/node_modules/dayjs/locale/ja.js +1 -0
  312. package/node_modules/dayjs/locale/jv.js +1 -0
  313. package/node_modules/dayjs/locale/ka.js +1 -0
  314. package/node_modules/dayjs/locale/kk.js +1 -0
  315. package/node_modules/dayjs/locale/km.js +1 -0
  316. package/node_modules/dayjs/locale/kn.js +1 -0
  317. package/node_modules/dayjs/locale/ko.js +1 -0
  318. package/node_modules/dayjs/locale/ku.js +1 -0
  319. package/node_modules/dayjs/locale/ky.js +1 -0
  320. package/node_modules/dayjs/locale/lb.js +1 -0
  321. package/node_modules/dayjs/locale/lo.js +1 -0
  322. package/node_modules/dayjs/locale/lt.js +1 -0
  323. package/node_modules/dayjs/locale/lv.js +1 -0
  324. package/node_modules/dayjs/locale/me.js +1 -0
  325. package/node_modules/dayjs/locale/mi.js +1 -0
  326. package/node_modules/dayjs/locale/mk.js +1 -0
  327. package/node_modules/dayjs/locale/ml.js +1 -0
  328. package/node_modules/dayjs/locale/mn.js +1 -0
  329. package/node_modules/dayjs/locale/mr.js +1 -0
  330. package/node_modules/dayjs/locale/ms-my.js +1 -0
  331. package/node_modules/dayjs/locale/ms.js +1 -0
  332. package/node_modules/dayjs/locale/mt.js +1 -0
  333. package/node_modules/dayjs/locale/my.js +1 -0
  334. package/node_modules/dayjs/locale/nb.js +1 -0
  335. package/node_modules/dayjs/locale/ne.js +1 -0
  336. package/node_modules/dayjs/locale/nl-be.js +1 -0
  337. package/node_modules/dayjs/locale/nl.js +1 -0
  338. package/node_modules/dayjs/locale/nn.js +1 -0
  339. package/node_modules/dayjs/locale/oc-lnc.js +1 -0
  340. package/node_modules/dayjs/locale/pa-in.js +1 -0
  341. package/node_modules/dayjs/locale/pl.js +1 -0
  342. package/node_modules/dayjs/locale/pt-br.js +1 -0
  343. package/node_modules/dayjs/locale/pt.js +1 -0
  344. package/node_modules/dayjs/locale/rn.js +1 -0
  345. package/node_modules/dayjs/locale/ro.js +1 -0
  346. package/node_modules/dayjs/locale/ru.js +1 -0
  347. package/node_modules/dayjs/locale/rw.js +1 -0
  348. package/node_modules/dayjs/locale/sd.js +1 -0
  349. package/node_modules/dayjs/locale/se.js +1 -0
  350. package/node_modules/dayjs/locale/si.js +1 -0
  351. package/node_modules/dayjs/locale/sk.js +1 -0
  352. package/node_modules/dayjs/locale/sl.js +1 -0
  353. package/node_modules/dayjs/locale/sq.js +1 -0
  354. package/node_modules/dayjs/locale/sr-cyrl.js +1 -0
  355. package/node_modules/dayjs/locale/sr.js +1 -0
  356. package/node_modules/dayjs/locale/ss.js +1 -0
  357. package/node_modules/dayjs/locale/sv-fi.js +1 -0
  358. package/node_modules/dayjs/locale/sv.js +1 -0
  359. package/node_modules/dayjs/locale/sw.js +1 -0
  360. package/node_modules/dayjs/locale/ta.js +1 -0
  361. package/node_modules/dayjs/locale/te.js +1 -0
  362. package/node_modules/dayjs/locale/tet.js +1 -0
  363. package/node_modules/dayjs/locale/tg.js +1 -0
  364. package/node_modules/dayjs/locale/th.js +1 -0
  365. package/node_modules/dayjs/locale/tk.js +1 -0
  366. package/node_modules/dayjs/locale/tl-ph.js +1 -0
  367. package/node_modules/dayjs/locale/tlh.js +1 -0
  368. package/node_modules/dayjs/locale/tr.js +1 -0
  369. package/node_modules/dayjs/locale/types.d.ts +33 -0
  370. package/node_modules/dayjs/locale/tzl.js +1 -0
  371. package/node_modules/dayjs/locale/tzm-latn.js +1 -0
  372. package/node_modules/dayjs/locale/tzm.js +1 -0
  373. package/node_modules/dayjs/locale/ug-cn.js +1 -0
  374. package/node_modules/dayjs/locale/uk.js +1 -0
  375. package/node_modules/dayjs/locale/ur.js +1 -0
  376. package/node_modules/dayjs/locale/uz-latn.js +1 -0
  377. package/node_modules/dayjs/locale/uz.js +1 -0
  378. package/node_modules/dayjs/locale/vi.js +1 -0
  379. package/node_modules/dayjs/locale/x-pseudo.js +1 -0
  380. package/node_modules/dayjs/locale/yo.js +1 -0
  381. package/node_modules/dayjs/locale/zh-cn.js +1 -0
  382. package/node_modules/dayjs/locale/zh-hk.js +1 -0
  383. package/node_modules/dayjs/locale/zh-tw.js +1 -0
  384. package/node_modules/dayjs/locale/zh.js +1 -0
  385. package/node_modules/dayjs/locale.json +1 -0
  386. package/node_modules/dayjs/package.json +86 -0
  387. package/node_modules/dayjs/plugin/advancedFormat.d.ts +4 -0
  388. package/node_modules/dayjs/plugin/advancedFormat.js +1 -0
  389. package/node_modules/dayjs/plugin/arraySupport.d.ts +10 -0
  390. package/node_modules/dayjs/plugin/arraySupport.js +1 -0
  391. package/node_modules/dayjs/plugin/badMutable.d.ts +4 -0
  392. package/node_modules/dayjs/plugin/badMutable.js +1 -0
  393. package/node_modules/dayjs/plugin/bigIntSupport.d.ts +11 -0
  394. package/node_modules/dayjs/plugin/bigIntSupport.js +1 -0
  395. package/node_modules/dayjs/plugin/buddhistEra.d.ts +4 -0
  396. package/node_modules/dayjs/plugin/buddhistEra.js +1 -0
  397. package/node_modules/dayjs/plugin/calendar.d.ts +10 -0
  398. package/node_modules/dayjs/plugin/calendar.js +1 -0
  399. package/node_modules/dayjs/plugin/customParseFormat.d.ts +8 -0
  400. package/node_modules/dayjs/plugin/customParseFormat.js +1 -0
  401. package/node_modules/dayjs/plugin/dayOfYear.d.ts +11 -0
  402. package/node_modules/dayjs/plugin/dayOfYear.js +1 -0
  403. package/node_modules/dayjs/plugin/devHelper.d.ts +4 -0
  404. package/node_modules/dayjs/plugin/devHelper.js +1 -0
  405. package/node_modules/dayjs/plugin/duration.d.ts +88 -0
  406. package/node_modules/dayjs/plugin/duration.js +1 -0
  407. package/node_modules/dayjs/plugin/isBetween.d.ts +10 -0
  408. package/node_modules/dayjs/plugin/isBetween.js +1 -0
  409. package/node_modules/dayjs/plugin/isLeapYear.d.ts +10 -0
  410. package/node_modules/dayjs/plugin/isLeapYear.js +1 -0
  411. package/node_modules/dayjs/plugin/isMoment.d.ts +10 -0
  412. package/node_modules/dayjs/plugin/isMoment.js +1 -0
  413. package/node_modules/dayjs/plugin/isSameOrAfter.d.ts +10 -0
  414. package/node_modules/dayjs/plugin/isSameOrAfter.js +1 -0
  415. package/node_modules/dayjs/plugin/isSameOrBefore.d.ts +10 -0
  416. package/node_modules/dayjs/plugin/isSameOrBefore.js +1 -0
  417. package/node_modules/dayjs/plugin/isToday.d.ts +10 -0
  418. package/node_modules/dayjs/plugin/isToday.js +1 -0
  419. package/node_modules/dayjs/plugin/isTomorrow.d.ts +10 -0
  420. package/node_modules/dayjs/plugin/isTomorrow.js +1 -0
  421. package/node_modules/dayjs/plugin/isYesterday.d.ts +10 -0
  422. package/node_modules/dayjs/plugin/isYesterday.js +1 -0
  423. package/node_modules/dayjs/plugin/isoWeek.d.ts +27 -0
  424. package/node_modules/dayjs/plugin/isoWeek.js +1 -0
  425. package/node_modules/dayjs/plugin/isoWeeksInYear.d.ts +10 -0
  426. package/node_modules/dayjs/plugin/isoWeeksInYear.js +1 -0
  427. package/node_modules/dayjs/plugin/localeData.d.ts +44 -0
  428. package/node_modules/dayjs/plugin/localeData.js +1 -0
  429. package/node_modules/dayjs/plugin/localizedFormat.d.ts +4 -0
  430. package/node_modules/dayjs/plugin/localizedFormat.js +1 -0
  431. package/node_modules/dayjs/plugin/minMax.d.ts +22 -0
  432. package/node_modules/dayjs/plugin/minMax.js +1 -0
  433. package/node_modules/dayjs/plugin/negativeYear.d.ts +4 -0
  434. package/node_modules/dayjs/plugin/negativeYear.js +1 -0
  435. package/node_modules/dayjs/plugin/objectSupport.d.ts +48 -0
  436. package/node_modules/dayjs/plugin/objectSupport.js +1 -0
  437. package/node_modules/dayjs/plugin/pluralGetSet.d.ts +44 -0
  438. package/node_modules/dayjs/plugin/pluralGetSet.js +1 -0
  439. package/node_modules/dayjs/plugin/preParsePostFormat.d.ts +4 -0
  440. package/node_modules/dayjs/plugin/preParsePostFormat.js +1 -0
  441. package/node_modules/dayjs/plugin/quarterOfYear.d.ts +26 -0
  442. package/node_modules/dayjs/plugin/quarterOfYear.js +1 -0
  443. package/node_modules/dayjs/plugin/relativeTime.d.ts +24 -0
  444. package/node_modules/dayjs/plugin/relativeTime.js +1 -0
  445. package/node_modules/dayjs/plugin/timezone.d.ts +20 -0
  446. package/node_modules/dayjs/plugin/timezone.js +1 -0
  447. package/node_modules/dayjs/plugin/toArray.d.ts +10 -0
  448. package/node_modules/dayjs/plugin/toArray.js +1 -0
  449. package/node_modules/dayjs/plugin/toObject.d.ts +20 -0
  450. package/node_modules/dayjs/plugin/toObject.js +1 -0
  451. package/node_modules/dayjs/plugin/updateLocale.d.ts +8 -0
  452. package/node_modules/dayjs/plugin/updateLocale.js +1 -0
  453. package/node_modules/dayjs/plugin/utc.d.ts +19 -0
  454. package/node_modules/dayjs/plugin/utc.js +1 -0
  455. package/node_modules/dayjs/plugin/weekOfYear.d.ts +12 -0
  456. package/node_modules/dayjs/plugin/weekOfYear.js +1 -0
  457. package/node_modules/dayjs/plugin/weekYear.d.ts +10 -0
  458. package/node_modules/dayjs/plugin/weekYear.js +1 -0
  459. package/node_modules/dayjs/plugin/weekday.d.ts +12 -0
  460. package/node_modules/dayjs/plugin/weekday.js +1 -0
  461. package/node_modules/deepmerge/.editorconfig +7 -0
  462. package/node_modules/deepmerge/.eslintcache +1 -0
  463. package/node_modules/deepmerge/changelog.md +167 -0
  464. package/node_modules/deepmerge/dist/cjs.js +133 -0
  465. package/node_modules/deepmerge/dist/umd.js +139 -0
  466. package/node_modules/deepmerge/index.d.ts +20 -0
  467. package/node_modules/deepmerge/index.js +106 -0
  468. package/node_modules/deepmerge/license.txt +21 -0
  469. package/node_modules/deepmerge/package.json +42 -0
  470. package/node_modules/deepmerge/readme.md +264 -0
  471. package/node_modules/deepmerge/rollup.config.js +22 -0
  472. package/node_modules/dom-serializer/LICENSE +7 -0
  473. package/node_modules/dom-serializer/README.md +115 -0
  474. package/node_modules/dom-serializer/dist/foreign-names.d.ts +11 -0
  475. package/node_modules/dom-serializer/dist/foreign-names.d.ts.map +1 -0
  476. package/node_modules/dom-serializer/dist/foreign-names.js +15 -0
  477. package/node_modules/dom-serializer/dist/foreign-names.js.map +1 -0
  478. package/node_modules/dom-serializer/dist/index.d.ts +72 -0
  479. package/node_modules/dom-serializer/dist/index.d.ts.map +1 -0
  480. package/node_modules/dom-serializer/dist/index.js +173 -0
  481. package/node_modules/dom-serializer/dist/index.js.map +1 -0
  482. package/node_modules/dom-serializer/package.json +69 -0
  483. package/node_modules/dom-serializer/src/foreign-names.ts +19 -0
  484. package/node_modules/dom-serializer/src/index.ts +315 -0
  485. package/node_modules/domelementtype/LICENSE +11 -0
  486. package/node_modules/domelementtype/dist/index.d.ts +48 -0
  487. package/node_modules/domelementtype/dist/index.d.ts.map +1 -0
  488. package/node_modules/domelementtype/dist/index.js +60 -0
  489. package/node_modules/domelementtype/package.json +59 -0
  490. package/node_modules/domelementtype/readme.md +1 -0
  491. package/node_modules/domhandler/LICENSE +11 -0
  492. package/node_modules/domhandler/dist/index.d.ts +79 -0
  493. package/node_modules/domhandler/dist/index.d.ts.map +1 -0
  494. package/node_modules/domhandler/dist/index.js +155 -0
  495. package/node_modules/domhandler/dist/node.d.ts +264 -0
  496. package/node_modules/domhandler/dist/node.d.ts.map +1 -0
  497. package/node_modules/domhandler/dist/node.js +359 -0
  498. package/node_modules/domhandler/package.json +65 -0
  499. package/node_modules/domhandler/readme.md +86 -0
  500. package/node_modules/domutils/LICENSE +11 -0
  501. package/node_modules/domutils/dist/feeds.d.ts +71 -0
  502. package/node_modules/domutils/dist/feeds.d.ts.map +1 -0
  503. package/node_modules/domutils/dist/feeds.js +180 -0
  504. package/node_modules/domutils/dist/feeds.js.map +1 -0
  505. package/node_modules/domutils/dist/helpers.d.ts +59 -0
  506. package/node_modules/domutils/dist/helpers.d.ts.map +1 -0
  507. package/node_modules/domutils/dist/helpers.js +136 -0
  508. package/node_modules/domutils/dist/helpers.js.map +1 -0
  509. package/node_modules/domutils/dist/index.d.ts +8 -0
  510. package/node_modules/domutils/dist/index.d.ts.map +1 -0
  511. package/node_modules/domutils/dist/index.js +8 -0
  512. package/node_modules/domutils/dist/index.js.map +1 -0
  513. package/node_modules/domutils/dist/legacy.d.ts +79 -0
  514. package/node_modules/domutils/dist/legacy.d.ts.map +1 -0
  515. package/node_modules/domutils/dist/legacy.js +152 -0
  516. package/node_modules/domutils/dist/legacy.js.map +1 -0
  517. package/node_modules/domutils/dist/manipulation.d.ts +49 -0
  518. package/node_modules/domutils/dist/manipulation.d.ts.map +1 -0
  519. package/node_modules/domutils/dist/manipulation.js +138 -0
  520. package/node_modules/domutils/dist/manipulation.js.map +1 -0
  521. package/node_modules/domutils/dist/querying.d.ts +54 -0
  522. package/node_modules/domutils/dist/querying.d.ts.map +1 -0
  523. package/node_modules/domutils/dist/querying.js +129 -0
  524. package/node_modules/domutils/dist/querying.js.map +1 -0
  525. package/node_modules/domutils/dist/stringify.d.ts +46 -0
  526. package/node_modules/domutils/dist/stringify.d.ts.map +1 -0
  527. package/node_modules/domutils/dist/stringify.js +81 -0
  528. package/node_modules/domutils/dist/stringify.js.map +1 -0
  529. package/node_modules/domutils/dist/traversal.d.ts +74 -0
  530. package/node_modules/domutils/dist/traversal.d.ts.map +1 -0
  531. package/node_modules/domutils/dist/traversal.js +105 -0
  532. package/node_modules/domutils/dist/traversal.js.map +1 -0
  533. package/node_modules/domutils/package.json +69 -0
  534. package/node_modules/domutils/readme.md +25 -0
  535. package/node_modules/domutils/src/__snapshots__/feeds.spec.ts.snap +103 -0
  536. package/node_modules/domutils/src/feeds.ts +301 -0
  537. package/node_modules/domutils/src/helpers.ts +154 -0
  538. package/node_modules/domutils/src/index.ts +7 -0
  539. package/node_modules/domutils/src/legacy.ts +224 -0
  540. package/node_modules/domutils/src/manipulation.ts +156 -0
  541. package/node_modules/domutils/src/querying.ts +172 -0
  542. package/node_modules/domutils/src/stringify.ts +90 -0
  543. package/node_modules/domutils/src/traversal.ts +132 -0
  544. package/node_modules/entities/LICENSE +11 -0
  545. package/node_modules/entities/dist/decode-codepoint.d.ts +28 -0
  546. package/node_modules/entities/dist/decode-codepoint.d.ts.map +1 -0
  547. package/node_modules/entities/dist/decode-codepoint.js +61 -0
  548. package/node_modules/entities/dist/decode-codepoint.js.map +1 -0
  549. package/node_modules/entities/dist/decode.d.ts +227 -0
  550. package/node_modules/entities/dist/decode.d.ts.map +1 -0
  551. package/node_modules/entities/dist/decode.js +1132 -0
  552. package/node_modules/entities/dist/decode.js.map +1 -0
  553. package/node_modules/entities/dist/encode.d.ts +26 -0
  554. package/node_modules/entities/dist/encode.d.ts.map +1 -0
  555. package/node_modules/entities/dist/encode.js +295 -0
  556. package/node_modules/entities/dist/encode.js.map +1 -0
  557. package/node_modules/entities/dist/escape.d.ts +60 -0
  558. package/node_modules/entities/dist/escape.d.ts.map +1 -0
  559. package/node_modules/entities/dist/escape.js +172 -0
  560. package/node_modules/entities/dist/escape.js.map +1 -0
  561. package/node_modules/entities/dist/generated/decode-data-html.d.ts +3 -0
  562. package/node_modules/entities/dist/generated/decode-data-html.d.ts.map +1 -0
  563. package/node_modules/entities/dist/generated/decode-data-html.js +5 -0
  564. package/node_modules/entities/dist/generated/decode-data-html.js.map +1 -0
  565. package/node_modules/entities/dist/generated/decode-data-xml.d.ts +3 -0
  566. package/node_modules/entities/dist/generated/decode-data-xml.d.ts.map +1 -0
  567. package/node_modules/entities/dist/generated/decode-data-xml.js +7 -0
  568. package/node_modules/entities/dist/generated/decode-data-xml.js.map +1 -0
  569. package/node_modules/entities/dist/generated/encode-html.d.ts +3 -0
  570. package/node_modules/entities/dist/generated/encode-html.d.ts.map +1 -0
  571. package/node_modules/entities/dist/generated/encode-html.js +3 -0
  572. package/node_modules/entities/dist/generated/encode-html.js.map +1 -0
  573. package/node_modules/entities/dist/index.d.ts +89 -0
  574. package/node_modules/entities/dist/index.d.ts.map +1 -0
  575. package/node_modules/entities/dist/index.js +87 -0
  576. package/node_modules/entities/dist/index.js.map +1 -0
  577. package/node_modules/entities/dist/internal/bin-trie-flags.d.ts +48 -0
  578. package/node_modules/entities/dist/internal/bin-trie-flags.d.ts.map +1 -0
  579. package/node_modules/entities/dist/internal/bin-trie-flags.js +49 -0
  580. package/node_modules/entities/dist/internal/bin-trie-flags.js.map +1 -0
  581. package/node_modules/entities/dist/internal/decode-shared.d.ts +38 -0
  582. package/node_modules/entities/dist/internal/decode-shared.d.ts.map +1 -0
  583. package/node_modules/entities/dist/internal/decode-shared.js +195 -0
  584. package/node_modules/entities/dist/internal/decode-shared.js.map +1 -0
  585. package/node_modules/entities/package.json +83 -0
  586. package/node_modules/entities/readme.md +131 -0
  587. package/node_modules/entities/src/decode-codepoint.ts +69 -0
  588. package/node_modules/entities/src/decode.ts +1368 -0
  589. package/node_modules/entities/src/encode.ts +337 -0
  590. package/node_modules/entities/src/escape.ts +187 -0
  591. package/node_modules/entities/src/generated/decode-data-html.ts +12 -0
  592. package/node_modules/entities/src/generated/decode-data-xml.ts +7 -0
  593. package/node_modules/entities/src/generated/encode-html.ts +3 -0
  594. package/node_modules/entities/src/index.ts +160 -0
  595. package/node_modules/entities/src/internal/bin-trie-flags.ts +47 -0
  596. package/node_modules/entities/src/internal/decode-shared.ts +209 -0
  597. package/node_modules/escape-string-regexp/index.d.ts +18 -0
  598. package/node_modules/escape-string-regexp/index.js +13 -0
  599. package/node_modules/escape-string-regexp/license +9 -0
  600. package/node_modules/escape-string-regexp/package.json +38 -0
  601. package/node_modules/escape-string-regexp/readme.md +34 -0
  602. package/node_modules/express-rate-limit/dist/index.cjs +9 -7
  603. package/node_modules/express-rate-limit/dist/index.mjs +9 -7
  604. package/node_modules/express-rate-limit/package.json +9 -9
  605. package/node_modules/htmlparser2/LICENSE +18 -0
  606. package/node_modules/htmlparser2/README.md +257 -0
  607. package/node_modules/htmlparser2/dist/Parser.d.ts +257 -0
  608. package/node_modules/htmlparser2/dist/Parser.d.ts.map +1 -0
  609. package/node_modules/htmlparser2/dist/Parser.js +644 -0
  610. package/node_modules/htmlparser2/dist/Parser.js.map +1 -0
  611. package/node_modules/htmlparser2/dist/Tokenizer.d.ts +194 -0
  612. package/node_modules/htmlparser2/dist/Tokenizer.d.ts.map +1 -0
  613. package/node_modules/htmlparser2/dist/Tokenizer.js +1056 -0
  614. package/node_modules/htmlparser2/dist/Tokenizer.js.map +1 -0
  615. package/node_modules/htmlparser2/dist/WebWritableStream.d.ts +24 -0
  616. package/node_modules/htmlparser2/dist/WebWritableStream.d.ts.map +1 -0
  617. package/node_modules/htmlparser2/dist/WebWritableStream.js +44 -0
  618. package/node_modules/htmlparser2/dist/WebWritableStream.js.map +1 -0
  619. package/node_modules/htmlparser2/dist/WritableStream.d.ts +14 -0
  620. package/node_modules/htmlparser2/dist/WritableStream.d.ts.map +1 -0
  621. package/node_modules/htmlparser2/dist/WritableStream.js +32 -0
  622. package/node_modules/htmlparser2/dist/WritableStream.js.map +1 -0
  623. package/node_modules/htmlparser2/dist/index.d.ts +34 -0
  624. package/node_modules/htmlparser2/dist/index.d.ts.map +1 -0
  625. package/node_modules/htmlparser2/dist/index.js +46 -0
  626. package/node_modules/htmlparser2/dist/index.js.map +1 -0
  627. package/node_modules/htmlparser2/package.json +86 -0
  628. package/node_modules/htmlparser2/src/Parser.ts +823 -0
  629. package/node_modules/htmlparser2/src/Tokenizer.ts +1150 -0
  630. package/node_modules/htmlparser2/src/WebWritableStream.ts +47 -0
  631. package/node_modules/htmlparser2/src/WritableStream.ts +42 -0
  632. package/node_modules/htmlparser2/src/index.ts +86 -0
  633. package/node_modules/launder/.travis.yml +4 -0
  634. package/node_modules/launder/CHANGELOG.md +80 -0
  635. package/node_modules/launder/LICENSE.md +7 -0
  636. package/node_modules/launder/README.md +177 -0
  637. package/node_modules/launder/eslint.config.js +6 -0
  638. package/node_modules/launder/index.js +538 -0
  639. package/node_modules/launder/logos/logo-box-madefor.png +0 -0
  640. package/node_modules/launder/package.json +38 -0
  641. package/node_modules/launder/test/test.js +775 -0
  642. package/node_modules/nanoid/LICENSE +20 -0
  643. package/node_modules/nanoid/README.md +39 -0
  644. package/node_modules/nanoid/async/index.browser.cjs +43 -0
  645. package/node_modules/nanoid/async/index.browser.js +43 -0
  646. package/node_modules/nanoid/async/index.cjs +47 -0
  647. package/node_modules/nanoid/async/index.d.cts +56 -0
  648. package/node_modules/nanoid/async/index.d.ts +56 -0
  649. package/node_modules/nanoid/async/index.js +47 -0
  650. package/node_modules/nanoid/async/index.native.js +38 -0
  651. package/node_modules/nanoid/async/package.json +12 -0
  652. package/node_modules/nanoid/bin/nanoid.cjs +55 -0
  653. package/node_modules/nanoid/index.browser.cjs +45 -0
  654. package/node_modules/nanoid/index.browser.js +45 -0
  655. package/node_modules/nanoid/index.cjs +63 -0
  656. package/node_modules/nanoid/index.d.cts +91 -0
  657. package/node_modules/nanoid/index.d.ts +91 -0
  658. package/node_modules/nanoid/index.js +63 -0
  659. package/node_modules/nanoid/nanoid.js +1 -0
  660. package/node_modules/nanoid/non-secure/index.cjs +24 -0
  661. package/node_modules/nanoid/non-secure/index.d.ts +33 -0
  662. package/node_modules/nanoid/non-secure/index.js +24 -0
  663. package/node_modules/nanoid/non-secure/package.json +6 -0
  664. package/node_modules/nanoid/package.json +89 -0
  665. package/node_modules/nanoid/url-alphabet/index.cjs +4 -0
  666. package/node_modules/nanoid/url-alphabet/index.js +4 -0
  667. package/node_modules/nanoid/url-alphabet/package.json +6 -0
  668. package/node_modules/parse-srcset/.jscs.json +83 -0
  669. package/node_modules/parse-srcset/.jshintrc +15 -0
  670. package/node_modules/parse-srcset/.npmignore +8 -0
  671. package/node_modules/parse-srcset/LICENSE +22 -0
  672. package/node_modules/parse-srcset/README.md +19 -0
  673. package/node_modules/parse-srcset/package.json +25 -0
  674. package/node_modules/parse-srcset/src/parse-srcset.js +330 -0
  675. package/node_modules/parse-srcset/tests/he.js +329 -0
  676. package/node_modules/parse-srcset/tests/intern.js +74 -0
  677. package/node_modules/parse-srcset/tests/unit/ps.js +345 -0
  678. package/node_modules/picocolors/LICENSE +15 -0
  679. package/node_modules/picocolors/README.md +21 -0
  680. package/node_modules/picocolors/package.json +25 -0
  681. package/node_modules/picocolors/picocolors.browser.js +4 -0
  682. package/node_modules/picocolors/picocolors.d.ts +5 -0
  683. package/node_modules/picocolors/picocolors.js +75 -0
  684. package/node_modules/picocolors/types.d.ts +51 -0
  685. package/node_modules/postcss/LICENSE +20 -0
  686. package/node_modules/postcss/README.md +27 -0
  687. package/node_modules/postcss/lib/at-rule.d.ts +139 -0
  688. package/node_modules/postcss/lib/at-rule.js +25 -0
  689. package/node_modules/postcss/lib/comment.d.ts +67 -0
  690. package/node_modules/postcss/lib/comment.js +13 -0
  691. package/node_modules/postcss/lib/container.d.ts +474 -0
  692. package/node_modules/postcss/lib/container.js +494 -0
  693. package/node_modules/postcss/lib/css-syntax-error.d.ts +247 -0
  694. package/node_modules/postcss/lib/css-syntax-error.js +133 -0
  695. package/node_modules/postcss/lib/declaration.d.ts +150 -0
  696. package/node_modules/postcss/lib/declaration.js +24 -0
  697. package/node_modules/postcss/lib/document.d.ts +68 -0
  698. package/node_modules/postcss/lib/document.js +33 -0
  699. package/node_modules/postcss/lib/fromJSON.d.ts +9 -0
  700. package/node_modules/postcss/lib/fromJSON.js +107 -0
  701. package/node_modules/postcss/lib/input.d.ts +226 -0
  702. package/node_modules/postcss/lib/input.js +282 -0
  703. package/node_modules/postcss/lib/lazy-result.d.ts +189 -0
  704. package/node_modules/postcss/lib/lazy-result.js +626 -0
  705. package/node_modules/postcss/lib/list.d.ts +60 -0
  706. package/node_modules/postcss/lib/list.js +79 -0
  707. package/node_modules/postcss/lib/map-generator.js +383 -0
  708. package/node_modules/postcss/lib/no-work-result.d.ts +45 -0
  709. package/node_modules/postcss/lib/no-work-result.js +137 -0
  710. package/node_modules/postcss/lib/node.d.ts +555 -0
  711. package/node_modules/postcss/lib/node.js +494 -0
  712. package/node_modules/postcss/lib/parse.d.ts +9 -0
  713. package/node_modules/postcss/lib/parse.js +42 -0
  714. package/node_modules/postcss/lib/parser.js +626 -0
  715. package/node_modules/postcss/lib/postcss.d.mts +66 -0
  716. package/node_modules/postcss/lib/postcss.d.ts +464 -0
  717. package/node_modules/postcss/lib/postcss.js +101 -0
  718. package/node_modules/postcss/lib/postcss.mjs +30 -0
  719. package/node_modules/postcss/lib/previous-map.d.ts +80 -0
  720. package/node_modules/postcss/lib/previous-map.js +176 -0
  721. package/node_modules/postcss/lib/processor.d.ts +114 -0
  722. package/node_modules/postcss/lib/processor.js +67 -0
  723. package/node_modules/postcss/lib/result.d.ts +204 -0
  724. package/node_modules/postcss/lib/result.js +42 -0
  725. package/node_modules/postcss/lib/root.d.ts +86 -0
  726. package/node_modules/postcss/lib/root.js +76 -0
  727. package/node_modules/postcss/lib/rule.d.ts +126 -0
  728. package/node_modules/postcss/lib/rule.js +27 -0
  729. package/node_modules/postcss/lib/stringifier.d.ts +45 -0
  730. package/node_modules/postcss/lib/stringifier.js +457 -0
  731. package/node_modules/postcss/lib/stringify.d.ts +9 -0
  732. package/node_modules/postcss/lib/stringify.js +69 -0
  733. package/node_modules/postcss/lib/symbols.js +5 -0
  734. package/node_modules/postcss/lib/terminal-highlight.js +70 -0
  735. package/node_modules/postcss/lib/tokenize.js +270 -0
  736. package/node_modules/postcss/lib/warn-once.js +13 -0
  737. package/node_modules/postcss/lib/warning.d.ts +146 -0
  738. package/node_modules/postcss/lib/warning.js +47 -0
  739. package/node_modules/postcss/package.json +88 -0
  740. package/node_modules/sanitize-html/LICENSE +7 -0
  741. package/node_modules/sanitize-html/README.md +877 -0
  742. package/node_modules/sanitize-html/index.js +1255 -0
  743. package/node_modules/sanitize-html/package.json +49 -0
  744. package/node_modules/source-map-js/LICENSE +28 -0
  745. package/node_modules/source-map-js/README.md +765 -0
  746. package/node_modules/source-map-js/lib/array-set.js +121 -0
  747. package/node_modules/source-map-js/lib/base64-vlq.js +140 -0
  748. package/node_modules/source-map-js/lib/base64.js +67 -0
  749. package/node_modules/source-map-js/lib/binary-search.js +111 -0
  750. package/node_modules/source-map-js/lib/mapping-list.js +79 -0
  751. package/node_modules/source-map-js/lib/quick-sort.js +141 -0
  752. package/node_modules/source-map-js/lib/source-map-consumer.d.ts +1 -0
  753. package/node_modules/source-map-js/lib/source-map-consumer.js +1236 -0
  754. package/node_modules/source-map-js/lib/source-map-generator.d.ts +1 -0
  755. package/node_modules/source-map-js/lib/source-map-generator.js +446 -0
  756. package/node_modules/source-map-js/lib/source-node.d.ts +1 -0
  757. package/node_modules/source-map-js/lib/source-node.js +420 -0
  758. package/node_modules/source-map-js/lib/util.js +594 -0
  759. package/node_modules/source-map-js/package.json +71 -0
  760. package/node_modules/source-map-js/source-map.d.ts +104 -0
  761. package/node_modules/source-map-js/source-map.js +8 -0
  762. package/package.json +5 -1
  763. package/dist/ui/assets/index-BKgX8_Zh.js +0 -111
@@ -1,4 +1,22 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ METRIC_LABELS,
4
+ fingerprintOf,
5
+ formatActionLabel,
6
+ formatCurrency,
7
+ formatDateTime,
8
+ formatDuration,
9
+ formatMetricValue,
10
+ parseCaseAttrs,
11
+ parseElements,
12
+ parseTimestampSeconds,
13
+ profileShortLabel,
14
+ readPairing,
15
+ resolveApprovalElement,
16
+ resolveCaseElement,
17
+ resolveMandateElement,
18
+ resolveTicketElement
19
+ } from "./chunk-JUFH4SKS.mjs";
2
20
 
3
21
  // bin/http.ts
4
22
  import { randomUUID as randomUUID2 } from "crypto";
@@ -112,42 +130,13 @@ function clientVersionHeaders() {
112
130
  };
113
131
  }
114
132
 
115
- // src/lib/as-pairing.ts
116
- import { createHash } from "crypto";
117
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, unlinkSync, writeFileSync } from "fs";
118
- import { dirname, join as join2 } from "path";
119
- function pairingPath(dataDir2) {
120
- return join2(dataDir2, "as-pairing.json");
121
- }
122
- function readPairing(dataDir2) {
123
- const path = pairingPath(dataDir2);
124
- if (!existsSync2(path)) return null;
125
- try {
126
- const data = JSON.parse(readFileSync2(path, "utf-8"));
127
- if (typeof data.asUrl !== "string" || typeof data.publicKeyHex !== "string") return null;
128
- return {
129
- asUrl: data.asUrl,
130
- publicKeyHex: data.publicKeyHex,
131
- pairedAt: data.pairedAt ?? "",
132
- ...typeof data.tlsSpkiPinHex === "string" ? { tlsSpkiPinHex: data.tlsSpkiPinHex } : {}
133
- };
134
- } catch {
135
- return null;
136
- }
137
- }
138
- function fingerprintOf(publicKeyHex) {
139
- const raw = Buffer.from(publicKeyHex, "hex");
140
- const digest = createHash("sha256").update(raw).digest("hex").toUpperCase();
141
- return digest.match(/.{1,4}/g)?.join(":") ?? digest;
142
- }
143
-
144
133
  // src/lib/as-config.ts
145
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
146
- import { dirname as dirname2, join as join4 } from "path";
134
+ import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync } from "fs";
135
+ import { dirname, join as join3 } from "path";
147
136
 
148
137
  // src/lib/policy.ts
149
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
150
- import { join as join3 } from "path";
138
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
139
+ import { join as join2 } from "path";
151
140
  import { spawnSync } from "child_process";
152
141
  var POLICY_KEYS = ["AsUrl", "CaFile", "PinTls", "Proxy", "NoProxy", "Simulation", "InstallMethod"];
153
142
  var DEFAULT_REGISTRY_BASE_KEY = "SOFTWARE\\Policies\\Suveren\\Gateway";
@@ -182,7 +171,7 @@ function validateAsUrl(candidate) {
182
171
  function validateCaFile(candidate) {
183
172
  const trimmed = candidate.trim();
184
173
  if (!trimmed) return { ok: false, error: "The CA file path is empty." };
185
- if (!existsSync3(trimmed)) return { ok: false, error: `No file at "${trimmed}".` };
174
+ if (!existsSync2(trimmed)) return { ok: false, error: `No file at "${trimmed}".` };
186
175
  return { ok: true, path: trimmed };
187
176
  }
188
177
  function validateProxyUrl(candidate) {
@@ -248,7 +237,7 @@ function policyFilePath() {
248
237
  if (process.env.SUVEREN_POLICY_FILE) return process.env.SUVEREN_POLICY_FILE;
249
238
  if (process.platform === "win32") {
250
239
  const programData = process.env.ProgramData || process.env.PROGRAMDATA || "C:\\ProgramData";
251
- return join3(programData, "Suveren", "gateway-policy.json");
240
+ return join2(programData, "Suveren", "gateway-policy.json");
252
241
  }
253
242
  if (process.platform === "darwin") {
254
243
  return "/Library/Application Support/Suveren/gateway-policy.json";
@@ -258,10 +247,10 @@ function policyFilePath() {
258
247
  function readPolicyFile() {
259
248
  const path = policyFilePath();
260
249
  const source = `the policy file (${path})`;
261
- if (!existsSync3(path)) return { values: {}, source };
250
+ if (!existsSync2(path)) return { values: {}, source };
262
251
  let data;
263
252
  try {
264
- data = JSON.parse(readFileSync3(path, "utf8"));
253
+ data = JSON.parse(readFileSync2(path, "utf8"));
265
254
  } catch (err) {
266
255
  throw new Error(`Could not parse policy file ${path}: ${err instanceof Error ? err.message : String(err)}`);
267
256
  }
@@ -365,14 +354,14 @@ function readPolicy() {
365
354
  // src/lib/as-config.ts
366
355
  var DEFAULT_AS_URL = "https://www.suveren.ai";
367
356
  function configPath(dataDir2) {
368
- return join4(dataDir2, "config.json");
357
+ return join3(dataDir2, "config.json");
369
358
  }
370
359
  function readAsConfigStrict(dataDir2) {
371
360
  const path = configPath(dataDir2);
372
- if (!existsSync4(path)) return {};
361
+ if (!existsSync3(path)) return {};
373
362
  let data;
374
363
  try {
375
- data = JSON.parse(readFileSync4(path, "utf-8"));
364
+ data = JSON.parse(readFileSync3(path, "utf-8"));
376
365
  } catch (err) {
377
366
  throw new Error(
378
367
  `Could not parse ${path}: ${err instanceof Error ? err.message : String(err)}`
@@ -387,9 +376,9 @@ function readAsConfigStrict(dataDir2) {
387
376
  }
388
377
  function readAsConfig(dataDir2) {
389
378
  const path = configPath(dataDir2);
390
- if (!existsSync4(path)) return {};
379
+ if (!existsSync3(path)) return {};
391
380
  try {
392
- const data = JSON.parse(readFileSync4(path, "utf-8"));
381
+ const data = JSON.parse(readFileSync3(path, "utf-8"));
393
382
  const out = {};
394
383
  if (typeof data.asUrl === "string") out.asUrl = data.asUrl;
395
384
  if (typeof data.caFile === "string") out.caFile = data.caFile;
@@ -461,10 +450,10 @@ function validatePinTlsForUrl(pinTls, asUrl) {
461
450
  }
462
451
 
463
452
  // src/lib/as-tls-pin.ts
464
- import { createHash as createHash2 } from "crypto";
453
+ import { createHash } from "crypto";
465
454
  import { checkServerIdentity as defaultCheckServerIdentity, rootCertificates } from "tls";
466
455
  import { Agent as HttpsAgent2 } from "https";
467
- import { readFileSync as readFileSync5 } from "fs";
456
+ import { readFileSync as readFileSync4 } from "fs";
468
457
  import { Agent, ProxyAgent, fetch as undiciFetch } from "undici";
469
458
 
470
459
  // src/lib/proxy-env.ts
@@ -514,7 +503,7 @@ function effectiveCa() {
514
503
  const path = process.env.NODE_EXTRA_CA_CERTS;
515
504
  if (!path) return void 0;
516
505
  try {
517
- return [...rootCertificates, readFileSync5(path, "utf-8")];
506
+ return [...rootCertificates, readFileSync4(path, "utf-8")];
518
507
  } catch {
519
508
  return void 0;
520
509
  }
@@ -542,7 +531,7 @@ function spkiSha256Hex(cert) {
542
531
  if (!cert.pubkey) {
543
532
  throw new Error("peer certificate carries no pubkey (expected the detailed certificate object)");
544
533
  }
545
- return createHash2("sha256").update(cert.pubkey).digest("hex");
534
+ return createHash("sha256").update(cert.pubkey).digest("hex");
546
535
  }
547
536
  function formatPinFingerprint(hex) {
548
537
  const upper = hex.toUpperCase();
@@ -1148,18 +1137,18 @@ var AttestationCache = class {
1148
1137
  };
1149
1138
 
1150
1139
  // src/lib/gate-store.ts
1151
- import { mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync3, existsSync as existsSync5, unlinkSync as unlinkSync2 } from "fs";
1140
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync2, existsSync as existsSync4, unlinkSync } from "fs";
1152
1141
  import { homedir } from "os";
1153
- import { dirname as dirname3, join as join5 } from "path";
1142
+ import { dirname as dirname2, join as join4 } from "path";
1154
1143
  import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
1155
- var DEFAULT_DIR = process.env.SUVEREN_DATA_DIR ?? join5(homedir(), ".suveren");
1144
+ var DEFAULT_DIR = process.env.SUVEREN_DATA_DIR ?? join4(homedir(), ".suveren");
1156
1145
  var GateStore = class {
1157
1146
  entries = /* @__PURE__ */ new Map();
1158
1147
  baseDir;
1159
1148
  vaultKey = null;
1160
1149
  constructor(filePath) {
1161
1150
  if (filePath && filePath.endsWith(".json")) {
1162
- this.baseDir = dirname3(filePath);
1151
+ this.baseDir = dirname2(filePath);
1163
1152
  } else {
1164
1153
  this.baseDir = filePath ?? DEFAULT_DIR;
1165
1154
  }
@@ -1170,13 +1159,13 @@ var GateStore = class {
1170
1159
  */
1171
1160
  setVaultKey(key) {
1172
1161
  this.vaultKey = key;
1173
- if (existsSync5(this.encryptedFilePath)) {
1162
+ if (existsSync4(this.encryptedFilePath)) {
1174
1163
  this.loadEncrypted();
1175
1164
  } else if (this.entries.size > 0) {
1176
1165
  this.persistEncrypted();
1177
- if (existsSync5(this.plaintextFilePath)) {
1166
+ if (existsSync4(this.plaintextFilePath)) {
1178
1167
  try {
1179
- unlinkSync2(this.plaintextFilePath);
1168
+ unlinkSync(this.plaintextFilePath);
1180
1169
  } catch {
1181
1170
  }
1182
1171
  }
@@ -1212,11 +1201,11 @@ var GateStore = class {
1212
1201
  clearAll() {
1213
1202
  this.entries = /* @__PURE__ */ new Map();
1214
1203
  try {
1215
- if (existsSync5(this.plaintextFilePath)) unlinkSync2(this.plaintextFilePath);
1204
+ if (existsSync4(this.plaintextFilePath)) unlinkSync(this.plaintextFilePath);
1216
1205
  } catch {
1217
1206
  }
1218
1207
  try {
1219
- if (existsSync5(this.encryptedFilePath)) unlinkSync2(this.encryptedFilePath);
1208
+ if (existsSync4(this.encryptedFilePath)) unlinkSync(this.encryptedFilePath);
1220
1209
  } catch {
1221
1210
  }
1222
1211
  }
@@ -1249,19 +1238,19 @@ var GateStore = class {
1249
1238
  }
1250
1239
  // ─── File paths ─────────────────────────────────────────────────────────
1251
1240
  get plaintextFilePath() {
1252
- return join5(this.baseDir, "gates.json");
1241
+ return join4(this.baseDir, "gates.json");
1253
1242
  }
1254
1243
  get encryptedFilePath() {
1255
- return join5(this.baseDir, "gates.enc.json");
1244
+ return join4(this.baseDir, "gates.enc.json");
1256
1245
  }
1257
1246
  // ─── Load / Persist ─────────────────────────────────────────────────────
1258
1247
  loadPlaintext() {
1259
- if (!existsSync5(this.plaintextFilePath)) {
1260
- mkdirSync3(this.baseDir, { recursive: true });
1248
+ if (!existsSync4(this.plaintextFilePath)) {
1249
+ mkdirSync2(this.baseDir, { recursive: true });
1261
1250
  return;
1262
1251
  }
1263
1252
  try {
1264
- const raw = readFileSync6(this.plaintextFilePath, "utf-8");
1253
+ const raw = readFileSync5(this.plaintextFilePath, "utf-8");
1265
1254
  const data = JSON.parse(raw);
1266
1255
  this.entries = new Map(Object.entries(data.entries));
1267
1256
  } catch {
@@ -1270,9 +1259,9 @@ var GateStore = class {
1270
1259
  }
1271
1260
  }
1272
1261
  loadEncrypted() {
1273
- if (!existsSync5(this.encryptedFilePath)) return;
1262
+ if (!existsSync4(this.encryptedFilePath)) return;
1274
1263
  try {
1275
- const raw = readFileSync6(this.encryptedFilePath, "utf-8");
1264
+ const raw = readFileSync5(this.encryptedFilePath, "utf-8");
1276
1265
  const data = JSON.parse(raw);
1277
1266
  this.entries = /* @__PURE__ */ new Map();
1278
1267
  for (const [key, blob] of Object.entries(data.entries)) {
@@ -1296,8 +1285,8 @@ var GateStore = class {
1296
1285
  version: 1,
1297
1286
  entries: Object.fromEntries(this.entries)
1298
1287
  };
1299
- mkdirSync3(this.baseDir, { recursive: true, mode: 448 });
1300
- writeFileSync3(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1288
+ mkdirSync2(this.baseDir, { recursive: true, mode: 448 });
1289
+ writeFileSync2(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1301
1290
  }
1302
1291
  persistEncrypted() {
1303
1292
  const data = {
@@ -1307,17 +1296,17 @@ var GateStore = class {
1307
1296
  for (const [key, entry] of this.entries) {
1308
1297
  data.entries[key] = this.encrypt(JSON.stringify(entry));
1309
1298
  }
1310
- mkdirSync3(this.baseDir, { recursive: true, mode: 448 });
1311
- writeFileSync3(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1299
+ mkdirSync2(this.baseDir, { recursive: true, mode: 448 });
1300
+ writeFileSync2(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1312
1301
  }
1313
1302
  };
1314
1303
 
1315
1304
  // src/lib/execution-log.ts
1316
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync4, existsSync as existsSync6, unlinkSync as unlinkSync3 } from "fs";
1305
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync3, existsSync as existsSync5, unlinkSync as unlinkSync2 } from "fs";
1317
1306
  import { homedir as homedir2 } from "os";
1318
- import { dirname as dirname4, join as join6 } from "path";
1307
+ import { dirname as dirname3, join as join5 } from "path";
1319
1308
  import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes2 } from "crypto";
1320
- var DEFAULT_DIR2 = process.env.SUVEREN_DATA_DIR ?? join6(homedir2(), ".suveren");
1309
+ var DEFAULT_DIR2 = process.env.SUVEREN_DATA_DIR ?? join5(homedir2(), ".suveren");
1321
1310
  var MAX_AGE_SECONDS = 31 * 24 * 60 * 60;
1322
1311
  var ExecutionLog = class {
1323
1312
  entries = [];
@@ -1325,7 +1314,7 @@ var ExecutionLog = class {
1325
1314
  vaultKey = null;
1326
1315
  constructor(filePath) {
1327
1316
  if (filePath && filePath.endsWith(".json")) {
1328
- this.baseDir = dirname4(filePath);
1317
+ this.baseDir = dirname3(filePath);
1329
1318
  } else {
1330
1319
  this.baseDir = filePath ?? DEFAULT_DIR2;
1331
1320
  }
@@ -1336,13 +1325,13 @@ var ExecutionLog = class {
1336
1325
  */
1337
1326
  setVaultKey(key) {
1338
1327
  this.vaultKey = key;
1339
- if (existsSync6(this.encryptedFilePath)) {
1328
+ if (existsSync5(this.encryptedFilePath)) {
1340
1329
  this.loadEncrypted();
1341
1330
  } else if (this.entries.length > 0) {
1342
1331
  this.persistEncrypted();
1343
- if (existsSync6(this.plaintextFilePath)) {
1332
+ if (existsSync5(this.plaintextFilePath)) {
1344
1333
  try {
1345
- unlinkSync3(this.plaintextFilePath);
1334
+ unlinkSync2(this.plaintextFilePath);
1346
1335
  } catch {
1347
1336
  }
1348
1337
  }
@@ -1444,19 +1433,19 @@ var ExecutionLog = class {
1444
1433
  }
1445
1434
  // ─── File paths ─────────────────────────────────────────────────────────
1446
1435
  get plaintextFilePath() {
1447
- return join6(this.baseDir, "execution-log.json");
1436
+ return join5(this.baseDir, "execution-log.json");
1448
1437
  }
1449
1438
  get encryptedFilePath() {
1450
- return join6(this.baseDir, "execution-log.enc.json");
1439
+ return join5(this.baseDir, "execution-log.enc.json");
1451
1440
  }
1452
1441
  // ─── Load / Persist ─────────────────────────────────────────────────────
1453
1442
  loadPlaintext() {
1454
- if (!existsSync6(this.plaintextFilePath)) {
1455
- mkdirSync4(this.baseDir, { recursive: true });
1443
+ if (!existsSync5(this.plaintextFilePath)) {
1444
+ mkdirSync3(this.baseDir, { recursive: true });
1456
1445
  return;
1457
1446
  }
1458
1447
  try {
1459
- const raw = readFileSync7(this.plaintextFilePath, "utf-8");
1448
+ const raw = readFileSync6(this.plaintextFilePath, "utf-8");
1460
1449
  const data = JSON.parse(raw);
1461
1450
  this.entries = data.entries;
1462
1451
  this.prune();
@@ -1466,9 +1455,9 @@ var ExecutionLog = class {
1466
1455
  }
1467
1456
  }
1468
1457
  loadEncrypted() {
1469
- if (!existsSync6(this.encryptedFilePath)) return;
1458
+ if (!existsSync5(this.encryptedFilePath)) return;
1470
1459
  try {
1471
- const raw = readFileSync7(this.encryptedFilePath, "utf-8");
1460
+ const raw = readFileSync6(this.encryptedFilePath, "utf-8");
1472
1461
  const data = JSON.parse(raw);
1473
1462
  const decrypted = this.decrypt(data.blob);
1474
1463
  const logFile = JSON.parse(decrypted);
@@ -1488,8 +1477,8 @@ var ExecutionLog = class {
1488
1477
  }
1489
1478
  persistPlaintext() {
1490
1479
  const data = { version: 1, entries: this.entries };
1491
- mkdirSync4(this.baseDir, { recursive: true, mode: 448 });
1492
- writeFileSync4(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1480
+ mkdirSync3(this.baseDir, { recursive: true, mode: 448 });
1481
+ writeFileSync3(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1493
1482
  }
1494
1483
  persistEncrypted() {
1495
1484
  const logFile = { version: 1, entries: this.entries };
@@ -1497,8 +1486,8 @@ var ExecutionLog = class {
1497
1486
  version: 1,
1498
1487
  blob: this.encrypt(JSON.stringify(logFile))
1499
1488
  };
1500
- mkdirSync4(this.baseDir, { recursive: true, mode: 448 });
1501
- writeFileSync4(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1489
+ mkdirSync3(this.baseDir, { recursive: true, mode: 448 });
1490
+ writeFileSync3(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1502
1491
  }
1503
1492
  };
1504
1493
  function windowCutoff(window, now) {
@@ -1515,11 +1504,11 @@ function windowCutoff(window, now) {
1515
1504
  }
1516
1505
 
1517
1506
  // src/lib/denial-log.ts
1518
- import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync5, existsSync as existsSync7, unlinkSync as unlinkSync4 } from "fs";
1507
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync4, existsSync as existsSync6, unlinkSync as unlinkSync3 } from "fs";
1519
1508
  import { homedir as homedir3 } from "os";
1520
- import { dirname as dirname5, join as join7 } from "path";
1509
+ import { dirname as dirname4, join as join6 } from "path";
1521
1510
  import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes3 } from "crypto";
1522
- var DEFAULT_DIR3 = process.env.SUVEREN_DATA_DIR ?? join7(homedir3(), ".suveren");
1511
+ var DEFAULT_DIR3 = process.env.SUVEREN_DATA_DIR ?? join6(homedir3(), ".suveren");
1523
1512
  var MAX_RECORDS = 200;
1524
1513
  var MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
1525
1514
  var DenialLog = class {
@@ -1527,18 +1516,18 @@ var DenialLog = class {
1527
1516
  baseDir;
1528
1517
  vaultKey = null;
1529
1518
  constructor(filePath) {
1530
- this.baseDir = filePath && filePath.endsWith(".json") ? dirname5(filePath) : filePath ?? DEFAULT_DIR3;
1519
+ this.baseDir = filePath && filePath.endsWith(".json") ? dirname4(filePath) : filePath ?? DEFAULT_DIR3;
1531
1520
  this.loadPlaintext();
1532
1521
  }
1533
1522
  setVaultKey(key) {
1534
1523
  this.vaultKey = key;
1535
- if (existsSync7(this.encryptedFilePath)) {
1524
+ if (existsSync6(this.encryptedFilePath)) {
1536
1525
  this.loadEncrypted();
1537
1526
  } else if (this.records.length > 0) {
1538
1527
  this.persistEncrypted();
1539
- if (existsSync7(this.plaintextFilePath)) {
1528
+ if (existsSync6(this.plaintextFilePath)) {
1540
1529
  try {
1541
- unlinkSync4(this.plaintextFilePath);
1530
+ unlinkSync3(this.plaintextFilePath);
1542
1531
  } catch {
1543
1532
  }
1544
1533
  }
@@ -1586,18 +1575,18 @@ var DenialLog = class {
1586
1575
  return Buffer.concat([decipher.update(Buffer.from(blob.ciphertext, "hex")), decipher.final()]).toString("utf8");
1587
1576
  }
1588
1577
  get plaintextFilePath() {
1589
- return join7(this.baseDir, "denials.json");
1578
+ return join6(this.baseDir, "denials.json");
1590
1579
  }
1591
1580
  get encryptedFilePath() {
1592
- return join7(this.baseDir, "denials.enc.json");
1581
+ return join6(this.baseDir, "denials.enc.json");
1593
1582
  }
1594
1583
  loadPlaintext() {
1595
- if (!existsSync7(this.plaintextFilePath)) {
1596
- mkdirSync5(this.baseDir, { recursive: true });
1584
+ if (!existsSync6(this.plaintextFilePath)) {
1585
+ mkdirSync4(this.baseDir, { recursive: true });
1597
1586
  return;
1598
1587
  }
1599
1588
  try {
1600
- const data = JSON.parse(readFileSync8(this.plaintextFilePath, "utf-8"));
1589
+ const data = JSON.parse(readFileSync7(this.plaintextFilePath, "utf-8"));
1601
1590
  this.records = data.records ?? [];
1602
1591
  } catch {
1603
1592
  console.error(`[DenialLog] Could not parse ${this.plaintextFilePath}, starting fresh`);
@@ -1605,9 +1594,9 @@ var DenialLog = class {
1605
1594
  }
1606
1595
  }
1607
1596
  loadEncrypted() {
1608
- if (!existsSync7(this.encryptedFilePath)) return;
1597
+ if (!existsSync6(this.encryptedFilePath)) return;
1609
1598
  try {
1610
- const data = JSON.parse(readFileSync8(this.encryptedFilePath, "utf-8"));
1599
+ const data = JSON.parse(readFileSync7(this.encryptedFilePath, "utf-8"));
1611
1600
  const logFile = JSON.parse(this.decrypt(data.blob));
1612
1601
  this.records = logFile.records ?? [];
1613
1602
  } catch (err) {
@@ -1621,23 +1610,23 @@ var DenialLog = class {
1621
1610
  }
1622
1611
  persistPlaintext() {
1623
1612
  const data = { version: 1, records: this.records };
1624
- mkdirSync5(this.baseDir, { recursive: true, mode: 448 });
1625
- writeFileSync5(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1613
+ mkdirSync4(this.baseDir, { recursive: true, mode: 448 });
1614
+ writeFileSync4(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1626
1615
  }
1627
1616
  persistEncrypted() {
1628
1617
  const logFile = { version: 1, records: this.records };
1629
1618
  const data = { version: 1, blob: this.encrypt(JSON.stringify(logFile)) };
1630
- mkdirSync5(this.baseDir, { recursive: true, mode: 448 });
1631
- writeFileSync5(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1619
+ mkdirSync4(this.baseDir, { recursive: true, mode: 448 });
1620
+ writeFileSync4(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1632
1621
  }
1633
1622
  };
1634
1623
 
1635
1624
  // src/lib/receipt-archive.ts
1636
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync6, existsSync as existsSync8, unlinkSync as unlinkSync5 } from "fs";
1625
+ import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync5, existsSync as existsSync7, unlinkSync as unlinkSync4 } from "fs";
1637
1626
  import { homedir as homedir4 } from "os";
1638
- import { dirname as dirname6, join as join8 } from "path";
1627
+ import { dirname as dirname5, join as join7 } from "path";
1639
1628
  import { createCipheriv as createCipheriv4, createDecipheriv as createDecipheriv4, randomBytes as randomBytes4 } from "crypto";
1640
- var DEFAULT_DIR4 = process.env.SUVEREN_DATA_DIR ?? join8(homedir4(), ".suveren");
1629
+ var DEFAULT_DIR4 = process.env.SUVEREN_DATA_DIR ?? join7(homedir4(), ".suveren");
1641
1630
  function stripPreviews(proposal) {
1642
1631
  const args = proposal.toolArgs;
1643
1632
  if (!args || typeof args !== "object") return proposal;
@@ -1651,7 +1640,7 @@ var ReceiptArchive = class {
1651
1640
  vaultKey = null;
1652
1641
  constructor(filePath) {
1653
1642
  if (filePath && filePath.endsWith(".json")) {
1654
- this.baseDir = dirname6(filePath);
1643
+ this.baseDir = dirname5(filePath);
1655
1644
  } else {
1656
1645
  this.baseDir = filePath ?? DEFAULT_DIR4;
1657
1646
  }
@@ -1662,13 +1651,13 @@ var ReceiptArchive = class {
1662
1651
  */
1663
1652
  setVaultKey(key) {
1664
1653
  this.vaultKey = key;
1665
- if (existsSync8(this.encryptedFilePath)) {
1654
+ if (existsSync7(this.encryptedFilePath)) {
1666
1655
  this.loadEncrypted();
1667
1656
  } else if (this.data.receipts.length > 0 || Object.keys(this.data.authorizations).length > 0) {
1668
1657
  this.persistEncrypted();
1669
- if (existsSync8(this.plaintextFilePath)) {
1658
+ if (existsSync7(this.plaintextFilePath)) {
1670
1659
  try {
1671
- unlinkSync5(this.plaintextFilePath);
1660
+ unlinkSync4(this.plaintextFilePath);
1672
1661
  } catch {
1673
1662
  }
1674
1663
  }
@@ -1680,7 +1669,7 @@ var ReceiptArchive = class {
1680
1669
  * this state — that would report a hollow success over unreadable evidence.
1681
1670
  */
1682
1671
  isLocked() {
1683
- return this.vaultKey === null && existsSync8(this.encryptedFilePath);
1672
+ return this.vaultKey === null && existsSync7(this.encryptedFilePath);
1684
1673
  }
1685
1674
  /**
1686
1675
  * Archive a signed receipt (and the grant it was issued under).
@@ -1688,8 +1677,8 @@ var ReceiptArchive = class {
1688
1677
  */
1689
1678
  record(entry, now = Math.floor(Date.now() / 1e3)) {
1690
1679
  let changed = false;
1691
- const receiptId = typeof entry.receipt?.id === "string" ? entry.receipt.id : void 0;
1692
- const alreadyArchived = receiptId !== void 0 && this.data.receipts.some((r) => r.receipt.id === receiptId);
1680
+ const receiptId2 = typeof entry.receipt?.id === "string" ? entry.receipt.id : void 0;
1681
+ const alreadyArchived = receiptId2 !== void 0 && this.data.receipts.some((r) => r.receipt.id === receiptId2);
1693
1682
  if (!alreadyArchived) {
1694
1683
  this.data.receipts.push({
1695
1684
  archivedAt: now,
@@ -1781,19 +1770,19 @@ var ReceiptArchive = class {
1781
1770
  }
1782
1771
  // ─── File paths ─────────────────────────────────────────────────────────
1783
1772
  get plaintextFilePath() {
1784
- return join8(this.baseDir, "receipt-archive.json");
1773
+ return join7(this.baseDir, "receipt-archive.json");
1785
1774
  }
1786
1775
  get encryptedFilePath() {
1787
- return join8(this.baseDir, "receipt-archive.enc.json");
1776
+ return join7(this.baseDir, "receipt-archive.enc.json");
1788
1777
  }
1789
1778
  // ─── Load / Persist ─────────────────────────────────────────────────────
1790
1779
  loadPlaintext() {
1791
- if (!existsSync8(this.plaintextFilePath)) {
1792
- mkdirSync6(this.baseDir, { recursive: true });
1780
+ if (!existsSync7(this.plaintextFilePath)) {
1781
+ mkdirSync5(this.baseDir, { recursive: true });
1793
1782
  return;
1794
1783
  }
1795
1784
  try {
1796
- const raw = readFileSync9(this.plaintextFilePath, "utf-8");
1785
+ const raw = readFileSync8(this.plaintextFilePath, "utf-8");
1797
1786
  const parsed = JSON.parse(raw);
1798
1787
  this.data = {
1799
1788
  version: 1,
@@ -1803,18 +1792,18 @@ var ReceiptArchive = class {
1803
1792
  } catch {
1804
1793
  console.error(`[ReceiptArchive] Could not parse ${this.plaintextFilePath} \u2014 preserving as .corrupt`);
1805
1794
  try {
1806
- writeFileSync6(
1795
+ writeFileSync5(
1807
1796
  `${this.plaintextFilePath}.corrupt-${Date.now()}`,
1808
- readFileSync9(this.plaintextFilePath)
1797
+ readFileSync8(this.plaintextFilePath)
1809
1798
  );
1810
1799
  } catch {
1811
1800
  }
1812
1801
  }
1813
1802
  }
1814
1803
  loadEncrypted() {
1815
- if (!existsSync8(this.encryptedFilePath)) return;
1804
+ if (!existsSync7(this.encryptedFilePath)) return;
1816
1805
  try {
1817
- const raw = readFileSync9(this.encryptedFilePath, "utf-8");
1806
+ const raw = readFileSync8(this.encryptedFilePath, "utf-8");
1818
1807
  const data = JSON.parse(raw);
1819
1808
  const decrypted = this.decrypt(data.blob);
1820
1809
  const parsed = JSON.parse(decrypted);
@@ -1826,9 +1815,9 @@ var ReceiptArchive = class {
1826
1815
  } catch (err) {
1827
1816
  console.error(`[ReceiptArchive] Could not decrypt ${this.encryptedFilePath} \u2014 preserving as .corrupt:`, err);
1828
1817
  try {
1829
- writeFileSync6(
1818
+ writeFileSync5(
1830
1819
  `${this.encryptedFilePath}.corrupt-${Date.now()}`,
1831
- readFileSync9(this.encryptedFilePath)
1820
+ readFileSync8(this.encryptedFilePath)
1832
1821
  );
1833
1822
  } catch {
1834
1823
  }
@@ -1842,29 +1831,29 @@ var ReceiptArchive = class {
1842
1831
  }
1843
1832
  }
1844
1833
  persistPlaintext() {
1845
- mkdirSync6(this.baseDir, { recursive: true, mode: 448 });
1846
- writeFileSync6(this.plaintextFilePath, JSON.stringify(this.data, null, 2), { encoding: "utf-8", mode: 384 });
1834
+ mkdirSync5(this.baseDir, { recursive: true, mode: 448 });
1835
+ writeFileSync5(this.plaintextFilePath, JSON.stringify(this.data, null, 2), { encoding: "utf-8", mode: 384 });
1847
1836
  }
1848
1837
  persistEncrypted() {
1849
1838
  const data = {
1850
1839
  version: 1,
1851
1840
  blob: this.encrypt(JSON.stringify(this.data))
1852
1841
  };
1853
- mkdirSync6(this.baseDir, { recursive: true, mode: 448 });
1854
- writeFileSync6(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1842
+ mkdirSync5(this.baseDir, { recursive: true, mode: 448 });
1843
+ writeFileSync5(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
1855
1844
  }
1856
1845
  };
1857
1846
 
1858
1847
  // src/lib/execution-journal.ts
1859
- import { mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync7, existsSync as existsSync9, renameSync } from "fs";
1848
+ import { mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync6, existsSync as existsSync8, renameSync } from "fs";
1860
1849
  import { homedir as homedir5 } from "os";
1861
- import { dirname as dirname7, join as join9 } from "path";
1862
- import { createHash as createHash3 } from "crypto";
1863
- var DEFAULT_DIR5 = process.env.SUVEREN_DATA_DIR ?? join9(homedir5(), ".suveren");
1850
+ import { dirname as dirname6, join as join8 } from "path";
1851
+ import { createHash as createHash2 } from "crypto";
1852
+ var DEFAULT_DIR5 = process.env.SUVEREN_DATA_DIR ?? join8(homedir5(), ".suveren");
1864
1853
  var FILE_NAME = "execution-journal.json";
1865
1854
  var MAX_AGE_SECONDS2 = 90 * 24 * 60 * 60;
1866
1855
  function hashToolArgs(args) {
1867
- return "sha256:" + createHash3("sha256").update(stableStringify(args)).digest("hex");
1856
+ return "sha256:" + createHash2("sha256").update(stableStringify(args)).digest("hex");
1868
1857
  }
1869
1858
  function stableStringify(value) {
1870
1859
  if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "undefined";
@@ -1876,8 +1865,8 @@ function stableStringify(value) {
1876
1865
  var ExecutionJournal = class {
1877
1866
  filePath;
1878
1867
  constructor(filePath) {
1879
- const baseDir = filePath && filePath.endsWith(".json") ? dirname7(filePath) : filePath ?? DEFAULT_DIR5;
1880
- this.filePath = join9(baseDir, FILE_NAME);
1868
+ const baseDir = filePath && filePath.endsWith(".json") ? dirname6(filePath) : filePath ?? DEFAULT_DIR5;
1869
+ this.filePath = join8(baseDir, FILE_NAME);
1881
1870
  }
1882
1871
  /** Look a ticket up. Always reads from disk — another process may have written. */
1883
1872
  get(ticketId) {
@@ -1916,9 +1905,9 @@ var ExecutionJournal = class {
1916
1905
  }
1917
1906
  // ─── Persistence ────────────────────────────────────────────────────────
1918
1907
  load() {
1919
- if (!existsSync9(this.filePath)) return { version: 1, entries: [] };
1908
+ if (!existsSync8(this.filePath)) return { version: 1, entries: [] };
1920
1909
  try {
1921
- const parsed = JSON.parse(readFileSync10(this.filePath, "utf8"));
1910
+ const parsed = JSON.parse(readFileSync9(this.filePath, "utf8"));
1922
1911
  if (parsed?.version !== 1 || !Array.isArray(parsed.entries)) {
1923
1912
  throw new Error("unexpected shape");
1924
1913
  }
@@ -1932,9 +1921,9 @@ var ExecutionJournal = class {
1932
1921
  persist(file) {
1933
1922
  const cutoff = nowSec() - MAX_AGE_SECONDS2;
1934
1923
  file.entries = file.entries.filter((e) => e.startedAt >= cutoff);
1935
- mkdirSync7(dirname7(this.filePath), { recursive: true, mode: 448 });
1924
+ mkdirSync6(dirname6(this.filePath), { recursive: true, mode: 448 });
1936
1925
  const tmp = this.filePath + ".tmp";
1937
- writeFileSync7(tmp, JSON.stringify(file, null, 2), { mode: 384 });
1926
+ writeFileSync6(tmp, JSON.stringify(file, null, 2), { mode: 384 });
1938
1927
  renameSync(tmp, this.filePath);
1939
1928
  }
1940
1929
  };
@@ -1943,10 +1932,10 @@ function nowSec() {
1943
1932
  }
1944
1933
 
1945
1934
  // src/lib/proposal-submission-store.ts
1946
- import { mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync8, existsSync as existsSync10, renameSync as renameSync2 } from "fs";
1935
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync7, existsSync as existsSync9, renameSync as renameSync2 } from "fs";
1947
1936
  import { homedir as homedir6 } from "os";
1948
- import { dirname as dirname8, join as join10 } from "path";
1949
- var DEFAULT_DIR6 = process.env.SUVEREN_DATA_DIR ?? join10(homedir6(), ".suveren");
1937
+ import { dirname as dirname7, join as join9 } from "path";
1938
+ var DEFAULT_DIR6 = process.env.SUVEREN_DATA_DIR ?? join9(homedir6(), ".suveren");
1950
1939
  var FILE_NAME2 = "proposal-submissions.json";
1951
1940
  var MAX_AGE_SECONDS3 = 90 * 24 * 60 * 60;
1952
1941
  function nowSec2() {
@@ -1955,8 +1944,8 @@ function nowSec2() {
1955
1944
  var ProposalSubmissionStore = class {
1956
1945
  filePath;
1957
1946
  constructor(filePath) {
1958
- const baseDir = filePath && filePath.endsWith(".json") ? dirname8(filePath) : filePath ?? DEFAULT_DIR6;
1959
- this.filePath = join10(baseDir, FILE_NAME2);
1947
+ const baseDir = filePath && filePath.endsWith(".json") ? dirname7(filePath) : filePath ?? DEFAULT_DIR6;
1948
+ this.filePath = join9(baseDir, FILE_NAME2);
1960
1949
  }
1961
1950
  /** Record what was submitted, right after a successful submitProposal(). */
1962
1951
  record(entry) {
@@ -1979,9 +1968,9 @@ var ProposalSubmissionStore = class {
1979
1968
  return this.load().entries.find((e) => e.proposalId === proposalId);
1980
1969
  }
1981
1970
  load() {
1982
- if (!existsSync10(this.filePath)) return { version: 1, entries: [] };
1971
+ if (!existsSync9(this.filePath)) return { version: 1, entries: [] };
1983
1972
  try {
1984
- const parsed = JSON.parse(readFileSync11(this.filePath, "utf-8"));
1973
+ const parsed = JSON.parse(readFileSync10(this.filePath, "utf-8"));
1985
1974
  const cutoff = nowSec2() - MAX_AGE_SECONDS3;
1986
1975
  parsed.entries = (parsed.entries ?? []).filter((e) => e.submittedAt >= cutoff);
1987
1976
  return parsed;
@@ -1990,9 +1979,9 @@ var ProposalSubmissionStore = class {
1990
1979
  }
1991
1980
  }
1992
1981
  persist(file) {
1993
- mkdirSync8(dirname8(this.filePath), { recursive: true, mode: 448 });
1982
+ mkdirSync7(dirname7(this.filePath), { recursive: true, mode: 448 });
1994
1983
  const tmpPath = `${this.filePath}.tmp`;
1995
- writeFileSync8(tmpPath, JSON.stringify(file, null, 2), { encoding: "utf-8", mode: 384 });
1984
+ writeFileSync7(tmpPath, JSON.stringify(file, null, 2), { encoding: "utf-8", mode: 384 });
1996
1985
  renameSync2(tmpPath, this.filePath);
1997
1986
  }
1998
1987
  };
@@ -2088,6 +2077,647 @@ var MCPGatekeeper = class {
2088
2077
  }
2089
2078
  };
2090
2079
 
2080
+ // src/lib/report/report-store.ts
2081
+ import { mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync8, existsSync as existsSync10, unlinkSync as unlinkSync5 } from "fs";
2082
+ import { homedir as homedir7 } from "os";
2083
+ import { dirname as dirname8, join as join10 } from "path";
2084
+ import { createCipheriv as createCipheriv5, createDecipheriv as createDecipheriv5, randomBytes as randomBytes5 } from "crypto";
2085
+
2086
+ // src/lib/report-brief.ts
2087
+ var REPORT_ELEMENTS = [
2088
+ "sv-ticket",
2089
+ "sv-approval",
2090
+ "sv-mandate",
2091
+ "sv-record",
2092
+ "sv-case",
2093
+ "sv-metric"
2094
+ ];
2095
+ var REPORT_BRIEF = `How to write the report
2096
+
2097
+ Purpose: show the company's management what the AI achieved in this test \u2014 case by case, from the request that started it to the goal that completed it \u2014 with proof for every fact that matters.
2098
+
2099
+ Who reads it: managers who are not technical. Plain words, short sentences, the result first.
2100
+
2101
+ What you write: one HTML page (HTML, CSS and inline SVG only \u2014 no JavaScript, no external files or links except the check links the gateway adds). The layout, headings, charts, tables and your assessment are yours.
2102
+
2103
+ It must read well everywhere: on a phone, in a narrow side panel (about 360 pixels wide) and on a large screen. Use fluid widths (no fixed page widths), let columns stack on narrow screens (CSS grid/flex with wrapping, or media queries), make wide tables scroll horizontally or turn into stacked rows, give SVG charts a viewBox so they scale, and keep text at a readable size.
2104
+
2105
+ What you cannot write yourself: facts that need proof. Place these elements instead; the gateway looks the data up, checks it and draws the element. You give references, never the content:
2106
+
2107
+ - <sv-ticket ref="TICKET_ID"></sv-ticket> \u2014 one action you took, with its signed ticket.
2108
+ - <sv-approval ticket="TICKET_ID"></sv-approval> \u2014 who approved that action, when, and how long it waited.
2109
+ - <sv-mandate ticket="TICKET_ID"></sv-mandate> \u2014 the authority the action ran under: limits, mode, intent.
2110
+ - <sv-record system="email|crm|erp" ref="RECORD_ID"></sv-record> \u2014 an email, CRM entry, quote or order.
2111
+ - <sv-case start="email:MESSAGE_ID" goal="ticket:TICKET_ID" steps="TICKET_ID TICKET_ID"></sv-case> \u2014 one business case: the incoming email that started it, the ticket that completed it, and the tickets in between.
2112
+ - <sv-metric kind="KIND" cases="all"></sv-metric> \u2014 a number the gateway computes over the cases you defined. KIND: completed, median-time, average-time, without-approval, approvals, median-approval-wait, tickets, refusals. cases is "all" or a space-separated list of case ids, e.g. cases="C1 C3".
2113
+
2114
+ Rules:
2115
+ 1. Define every case you worked on with sv-case \u2014 also the ones that did not reach their goal (omit goal, or say why in your text). The gateway shows management how many of the loaded cases your report covers and names the missing ones \u2014 and lists every ticket from the test period that your report does not reference, so name every step.
2116
+ 2. Use sv-metric for every headline number. Numbers you compute yourself are shown as "AI analysis \u2014 not verified".
2117
+ 3. A case's goal must be what actually completed it \u2014 for an email reply, the reply to the start email. The gateway checks this link.
2118
+ 4. A wrong or unknown reference is shown as "not verifiable". Do not guess IDs \u2014 read them first.
2119
+ 5. Never claim more than the elements prove. Say plainly what went wrong or waited for a person.
2120
+
2121
+ Suggested structure:
2122
+ 1. The result in one sentence, then 3\u20134 sv-metric figures (completed, median time, share without approval, approvals).
2123
+ 2. All cases at a glance \u2014 a table with one row per case, linked to its sv-case below.
2124
+ 3. Each case: sv-case, then the sv-ticket and sv-approval elements that explain it.
2125
+ 4. What was stopped or needed a person, and why (sv-approval, refusals).
2126
+ 5. Your assessment: what worked, what slowed things down, what a different mandate would change \u2014 marked as your view.
2127
+
2128
+ Update the report whenever cases progress; each write replaces the previous report.`;
2129
+
2130
+ // src/lib/report/sanitize.ts
2131
+ import sanitizeHtmlLib from "sanitize-html";
2132
+ var FORBIDDEN_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "link"]);
2133
+ function isUrlAttribute(name) {
2134
+ const n = name.toLowerCase();
2135
+ return n === "href" || n === "src" || n === "xlink:href" || n.endsWith(":href");
2136
+ }
2137
+ function isAllowedUrl(value) {
2138
+ const v = value.trim();
2139
+ if (v.startsWith("#")) return true;
2140
+ if (/^data:image\//i.test(v)) return true;
2141
+ return false;
2142
+ }
2143
+ function sanitizeReportHtml(html) {
2144
+ return sanitizeHtmlLib(html, {
2145
+ // Allow every tag/attribute by default — see module doc comment for why
2146
+ // this is deny-by-name rather than allow-by-name. `transformTags['*']`
2147
+ // below is then the ONLY attribute filter (allowedAttributes: false
2148
+ // skips sanitize-html's own, so there is exactly one place attributes
2149
+ // are decided, not two that could disagree). Logs a harmless warning for
2150
+ // "script"/"style" on every call (sanitize-html's own vulnerable-tag
2151
+ // notice, fired from its internal tag list even though we pass `false`,
2152
+ // not an array containing them) — `allowVulnerableTags` is the
2153
+ // documented way to accept that, and <script> is still removed, by
2154
+ // `exclusiveFilter` below, regardless of this flag.
2155
+ allowedTags: false,
2156
+ allowedAttributes: false,
2157
+ allowVulnerableTags: true,
2158
+ // sanitize-html's OWN scheme check (independent of transformTags, and
2159
+ // applied to it/src/cite only — NOT xlink:href, which is why the
2160
+ // transformTags filter above is the one actually relied on for SVG) uses
2161
+ // this list; it has no "data" scheme by default, which would undo our
2162
+ // own decision to keep `data:image/*` sources. Nothing wider is opened:
2163
+ // transformTags has already removed every href/src that isn't a
2164
+ // fragment link or a data:image/* URI by the time this check runs.
2165
+ allowedSchemes: [...sanitizeHtmlLib.defaults.allowedSchemes, "data"],
2166
+ // Preserve attribute name casing — inline SVG uses camelCase attributes
2167
+ // (viewBox, preserveAspectRatio, …) that lowercasing would silently
2168
+ // break. Safe for the `on*`/url checks below: both compare case-folded.
2169
+ parser: { lowerCaseAttributeNames: false },
2170
+ // Removes the named tag AND all of its children/text — the only correct
2171
+ // behaviour for <script>: dropping just the tag would leave its JS as
2172
+ // visible text, but the content must not survive either.
2173
+ exclusiveFilter: (frame) => {
2174
+ const tag = frame.tag.toLowerCase();
2175
+ if (FORBIDDEN_TAGS.has(tag)) return true;
2176
+ if (tag === "meta" && Object.keys(frame.attribs).some((a) => a.toLowerCase() === "http-equiv")) {
2177
+ return true;
2178
+ }
2179
+ return false;
2180
+ },
2181
+ transformTags: {
2182
+ "*": (tagName, attribs) => {
2183
+ const kept = {};
2184
+ for (const [name, value] of Object.entries(attribs)) {
2185
+ if (name.toLowerCase().startsWith("on")) continue;
2186
+ if (isUrlAttribute(name) && !isAllowedUrl(value)) continue;
2187
+ kept[name] = value;
2188
+ }
2189
+ return { tagName, attribs: kept };
2190
+ }
2191
+ }
2192
+ });
2193
+ }
2194
+
2195
+ // src/lib/report/record-resolvers.ts
2196
+ function findById(rows, id) {
2197
+ return rows.find((r) => r.id === id);
2198
+ }
2199
+ function resolveEmailRecord(exportData, ref) {
2200
+ const inInbox = findById(exportData.inbox, ref);
2201
+ if (inInbox) return { status: "verified", data: { kind: "message", folder: "inbox", ...inInbox } };
2202
+ const inSent = findById(exportData.sent, ref);
2203
+ if (inSent) return { status: "verified", data: { kind: "message", folder: "sent", ...inSent } };
2204
+ const change = findById(exportData.changes, ref);
2205
+ if (change) return { status: "verified", data: { kind: "change", causingReceiptId: change.receipt_id ?? null, ...change } };
2206
+ const refusal = findById(exportData.refusals, ref);
2207
+ if (refusal) return { status: "verified", data: { kind: "refusal", ...refusal } };
2208
+ return { status: "unverifiable", reason: `No email record "${ref}" in the simulator export.` };
2209
+ }
2210
+ function resolveErpRecord(exportData, ref) {
2211
+ const quote = findById(exportData.quotes, ref) ?? exportData.quotes.find((q) => q.number === ref);
2212
+ if (quote) return { status: "verified", data: { kind: "quote", ...quote } };
2213
+ const order = findById(exportData.orders, ref) ?? exportData.orders.find((o) => o.number === ref);
2214
+ if (order) return { status: "verified", data: { kind: "order", ...order } };
2215
+ const change = findById(exportData.changes, ref);
2216
+ if (change) return { status: "verified", data: { kind: "change", causingReceiptId: change.receipt_id ?? null, ...change } };
2217
+ const refusal = findById(exportData.refusals, ref);
2218
+ if (refusal) return { status: "verified", data: { kind: "refusal", ...refusal } };
2219
+ return { status: "unverifiable", reason: `No ERP record "${ref}" in the simulator export.` };
2220
+ }
2221
+ function resolveCrmRecord(exportData, ref) {
2222
+ for (const [kind, rows] of [
2223
+ ["contact", exportData.contacts],
2224
+ ["deal", exportData.deals],
2225
+ ["task", exportData.tasks],
2226
+ ["activity", exportData.activities]
2227
+ ]) {
2228
+ const row = findById(rows, ref);
2229
+ if (row) return { status: "verified", data: { kind, ...row } };
2230
+ }
2231
+ const change = findById(exportData.changes, ref);
2232
+ if (change) return { status: "verified", data: { kind: "change", causingReceiptId: change.receipt_id ?? null, ...change } };
2233
+ const refusal = findById(exportData.refusals, ref);
2234
+ if (refusal) return { status: "verified", data: { kind: "refusal", ...refusal } };
2235
+ return { status: "unverifiable", reason: `No CRM record "${ref}" in the simulator export.` };
2236
+ }
2237
+ function resolveRecord(system, exportData, ref) {
2238
+ if (system === "email") return resolveEmailRecord(exportData, ref);
2239
+ if (system === "erp") return resolveErpRecord(exportData, ref);
2240
+ return resolveCrmRecord(exportData, ref);
2241
+ }
2242
+
2243
+ // src/lib/report/metric-resolvers.ts
2244
+ var METRIC_KINDS = [
2245
+ "completed",
2246
+ "median-time",
2247
+ "average-time",
2248
+ "without-approval",
2249
+ "approvals",
2250
+ "median-approval-wait",
2251
+ "tickets",
2252
+ "refusals"
2253
+ ];
2254
+ var UnknownMetricKindError = class extends Error {
2255
+ constructor(kind) {
2256
+ super(`Unknown sv-metric kind "${kind}" \u2014 expected one of: ${METRIC_KINDS.join(", ")}.`);
2257
+ this.name = "UnknownMetricKindError";
2258
+ }
2259
+ };
2260
+ function median(values) {
2261
+ if (values.length === 0) return 0;
2262
+ const sorted = [...values].sort((a, b) => a - b);
2263
+ const mid = Math.floor(sorted.length / 2);
2264
+ return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
2265
+ }
2266
+ function average(values) {
2267
+ if (values.length === 0) return 0;
2268
+ return values.reduce((a, b) => a + b, 0) / values.length;
2269
+ }
2270
+ function computeMetric(kind, cases, refusalTimes = []) {
2271
+ switch (kind) {
2272
+ case "completed":
2273
+ return cases.length;
2274
+ case "median-time":
2275
+ return median(cases.map((c) => c.totalDurationSeconds));
2276
+ case "average-time":
2277
+ return average(cases.map((c) => c.totalDurationSeconds));
2278
+ case "without-approval": {
2279
+ if (cases.length === 0) return 0;
2280
+ const withoutApproval = cases.filter((c) => c.approvals.length === 0).length;
2281
+ return withoutApproval / cases.length;
2282
+ }
2283
+ case "approvals":
2284
+ return cases.reduce((sum, c) => sum + c.approvals.length, 0);
2285
+ case "median-approval-wait":
2286
+ return median(cases.flatMap((c) => c.approvals.map((a) => a.waitSeconds).filter((w) => typeof w === "number")));
2287
+ case "tickets": {
2288
+ const ids = new Set(cases.flatMap((c) => c.ticketIds));
2289
+ return ids.size;
2290
+ }
2291
+ case "refusals":
2292
+ return cases.reduce(
2293
+ (sum, c) => sum + refusalTimes.filter((t) => t >= c.startTime && t <= c.goalTime).length,
2294
+ 0
2295
+ );
2296
+ default:
2297
+ throw new UnknownMetricKindError(kind);
2298
+ }
2299
+ }
2300
+
2301
+ // src/lib/report/types.ts
2302
+ function isEmailExport(v) {
2303
+ const o = v;
2304
+ return !!o && Array.isArray(o.inbox) && Array.isArray(o.sent) && Array.isArray(o.changes) && Array.isArray(o.refusals);
2305
+ }
2306
+ function isErpExport(v) {
2307
+ const o = v;
2308
+ return !!o && Array.isArray(o.quotes) && Array.isArray(o.orders) && Array.isArray(o.changes) && Array.isArray(o.refusals);
2309
+ }
2310
+ function isCrmExport(v) {
2311
+ const o = v;
2312
+ return !!o && Array.isArray(o.contacts) && Array.isArray(o.deals) && Array.isArray(o.changes) && Array.isArray(o.refusals);
2313
+ }
2314
+
2315
+ // src/lib/report/verify-report.ts
2316
+ var KNOWN_KINDS = new Set(REPORT_ELEMENTS);
2317
+ async function verifyReport(html, sources) {
2318
+ const sanitized = sanitizeReportHtml(html);
2319
+ const parsed = parseElements(sanitized);
2320
+ const exportCache = /* @__PURE__ */ new Map();
2321
+ function getExport(system) {
2322
+ let p = exportCache.get(system);
2323
+ if (!p) {
2324
+ p = sources.runExport(system).then(
2325
+ (data) => ({ ok: true, data }),
2326
+ (err) => ({ ok: false, reason: err instanceof Error ? err.message : String(err) })
2327
+ );
2328
+ exportCache.set(system, p);
2329
+ }
2330
+ return p;
2331
+ }
2332
+ const elements = [];
2333
+ const caseElements = [];
2334
+ const metricParsed = [];
2335
+ async function resolveOne(p) {
2336
+ try {
2337
+ switch (p.kind) {
2338
+ case "sv-ticket": {
2339
+ const r = await resolveTicketElement(sources.archive, p.attrs.ref ?? "");
2340
+ return { id: p.id, kind: p.kind, attrs: p.attrs, ...r };
2341
+ }
2342
+ case "sv-approval": {
2343
+ const r = await resolveApprovalElement(sources.archive, p.attrs.ticket ?? "");
2344
+ return { id: p.id, kind: p.kind, attrs: p.attrs, ...r };
2345
+ }
2346
+ case "sv-mandate": {
2347
+ const r = await resolveMandateElement(sources.archive, p.attrs.ticket ?? "");
2348
+ return { id: p.id, kind: p.kind, attrs: p.attrs, ...r };
2349
+ }
2350
+ case "sv-record": {
2351
+ const system = p.attrs.system;
2352
+ if (system !== "email" && system !== "crm" && system !== "erp") {
2353
+ return { id: p.id, kind: p.kind, attrs: p.attrs, status: "unverifiable", reason: `Unknown system "${p.attrs.system ?? ""}".` };
2354
+ }
2355
+ const exp = await getExport(system);
2356
+ if (!exp.ok) {
2357
+ return { id: p.id, kind: p.kind, attrs: p.attrs, status: "unverifiable", reason: `Could not read the ${system} simulator export: ${exp.reason}` };
2358
+ }
2359
+ const r = resolveRecord(system, exp.data, p.attrs.ref ?? "");
2360
+ return { id: p.id, kind: p.kind, attrs: p.attrs, ...r };
2361
+ }
2362
+ case "sv-case": {
2363
+ const exp = await getExport("email");
2364
+ if (!exp.ok || !isEmailExport(exp.data)) {
2365
+ return {
2366
+ id: p.id,
2367
+ kind: p.kind,
2368
+ attrs: p.attrs,
2369
+ status: "unverifiable",
2370
+ reason: `Could not read the email simulator export: ${!exp.ok ? exp.reason : "unexpected shape"}`
2371
+ };
2372
+ }
2373
+ const resolution = await resolveCaseElement(sources.archive, exp.data, p.attrs);
2374
+ const el = {
2375
+ id: p.id,
2376
+ kind: p.kind,
2377
+ attrs: p.attrs,
2378
+ status: resolution.status,
2379
+ ...resolution.reason ? { reason: resolution.reason } : {},
2380
+ ...resolution.data ? { data: resolution.data } : {}
2381
+ };
2382
+ caseElements.push({ el, resolution });
2383
+ return el;
2384
+ }
2385
+ default:
2386
+ return { id: p.id, kind: p.kind, attrs: p.attrs, status: "unverifiable", reason: "Unhandled element kind." };
2387
+ }
2388
+ } catch (err) {
2389
+ return { id: p.id, kind: p.kind, attrs: p.attrs, status: "unverifiable", reason: err instanceof Error ? err.message : String(err) };
2390
+ }
2391
+ }
2392
+ for (const p of parsed) {
2393
+ if (!KNOWN_KINDS.has(p.kind)) {
2394
+ elements.push({
2395
+ id: p.id,
2396
+ kind: p.kind,
2397
+ attrs: p.attrs,
2398
+ status: "unverifiable",
2399
+ reason: `Unknown element "${p.kind}" \u2014 not one of the six elements report-brief.ts defines.`
2400
+ });
2401
+ continue;
2402
+ }
2403
+ if (p.kind === "sv-metric") {
2404
+ metricParsed.push(p);
2405
+ continue;
2406
+ }
2407
+ elements.push(await resolveOne(p));
2408
+ }
2409
+ for (const p of metricParsed) {
2410
+ try {
2411
+ const kind = p.attrs.kind ?? "";
2412
+ const casesAttr = (p.attrs.cases ?? "all").trim();
2413
+ const requestedCount = casesAttr === "all" ? caseElements.length : new Set(casesAttr.split(/\s+/).filter(Boolean)).size;
2414
+ let selected = caseElements.filter((c) => c.resolution.status !== "unverifiable" && c.resolution.data);
2415
+ if (casesAttr !== "all") {
2416
+ const wanted = new Set(casesAttr.split(/\s+/).filter(Boolean));
2417
+ selected = selected.filter((c) => wanted.has(c.resolution.data.caseId));
2418
+ }
2419
+ const caseInputs = selected.map((c) => ({
2420
+ caseId: c.resolution.data.caseId,
2421
+ startTime: c.resolution.data.start.time,
2422
+ goalTime: c.resolution.data.goal.time,
2423
+ totalDurationSeconds: c.resolution.data.totalDurationSeconds,
2424
+ ticketIds: [c.resolution.data.goal.ticketId, ...c.resolution.data.steps.map((s) => s.ticketId)],
2425
+ approvals: c.resolution.data.approvals
2426
+ }));
2427
+ const verifiedCount = caseInputs.length;
2428
+ if (verifiedCount === 0) {
2429
+ elements.push({
2430
+ id: p.id,
2431
+ kind: p.kind,
2432
+ attrs: p.attrs,
2433
+ status: "unverifiable",
2434
+ reason: requestedCount > 0 ? `No verified cases (0 of ${requestedCount} requested) \u2014 no figure.` : "No verified cases \u2014 no figure."
2435
+ });
2436
+ continue;
2437
+ }
2438
+ const refusalTimes = kind === "refusals" ? await collectRefusalTimes(getExport) : [];
2439
+ const value = computeMetric(kind, caseInputs, refusalTimes);
2440
+ const data = { kind, cases: casesAttr, value, caseCount: verifiedCount };
2441
+ if (verifiedCount < requestedCount) {
2442
+ elements.push({
2443
+ id: p.id,
2444
+ kind: p.kind,
2445
+ attrs: p.attrs,
2446
+ status: "warning",
2447
+ reason: `Computed over ${verifiedCount} of ${requestedCount} requested cases \u2014 the rest did not verify.`,
2448
+ data
2449
+ });
2450
+ } else {
2451
+ elements.push({ id: p.id, kind: p.kind, attrs: p.attrs, status: "verified", data });
2452
+ }
2453
+ } catch (err) {
2454
+ elements.push({ id: p.id, kind: p.kind, attrs: p.attrs, status: "unverifiable", reason: err instanceof Error ? err.message : String(err) });
2455
+ }
2456
+ }
2457
+ const proof = buildProof(elements, caseElements);
2458
+ const coverage = await buildCoverage(caseElements, getExport, sources.archive, proof.ticketsReferenced);
2459
+ return { html: sanitized, elements, proof, coverage };
2460
+ }
2461
+ async function collectRefusalTimes(getExport) {
2462
+ const times = [];
2463
+ for (const system of ["email", "crm", "erp"]) {
2464
+ const exp = await getExport(system);
2465
+ if (!exp.ok) throw new Error(`Could not read the ${system} simulator export: ${exp.reason}`);
2466
+ const refusals = exp.data.refusals ?? [];
2467
+ for (const r of refusals) {
2468
+ const t = parseTimestampSeconds(r.at);
2469
+ if (t !== void 0) times.push(t);
2470
+ }
2471
+ }
2472
+ return times;
2473
+ }
2474
+ function summarize(el) {
2475
+ const d = el.data ?? {};
2476
+ switch (el.kind) {
2477
+ case "sv-ticket": {
2478
+ const actionLabel = typeof d.actionLabel === "string" ? d.actionLabel : formatActionLabel(d.action);
2479
+ const timeLabel = typeof d.timeLabel === "string" ? d.timeLabel : formatDateTime(d.time);
2480
+ return `${actionLabel} \u2014 ${timeLabel}`;
2481
+ }
2482
+ case "sv-approval": {
2483
+ const who = typeof d.whoLabel === "string" ? d.whoLabel : d.who?.join(", ") ?? "unknown";
2484
+ const waitLabel = typeof d.waitLabel === "string" ? d.waitLabel : typeof d.waitSeconds === "number" ? formatDuration(d.waitSeconds) : "unknown";
2485
+ return `Approval by ${who} \u2014 waited ${waitLabel}`;
2486
+ }
2487
+ case "sv-mandate": {
2488
+ const profileLabel = typeof d.profileLabel === "string" ? d.profileLabel : profileShortLabel(typeof d.profile === "string" ? d.profile : void 0);
2489
+ const owners = Array.isArray(d.owners) && d.owners.length > 0 ? d.owners.join(", ") : "unknown owner";
2490
+ return `Mandate: ${profileLabel} \xB7 ${owners}`;
2491
+ }
2492
+ case "sv-record":
2493
+ return `${String(d.kind ?? "record")} record checked`;
2494
+ case "sv-case": {
2495
+ const steps = d.steps?.length ?? 0;
2496
+ return `Case ${String(d.caseId)}: ${steps} ${steps === 1 ? "step" : "steps"}, ${formatDuration(d.totalDurationSeconds)}`;
2497
+ }
2498
+ case "sv-metric": {
2499
+ const kind = String(d.kind ?? "");
2500
+ const label = METRIC_LABELS[kind] ?? kind;
2501
+ return `${label} = ${formatMetricValue(kind, d.value)}`;
2502
+ }
2503
+ default:
2504
+ return el.id;
2505
+ }
2506
+ }
2507
+ function buildProof(elements, caseElements) {
2508
+ const ticketsReferenced = /* @__PURE__ */ new Set();
2509
+ const signaturesValid = /* @__PURE__ */ new Set();
2510
+ let recordsChecked = 0;
2511
+ let unverifiableCount = 0;
2512
+ const verifiedValues = [];
2513
+ for (const el of elements) {
2514
+ if (el.status === "unverifiable") unverifiableCount++;
2515
+ if (el.status === "verified" || el.status === "warning") {
2516
+ verifiedValues.push({ elementId: el.id, kind: el.kind, summary: summarize(el) });
2517
+ }
2518
+ if (el.kind === "sv-ticket" && el.attrs.ref) {
2519
+ ticketsReferenced.add(el.attrs.ref);
2520
+ if (el.status !== "unverifiable") signaturesValid.add(el.attrs.ref);
2521
+ }
2522
+ if ((el.kind === "sv-approval" || el.kind === "sv-mandate") && el.attrs.ticket) {
2523
+ ticketsReferenced.add(el.attrs.ticket);
2524
+ if (el.status !== "unverifiable") signaturesValid.add(el.attrs.ticket);
2525
+ }
2526
+ if (el.kind === "sv-record" && el.status === "verified") {
2527
+ recordsChecked++;
2528
+ }
2529
+ }
2530
+ for (const { el, resolution } of caseElements) {
2531
+ const { goalId, stepIds } = parseCaseAttrs(el.attrs);
2532
+ for (const id of [goalId, ...stepIds]) {
2533
+ if (!id) continue;
2534
+ ticketsReferenced.add(id);
2535
+ if (resolution.status !== "unverifiable") signaturesValid.add(id);
2536
+ }
2537
+ }
2538
+ return {
2539
+ ticketsReferenced: [...ticketsReferenced],
2540
+ signaturesValid: signaturesValid.size,
2541
+ recordsChecked,
2542
+ unverifiableCount,
2543
+ verifiedValues
2544
+ };
2545
+ }
2546
+ async function buildCoverage(caseElements, getExport, archive, referenced) {
2547
+ const exp = await getExport("email");
2548
+ const emailExportError = !exp.ok ? exp.reason : !isEmailExport(exp.data) ? "Email simulator export had an unexpected shape." : void 0;
2549
+ const loadedCases = exp.ok && isEmailExport(exp.data) ? [...new Set(exp.data.inbox.map((m) => m.case_id).filter((c) => !!c))] : [];
2550
+ const covered = new Set(
2551
+ caseElements.map((c) => c.resolution.startCaseId).filter((c) => !!c)
2552
+ );
2553
+ const coveredCases = loadedCases.filter((c) => covered.has(c));
2554
+ const missingCases = loadedCases.filter((c) => !covered.has(c));
2555
+ const loadedAt = exp.ok && isEmailExport(exp.data) ? exp.data.simulation_load?.loaded_at : void 0;
2556
+ const periodStart = loadedAt !== void 0 ? parseTimestampSeconds(loadedAt) ?? null : null;
2557
+ const inPeriod = archive.getReceipts().map((r) => ({ id: String(r.receipt.id ?? ""), time: Number(r.receipt.timestamp ?? r.archivedAt) })).filter((t) => t.id && (periodStart === null || t.time >= periodStart)).sort((a, b) => a.time - b.time).map((t) => t.id);
2558
+ const referencedSet = new Set(referenced);
2559
+ const ticketsReferenced = inPeriod.filter((id) => referencedSet.has(id));
2560
+ const ticketsNotReferenced = inPeriod.filter((id) => !referencedSet.has(id));
2561
+ return {
2562
+ ...emailExportError ? { emailExportError } : {},
2563
+ loadedCases,
2564
+ coveredCases,
2565
+ missingCases,
2566
+ periodStart,
2567
+ ticketsInPeriod: inPeriod,
2568
+ ticketsReferenced,
2569
+ ticketsNotReferenced
2570
+ };
2571
+ }
2572
+
2573
+ // src/lib/report/report-store.ts
2574
+ var DEFAULT_DIR7 = process.env.SUVEREN_DATA_DIR ?? join10(homedir7(), ".suveren");
2575
+ var ReportStore = class {
2576
+ report = null;
2577
+ baseDir;
2578
+ vaultKey = null;
2579
+ constructor(filePath) {
2580
+ if (filePath && filePath.endsWith(".json")) {
2581
+ this.baseDir = dirname8(filePath);
2582
+ } else {
2583
+ this.baseDir = filePath ?? DEFAULT_DIR7;
2584
+ }
2585
+ this.loadPlaintext();
2586
+ }
2587
+ /** Set the vault key for encryption. Triggers migration from plaintext if needed. */
2588
+ setVaultKey(key) {
2589
+ this.vaultKey = key;
2590
+ if (existsSync10(this.encryptedFilePath)) {
2591
+ this.loadEncrypted();
2592
+ } else if (this.report !== null) {
2593
+ this.persistEncrypted();
2594
+ if (existsSync10(this.plaintextFilePath)) {
2595
+ try {
2596
+ unlinkSync5(this.plaintextFilePath);
2597
+ } catch {
2598
+ }
2599
+ }
2600
+ }
2601
+ }
2602
+ /**
2603
+ * True when encrypted evidence exists on disk that this process cannot
2604
+ * read yet (no vault key). Callers MUST NOT present the store as "no
2605
+ * report yet" in this state — that would claim a different fact than
2606
+ * "the report exists but is locked".
2607
+ */
2608
+ isLocked() {
2609
+ return this.vaultKey === null && existsSync10(this.encryptedFilePath);
2610
+ }
2611
+ /** The stored, already-verified report — or null if none has been saved
2612
+ * (and the store is not locked; check `isLocked()` first). */
2613
+ getReport() {
2614
+ return this.report;
2615
+ }
2616
+ /**
2617
+ * Replace the current report with `html`, verifying it ONCE against
2618
+ * `sources` before storing. Always replaces — there is only ever one
2619
+ * current report (plan decision).
2620
+ */
2621
+ async saveReport(html, sources, now = Math.floor(Date.now() / 1e3)) {
2622
+ const result = await verifyReport(html, sources);
2623
+ this.report = { html: result.html, savedAt: now, checkedAt: now, result };
2624
+ this.persist();
2625
+ return this.report;
2626
+ }
2627
+ /**
2628
+ * Re-run verification against the CURRENTLY stored report's html — "Check
2629
+ * again" in the UI. Does not change `savedAt` (the AI did not rewrite
2630
+ * anything); only `checkedAt` and `result` move. Returns null if there is
2631
+ * no report to recheck.
2632
+ */
2633
+ async recheck(sources, now = Math.floor(Date.now() / 1e3)) {
2634
+ if (!this.report) return null;
2635
+ const result = await verifyReport(this.report.html, sources);
2636
+ this.report = { ...this.report, checkedAt: now, result };
2637
+ this.persist();
2638
+ return this.report;
2639
+ }
2640
+ // ─── Encryption helpers ─────────────────────────────────────────────────
2641
+ encrypt(plaintext) {
2642
+ if (!this.vaultKey) throw new Error("No vault key");
2643
+ const iv = randomBytes5(12);
2644
+ const cipher = createCipheriv5("aes-256-gcm", this.vaultKey, iv);
2645
+ const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
2646
+ const tag = cipher.getAuthTag();
2647
+ return { iv: iv.toString("hex"), ciphertext: encrypted.toString("hex"), tag: tag.toString("hex") };
2648
+ }
2649
+ decrypt(blob) {
2650
+ if (!this.vaultKey) throw new Error("No vault key");
2651
+ const decipher = createDecipheriv5("aes-256-gcm", this.vaultKey, Buffer.from(blob.iv, "hex"));
2652
+ decipher.setAuthTag(Buffer.from(blob.tag, "hex"));
2653
+ const decrypted = Buffer.concat([decipher.update(Buffer.from(blob.ciphertext, "hex")), decipher.final()]);
2654
+ return decrypted.toString("utf8");
2655
+ }
2656
+ // ─── File paths ─────────────────────────────────────────────────────────
2657
+ get plaintextFilePath() {
2658
+ return join10(this.baseDir, "report.json");
2659
+ }
2660
+ get encryptedFilePath() {
2661
+ return join10(this.baseDir, "report.enc.json");
2662
+ }
2663
+ // ─── Load / Persist ─────────────────────────────────────────────────────
2664
+ loadPlaintext() {
2665
+ if (!existsSync10(this.plaintextFilePath)) {
2666
+ mkdirSync8(this.baseDir, { recursive: true });
2667
+ return;
2668
+ }
2669
+ try {
2670
+ const raw = readFileSync11(this.plaintextFilePath, "utf-8");
2671
+ const parsed = JSON.parse(raw);
2672
+ this.report = parsed.report ?? null;
2673
+ } catch {
2674
+ console.error(`[ReportStore] Could not parse ${this.plaintextFilePath} \u2014 preserving as .corrupt`);
2675
+ try {
2676
+ writeFileSync8(`${this.plaintextFilePath}.corrupt-${Date.now()}`, readFileSync11(this.plaintextFilePath));
2677
+ } catch {
2678
+ }
2679
+ this.report = null;
2680
+ }
2681
+ }
2682
+ loadEncrypted() {
2683
+ if (!existsSync10(this.encryptedFilePath)) return;
2684
+ try {
2685
+ const raw = readFileSync11(this.encryptedFilePath, "utf-8");
2686
+ const data = JSON.parse(raw);
2687
+ const decrypted = this.decrypt(data.blob);
2688
+ const parsed = JSON.parse(decrypted);
2689
+ this.report = parsed.report ?? null;
2690
+ } catch (err) {
2691
+ console.error(`[ReportStore] Could not decrypt ${this.encryptedFilePath} \u2014 preserving as .corrupt:`, err);
2692
+ try {
2693
+ writeFileSync8(`${this.encryptedFilePath}.corrupt-${Date.now()}`, readFileSync11(this.encryptedFilePath));
2694
+ } catch {
2695
+ }
2696
+ this.report = null;
2697
+ }
2698
+ }
2699
+ persist() {
2700
+ if (this.vaultKey) {
2701
+ this.persistEncrypted();
2702
+ } else {
2703
+ this.persistPlaintext();
2704
+ }
2705
+ }
2706
+ persistPlaintext() {
2707
+ const data = { version: 1, report: this.report };
2708
+ mkdirSync8(this.baseDir, { recursive: true, mode: 448 });
2709
+ writeFileSync8(this.plaintextFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
2710
+ }
2711
+ persistEncrypted() {
2712
+ const data = {
2713
+ version: 1,
2714
+ blob: this.encrypt(JSON.stringify({ version: 1, report: this.report }))
2715
+ };
2716
+ mkdirSync8(this.baseDir, { recursive: true, mode: 448 });
2717
+ writeFileSync8(this.encryptedFilePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
2718
+ }
2719
+ };
2720
+
2091
2721
  // src/lib/shared-state.ts
2092
2722
  var SharedState = class {
2093
2723
  spClient;
@@ -2096,6 +2726,9 @@ var SharedState = class {
2096
2726
  executionLog;
2097
2727
  denialLog;
2098
2728
  receiptArchive;
2729
+ /** The one current evidence-backed report the user's AI has written —
2730
+ * see report/report-store.ts. Vault-encrypted, like the stores above. */
2731
+ reportStore;
2099
2732
  /** Which tickets this Gatekeeper has executed — the "one execution per ticket" half of exactly-once. */
2100
2733
  executionJournal;
2101
2734
  /** What THIS gateway submitted for each review-mode proposal it created —
@@ -2116,6 +2749,7 @@ var SharedState = class {
2116
2749
  this.executionLog = new ExecutionLog(gateStorePath);
2117
2750
  this.denialLog = new DenialLog(gateStorePath);
2118
2751
  this.receiptArchive = new ReceiptArchive(gateStorePath);
2752
+ this.reportStore = new ReportStore(gateStorePath);
2119
2753
  this.executionJournal = new ExecutionJournal(gateStorePath);
2120
2754
  this.proposalSubmissions = new ProposalSubmissionStore(gateStorePath);
2121
2755
  this.gatekeeper = new MCPGatekeeper(this.cache);
@@ -2271,12 +2905,12 @@ function formatConsumptionFull(entries) {
2271
2905
 
2272
2906
  // src/lib/context-loader.ts
2273
2907
  import { readFileSync as readFileSync12, existsSync as existsSync11, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, renameSync as renameSync3 } from "fs";
2274
- import { homedir as homedir7 } from "os";
2908
+ import { homedir as homedir8 } from "os";
2275
2909
  import { join as join11, dirname as dirname9 } from "path";
2276
- var DEFAULT_DIR7 = process.env.SUVEREN_DATA_DIR ?? join11(homedir7(), ".suveren");
2910
+ var DEFAULT_DIR8 = process.env.SUVEREN_DATA_DIR ?? join11(homedir8(), ".suveren");
2277
2911
  var CONTEXT_MAX_BYTES = 16 * 1024;
2278
2912
  function contextFilePath(dataDir2) {
2279
- return join11(dataDir2 ?? DEFAULT_DIR7, "context.md");
2913
+ return join11(dataDir2 ?? DEFAULT_DIR8, "context.md");
2280
2914
  }
2281
2915
  function writeContextFile(content, dataDir2) {
2282
2916
  const bytes = Buffer.byteLength(content, "utf-8");
@@ -2381,8 +3015,8 @@ var FOOTER_RE = /\n*(?:—|--) (?:Sent|Published) by (?:an AI agent|[^\n]+?'s AI
2381
3015
  function shouldAttachFooter() {
2382
3016
  return true;
2383
3017
  }
2384
- function receiptUrl(receiptId) {
2385
- return `${AS_BASE}/r/${receiptId}`;
3018
+ function receiptUrl(receiptId2) {
3019
+ return `${AS_BASE}/r/${receiptId2}`;
2386
3020
  }
2387
3021
  function verbForProfile(profile) {
2388
3022
  return profile === "publish" ? "Published" : "Sent";
@@ -2390,11 +3024,11 @@ function verbForProfile(profile) {
2390
3024
  function hapLine() {
2391
3025
  return `-- ${OPERATOR_NAME} implements HAP, the open Human Agency Protocol: ${HAP_URL}`;
2392
3026
  }
2393
- function footerText(receiptId, verb, subject) {
3027
+ function footerText(receiptId2, verb, subject) {
2394
3028
  const identity = deriveIdentityLine(subject, { operatorName: OPERATOR_NAME }).replace(/^Sent\b/, verb);
2395
3029
  return `
2396
3030
 
2397
- -- ${identity}. Receipt: ${receiptUrl(receiptId)}
3031
+ -- ${identity}. Receipt: ${receiptUrl(receiptId2)}
2398
3032
 
2399
3033
  ${hapLine()}`;
2400
3034
  }
@@ -2413,13 +3047,13 @@ function detectContentField(tool) {
2413
3047
  function stripFooter(value) {
2414
3048
  return value.replace(FOOTER_RE, "").replace(/\n+$/, "");
2415
3049
  }
2416
- function appendVerificationFooter(tool, args, receiptId, subject) {
3050
+ function appendVerificationFooter(tool, args, receiptId2, subject) {
2417
3051
  const profile = tool.gating?.profile;
2418
3052
  if (!profile || !FOOTER_PROFILES.has(profile)) return args;
2419
3053
  const field = detectContentField(tool);
2420
3054
  if (!field) return args;
2421
3055
  const current = typeof args[field] === "string" ? args[field] : "";
2422
- return { ...args, [field]: stripFooter(current) + footerText(receiptId, verbForProfile(profile), subject) };
3056
+ return { ...args, [field]: stripFooter(current) + footerText(receiptId2, verbForProfile(profile), subject) };
2423
3057
  }
2424
3058
 
2425
3059
  // src/lib/content-binding.ts
@@ -2472,10 +3106,10 @@ function computeContentBinding(profileId, tool, toolArgs, actionType) {
2472
3106
  boundContent
2473
3107
  };
2474
3108
  }
2475
- function attachReceiptId(tool, args, receiptId) {
3109
+ function attachReceiptId(tool, args, receiptId2) {
2476
3110
  const schema = tool.inputSchema;
2477
3111
  if (!schema?.properties || !("receipt_id" in schema.properties)) return args;
2478
- return { ...args, receipt_id: receiptId };
3112
+ return { ...args, receipt_id: receiptId2 };
2479
3113
  }
2480
3114
 
2481
3115
  // src/lib/ticket-verify.ts
@@ -3365,7 +3999,7 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
3365
3999
  };
3366
4000
  }
3367
4001
  }
3368
- let receiptId;
4002
+ let receiptId2;
3369
4003
  try {
3370
4004
  const actionType = declaredActionType;
3371
4005
  const binding = computeContentBinding(auth.profileId, tool, args, actionType);
@@ -3387,7 +4021,7 @@ Proposal ID: ${proposal.id}. Check status with check-pending-commitments(proposa
3387
4021
  // field by field rather than spread.
3388
4022
  ...binding ? { contentHash: binding.contentHash, contentBinding: binding.contentBinding } : {}
3389
4023
  });
3390
- receiptId = typeof receipt?.id === "string" ? receipt.id : void 0;
4024
+ receiptId2 = typeof receipt?.id === "string" ? receipt.id : void 0;
3391
4025
  await verifyTicket(state2.cache, receipt, {
3392
4026
  action: tool.namespacedName,
3393
4027
  executionContext: { ...execution },
@@ -3541,12 +4175,12 @@ Proposal ID: ${proposal.id}. Use check-pending-commitments to track status.`
3541
4175
  execution: { ...execution },
3542
4176
  timestamp: Math.floor(Date.now() / 1e3)
3543
4177
  });
3544
- let outgoingArgs = shouldAttachFooter() && receiptId ? appendVerificationFooter(tool, args, receiptId, auth.subjects?.[0]) : args;
3545
- if (receiptId) outgoingArgs = attachReceiptId(tool, outgoingArgs, receiptId);
4178
+ let outgoingArgs = shouldAttachFooter() && receiptId2 ? appendVerificationFooter(tool, args, receiptId2, auth.subjects?.[0]) : args;
4179
+ if (receiptId2) outgoingArgs = attachReceiptId(tool, outgoingArgs, receiptId2);
3546
4180
  outgoingArgs = encodeOutgoingArgs(tool, outgoingArgs);
3547
- if (receiptId) {
4181
+ if (receiptId2) {
3548
4182
  const begun = state2.executionJournal.begin({
3549
- ticketId: receiptId,
4183
+ ticketId: receiptId2,
3550
4184
  tool: tool.namespacedName,
3551
4185
  argsHash: hashToolArgs(args)
3552
4186
  });
@@ -3554,17 +4188,17 @@ Proposal ID: ${proposal.id}. Use check-pending-commitments to track status.`
3554
4188
  return {
3555
4189
  content: [{
3556
4190
  type: "text",
3557
- text: `Blocked: ticket ${receiptId} was already used to execute ${tool.namespacedName} (state: ${begun.existing.state}). Not running it again.`
4191
+ text: `Blocked: ticket ${receiptId2} was already used to execute ${tool.namespacedName} (state: ${begun.existing.state}). Not running it again.`
3558
4192
  }],
3559
4193
  isError: true
3560
4194
  };
3561
4195
  }
3562
4196
  try {
3563
4197
  const result = await integrationManager2.callTool(tool.integrationId, tool.originalName, outgoingArgs);
3564
- state2.executionJournal.complete(receiptId, "done");
4198
+ state2.executionJournal.complete(receiptId2, "done");
3565
4199
  return result;
3566
4200
  } catch (err) {
3567
- state2.executionJournal.complete(receiptId, "failed");
4201
+ state2.executionJournal.complete(receiptId2, "failed");
3568
4202
  throw err;
3569
4203
  }
3570
4204
  }
@@ -4045,7 +4679,7 @@ async function executeCommitted(proposal, state2, integrationManager2) {
4045
4679
  };
4046
4680
  }
4047
4681
  }
4048
- let receiptId;
4682
+ let receiptId2;
4049
4683
  let replayed = false;
4050
4684
  try {
4051
4685
  const binding = computeContentBinding(
@@ -4078,7 +4712,7 @@ async function executeCommitted(proposal, state2, integrationManager2) {
4078
4712
  // this machine — see the archive call below.
4079
4713
  ...binding ? { contentHash: binding.contentHash, contentBinding: binding.contentBinding } : {}
4080
4714
  });
4081
- receiptId = typeof receipt?.id === "string" ? receipt.id : void 0;
4715
+ receiptId2 = typeof receipt?.id === "string" ? receipt.id : void 0;
4082
4716
  replayed = idempotent;
4083
4717
  await verifyTicket(state2.cache, receipt, {
4084
4718
  action: proposal.tool,
@@ -4133,14 +4767,14 @@ async function executeCommitted(proposal, state2, integrationManager2) {
4133
4767
  isError: true
4134
4768
  };
4135
4769
  }
4136
- if (!receiptId) {
4770
+ if (!receiptId2) {
4137
4771
  return {
4138
4772
  text: `Proposal ${proposal.id}: the ticket carries no id \u2014 refusing to execute an action that could not be recorded.`,
4139
4773
  isError: true
4140
4774
  };
4141
4775
  }
4142
4776
  const begun = state2.executionJournal.begin({
4143
- ticketId: receiptId,
4777
+ ticketId: receiptId2,
4144
4778
  proposalId: proposal.id,
4145
4779
  tool: proposal.tool,
4146
4780
  argsHash: hashToolArgs(proposal.toolArgs)
@@ -4150,36 +4784,36 @@ async function executeCommitted(proposal, state2, integrationManager2) {
4150
4784
  const when = new Date(prior.startedAt * 1e3).toISOString();
4151
4785
  if (prior.state === "done") {
4152
4786
  return {
4153
- text: `Proposal ${proposal.id} was already executed under ticket ${receiptId} at ${when}. Not running it again.`
4787
+ text: `Proposal ${proposal.id} was already executed under ticket ${receiptId2} at ${when}. Not running it again.`
4154
4788
  };
4155
4789
  }
4156
4790
  return {
4157
- text: `Proposal ${proposal.id}: an execution under ticket ${receiptId} started at ${when} (pid ${prior.pid}) and ${prior.state === "failed" ? "reported failure" : "never reported completion"}. Not re-running: the action may already have taken effect. Check the downstream system before deciding.`,
4791
+ text: `Proposal ${proposal.id}: an execution under ticket ${receiptId2} started at ${when} (pid ${prior.pid}) and ${prior.state === "failed" ? "reported failure" : "never reported completion"}. Not re-running: the action may already have taken effect. Check the downstream system before deciding.`,
4158
4792
  isError: true
4159
4793
  };
4160
4794
  }
4161
4795
  if (replayed) {
4162
4796
  console.error(
4163
- `[Suveren MCP] Proposal ${proposal.id}: ticket ${receiptId} was replayed by the AS with no local execution record \u2014 executing once (lost-response recovery).`
4797
+ `[Suveren MCP] Proposal ${proposal.id}: ticket ${receiptId2} was replayed by the AS with no local execution record \u2014 executing once (lost-response recovery).`
4164
4798
  );
4165
4799
  }
4166
4800
  try {
4167
4801
  let outgoingArgs = proposal.toolArgs;
4168
- if (discovered && receiptId) {
4802
+ if (discovered && receiptId2) {
4169
4803
  if (shouldAttachFooter()) {
4170
- outgoingArgs = appendVerificationFooter(discovered, outgoingArgs, receiptId, cachedAuth?.subjects?.[0]);
4804
+ outgoingArgs = appendVerificationFooter(discovered, outgoingArgs, receiptId2, cachedAuth?.subjects?.[0]);
4171
4805
  }
4172
- outgoingArgs = attachReceiptId(discovered, outgoingArgs, receiptId);
4806
+ outgoingArgs = attachReceiptId(discovered, outgoingArgs, receiptId2);
4173
4807
  outgoingArgs = encodeOutgoingArgs(discovered, outgoingArgs);
4174
4808
  }
4175
4809
  let result;
4176
4810
  try {
4177
4811
  result = await integrationManager2.callTool(integrationId, toolName, outgoingArgs);
4178
4812
  } catch (err) {
4179
- state2.executionJournal.complete(receiptId, "failed");
4813
+ state2.executionJournal.complete(receiptId2, "failed");
4180
4814
  throw err;
4181
4815
  }
4182
- state2.executionJournal.complete(receiptId, "done");
4816
+ state2.executionJournal.complete(receiptId2, "done");
4183
4817
  state2.executionLog.record({
4184
4818
  profileId: proposal.profileId,
4185
4819
  path: proposal.path,
@@ -4512,9 +5146,9 @@ function verifyGateContentHashes(content, auth) {
4512
5146
 
4513
5147
  // src/lib/integration-registry.ts
4514
5148
  import { mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync10, existsSync as existsSync12 } from "fs";
4515
- import { homedir as homedir8 } from "os";
5149
+ import { homedir as homedir9 } from "os";
4516
5150
  import { dirname as dirname10, join as join12 } from "path";
4517
- var DEFAULT_DATA_DIR = process.env.SUVEREN_DATA_DIR ?? join12(homedir8(), ".suveren");
5151
+ var DEFAULT_DATA_DIR = process.env.SUVEREN_DATA_DIR ?? join12(homedir9(), ".suveren");
4518
5152
  var IntegrationRegistry = class {
4519
5153
  integrations = /* @__PURE__ */ new Map();
4520
5154
  filePath;
@@ -4591,7 +5225,7 @@ var IntegrationRegistry = class {
4591
5225
  };
4592
5226
 
4593
5227
  // src/lib/integration-manager.ts
4594
- import { homedir as homedir9 } from "os";
5228
+ import { homedir as homedir10 } from "os";
4595
5229
  import { join as join14, delimiter } from "path";
4596
5230
  import { existsSync as existsSync14, writeFileSync as writeFileSync11, mkdirSync as mkdirSync11, readFileSync as readFileSync15, rmSync } from "fs";
4597
5231
  import { execFile } from "child_process";
@@ -4730,7 +5364,7 @@ function safeHost(url) {
4730
5364
  }
4731
5365
 
4732
5366
  // src/lib/integration-manager.ts
4733
- var DEFAULT_DATA_DIR2 = process.env.SUVEREN_DATA_DIR ?? join14(homedir9(), ".suveren");
5367
+ var DEFAULT_DATA_DIR2 = process.env.SUVEREN_DATA_DIR ?? join14(homedir10(), ".suveren");
4734
5368
  var INTEGRATIONS_DIR = process.env.SUVEREN_INTEGRATIONS_DIR ?? join14(DEFAULT_DATA_DIR2, "integrations");
4735
5369
  var OFFLINE_MODE = process.env.SUVEREN_OFFLINE === "1";
4736
5370
  var installLock = Promise.resolve();
@@ -4740,6 +5374,9 @@ function withInstallLock(task) {
4740
5374
  return run;
4741
5375
  }
4742
5376
  var INTEGRATIONS_BIN = join14(INTEGRATIONS_DIR, "node_modules", ".bin");
5377
+ function getIntegrationsBinDir() {
5378
+ return INTEGRATIONS_BIN;
5379
+ }
4743
5380
  function buildPath() {
4744
5381
  const base = process.env.PATH ?? "";
4745
5382
  return [INTEGRATIONS_BIN, base].join(delimiter);
@@ -5561,6 +6198,420 @@ var IntegrationManager = class {
5561
6198
  }
5562
6199
  };
5563
6200
 
6201
+ // src/lib/report/connector-export.ts
6202
+ import { execFile as execFile2 } from "child_process";
6203
+ import { delimiter as delimiter2 } from "path";
6204
+ var DEFAULT_BIN_NAMES = {
6205
+ email: "email-mcp",
6206
+ crm: "crm-mcp",
6207
+ erp: "erp-mcp"
6208
+ };
6209
+ var ConnectorExportError = class extends Error {
6210
+ constructor(message, system, cause) {
6211
+ super(message);
6212
+ this.system = system;
6213
+ this.cause = cause;
6214
+ this.name = "ConnectorExportError";
6215
+ }
6216
+ };
6217
+ function execFileAsync(command, args, options) {
6218
+ return new Promise((resolve3, reject) => {
6219
+ execFile2(command, args, options, (err, stdout, stderr) => {
6220
+ if (err) reject(Object.assign(err, { stdout, stderr }));
6221
+ else resolve3({ stdout, stderr });
6222
+ });
6223
+ });
6224
+ }
6225
+ function createConnectorExportRunner(config) {
6226
+ return async (system) => {
6227
+ const bin = config.binNames?.[system] ?? DEFAULT_BIN_NAMES[system];
6228
+ const env = {
6229
+ ...process.env,
6230
+ PATH: [config.integrationsBinDir, process.env.PATH ?? ""].join(delimiter2),
6231
+ HAP_DATA_DIR: config.dataDir
6232
+ };
6233
+ let stdout;
6234
+ try {
6235
+ const result = await execFileAsync(bin, ["export"], {
6236
+ env,
6237
+ timeout: config.timeoutMs ?? 15e3,
6238
+ maxBuffer: 64 * 1024 * 1024,
6239
+ shell: process.platform === "win32"
6240
+ });
6241
+ stdout = result.stdout;
6242
+ } catch (err) {
6243
+ throw new ConnectorExportError(
6244
+ `${bin} export failed: ${err instanceof Error ? err.message : String(err)}`,
6245
+ system,
6246
+ err
6247
+ );
6248
+ }
6249
+ try {
6250
+ return JSON.parse(stdout);
6251
+ } catch (err) {
6252
+ throw new ConnectorExportError(
6253
+ `${bin} export did not print valid JSON on stdout`,
6254
+ system,
6255
+ err
6256
+ );
6257
+ }
6258
+ };
6259
+ }
6260
+
6261
+ // src/lib/report/render-report.ts
6262
+ import { Parser } from "htmlparser2";
6263
+ function findElementSpans(html) {
6264
+ const spans = [];
6265
+ const seenCount = /* @__PURE__ */ new Map();
6266
+ const openStack = [];
6267
+ let parserRef;
6268
+ const parser = new Parser(
6269
+ {
6270
+ onparserinit(p) {
6271
+ parserRef = p;
6272
+ },
6273
+ onopentag(name) {
6274
+ if (!name.startsWith("sv-") || !parserRef) return;
6275
+ const n = seenCount.get(name) ?? 0;
6276
+ seenCount.set(name, n + 1);
6277
+ openStack.push({ tag: name, id: `${name}-${n}`, start: parserRef.startIndex });
6278
+ },
6279
+ onclosetag(name) {
6280
+ if (!name.startsWith("sv-") || !parserRef) return;
6281
+ const idx = [...openStack].reverse().findIndex((o) => o.tag === name);
6282
+ if (idx === -1) return;
6283
+ const realIdx = openStack.length - 1 - idx;
6284
+ const [open] = openStack.splice(realIdx, 1);
6285
+ spans.push({ id: open.id, kind: open.tag, start: open.start, end: parserRef.endIndex + 1 });
6286
+ }
6287
+ },
6288
+ { decodeEntities: true, recognizeSelfClosing: true }
6289
+ );
6290
+ parser.write(html);
6291
+ parser.end();
6292
+ return spans.sort((a, b) => a.start - b.start);
6293
+ }
6294
+ function escapeHtml(value) {
6295
+ return String(value ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
6296
+ }
6297
+ function detailLink(id, ticketId) {
6298
+ const qs = ticketId ? `?element=${encodeURIComponent(id)}&ticket=${encodeURIComponent(ticketId)}` : `?element=${encodeURIComponent(id)}`;
6299
+ return `/reports${qs}`;
6300
+ }
6301
+ function badge(status, okLabel) {
6302
+ if (status === "verified") return `<span class="sv-badge sv-badge-ok">\u2713 ${escapeHtml(okLabel)}</span>`;
6303
+ if (status === "warning") return `<span class="sv-badge sv-badge-warn">\u26A0 verified with a note</span>`;
6304
+ return `<span class="sv-badge sv-badge-bad">\u2717 not verifiable</span>`;
6305
+ }
6306
+ function unverifiableCard(el) {
6307
+ return `<div class="sv-el sv-el-unverifiable" data-sv-id="${escapeHtml(el.id)}"><div class="sv-el-row"><b>Not verifiable</b>${badge("unverifiable", "")}</div><div class="sv-el-reason">${escapeHtml(el.reason ?? "This reference could not be checked.")}</div></div>`;
6308
+ }
6309
+ function renderTicket(el, interactive) {
6310
+ if (el.status === "unverifiable" || !el.data) return unverifiableCard(el);
6311
+ const d = el.data;
6312
+ const href = typeof d.checkUrl === "string" ? d.checkUrl : void 0;
6313
+ const actionLabel = typeof d.actionLabel === "string" ? d.actionLabel : formatActionLabel(d.action);
6314
+ const timeLabel = typeof d.timeLabel === "string" ? d.timeLabel : formatDateTime(d.time);
6315
+ const profileLabel = typeof d.profileLabel === "string" ? d.profileLabel : escapeHtml(d.profile ?? "");
6316
+ const links = [
6317
+ href ? `<a href="${escapeHtml(href)}" target="_blank" rel="noopener noreferrer">Check on suveren.ai \u2197</a>` : "",
6318
+ interactive ? `<a href="${escapeHtml(detailLink(el.id))}" target="_top">Details</a>` : ""
6319
+ ].filter(Boolean);
6320
+ return `<div class="sv-el sv-el-${el.status}" data-sv-id="${escapeHtml(el.id)}"><div class="sv-el-row"><b>${escapeHtml(actionLabel)}</b>${badge(el.status, "signature valid")}</div><div class="sv-el-row"><span>${escapeHtml(profileLabel)} \xB7 ${escapeHtml(timeLabel)}</span></div>` + (links.length > 0 ? `<div class="sv-el-row"><span>${links.join(" \xB7 ")}</span></div>` : "") + `</div>`;
6321
+ }
6322
+ function renderApproval(el, interactive) {
6323
+ if (el.status === "unverifiable" || !el.data) return unverifiableCard(el);
6324
+ const d = el.data;
6325
+ const who = typeof d.whoLabel === "string" ? d.whoLabel : Array.isArray(d.who) ? d.who.join(", ") : "unknown";
6326
+ const asked = typeof d.createdAtLabel === "string" ? d.createdAtLabel : "unknown";
6327
+ const approved = typeof d.decidedAtLabel === "string" ? d.decidedAtLabel : "unknown";
6328
+ const waited = typeof d.waitLabel === "string" ? d.waitLabel : "unknown";
6329
+ return `<div class="sv-el sv-el-${el.status}" data-sv-id="${escapeHtml(el.id)}"><div class="sv-el-row"><b>Approval</b>${badge(el.status, "from ticket archive")}</div><div class="sv-el-row"><span>asked ${escapeHtml(asked)} \xB7 approved ${escapeHtml(approved)} by ${escapeHtml(who)} (${escapeHtml(waited)})</span></div>` + (interactive ? `<div class="sv-el-row"><a href="${escapeHtml(detailLink(el.id, String(d.ticketId ?? "")))}" target="_top">Details</a></div>` : "") + `</div>`;
6330
+ }
6331
+ function renderMandate(el, interactive) {
6332
+ if (el.status === "unverifiable" || !el.data) return unverifiableCard(el);
6333
+ const d = el.data;
6334
+ const profileLabel = typeof d.profileLabel === "string" ? d.profileLabel : String(d.profile ?? "");
6335
+ const owners = Array.isArray(d.owners) && d.owners.length > 0 ? d.owners.join(", ") : "unknown owner";
6336
+ const limits = Array.isArray(d.limits) && d.limits.length > 0 ? d.limits.join(" \xB7 ") : "";
6337
+ return `<div class="sv-el sv-el-${el.status}" data-sv-id="${escapeHtml(el.id)}"><div class="sv-el-row"><b>${escapeHtml(profileLabel)} \xB7 ${escapeHtml(owners)}</b>${badge(el.status, "matches ticket")}</div>` + (limits ? `<div class="sv-el-row">${escapeHtml(limits)}${d.mode ? ` \xB7 ${escapeHtml(d.mode)}` : ""}</div>` : "") + (d.intent ? `<div class="sv-el-intent">Intent: \u201C${escapeHtml(d.intent)}\u201D</div>` : "") + (interactive ? `<div class="sv-el-row"><a href="${escapeHtml(detailLink(el.id))}" target="_top">Details</a></div>` : "") + `</div>`;
6338
+ }
6339
+ var RECORD_FIELD_ORDER = [
6340
+ "subject",
6341
+ "from_email",
6342
+ "from_name",
6343
+ "to_json",
6344
+ "received_at",
6345
+ "number",
6346
+ "status",
6347
+ "net_total",
6348
+ "customer_id",
6349
+ "causingReceiptId",
6350
+ "message"
6351
+ ];
6352
+ var RECORD_TIME_FIELDS = /* @__PURE__ */ new Set(["received_at", "created_at", "sent_at"]);
6353
+ function renderRecordField(key, d) {
6354
+ if (key === "net_total") {
6355
+ const currency = typeof d.currency === "string" ? d.currency : void 0;
6356
+ return `<div class="sv-el-row"><span>Value</span><span>${escapeHtml(formatCurrency(d.net_total, currency))}</span></div>`;
6357
+ }
6358
+ if (RECORD_TIME_FIELDS.has(key)) {
6359
+ const t = parseTimestampSeconds(d[key]);
6360
+ const display = t !== void 0 ? formatDateTime(t) : d[key];
6361
+ return `<div class="sv-el-row"><span>${escapeHtml(key)}</span><span>${escapeHtml(display)}</span></div>`;
6362
+ }
6363
+ return `<div class="sv-el-row"><span>${escapeHtml(key)}</span><span>${escapeHtml(d[key])}</span></div>`;
6364
+ }
6365
+ function renderRecord(el) {
6366
+ if (el.status === "unverifiable" || !el.data) return unverifiableCard(el);
6367
+ const d = el.data;
6368
+ const kind = String(d.kind ?? "record");
6369
+ const rows = RECORD_FIELD_ORDER.filter((k) => d[k] !== void 0 && d[k] !== null && d[k] !== "").slice(0, 5).map((k) => renderRecordField(k, d)).join("");
6370
+ return `<div class="sv-el sv-el-${el.status}" data-sv-id="${escapeHtml(el.id)}"><div class="sv-el-row"><b>${escapeHtml(kind)} record</b>${badge(el.status, "in simulator database")}</div>` + rows + `</div>`;
6371
+ }
6372
+ function renderCaseTicketStep(caseElementId, node, isGoal, interactive) {
6373
+ const cls = isGoal ? "sv-step sv-step-goal" : "sv-step";
6374
+ const kind = isGoal ? "goal" : "ticket";
6375
+ const inner = `<div class="sv-step-k">${kind}</div><div class="sv-step-t">${escapeHtml(formatActionLabel(node.action))}</div>${formatDateTime(node.time)}`;
6376
+ if (!interactive) return `<div class="${cls}">${inner}</div>`;
6377
+ return `<a class="${cls}" href="${escapeHtml(detailLink(caseElementId, node.ticketId))}" target="_top">${inner}</a>`;
6378
+ }
6379
+ function renderCaseApprovalStep(approval) {
6380
+ const who = approval.whoLabel ?? (Array.isArray(approval.who) ? approval.who.join(", ") : "unknown");
6381
+ const asked = approval.createdAtLabel ?? "unknown";
6382
+ const decided = approval.decidedAtLabel ?? "unknown";
6383
+ const waited = approval.waitLabel ?? "unknown";
6384
+ return `<div class="sv-step sv-step-approval"><div class="sv-step-k">approval</div><div class="sv-step-t">Approval</div><div class="sv-step-sub">asked ${escapeHtml(asked)} \xB7 approved ${escapeHtml(decided)} by ${escapeHtml(who)} (${escapeHtml(waited)})</div></div>`;
6385
+ }
6386
+ function renderCase(el, interactive) {
6387
+ if (el.status === "unverifiable" || !el.data) return unverifiableCard(el);
6388
+ const d = el.data;
6389
+ const steps = Array.isArray(d.steps) ? d.steps : [];
6390
+ const goal = d.goal;
6391
+ const approvalsByTicket = /* @__PURE__ */ new Map();
6392
+ if (Array.isArray(d.approvals)) {
6393
+ for (const a of d.approvals) {
6394
+ approvalsByTicket.set(a.ticketId, a);
6395
+ }
6396
+ }
6397
+ const start = d.start;
6398
+ const startStep = start ? { time: start.time, html: `<div class="sv-step"><div class="sv-step-k">start</div><div class="sv-step-t">Email in</div>${formatDateTime(start.time)}</div>` } : void 0;
6399
+ const ticketNodes = [
6400
+ ...steps.map((s) => ({ node: s, isGoal: false })),
6401
+ ...goal ? [{ node: goal, isGoal: true }] : []
6402
+ ];
6403
+ const items = [];
6404
+ if (startStep) items.push(startStep);
6405
+ for (const { node, isGoal } of ticketNodes) {
6406
+ const approval = approvalsByTicket.get(node.ticketId);
6407
+ if (approval) {
6408
+ const approvalTime = Math.min(approval.decidedAt ?? approval.createdAt ?? node.time, node.time);
6409
+ items.push({ time: approvalTime, html: renderCaseApprovalStep(approval) });
6410
+ }
6411
+ items.push({ time: node.time, html: renderCaseTicketStep(el.id, node, isGoal, interactive) });
6412
+ }
6413
+ items.sort((a, b) => a.time - b.time);
6414
+ const stepHtml = items.map((i) => i.html).join("");
6415
+ return `<div class="sv-el sv-el-${el.status}" data-sv-id="${escapeHtml(el.id)}"><div class="sv-el-row"><b>Case ${escapeHtml(d.caseId)} \xB7 ${formatDuration(d.totalDurationSeconds)}</b>${badge(el.status, "assembled by gateway")}</div>` + (el.status === "warning" && el.reason ? `<div class="sv-el-warn">${escapeHtml(el.reason)}</div>` : "") + `<div class="sv-tl">${stepHtml}</div>` + (interactive ? `<div class="sv-el-row"><a href="${escapeHtml(detailLink(el.id))}" target="_top">Case details</a></div>` : "") + `</div>`;
6416
+ }
6417
+ function renderMetric(el) {
6418
+ if (el.status === "unverifiable" || !el.data) return unverifiableCard(el);
6419
+ const d = el.data;
6420
+ const kind = String(d.kind ?? "");
6421
+ const label = METRIC_LABELS[kind] ?? kind;
6422
+ const display = formatMetricValue(kind, d.value);
6423
+ return `<div class="sv-el sv-el-${el.status} sv-el-metric" data-sv-id="${escapeHtml(el.id)}"><div class="sv-big">${escapeHtml(display)}</div><div class="sv-el-row"><span>${escapeHtml(label)} (${escapeHtml(d.caseCount ?? 0)} case${d.caseCount === 1 ? "" : "s"})</span>${badge(el.status, "computed by gateway")}</div>` + (el.status === "warning" && el.reason ? `<div class="sv-el-warn">${escapeHtml(el.reason)}</div>` : "") + `</div>`;
6424
+ }
6425
+ function renderElement(el, interactive) {
6426
+ switch (el.kind) {
6427
+ case "sv-ticket":
6428
+ return renderTicket(el, interactive);
6429
+ case "sv-approval":
6430
+ return renderApproval(el, interactive);
6431
+ case "sv-mandate":
6432
+ return renderMandate(el, interactive);
6433
+ case "sv-record":
6434
+ return renderRecord(el);
6435
+ case "sv-case":
6436
+ return renderCase(el, interactive);
6437
+ case "sv-metric":
6438
+ return renderMetric(el);
6439
+ default:
6440
+ return unverifiableCard(el);
6441
+ }
6442
+ }
6443
+ var DRAWN_ELEMENT_STYLES = `
6444
+ .sv-el { border:1px solid #e5e5e5; border-radius:10px; padding:10px 12px; margin:10px 0; font:13px/1.5 system-ui, sans-serif; background:#fff; }
6445
+ .sv-el-unverifiable { outline:2px solid #b91c1c; outline-offset:2px; }
6446
+ .sv-el-verified, .sv-el-warning { outline:2px solid #15803d; outline-offset:2px; }
6447
+ .sv-el-row { display:flex; justify-content:space-between; gap:10px; flex-wrap:wrap; margin:2px 0; }
6448
+ .sv-el-reason, .sv-el-warn { color:#b45309; font-size:12px; margin-top:4px; }
6449
+ .sv-el-intent { color:#666; font-size:12px; margin-top:4px; }
6450
+ .sv-badge { display:inline-flex; gap:4px; font-size:10.5px; font-weight:600; padding:1px 7px; border-radius:999px; white-space:nowrap; }
6451
+ .sv-badge-ok { color:#15803d; background:#ecfdf3; }
6452
+ .sv-badge-warn { color:#b45309; background:#fff7e6; }
6453
+ .sv-badge-bad { color:#b91c1c; background:#fdecea; }
6454
+ .sv-big { font-size:24px; font-weight:700; }
6455
+ .sv-tl { display:flex; flex-wrap:wrap; gap:10px 16px; padding:6px 0; }
6456
+ .sv-step { min-width:100px; border:1px solid #e5e5e5; border-radius:8px; padding:6px 8px; font-size:11.5px; text-decoration:none; color:inherit; flex-shrink:0; }
6457
+ .sv-step-k { font-size:9.5px; text-transform:uppercase; color:#666; }
6458
+ .sv-step-t { font-weight:600; font-size:12px; }
6459
+ .sv-step-sub { color:#666; white-space:normal; }
6460
+ /* The approval step's text ("asked ... approved ... by ... (duration)") is
6461
+ * longer than a ticket step's \u2014 without a width to wrap against, a
6462
+ * flex item with flex-shrink:0 takes its one-line content width instead of
6463
+ * wrapping, which reads as the text being cut off at the container's visible
6464
+ * edge (polish 2026-10-05, second pass). */
6465
+ .sv-step-approval { max-width:240px; white-space:normal; }
6466
+ @media (max-width: 480px) {
6467
+ .sv-tl { flex-direction:column; overflow-x:visible; }
6468
+ .sv-step { min-width:0; }
6469
+ .sv-step-approval { max-width:none; }
6470
+ .sv-el-row { flex-direction:column; gap:2px; }
6471
+ }
6472
+ `;
6473
+ function renderReportHtml(html, elements, interactive = true) {
6474
+ const byId = new Map(elements.map((e) => [e.id, e]));
6475
+ const spans = findElementSpans(html);
6476
+ let out = "";
6477
+ let cursor = 0;
6478
+ for (const span of spans) {
6479
+ out += html.slice(cursor, span.start);
6480
+ const el = byId.get(span.id) ?? { id: span.id, kind: span.kind, attrs: {}, status: "unverifiable", reason: "No verification result for this element." };
6481
+ out += renderElement(el, interactive);
6482
+ cursor = span.end;
6483
+ }
6484
+ out += html.slice(cursor);
6485
+ const styleTag = `<style data-sv-drawn-styles="1">${DRAWN_ELEMENT_STYLES}</style>`;
6486
+ if (/<body[^>]*>/i.test(out)) {
6487
+ return out.replace(/<body([^>]*)>/i, (m) => `${m}${styleTag}`);
6488
+ }
6489
+ return styleTag + out;
6490
+ }
6491
+
6492
+ // src/lib/report/ticket-details.ts
6493
+ async function buildTicketDetails(archive, ticketIds) {
6494
+ const out = {};
6495
+ for (const id of ticketIds) {
6496
+ const [ticket, approval, mandate] = await Promise.all([
6497
+ resolveTicketElement(archive, id),
6498
+ resolveApprovalElement(archive, id),
6499
+ resolveMandateElement(archive, id)
6500
+ ]);
6501
+ out[id] = { ticket, approval, mandate };
6502
+ }
6503
+ return out;
6504
+ }
6505
+
6506
+ // src/lib/report/export-report.ts
6507
+ function receiptId(receipt) {
6508
+ return typeof receipt.id === "string" ? receipt.id : "";
6509
+ }
6510
+ function buildExportBundle(params) {
6511
+ const { stored, archive, authorityServer, gatewayVersion, now = Math.floor(Date.now() / 1e3) } = params;
6512
+ const proof = stored.result.proof;
6513
+ const coverage = stored.result.coverage;
6514
+ const ticketIdSet = /* @__PURE__ */ new Set([...proof.ticketsReferenced, ...coverage.ticketsInPeriod]);
6515
+ const entries = archive.getReceipts().filter((r) => ticketIdSet.has(receiptId(r.receipt)));
6516
+ const tickets = entries.map((r) => r.receipt);
6517
+ const authorizationIds = new Set(entries.map((r) => r.authorizationId));
6518
+ const authorizations = {};
6519
+ for (const a of archive.getAuthorizations()) {
6520
+ if (authorizationIds.has(a.authorizationId)) authorizations[a.authorizationId] = a;
6521
+ }
6522
+ return {
6523
+ format: "suveren-report-export",
6524
+ version: 1,
6525
+ exportedAt: now,
6526
+ gatewayVersion,
6527
+ report: { html: stored.html, savedAt: stored.savedAt, checkedAt: stored.checkedAt },
6528
+ proof,
6529
+ coverage,
6530
+ authorityServer,
6531
+ tickets,
6532
+ authorizations
6533
+ };
6534
+ }
6535
+ function countLine(count, noneText = "none in this report") {
6536
+ return count > 0 ? `${count} \u2713` : noneText;
6537
+ }
6538
+ function renderProofCoveragePanels(proof, coverage) {
6539
+ const casesLine = coverage.emailExportError ? "unknown \u2014 the email simulator could not be read" : `${coverage.coveredCases.length} of ${coverage.loadedCases.length}`;
6540
+ const periodNote = coverage.periodStart === null ? `<p class="sv-export-note">${coverage.emailExportError ? "Test period start unknown \u2014 the email simulator could not be read. All saved tickets were counted." : "Test period start unknown \u2014 all saved tickets were counted."}</p>` : "";
6541
+ const missingParts = [];
6542
+ if (coverage.missingCases.length > 0) missingParts.push(`cases ${coverage.missingCases.map(escapeHtml).join(", ")}`);
6543
+ if (coverage.ticketsNotReferenced.length > 0) missingParts.push(`${coverage.ticketsNotReferenced.length} ticket${coverage.ticketsNotReferenced.length === 1 ? "" : "s"}`);
6544
+ const missingLine = missingParts.length > 0 ? `<p class="sv-export-missing">Not in the report: ${missingParts.join(" \xB7 ")}</p>` : "";
6545
+ const checkedValues = proof.verifiedValues.length > 0 ? `<div class="sv-export-card"><div class="sv-export-card-title">Checked values</div>${proof.verifiedValues.map((v) => `<div class="sv-export-row"><span>${escapeHtml(v.summary)}</span></div>`).join("")}</div>` : "";
6546
+ return `<aside class="sv-export-side"><div class="sv-export-card"><div class="sv-export-card-title">Proof</div><div class="sv-export-row"><span>Tickets referenced</span><b>${proof.ticketsReferenced.length}</b></div><div class="sv-export-row"><span>Signatures valid</span><b>${escapeHtml(countLine(proof.signaturesValid))}</b></div><div class="sv-export-row"><span>Records checked</span><b>${escapeHtml(countLine(proof.recordsChecked))}</b></div><div class="sv-export-row"><span>Not verifiable</span><b>${proof.unverifiableCount}</b></div></div><div class="sv-export-card"><div class="sv-export-card-title">Coverage</div><div class="sv-export-row"><span>Cases</span><b>${casesLine}</b></div><div class="sv-export-row"><span>Tickets in test period</span><b>${coverage.ticketsReferenced.length} of ${coverage.ticketsInPeriod.length}</b></div>` + periodNote + missingLine + `</div>` + checkedValues + `</aside>`;
6547
+ }
6548
+ function ensureHtmlDocument(html) {
6549
+ if (/<html[^>]*>/i.test(html)) return html;
6550
+ return `<!doctype html><html><head><meta charset="utf-8"></head><body>${html}</body></html>`;
6551
+ }
6552
+ function injectIntoHead(html, insert) {
6553
+ if (/<head[^>]*>/i.test(html)) return html.replace(/<head([^>]*)>/i, (m) => `${m}${insert}`);
6554
+ if (/<html[^>]*>/i.test(html)) return html.replace(/<html([^>]*)>/i, (m) => `${m}<head>${insert}</head>`);
6555
+ return `<head>${insert}</head>${html}`;
6556
+ }
6557
+ function injectAfterBodyOpen(html, insert) {
6558
+ if (/<body[^>]*>/i.test(html)) return html.replace(/<body([^>]*)>/i, (m) => `${m}${insert}`);
6559
+ return `${insert}${html}`;
6560
+ }
6561
+ function injectBeforeBodyClose(html, insert) {
6562
+ if (/<\/body>/i.test(html)) return html.replace(/<\/body>/i, `${insert}</body>`);
6563
+ return `${html}${insert}`;
6564
+ }
6565
+ var EXPORT_PAGE_STYLES = `
6566
+ .sv-export-header { font:13px/1.5 system-ui, sans-serif; background:#f6f6f4; border-bottom:1px solid #e5e5e5; padding:14px 20px; }
6567
+ .sv-export-meta { margin:0 0 6px 0; font-weight:600; }
6568
+ .sv-export-howto { margin:0; color:#444; }
6569
+ .sv-export-howto code { background:#eee; border-radius:4px; padding:1px 5px; font-size:12px; }
6570
+ .sv-export-layout { display:flex; gap:20px; align-items:flex-start; padding:20px; font:13px/1.5 system-ui, sans-serif; }
6571
+ .sv-export-main { flex:1 1 auto; min-width:0; }
6572
+ .sv-export-side { flex:0 0 260px; }
6573
+ .sv-export-card { border:1px solid #e5e5e5; border-radius:10px; padding:10px 12px; margin-bottom:12px; background:#fff; }
6574
+ .sv-export-card-title { font-weight:700; margin-bottom:6px; }
6575
+ .sv-export-row { display:flex; justify-content:space-between; gap:10px; margin:2px 0; }
6576
+ .sv-export-note, .sv-export-missing { color:#b45309; font-size:12px; margin:4px 0 0 0; }
6577
+ @media (max-width: 720px) {
6578
+ .sv-export-layout { flex-direction:column; }
6579
+ .sv-export-side { flex:1 1 auto; width:100%; }
6580
+ }
6581
+ `;
6582
+ function formatDateTimeWithYear(value) {
6583
+ const base = formatDateTime(value);
6584
+ const year = new Date(value * 1e3).getFullYear();
6585
+ return base.replace(",", ` ${year},`);
6586
+ }
6587
+ function utcOffsetLabel(value) {
6588
+ const offsetMin = -new Date(value * 1e3).getTimezoneOffset();
6589
+ const sign = offsetMin >= 0 ? "+" : "-";
6590
+ const abs = Math.abs(offsetMin);
6591
+ const hh = Math.floor(abs / 60);
6592
+ const mm = abs % 60;
6593
+ return `UTC${sign}${hh}${mm ? ":" + String(mm).padStart(2, "0") : ""}`;
6594
+ }
6595
+ function buildExportDocument(params) {
6596
+ const { bundle, renderedHtml } = params;
6597
+ const exportedDate = new Date(bundle.exportedAt * 1e3).toISOString().slice(0, 10);
6598
+ const exportedLabel = formatDateTimeWithYear(bundle.exportedAt);
6599
+ const checkedLabel = formatDateTime(bundle.report.checkedAt);
6600
+ const tzLabel = utcOffsetLabel(bundle.exportedAt);
6601
+ const headerHtml = `<div class="sv-export-header"><p class="sv-export-meta">Suveren Gateway ${escapeHtml(bundle.gatewayVersion)} \u2014 exported ${escapeHtml(exportedLabel)} &middot; checked ${escapeHtml(checkedLabel)} (times in ${escapeHtml(tzLabel)})</p><p class="sv-export-howto">How to check this report: each ticket below links to its public record on suveren.ai ("Check on suveren.ai \u2197"). To verify this entire file offline (including every signature), run <code>suveren-gateway verify-report ${escapeHtml(suggestedFilename(bundle))}</code> from a terminal with the Suveren gateway CLI installed.</p></div>`;
6602
+ const proofScriptJson = JSON.stringify(bundle).replace(/<\//g, "<\\/");
6603
+ const proofScript = `<script type="application/json" id="suveren-proof">${proofScriptJson}</script>`;
6604
+ let doc = ensureHtmlDocument(renderedHtml);
6605
+ doc = injectIntoHead(doc, `<meta charset="utf-8"><title>Suveren report export \u2014 ${escapeHtml(exportedDate)}</title><style>${DRAWN_ELEMENT_STYLES}${EXPORT_PAGE_STYLES}</style>`);
6606
+ doc = injectAfterBodyOpen(doc, headerHtml + `<div class="sv-export-layout"><div class="sv-export-main">`);
6607
+ doc = injectBeforeBodyClose(doc, `</div>${renderProofCoveragePanels(bundle.proof, bundle.coverage)}</div>${proofScript}`);
6608
+ return doc;
6609
+ }
6610
+ function suggestedFilename(bundle) {
6611
+ const date = new Date(bundle.exportedAt * 1e3).toISOString().slice(0, 10);
6612
+ return `suveren-report-${date}.html`;
6613
+ }
6614
+
5564
6615
  // src/lib/profile-loader.ts
5565
6616
  import { readFileSync as readFileSync16, existsSync as existsSync15 } from "fs";
5566
6617
  import { join as join15, resolve as resolve2 } from "path";
@@ -5620,6 +6671,251 @@ function builtinText(text) {
5620
6671
  return { content: [{ type: "text", text }] };
5621
6672
  }
5622
6673
 
6674
+ // src/lib/builtins/report.ts
6675
+ var MAX_REPORT_HTML_BYTES = 512 * 1024;
6676
+ var READ_GATE = { category: "read", boundField: "read_access", requiredValue: "unlimited" };
6677
+ var EMAIL_RECORD_KINDS = ["inbox", "sent", "changes", "refusals"];
6678
+ var ERP_RECORD_KINDS = ["quotes", "orders", "changes", "refusals"];
6679
+ var CRM_RECORD_KINDS = ["contacts", "deals", "tasks", "activities", "changes", "refusals"];
6680
+ function errorText(text) {
6681
+ return { content: [{ type: "text", text }], isError: true };
6682
+ }
6683
+ function listTicketsTool(deps) {
6684
+ return {
6685
+ name: "list_tickets",
6686
+ description: "List tickets (signed executions) from the local receipt archive: id, time, action, action type, profile, authorizationId, the limits used, and whether an approval was archived for it. Optionally filter by since/until (unix seconds). Use the ids with get_ticket for full detail, and with <sv-ticket>, <sv-approval>, <sv-mandate> and <sv-case> in the report.",
6687
+ inputSchema: {
6688
+ type: "object",
6689
+ properties: {
6690
+ since: { type: "number", description: "Only tickets timestamped at or after this unix-seconds value." },
6691
+ until: { type: "number", description: "Only tickets timestamped at or before this unix-seconds value." }
6692
+ }
6693
+ },
6694
+ handler: async (args) => {
6695
+ const since = typeof args.since === "number" ? args.since : void 0;
6696
+ const until = typeof args.until === "number" ? args.until : void 0;
6697
+ const tickets = deps.reportSources.archive.getReceipts().map((entry) => {
6698
+ const r = entry.receipt;
6699
+ const time = typeof r.timestamp === "number" ? r.timestamp : void 0;
6700
+ return {
6701
+ id: typeof r.id === "string" ? r.id : String(r.id ?? ""),
6702
+ time,
6703
+ action: r.action,
6704
+ actionType: r.actionType ?? null,
6705
+ profile: r.profileId,
6706
+ authorizationId: r.authorizationId,
6707
+ limitsUsed: r.limits ?? r.executionContext ?? {},
6708
+ hasApproval: Boolean(entry.proposal)
6709
+ };
6710
+ }).filter((t) => t.id !== "").filter((t) => since === void 0 || t.time !== void 0 && t.time >= since).filter((t) => until === void 0 || t.time !== void 0 && t.time <= until).sort((a, b) => (a.time ?? 0) - (b.time ?? 0));
6711
+ return builtinText(JSON.stringify({ tickets }, null, 2));
6712
+ }
6713
+ };
6714
+ }
6715
+ function getTicketTool(deps) {
6716
+ return {
6717
+ name: "get_ticket",
6718
+ description: 'Full detail for one ticket: the ticket itself (action, time, limits used, public-check link), its archived approval (who approved it, when it was requested and decided, how long it waited), and the mandate it ran under (limits, commitment mode, intent). Each part reports "unverifiable" on its own if it could not be checked \u2014 e.g. an automatic-mode ticket has no approval. Use this to decide what a ticket actually proves before referencing it in the report.',
6719
+ inputSchema: {
6720
+ type: "object",
6721
+ properties: { id: { type: "string", description: "The ticket id, as listed by list_tickets." } },
6722
+ required: ["id"]
6723
+ },
6724
+ handler: async (args) => {
6725
+ const id = typeof args.id === "string" ? args.id.trim() : "";
6726
+ if (!id) return errorText("id is required.");
6727
+ const details = await buildTicketDetails(deps.reportSources.archive, [id]);
6728
+ const detail = details[id];
6729
+ if (!detail || detail.ticket.status !== "verified") {
6730
+ return errorText(detail?.ticket.reason ?? `No ticket "${id}" in the local archive.`);
6731
+ }
6732
+ return builtinText(JSON.stringify({
6733
+ ticket: detail.ticket.data,
6734
+ approval: detail.approval.status === "verified" ? { verified: true, ...detail.approval.data } : { verified: false, reason: detail.approval.reason },
6735
+ mandate: detail.mandate.status === "verified" ? { verified: true, ...detail.mandate.data } : { verified: false, reason: detail.mandate.reason }
6736
+ }, null, 2));
6737
+ }
6738
+ };
6739
+ }
6740
+ function listCasesTool(deps) {
6741
+ return {
6742
+ name: "list_cases",
6743
+ description: "Loaded business cases from the connected email system, plus every sent mail \u2014 so you can define sv-case elements without guessing ids. Returns: when the test data was loaded (testDataLoadedAt); cases (caseId, the starting inbox message id, sender, subject, received time); and sent mails (id, inReplyTo, the receiptId of the ticket that sent it, subject, sentAt) so you can confirm which ticket closed which case. Never includes the team's own reference replies \u2014 those are not part of this report.",
6744
+ inputSchema: { type: "object", properties: {} },
6745
+ handler: async () => {
6746
+ let exported;
6747
+ try {
6748
+ exported = await deps.reportSources.runExport("email");
6749
+ } catch (err) {
6750
+ return errorText(`Could not read email records: ${err instanceof Error ? err.message : String(err)}`);
6751
+ }
6752
+ if (!isEmailExport(exported)) return errorText("Email records were returned in an unexpected shape.");
6753
+ const exp = exported;
6754
+ const cases = exp.inbox.filter((m) => !!m.case_id).map((m) => ({
6755
+ caseId: m.case_id,
6756
+ startMessageId: m.id,
6757
+ from: m.from_email,
6758
+ subject: m.subject,
6759
+ receivedAt: m.received_at
6760
+ }));
6761
+ const sent = exp.sent.map((m) => ({
6762
+ id: m.id,
6763
+ inReplyTo: m.in_reply_to ?? null,
6764
+ receiptId: m.receipt_id ?? null,
6765
+ subject: m.subject,
6766
+ sentAt: m.received_at
6767
+ }));
6768
+ return builtinText(JSON.stringify({
6769
+ testDataLoadedAt: exp.simulation_load?.loaded_at ?? null,
6770
+ cases,
6771
+ sent
6772
+ }, null, 2));
6773
+ }
6774
+ };
6775
+ }
6776
+ function recordKindsFor(system) {
6777
+ if (system === "email") return EMAIL_RECORD_KINDS;
6778
+ if (system === "erp") return ERP_RECORD_KINDS;
6779
+ return CRM_RECORD_KINDS;
6780
+ }
6781
+ function getRecordsTool(deps) {
6782
+ return {
6783
+ name: "get_records",
6784
+ description: `Rows from one connected system (email, erp or crm) that you may reference with <sv-record system="..." ref="...">. Optionally narrow to one table via "kind" (email: inbox/sent/changes/refusals; erp: quotes/orders/changes/refusals; crm: contacts/deals/tasks/activities/changes/refusals) \u2014 omit it to get every table for that system. Never returns the team's own reference replies.`,
6785
+ inputSchema: {
6786
+ type: "object",
6787
+ properties: {
6788
+ system: { type: "string", enum: ["email", "erp", "crm"] },
6789
+ kind: { type: "string", description: "Optional: one table name within that system's records." }
6790
+ },
6791
+ required: ["system"]
6792
+ },
6793
+ handler: async (args) => {
6794
+ const system = args.system;
6795
+ if (system !== "email" && system !== "erp" && system !== "crm") {
6796
+ return errorText('system must be one of "email", "erp", "crm".');
6797
+ }
6798
+ let exported;
6799
+ try {
6800
+ exported = await deps.reportSources.runExport(system);
6801
+ } catch (err) {
6802
+ return errorText(`Could not read ${system} records: ${err instanceof Error ? err.message : String(err)}`);
6803
+ }
6804
+ const ok = system === "email" ? isEmailExport(exported) : system === "erp" ? isErpExport(exported) : isCrmExport(exported);
6805
+ if (!ok) return errorText(`${system} records were returned in an unexpected shape.`);
6806
+ const allowedKinds = recordKindsFor(system);
6807
+ const requestedKind = typeof args.kind === "string" ? args.kind : void 0;
6808
+ if (requestedKind && !allowedKinds.includes(requestedKind)) {
6809
+ return errorText(`kind must be one of ${allowedKinds.join(", ")} for system "${system}".`);
6810
+ }
6811
+ const kinds = requestedKind ? [requestedKind] : allowedKinds;
6812
+ const records = {};
6813
+ const exp = exported;
6814
+ for (const kind of kinds) {
6815
+ records[kind] = exp[kind] ?? [];
6816
+ }
6817
+ return builtinText(JSON.stringify({ system, records }, null, 2));
6818
+ }
6819
+ };
6820
+ }
6821
+ function summarizeWrite(result) {
6822
+ const verified = result.elements.filter((e) => e.status === "verified");
6823
+ const warnings = result.elements.filter((e) => e.status === "warning");
6824
+ const unverifiable = result.elements.filter((e) => e.status === "unverifiable");
6825
+ const lines = [];
6826
+ lines.push(
6827
+ `Report stored. ${verified.length} element(s) verified, ${warnings.length} warning(s), ${unverifiable.length} not verifiable.`
6828
+ );
6829
+ if (warnings.length > 0) {
6830
+ lines.push("Warnings:");
6831
+ for (const w of warnings) lines.push(` - ${w.kind} (${w.id}): ${w.reason ?? "unspecified"}`);
6832
+ }
6833
+ if (unverifiable.length > 0) {
6834
+ lines.push("Not verifiable \u2014 fix these references and write again:");
6835
+ for (const u of unverifiable) lines.push(` - ${u.kind} (${u.id}): ${u.reason ?? "unspecified"}`);
6836
+ }
6837
+ const cov = result.coverage;
6838
+ if (cov.emailExportError) {
6839
+ lines.push(`Coverage could not be checked: ${cov.emailExportError}`);
6840
+ } else {
6841
+ lines.push(`Coverage: ${cov.coveredCases.length} of ${cov.loadedCases.length} loaded case(s) covered.`);
6842
+ if (cov.missingCases.length > 0) lines.push(`Missing cases (not defined with sv-case): ${cov.missingCases.join(", ")}`);
6843
+ if (cov.ticketsNotReferenced.length > 0) {
6844
+ lines.push(`Tickets from the test period not referenced anywhere in the report: ${cov.ticketsNotReferenced.join(", ")}`);
6845
+ }
6846
+ }
6847
+ return lines.join("\n");
6848
+ }
6849
+ function writeReportRefusal(args) {
6850
+ const html = typeof args.html === "string" ? args.html : "";
6851
+ if (!html.trim()) return "`html` must be a non-empty string.";
6852
+ const bytes = Buffer.byteLength(html, "utf8");
6853
+ if (bytes > MAX_REPORT_HTML_BYTES) {
6854
+ return `the report is ${bytes} bytes, over the ${MAX_REPORT_HTML_BYTES}-byte limit. Shorten it (the gateway draws the verifiable elements for you \u2014 you do not need to inline their data) and write again.`;
6855
+ }
6856
+ return void 0;
6857
+ }
6858
+ function writeReportTool(deps) {
6859
+ return {
6860
+ name: "write_report",
6861
+ // The brief IS the description — this is how it reaches the AI (R3/R4 plan,
6862
+ // the same pattern mail.json's load_simulation uses for its package guide).
6863
+ description: REPORT_BRIEF,
6864
+ inputSchema: {
6865
+ type: "object",
6866
+ properties: {
6867
+ html: { type: "string", description: "The full report HTML \u2014 see the tool description for how to write it." },
6868
+ receipt_id: { type: "string" }
6869
+ },
6870
+ required: ["html"]
6871
+ },
6872
+ // Empty/oversize html is refused here, BEFORE the gate requests a ticket
6873
+ // (precheckBuiltin) — a refused write must not consume report_daily_max.
6874
+ validate: writeReportRefusal,
6875
+ handler: async (args) => {
6876
+ const refusal = writeReportRefusal(args);
6877
+ if (refusal) return errorText(`Refused: ${refusal}`);
6878
+ const html = args.html;
6879
+ if (deps.state.reportStore.isLocked()) {
6880
+ return errorText("The report store is locked (the vault is not unlocked) \u2014 cannot save a report right now.");
6881
+ }
6882
+ try {
6883
+ const stored = await deps.state.reportStore.saveReport(html, deps.reportSources);
6884
+ return builtinText(summarizeWrite(stored.result));
6885
+ } catch (err) {
6886
+ return errorText(`Could not verify and store the report: ${err instanceof Error ? err.message : String(err)}`);
6887
+ }
6888
+ }
6889
+ };
6890
+ }
6891
+ var reportBuiltin = (deps) => ({
6892
+ id: "report",
6893
+ name: "Report",
6894
+ // Short name — matches the real registration in profile-loader.ts (full id
6895
+ // AND short name both registered); profileMatches() accepts either.
6896
+ profile: "reporting",
6897
+ // Touches no real system (reads the local archive + each simulator's own
6898
+ // read-only export CLI; writes only the local, vault-encrypted report file)
6899
+ // — safe during a simulation-mode test.
6900
+ simulation: true,
6901
+ toolGating: {
6902
+ overrides: {
6903
+ list_tickets: READ_GATE,
6904
+ get_ticket: READ_GATE,
6905
+ list_cases: READ_GATE,
6906
+ get_records: READ_GATE,
6907
+ write_report: { executionMapping: {}, staticExecution: { action_type: "report" } }
6908
+ }
6909
+ },
6910
+ tools: [
6911
+ listTicketsTool(deps),
6912
+ getTicketTool(deps),
6913
+ listCasesTool(deps),
6914
+ getRecordsTool(deps),
6915
+ writeReportTool(deps)
6916
+ ]
6917
+ });
6918
+
5623
6919
  // src/lib/cp-mandate.ts
5624
6920
  var CP_PORT2 = process.env.SUVEREN_CP_PORT ?? "3402";
5625
6921
  var CP_BASE2 = process.env.SUVEREN_CP_INTERNAL_URL ?? `http://127.0.0.1:${CP_PORT2}`;
@@ -5841,7 +7137,7 @@ ${guide.body.trim()}`);
5841
7137
  inputSchema: {
5842
7138
  type: "object",
5843
7139
  properties: {
5844
- team: { type: "string", description: "Team name or id. Omit for the personal workspace." },
7140
+ team: { type: "string", description: 'Team name or id, or "personal". Omit to use the workspace of your Delegation mandate.' },
5845
7141
  profile: { type: "string", description: 'Profile, e.g. "sales" (newest version) or a full profile id.' },
5846
7142
  limits: { type: "object", description: "The limits (bounds) by field name, as the profile defines them." },
5847
7143
  scope: { type: "object", description: "The scope (context) by field name, as the profile defines it." },
@@ -5886,7 +7182,7 @@ function mandateRequest(args) {
5886
7182
  }
5887
7183
 
5888
7184
  // src/lib/builtins/index.ts
5889
- var BUILTIN_FACTORIES = [setupBuiltin];
7185
+ var BUILTIN_FACTORIES = [setupBuiltin, reportBuiltin];
5890
7186
  function registerBuiltins(deps, factories = BUILTIN_FACTORIES) {
5891
7187
  const registered = [];
5892
7188
  for (const factory of factories) {
@@ -5985,7 +7281,7 @@ function isAlive(pid) {
5985
7281
  }
5986
7282
 
5987
7283
  // bin/http.ts
5988
- import { homedir as homedir10 } from "os";
7284
+ import { homedir as homedir11 } from "os";
5989
7285
  import { join as join19 } from "path";
5990
7286
 
5991
7287
  // src/lib/mcp-as-tracker.ts
@@ -6011,12 +7307,16 @@ function writeMcpPairedAsUrl(dataDir2, asUrl) {
6011
7307
  }
6012
7308
 
6013
7309
  // bin/http.ts
6014
- var dataDir = process.env.SUVEREN_DATA_DIR ?? join19(homedir10(), ".suveren");
7310
+ var dataDir = process.env.SUVEREN_DATA_DIR ?? join19(homedir11(), ".suveren");
6015
7311
  var spUrl = resolveAsUrl(dataDir);
6016
7312
  validatePinTlsForUrl(resolvePinTls(dataDir), spUrl);
6017
7313
  var port = parseInt(process.env.SUVEREN_MCP_PORT ?? "3430", 10);
6018
7314
  setAsBaseUrl(spUrl);
6019
7315
  var state = new SharedState(spUrl, void 0, dataDir);
7316
+ var reportSources = {
7317
+ archive: state.receiptArchive,
7318
+ runExport: createConnectorExportRunner({ integrationsBinDir: getIntegrationsBinDir(), dataDir })
7319
+ };
6020
7320
  (function repairIfAsUrlChanged() {
6021
7321
  const lastKnown = readMcpPairedAsUrl(dataDir);
6022
7322
  if (lastKnown !== null && lastKnown !== spUrl) {
@@ -6092,7 +7392,8 @@ app.post("/internal/configure", internalOnly, (req, res) => {
6092
7392
  state.gateStore.setVaultKey(key);
6093
7393
  state.denialLog.setVaultKey(key);
6094
7394
  state.receiptArchive.setVaultKey(key);
6095
- console.error("[Suveren MCP] Vault key configured \u2014 gate store + denial log + receipt archive encryption active");
7395
+ state.reportStore.setVaultKey(key);
7396
+ console.error("[Suveren MCP] Vault key configured \u2014 gate store + denial log + receipt archive + report store encryption active");
6096
7397
  }
6097
7398
  if (apiKey) {
6098
7399
  state.spClient.setApiKey(apiKey);
@@ -6432,6 +7733,107 @@ app.get("/internal/evidence", internalOnly, (_req, res) => {
6432
7733
  gates: state.gateStore.getAll()
6433
7734
  });
6434
7735
  });
7736
+ async function reportResponsePayload(stored) {
7737
+ const ticketDetails = await buildTicketDetails(state.receiptArchive, stored.result.proof.ticketsReferenced);
7738
+ return {
7739
+ savedAt: stored.savedAt,
7740
+ checkedAt: stored.checkedAt,
7741
+ renderedHtml: renderReportHtml(stored.result.html, stored.result.elements),
7742
+ proof: stored.result.proof,
7743
+ coverage: stored.result.coverage,
7744
+ elements: stored.result.elements,
7745
+ ticketDetails
7746
+ };
7747
+ }
7748
+ app.get("/internal/report", internalOnly, async (_req, res) => {
7749
+ if (state.reportStore.isLocked()) {
7750
+ res.status(503).json({ error: "Vault locked \u2014 the report is encrypted until sign-in." });
7751
+ return;
7752
+ }
7753
+ const stored = state.reportStore.getReport();
7754
+ if (!stored) {
7755
+ res.json({ report: null });
7756
+ return;
7757
+ }
7758
+ res.json({ report: await reportResponsePayload(stored) });
7759
+ });
7760
+ app.post("/internal/report", internalOnly, async (req, res) => {
7761
+ if (state.reportStore.isLocked()) {
7762
+ res.status(503).json({ error: "Vault locked \u2014 cannot save a report until sign-in." });
7763
+ return;
7764
+ }
7765
+ const html = req.body?.html;
7766
+ if (typeof html !== "string" || !html.trim()) {
7767
+ res.status(400).json({ error: "Missing required field: html (non-empty string)" });
7768
+ return;
7769
+ }
7770
+ try {
7771
+ const stored = await state.reportStore.saveReport(html, reportSources);
7772
+ res.json({ report: await reportResponsePayload(stored) });
7773
+ } catch (err) {
7774
+ console.error("[Suveren MCP] /internal/report save failed:", err);
7775
+ res.status(500).json({ error: err instanceof Error ? err.message : "Report verification failed" });
7776
+ }
7777
+ });
7778
+ app.post("/internal/report/recheck", internalOnly, async (_req, res) => {
7779
+ if (state.reportStore.isLocked()) {
7780
+ res.status(503).json({ error: "Vault locked \u2014 cannot recheck until sign-in." });
7781
+ return;
7782
+ }
7783
+ try {
7784
+ const stored = await state.reportStore.recheck(reportSources);
7785
+ if (!stored) {
7786
+ res.json({ report: null });
7787
+ return;
7788
+ }
7789
+ res.json({ report: await reportResponsePayload(stored) });
7790
+ } catch (err) {
7791
+ console.error("[Suveren MCP] /internal/report/recheck failed:", err);
7792
+ res.status(500).json({ error: err instanceof Error ? err.message : "Recheck failed" });
7793
+ }
7794
+ });
7795
+ function resolveExportAuthorityServer() {
7796
+ const pin = readPairing(dataDir);
7797
+ if (pin) return { url: pin.asUrl, publicKeyHex: pin.publicKeyHex };
7798
+ const withKey = state.receiptArchive.getReceipts().filter((r) => !!r.asPublicKey).sort((a, b) => b.archivedAt - a.archivedAt);
7799
+ if (withKey.length > 0) return { url: withKey[0].asUrl, publicKeyHex: withKey[0].asPublicKey };
7800
+ return { url: spUrl, publicKeyHex: "" };
7801
+ }
7802
+ app.get("/internal/report/export", internalOnly, async (req, res) => {
7803
+ if (state.reportStore.isLocked() || state.receiptArchive.isLocked()) {
7804
+ res.status(503).json({ error: "Vault locked \u2014 the report is encrypted until sign-in." });
7805
+ return;
7806
+ }
7807
+ let stored;
7808
+ try {
7809
+ stored = await state.reportStore.recheck(reportSources);
7810
+ } catch (err) {
7811
+ console.error("[Suveren MCP] /internal/report/export recheck failed:", err);
7812
+ res.status(500).json({ error: err instanceof Error ? err.message : "Recheck failed" });
7813
+ return;
7814
+ }
7815
+ if (!stored) {
7816
+ res.status(404).json({ error: "No report to export yet \u2014 the AI writes it with the Reporting mandate." });
7817
+ return;
7818
+ }
7819
+ const authorityServer = resolveExportAuthorityServer();
7820
+ if (!authorityServer.publicKeyHex) {
7821
+ res.status(503).json({
7822
+ error: "No Authority Server key is available yet to anchor this export \u2014 sign in once, or execute at least one gated action, before exporting."
7823
+ });
7824
+ return;
7825
+ }
7826
+ const gatewayVersion = typeof req.query.gatewayVersion === "string" ? req.query.gatewayVersion : "unknown";
7827
+ const bundle = buildExportBundle({
7828
+ stored,
7829
+ archive: state.receiptArchive,
7830
+ authorityServer,
7831
+ gatewayVersion
7832
+ });
7833
+ const renderedHtml = renderReportHtml(stored.result.html, stored.result.elements, false);
7834
+ const document = buildExportDocument({ bundle, renderedHtml });
7835
+ res.setHeader("Content-Type", "text/html; charset=utf-8").setHeader("Content-Disposition", `attachment; filename="${suggestedFilename(bundle)}"`).setHeader("Cache-Control", "no-store").send(document);
7836
+ });
6435
7837
  app.get("/internal/brief", internalOnly, (_req, res) => {
6436
7838
  try {
6437
7839
  const enriched = state.getEnrichedAuthorizations();
@@ -6502,7 +7904,7 @@ app.listen(port, "0.0.0.0", () => {
6502
7904
  console.error(`[Suveren MCP] SP server: ${spUrl}`);
6503
7905
  profilesLoaded = loadProfiles();
6504
7906
  loadManifests();
6505
- registerBuiltins({ state, integrationManager });
7907
+ registerBuiltins({ state, integrationManager, reportSources });
6506
7908
  if (process.env.SUVEREN_DISABLE_AUTO_INTEGRATIONS !== "1" && integrationRegistry.getEnabled().length === 0) {
6507
7909
  const personalManifests = getAllManifests().filter((m) => m.personalDefault);
6508
7910
  for (const manifest of personalManifests) {
@@ -6545,7 +7947,7 @@ app.listen(port, "0.0.0.0", () => {
6545
7947
  (proposal) => executeCommitted(proposal, state, integrationManager)
6546
7948
  );
6547
7949
  installCommittedExecutor(committedExecutor);
6548
- const dataDir2 = process.env.SUVEREN_DATA_DIR ?? join19(homedir10(), ".suveren");
7950
+ const dataDir2 = process.env.SUVEREN_DATA_DIR ?? join19(homedir11(), ".suveren");
6549
7951
  const executorLock = new ExecutorLock(dataDir2);
6550
7952
  const lock = executorLock.acquire();
6551
7953
  if (!lock.held) {