aegis-bridge 0.1.0 → 0.4.0-alpha

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 (339) hide show
  1. package/README.md +114 -16
  2. package/dashboard/dist/assets/AuditPage-8FPmFJeT.js +16 -0
  3. package/dashboard/dist/assets/AuditPage-8FPmFJeT.js.map +1 -0
  4. package/dashboard/dist/assets/AuthKeysPage-B6MWGnkC.js +6 -0
  5. package/dashboard/dist/assets/AuthKeysPage-B6MWGnkC.js.map +1 -0
  6. package/dashboard/dist/assets/ConfirmDialog-COiUPUp_.js +1 -0
  7. package/dashboard/dist/assets/ConfirmDialog-COiUPUp_.js.map +1 -0
  8. package/dashboard/dist/assets/LoginPage-BRx1aLi6.js +1 -0
  9. package/dashboard/dist/assets/LoginPage-BRx1aLi6.js.map +1 -0
  10. package/dashboard/dist/assets/MetricCard-CQ1XYP_b.js +1 -0
  11. package/dashboard/dist/assets/MetricCard-CQ1XYP_b.js.map +1 -0
  12. package/dashboard/dist/assets/NotFoundPage-JmXHxvMq.js +1 -0
  13. package/dashboard/dist/assets/NotFoundPage-JmXHxvMq.js.map +1 -0
  14. package/dashboard/dist/assets/OverviewPage-C1PUocRu.js +96 -0
  15. package/dashboard/dist/assets/OverviewPage-C1PUocRu.js.map +1 -0
  16. package/dashboard/dist/assets/PipelineDetailPage-CGhiUxvB.js +1 -0
  17. package/dashboard/dist/assets/PipelineDetailPage-CGhiUxvB.js.map +1 -0
  18. package/dashboard/dist/assets/PipelineStatusBadge-DoemuWsu.js +1 -0
  19. package/dashboard/dist/assets/PipelineStatusBadge-DoemuWsu.js.map +1 -0
  20. package/dashboard/dist/assets/PipelinesPage-D-o2aoFl.js +1 -0
  21. package/dashboard/dist/assets/PipelinesPage-D-o2aoFl.js.map +1 -0
  22. package/dashboard/dist/assets/SessionDetailPage-CrcYIdQL.js +12 -0
  23. package/dashboard/dist/assets/SessionDetailPage-CrcYIdQL.js.map +1 -0
  24. package/dashboard/dist/assets/StatusDot-oQYwxCmp.js +1 -0
  25. package/dashboard/dist/assets/StatusDot-oQYwxCmp.js.map +1 -0
  26. package/dashboard/dist/assets/eye-BMuhGY5-.js +11 -0
  27. package/dashboard/dist/assets/eye-BMuhGY5-.js.map +1 -0
  28. package/dashboard/dist/assets/format-DhqF4LAD.js +1 -0
  29. package/dashboard/dist/assets/format-DhqF4LAD.js.map +1 -0
  30. package/dashboard/dist/assets/index-B6Xt25Fx.js +89 -0
  31. package/dashboard/dist/assets/index-B6Xt25Fx.js.map +1 -0
  32. package/dashboard/dist/assets/index-vv20jxdL.css +1 -0
  33. package/dashboard/dist/assets/loader-circle-CnfU68Ly.js +6 -0
  34. package/dashboard/dist/assets/loader-circle-CnfU68Ly.js.map +1 -0
  35. package/dashboard/dist/assets/react-vendor-D39sujLR.js +49 -0
  36. package/dashboard/dist/assets/react-vendor-D39sujLR.js.map +1 -0
  37. package/dashboard/dist/assets/router-vendor-CSOqEeqr.js +12 -0
  38. package/dashboard/dist/assets/router-vendor-CSOqEeqr.js.map +1 -0
  39. package/dashboard/dist/assets/send-MshbEk9f.js +11 -0
  40. package/dashboard/dist/assets/send-MshbEk9f.js.map +1 -0
  41. package/dashboard/dist/assets/terminal-vendor-CpEbvKnu.js +9 -0
  42. package/dashboard/dist/assets/terminal-vendor-CpEbvKnu.js.map +1 -0
  43. package/dashboard/dist/assets/terminal-vendor-DYP7pi_n.css +32 -0
  44. package/dashboard/dist/assets/trash-2-DwBqM5Mz.js +11 -0
  45. package/dashboard/dist/assets/trash-2-DwBqM5Mz.js.map +1 -0
  46. package/dashboard/dist/assets/utils-vendor-Bk4NZbDs.js +39 -0
  47. package/dashboard/dist/assets/utils-vendor-Bk4NZbDs.js.map +1 -0
  48. package/dashboard/dist/index.html +5 -2
  49. package/dist/alerting.d.ts +65 -0
  50. package/dist/alerting.js +158 -0
  51. package/dist/api-contracts.d.ts +9 -0
  52. package/dist/audit.d.ts +72 -0
  53. package/dist/audit.js +239 -0
  54. package/dist/auth/index.d.ts +7 -0
  55. package/dist/auth/index.js +7 -0
  56. package/dist/auth/roles.d.ts +55 -0
  57. package/dist/auth/roles.js +150 -0
  58. package/dist/auth.d.ts +4 -85
  59. package/dist/auth.js +3 -274
  60. package/dist/batch-limiter.d.ts +45 -0
  61. package/dist/batch-limiter.js +62 -0
  62. package/dist/channels/email.d.ts +80 -0
  63. package/dist/channels/email.js +194 -0
  64. package/dist/channels/index.d.ts +2 -0
  65. package/dist/channels/index.js +3 -0
  66. package/dist/channels/slack.d.ts +57 -0
  67. package/dist/channels/slack.js +179 -0
  68. package/dist/channels/telegram.js +16 -2
  69. package/dist/channels/webhook.d.ts +7 -1
  70. package/dist/channels/webhook.js +27 -11
  71. package/dist/cli.d.ts +1 -1
  72. package/dist/cli.js +17 -17
  73. package/dist/config.d.ts +17 -0
  74. package/dist/config.js +91 -11
  75. package/dist/consensus.d.ts +14 -0
  76. package/dist/consensus.js +27 -0
  77. package/dist/container.d.ts +35 -0
  78. package/dist/container.js +166 -0
  79. package/dist/dashboard/assets/AuditPage-8FPmFJeT.js +16 -0
  80. package/dist/dashboard/assets/AuditPage-BJAQ2zUy.js +1 -0
  81. package/dist/dashboard/assets/AuditPage-Bb7zMUgy.js +1 -0
  82. package/dist/dashboard/assets/AuditPage-D6WqyyNC.js +1 -0
  83. package/dist/dashboard/assets/AuditPage-D8Qh8xhM.js +1 -0
  84. package/dist/dashboard/assets/AuditPage-Dha9DW1X.js +1 -0
  85. package/dist/dashboard/assets/AuditPage-iOdPRpWv.js +1 -0
  86. package/dist/dashboard/assets/AuthKeysPage-B6MWGnkC.js +6 -0
  87. package/dist/dashboard/assets/AuthKeysPage-BDglE6gd.js +1 -0
  88. package/dist/dashboard/assets/AuthKeysPage-BP0yhg5c.js +1 -0
  89. package/dist/dashboard/assets/AuthKeysPage-BcAxBDOg.js +1 -0
  90. package/dist/dashboard/assets/AuthKeysPage-BeCAQ2pD.js +1 -0
  91. package/dist/dashboard/assets/AuthKeysPage-BfpqJJre.js +1 -0
  92. package/dist/dashboard/assets/AuthKeysPage-Bj4fr2Mh.js +1 -0
  93. package/dist/dashboard/assets/AuthKeysPage-C3zQUCXQ.js +1 -0
  94. package/dist/dashboard/assets/AuthKeysPage-CCJHhI4z.js +1 -0
  95. package/dist/dashboard/assets/AuthKeysPage-Ca0l7L2m.js +1 -0
  96. package/dist/dashboard/assets/AuthKeysPage-WYXhlPR1.js +1 -0
  97. package/dist/dashboard/assets/AuthKeysPage-_Go2Rvxq.js +16 -0
  98. package/dist/dashboard/assets/AuthKeysPage-z3OQGMzB.js +1 -0
  99. package/dist/dashboard/assets/ConfirmDialog-BarTYcWS.js +1 -0
  100. package/dist/dashboard/assets/ConfirmDialog-BgRsTUsY.js +1 -0
  101. package/dist/dashboard/assets/ConfirmDialog-COiUPUp_.js +1 -0
  102. package/dist/dashboard/assets/ConfirmDialog-Cwdz-sYy.js +1 -0
  103. package/dist/dashboard/assets/ConfirmDialog-D3wZxAyR.js +1 -0
  104. package/dist/dashboard/assets/ConfirmDialog-Qx_3TQ-2.js +1 -0
  105. package/dist/dashboard/assets/LoginPage-0-hjXyDM.js +1 -0
  106. package/dist/dashboard/assets/LoginPage-BRx1aLi6.js +1 -0
  107. package/dist/dashboard/assets/LoginPage-BdWa78_y.js +1 -0
  108. package/dist/dashboard/assets/LoginPage-DvJbUi6y.js +1 -0
  109. package/dist/dashboard/assets/MetricCard-C8lS6Rmr.js +1 -0
  110. package/dist/dashboard/assets/MetricCard-CA-Wh7L8.js +1 -0
  111. package/dist/dashboard/assets/MetricCard-CQ1XYP_b.js +1 -0
  112. package/dist/dashboard/assets/MetricCard-Cg3J35gc.js +1 -0
  113. package/dist/dashboard/assets/MetricCard-Cw2O0g91.js +1 -0
  114. package/dist/dashboard/assets/MetricCard-CxwnXoLd.js +1 -0
  115. package/dist/dashboard/assets/NotFoundPage-B9Y4WK2a.js +1 -0
  116. package/dist/dashboard/assets/NotFoundPage-BFHpzsFa.js +1 -0
  117. package/dist/dashboard/assets/NotFoundPage-BXr_tjI8.js +1 -0
  118. package/dist/dashboard/assets/NotFoundPage-ByZM4LcD.js +1 -0
  119. package/dist/dashboard/assets/NotFoundPage-CDmOjrx9.js +1 -0
  120. package/dist/dashboard/assets/NotFoundPage-CFr2Up1g.js +1 -0
  121. package/dist/dashboard/assets/NotFoundPage-Calmb2-n.js +1 -0
  122. package/dist/dashboard/assets/NotFoundPage-CfwD1Bg_.js +1 -0
  123. package/dist/dashboard/assets/NotFoundPage-DU2xrDWg.js +1 -0
  124. package/dist/dashboard/assets/NotFoundPage-JmXHxvMq.js +1 -0
  125. package/dist/dashboard/assets/NotFoundPage-m9WrZ4C7.js +1 -0
  126. package/dist/dashboard/assets/NotFoundPage-rp5FAiUO.js +1 -0
  127. package/dist/dashboard/assets/NotFoundPage-yU6Fky-8.js +1 -0
  128. package/dist/dashboard/assets/OverviewPage-BTf6mue5.js +1 -0
  129. package/dist/dashboard/assets/OverviewPage-BgXU0wAL.js +1 -0
  130. package/dist/dashboard/assets/OverviewPage-BxlQxkeN.js +1 -0
  131. package/dist/dashboard/assets/OverviewPage-C1PUocRu.js +96 -0
  132. package/dist/dashboard/assets/OverviewPage-C5PzLPQt.js +1 -0
  133. package/dist/dashboard/assets/OverviewPage-CXJpWM5f.js +1 -0
  134. package/dist/dashboard/assets/OverviewPage-CZef-a9Q.js +1 -0
  135. package/dist/dashboard/assets/OverviewPage-Ck6CZo_u.js +1 -0
  136. package/dist/dashboard/assets/OverviewPage-Cn2Cdn-g.js +1 -0
  137. package/dist/dashboard/assets/OverviewPage-CyR3B8ew.js +1 -0
  138. package/dist/dashboard/assets/OverviewPage-CylzGf_s.js +96 -0
  139. package/dist/dashboard/assets/OverviewPage-DQXjogwj.js +1 -0
  140. package/dist/dashboard/assets/OverviewPage-gaR8L6sx.js +1 -0
  141. package/dist/dashboard/assets/PipelineDetailPage-B4KVTqfb.js +1 -0
  142. package/dist/dashboard/assets/PipelineDetailPage-BCsjmefs.js +1 -0
  143. package/dist/dashboard/assets/PipelineDetailPage-BITsKxeD.js +1 -0
  144. package/dist/dashboard/assets/PipelineDetailPage-BVRaxdkz.js +1 -0
  145. package/dist/dashboard/assets/PipelineDetailPage-BiUAQGyX.js +1 -0
  146. package/dist/dashboard/assets/PipelineDetailPage-CEaDx5xq.js +1 -0
  147. package/dist/dashboard/assets/PipelineDetailPage-CGhiUxvB.js +1 -0
  148. package/dist/dashboard/assets/PipelineDetailPage-CSa0NC9E.js +1 -0
  149. package/dist/dashboard/assets/PipelineDetailPage-D5B4qauY.js +1 -0
  150. package/dist/dashboard/assets/PipelineDetailPage-DKnOPzpN.js +1 -0
  151. package/dist/dashboard/assets/PipelineDetailPage-DykyiAyr.js +1 -0
  152. package/dist/dashboard/assets/PipelineDetailPage-XsiWG7vw.js +1 -0
  153. package/dist/dashboard/assets/PipelineDetailPage-nQ0T7-Qw.js +1 -0
  154. package/dist/dashboard/assets/PipelineStatusBadge-1lQ5aAsC.js +1 -0
  155. package/dist/dashboard/assets/PipelineStatusBadge-BRrxDcAe.js +1 -0
  156. package/dist/dashboard/assets/PipelineStatusBadge-C3suxo-R.js +1 -0
  157. package/dist/dashboard/assets/PipelineStatusBadge-D0ZI4tA8.js +1 -0
  158. package/dist/dashboard/assets/PipelineStatusBadge-D4Q_ZqID.js +1 -0
  159. package/dist/dashboard/assets/PipelineStatusBadge-DoemuWsu.js +1 -0
  160. package/dist/dashboard/assets/PipelinesPage-B5dwUYlq.js +1 -0
  161. package/dist/dashboard/assets/PipelinesPage-BG1V8n7p.js +1 -0
  162. package/dist/dashboard/assets/PipelinesPage-Bf4h7DsJ.js +1 -0
  163. package/dist/dashboard/assets/PipelinesPage-Bjc5WFPd.js +1 -0
  164. package/dist/dashboard/assets/PipelinesPage-C9ZmRzfT.js +1 -0
  165. package/dist/dashboard/assets/PipelinesPage-CFyY1Eyc.js +1 -0
  166. package/dist/dashboard/assets/PipelinesPage-C_b1tT5D.js +1 -0
  167. package/dist/dashboard/assets/PipelinesPage-CjIx2DgH.js +1 -0
  168. package/dist/dashboard/assets/PipelinesPage-D-o2aoFl.js +1 -0
  169. package/dist/dashboard/assets/PipelinesPage-D6ELsCwK.js +1 -0
  170. package/dist/dashboard/assets/PipelinesPage-DTL4nbJf.js +1 -0
  171. package/dist/dashboard/assets/PipelinesPage-LtszcrdM.js +1 -0
  172. package/dist/dashboard/assets/PipelinesPage-v0cABBK8.js +1 -0
  173. package/dist/dashboard/assets/SessionDetailPage-BCuNuvrf.js +2 -0
  174. package/dist/dashboard/assets/SessionDetailPage-BQtLZTju.js +2 -0
  175. package/dist/dashboard/assets/SessionDetailPage-Bqh-a9gV.js +2 -0
  176. package/dist/dashboard/assets/SessionDetailPage-C4u_pcW8.js +2 -0
  177. package/dist/dashboard/assets/SessionDetailPage-CA8rMlnz.js +2 -0
  178. package/dist/dashboard/assets/SessionDetailPage-CrcYIdQL.js +12 -0
  179. package/dist/dashboard/assets/SessionDetailPage-DJ219S64.js +2 -0
  180. package/dist/dashboard/assets/SessionDetailPage-DOMkcsw9.js +2 -0
  181. package/dist/dashboard/assets/SessionDetailPage-GyNUdwo-.js +2 -0
  182. package/dist/dashboard/assets/SessionDetailPage-gRNoE4M0.js +12 -0
  183. package/dist/dashboard/assets/SessionDetailPage-n2Xf0jH1.js +2 -0
  184. package/dist/dashboard/assets/SessionDetailPage-oUyUCfI5.js +2 -0
  185. package/dist/dashboard/assets/SessionDetailPage-z644YFe_.js +2 -0
  186. package/dist/dashboard/assets/StatusDot-CXY-AWq7.js +1 -0
  187. package/dist/dashboard/assets/StatusDot-C_nDkP7d.js +1 -0
  188. package/dist/dashboard/assets/StatusDot-Co3kfS41.js +1 -0
  189. package/dist/dashboard/assets/StatusDot-D7BAOp86.js +1 -0
  190. package/dist/dashboard/assets/StatusDot-e5wUNlQC.js +1 -0
  191. package/dist/dashboard/assets/StatusDot-oQYwxCmp.js +1 -0
  192. package/dist/dashboard/assets/chevron-right-DlmxU8KT.js +1 -0
  193. package/dist/dashboard/assets/client-BJZVITiU.js +1 -0
  194. package/dist/dashboard/assets/client-CKeyZ1CU.js +1 -0
  195. package/dist/dashboard/assets/client-COnfKa4_.js +1 -0
  196. package/dist/dashboard/assets/createLucideIcon-Czl9a3rs.js +1 -0
  197. package/dist/dashboard/assets/eye-BMuhGY5-.js +11 -0
  198. package/dist/dashboard/assets/eye-BqacmcMi.js +1 -0
  199. package/dist/dashboard/assets/format-D6mU9qLA.js +1 -0
  200. package/dist/dashboard/assets/format-D8jvtaYm.js +1 -0
  201. package/dist/dashboard/assets/format-DhqF4LAD.js +1 -0
  202. package/dist/dashboard/assets/format-jstMWgFe.js +1 -0
  203. package/dist/dashboard/assets/format-tpV1-pAj.js +1 -0
  204. package/dist/dashboard/assets/format-vqj6b6B5.js +1 -0
  205. package/dist/dashboard/assets/index-0h4DiyEe.css +2 -0
  206. package/dist/dashboard/assets/index-B1jtvS-P.css +2 -0
  207. package/dist/dashboard/assets/index-B6Xt25Fx.js +89 -0
  208. package/dist/dashboard/assets/index-BBSOmdDf.css +2 -0
  209. package/dist/dashboard/assets/index-BScq5b40.css +2 -0
  210. package/dist/dashboard/assets/index-BaD7wnOM.css +2 -0
  211. package/dist/dashboard/assets/index-C982XwN8.js +4 -0
  212. package/dist/dashboard/assets/index-CeCYnwhf.js +4 -0
  213. package/dist/dashboard/assets/index-ClGuVkZn.css +2 -0
  214. package/dist/dashboard/assets/index-Cu1pir_U.js +11 -0
  215. package/dist/dashboard/assets/index-DCWsqNmv.css +1 -0
  216. package/dist/dashboard/assets/index-DuPPhqKT.js +11 -0
  217. package/dist/dashboard/assets/index-DupuFhBM.css +2 -0
  218. package/dist/dashboard/assets/index-I4pr4h-O.js +11 -0
  219. package/dist/dashboard/assets/index-IztqRR6v.js +4 -0
  220. package/dist/dashboard/assets/index-Nnmgi6GO.js +4 -0
  221. package/dist/dashboard/assets/index-THIHto7A.js +11 -0
  222. package/dist/dashboard/assets/index-akAsVcu2.js +11 -0
  223. package/dist/dashboard/assets/index-bDeZZ8_e.js +62 -0
  224. package/dist/dashboard/assets/index-bXlnsTVc.css +2 -0
  225. package/dist/dashboard/assets/index-cGknudvx.js +4 -0
  226. package/dist/dashboard/assets/index-v3T3Qn2b.js +4 -0
  227. package/dist/dashboard/assets/index-vv20jxdL.css +1 -0
  228. package/dist/dashboard/assets/loader-circle-B2QkXu8H.js +1 -0
  229. package/dist/dashboard/assets/loader-circle-B4oDh9kS.js +1 -0
  230. package/dist/dashboard/assets/loader-circle-CnfU68Ly.js +6 -0
  231. package/dist/dashboard/assets/loader-circle-RRm8ynNB.js +6 -0
  232. package/dist/dashboard/assets/react-DAurLNp8.js +1 -0
  233. package/dist/dashboard/assets/react-vendor-D39sujLR.js +49 -0
  234. package/dist/dashboard/assets/react-vendor-a8s_Rc4g.js +9 -0
  235. package/dist/dashboard/assets/rolldown-runtime-DF2fYuay.js +1 -0
  236. package/dist/dashboard/assets/router-vendor-BaCBF0X2.js +12 -0
  237. package/dist/dashboard/assets/router-vendor-CSOqEeqr.js +12 -0
  238. package/dist/dashboard/assets/send-Bdh__KTa.js +1 -0
  239. package/dist/dashboard/assets/send-C9VOxgB-.js +11 -0
  240. package/dist/dashboard/assets/send-MshbEk9f.js +11 -0
  241. package/dist/dashboard/assets/terminal-vendor-B3n7HmZt.js +7 -0
  242. package/dist/dashboard/assets/terminal-vendor-Ba5OLHmD.js +7 -0
  243. package/dist/dashboard/assets/terminal-vendor-BzA0Hyyi.js +7 -0
  244. package/dist/dashboard/assets/terminal-vendor-CHMNpNzY.js +7 -0
  245. package/dist/dashboard/assets/terminal-vendor-CpEbvKnu.js +9 -0
  246. package/dist/dashboard/assets/terminal-vendor-DYP7pi_n.css +32 -0
  247. package/dist/dashboard/assets/terminal-vendor-kHJ-D0s7.css +1 -0
  248. package/dist/dashboard/assets/terminal-vendor-yUa9KTZY.js +7 -0
  249. package/dist/dashboard/assets/trash-2-BHGzwzwW.js +1 -0
  250. package/dist/dashboard/assets/trash-2-CXbGaZOf.js +11 -0
  251. package/dist/dashboard/assets/trash-2-DwBqM5Mz.js +11 -0
  252. package/dist/dashboard/assets/trash-2-beMuhxkL.js +1 -0
  253. package/dist/dashboard/assets/useStore-BzzfL1dv.js +1 -0
  254. package/dist/dashboard/assets/useToastStore-B5xbRczx.js +1 -0
  255. package/dist/dashboard/assets/useToastStore-BflA987H.js +1 -0
  256. package/dist/dashboard/assets/useToastStore-Dd9xQMqb.js +1 -0
  257. package/dist/dashboard/assets/utils-vendor-BA_O6Xe2.js +39 -0
  258. package/dist/dashboard/assets/utils-vendor-Bk4NZbDs.js +39 -0
  259. package/dist/dashboard/assets/utils-vendor-CTlUhL8n.js +39 -0
  260. package/dist/dashboard/assets/utils-vendor-D_TaL8RO.js +39 -0
  261. package/dist/dashboard/index.html +17 -0
  262. package/dist/diagnostics.d.ts +1 -0
  263. package/dist/error-parser.d.ts +23 -0
  264. package/dist/error-parser.js +74 -0
  265. package/dist/fix-loop.d.ts +24 -0
  266. package/dist/fix-loop.js +68 -0
  267. package/dist/hook.d.ts +2 -0
  268. package/dist/hook.js +139 -57
  269. package/dist/hooks.d.ts +1 -0
  270. package/dist/hooks.js +24 -5
  271. package/dist/jsonl-watcher.d.ts +9 -0
  272. package/dist/jsonl-watcher.js +51 -2
  273. package/dist/logger.d.ts +2 -0
  274. package/dist/logger.js +2 -0
  275. package/dist/mcp-server.d.ts +17 -3
  276. package/dist/mcp-server.js +136 -54
  277. package/dist/memory-bridge.js +1 -1
  278. package/dist/memory-routes.js +1 -4
  279. package/dist/metrics.d.ts +3 -0
  280. package/dist/metrics.js +54 -7
  281. package/dist/monitor.d.ts +21 -1
  282. package/dist/monitor.js +68 -14
  283. package/dist/permission-evaluator.js +27 -2
  284. package/dist/permission-routes.d.ts +3 -2
  285. package/dist/permission-routes.js +15 -3
  286. package/dist/permissions.d.ts +55 -0
  287. package/dist/permissions.js +220 -0
  288. package/dist/pipeline.d.ts +16 -2
  289. package/dist/pipeline.js +136 -3
  290. package/dist/prometheus.d.ts +33 -0
  291. package/dist/prometheus.js +143 -0
  292. package/dist/retry.d.ts +5 -0
  293. package/dist/retry.js +7 -1
  294. package/dist/server.d.ts +5 -0
  295. package/dist/server.js +545 -248
  296. package/dist/services/auth/AuthManager.d.ts +108 -0
  297. package/dist/services/auth/AuthManager.js +345 -0
  298. package/dist/services/auth/RateLimiter.d.ts +13 -0
  299. package/dist/services/auth/RateLimiter.js +87 -0
  300. package/dist/services/auth/index.d.ts +3 -0
  301. package/dist/services/auth/index.js +2 -0
  302. package/dist/services/auth/types.d.ts +16 -0
  303. package/dist/services/auth/types.js +1 -0
  304. package/dist/services/permission/evaluator.d.ts +2 -0
  305. package/dist/services/permission/evaluator.js +94 -0
  306. package/dist/services/permission/index.d.ts +2 -0
  307. package/dist/services/permission/index.js +1 -0
  308. package/dist/services/permission/types.d.ts +9 -0
  309. package/dist/services/permission/types.js +1 -0
  310. package/dist/session.d.ts +16 -1
  311. package/dist/session.js +43 -15
  312. package/dist/signal-cleanup-helper.d.ts +3 -2
  313. package/dist/signal-cleanup-helper.js +9 -2
  314. package/dist/sse-connection-manager.d.ts +31 -0
  315. package/dist/sse-connection-manager.js +63 -0
  316. package/dist/startup.d.ts +1 -1
  317. package/dist/startup.js +4 -2
  318. package/dist/swarm-monitor.d.ts +5 -2
  319. package/dist/swarm-monitor.js +23 -4
  320. package/dist/terminal-parser.d.ts +6 -0
  321. package/dist/terminal-parser.js +13 -0
  322. package/dist/tmux-capture-cache.d.ts +11 -2
  323. package/dist/tmux-capture-cache.js +38 -2
  324. package/dist/tmux.d.ts +7 -2
  325. package/dist/tmux.js +40 -22
  326. package/dist/tracing.d.ts +75 -0
  327. package/dist/tracing.js +225 -0
  328. package/dist/transcript.js +2 -2
  329. package/dist/validation.d.ts +89 -6
  330. package/dist/validation.js +132 -21
  331. package/dist/verification.js +7 -7
  332. package/dist/verifier.d.ts +20 -0
  333. package/dist/verifier.js +60 -0
  334. package/dist/ws-terminal.d.ts +1 -1
  335. package/dist/ws-terminal.js +8 -2
  336. package/package.json +23 -3
  337. package/dashboard/dist/assets/index-BoZwGLAx.css +0 -32
  338. package/dashboard/dist/assets/index-C61BkKH-.js +0 -312
  339. package/dashboard/dist/assets/index-C61BkKH-.js.map +0 -1
package/README.md CHANGED
@@ -3,15 +3,17 @@
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
- <img src="https://img.shields.io/npm/v/aegis-bridge.svg" alt="npm" />
6
+ <img src="https://img.shields.io/npm/v/@onestepat4time/aegis.svg" alt="npm" />
7
7
  <img src="https://img.shields.io/github/actions/workflow/status/OneStepAt4time/aegis/ci.yml?branch=main" alt="CI" />
8
- <img src="https://img.shields.io/npm/l/aegis-bridge.svg" alt="license" />
8
+ <img src="https://img.shields.io/npm/l/@onestepat4time/aegis.svg" alt="license" />
9
9
  <img src="https://img.shields.io/badge/node-%3E%3D20.0.0-blue.svg" alt="node" />
10
10
  <img src="https://img.shields.io/badge/MCP-ready-green.svg" alt="MCP ready" />
11
11
  <a href="https://github.com/OneStepAt4time/aegis/blob/main/ROADMAP.md"><img src="https://img.shields.io/badge/roadmap-alpha-orange" alt="Roadmap" /></a>
12
12
  </p>
13
13
 
14
14
  > ⚠️ **Aegis is in Alpha.** APIs may change. See [ROADMAP.md](./ROADMAP.md) for the path to stable.
15
+ >
16
+ > 📦 **Package renamed:** `aegis-bridge` → [`@onestepat4time/aegis`](https://www.npmjs.com/package/@onestepat4time/aegis). See [Migration Guide](docs/migration-guide.md) if you're upgrading.
15
17
 
16
18
  <p align="center">
17
19
  <strong>Orchestrate Claude Code sessions via REST API, MCP, CLI, webhooks, or Telegram.</strong>
@@ -27,7 +29,7 @@
27
29
 
28
30
  ```bash
29
31
  # Install and start
30
- npx aegis-bridge
32
+ npx @onestepat4time/aegis
31
33
 
32
34
  # Create a session
33
35
  curl -X POST http://localhost:9100/v1/sessions \
@@ -48,12 +50,12 @@ On Windows, use psmux as the tmux-compatible backend before starting Aegis.
48
50
 
49
51
  ```powershell
50
52
  choco install psmux -y
51
- npx aegis-bridge
53
+ npx @onestepat4time/aegis
52
54
  ```
53
55
 
54
56
  For full setup, verification, and troubleshooting, see [Windows Setup](docs/windows-setup.md).
55
57
 
56
- Need a full walkthrough from install to first session? See [Getting Started](docs/getting-started.md).
58
+ For a full walkthrough from install to first session, see [Getting Started](docs/getting-started.md). For advanced features (pipelines, consensus, model router), see [Advanced Features](docs/advanced.md). For the full MCP tools reference, see [MCP Tools](docs/mcp-tools.md).
57
59
 
58
60
  ---
59
61
 
@@ -65,7 +67,7 @@ Aegis wraps Claude Code in tmux sessions and exposes everything through a unifie
65
67
  2. Sends messages via `tmux send-keys` with delivery verification (up to 3 retries)
66
68
  3. Parses output from both terminal capture and JSONL transcripts
67
69
  4. Detects state changes: working, idle, permission prompts, stalls
68
- 5. Fans out events to Telegram, webhooks, and SSE streams
70
+ 5. Fans out events to Telegram, Slack, Email, webhooks, and SSE streams
69
71
 
70
72
  ```mermaid
71
73
  graph LR
@@ -86,10 +88,10 @@ Connect any MCP-compatible agent to Claude Code — the fastest way to build mul
86
88
 
87
89
  ```bash
88
90
  # Start standalone
89
- aegis-bridge mcp
91
+ @onestepat4time/aegis mcp
90
92
 
91
93
  # Add to Claude Code
92
- claude mcp add --scope user aegis -- npx aegis-bridge mcp
94
+ claude mcp add --scope user aegis -- npx @onestepat4time/aegis mcp
93
95
  ```
94
96
 
95
97
  Or via `.mcp.json`:
@@ -99,13 +101,13 @@ Or via `.mcp.json`:
99
101
  "mcpServers": {
100
102
  "aegis": {
101
103
  "command": "npx",
102
- "args": ["aegis-bridge", "mcp"]
104
+ "args": ["@onestepat4time/aegis", "mcp"]
103
105
  }
104
106
  }
105
107
  }
106
108
  ```
107
109
 
108
- **21 tools** — `create_session`, `send_message`, `get_transcript`, `approve_permission`, `batch_create_sessions`, `create_pipeline`, and more.
110
+ **25 tools** — `create_session`, `send_message`, `get_transcript`, `approve_permission`, `batch_create_sessions`, `create_pipeline`, `state_set`, and more.
109
111
 
110
112
  **4 resources** — `aegis://sessions`, `aegis://sessions/{id}/transcript`, `aegis://sessions/{id}/pane`, `aegis://health`
111
113
 
@@ -115,6 +117,8 @@ Or via `.mcp.json`:
115
117
 
116
118
  Aegis works beyond Claude Code anywhere an MCP host can launch a local stdio server.
117
119
 
120
+ - [CLI Reference](docs/integrations/cli.md) — `aegis` command-line tool
121
+ - [Notification Channels](docs/integrations/notifications.md) — Telegram, Slack, Email, Webhooks
118
122
  - [Cursor integration](docs/integrations/cursor.md)
119
123
  - [Windsurf integration](docs/integrations/windsurf.md)
120
124
  - [MCP Registry preparation](docs/integrations/mcp-registry.md)
@@ -141,6 +145,18 @@ All endpoints under `/v1/`.
141
145
  | `POST` | `/v1/sessions/batch` | Batch create |
142
146
  | `POST` | `/v1/handshake` | Capability negotiation |
143
147
  | `POST` | `/v1/pipelines` | Create pipeline |
148
+ | `POST` | `/v1/memory` | Set memory entry |
149
+ | `GET` | `/v1/memory` | List memory entries |
150
+ | `GET` | `/v1/memory/:key` | Get memory entry |
151
+ | `DELETE` | `/v1/memory/:key` | Delete memory entry |
152
+ | `POST` | `/v1/templates` | Create session template |
153
+ | `GET` | `/v1/templates` | List templates |
154
+ | `GET` | `/v1/templates/:id` | Get template |
155
+ | `PUT` | `/v1/templates/:id` | Update template |
156
+ | `DELETE` | `/v1/templates/:id` | Delete template |
157
+ | `POST` | `/v1/dev/route-task` | Route task to model tier |
158
+ | `GET` | `/v1/dev/model-tiers` | List model tiers |
159
+ | `GET` | `/v1/diagnostics` | Server diagnostics |
144
160
 
145
161
  <details>
146
162
  <summary>Full API Reference</summary>
@@ -306,17 +322,52 @@ Works with [OpenClaw](https://openclaw.ai), custom orchestrators, or any agent t
306
322
  Aegis ships with a built-in dashboard at `http://localhost:9100/dashboard/` — real-time session monitoring, activity streams, and health overview.
307
323
 
308
324
  ```bash
309
- npx aegis-bridge # visit http://localhost:9100/dashboard/
325
+ npx @onestepat4time/aegis # visit http://localhost:9100/dashboard/
310
326
  ```
311
327
 
312
328
  ---
313
329
 
330
+ ## Use Cases & Deployment Tiers
331
+
332
+ Aegis serves three deployment scenarios:
333
+
334
+ ### Tier 1 — Local Orchestration
335
+ **Single developer.** Run Claude Code tasks in the background, monitor via dashboard, approve via Telegram.
336
+
337
+ ```bash
338
+ aegis
339
+ # Dashboard: http://localhost:9100/dashboard/
340
+ # Telegram approvals while AFK
341
+ ```
342
+
343
+ ### Tier 2 — CI/CD & Team Automation
344
+ **Development teams.** Policy-based permission control, batch operations, Slack notifications.
345
+
346
+ ```bash
347
+ # Blueprint: PR Reviewer
348
+ curl -X POST http://localhost:9100/v1/pipelines \
349
+ -H "Authorization: Bearer $TOKEN" \
350
+ -d '{"name":"pr-reviewer","stages":[...],"permissionMode":"plan"}'
351
+ ```
352
+
353
+ ### Tier 3 — Zero-Trust Enterprise
354
+ **Banks, SaaS, regulated industries.** Docker-isolated containers, no network egress, audit-first.
355
+
356
+ - Each task runs in an ephemeral Docker container
357
+ - No cross-container networking
358
+ - Immutable audit log for compliance
359
+ - See [Enterprise Deployment](docs/enterprise.md) for production hardening guide
360
+
361
+ **Golden rule:** Intelligence stays outside Aegis. Aegis is a stupid-but-powerful middleware — flows, security, audit. OpenClaw (or any external orchestrator) provides the brains.
362
+
363
+ ---
364
+
314
365
  ## Security
315
366
 
316
367
  Aegis includes built-in security defaults:
317
368
 
318
369
  - **Permission mode** — `default` requires approval for dangerous operations (shell commands, file writes). Change with `permissionMode` when creating a session.
319
- - **Hook secrets** — webhook and hook secrets are passed via headers (not query params) to prevent log leakage.
370
+ - **Hook secrets** — use `X-Hook-Secret` header (preferred). Query-param `secret` remains backward compatible by default but is deprecated.
320
371
  - **Auth tokens** — protect the API with `AEGIS_AUTH_TOKEN` (Bearer auth on all endpoints except `/v1/health`).
321
372
  - **WebSocket auth** — session existence is not revealed before authentication.
322
373
 
@@ -336,6 +387,7 @@ Aegis includes built-in security defaults:
336
387
  | `AEGIS_TG_TOKEN` | — | Telegram bot token |
337
388
  | `AEGIS_TG_GROUP` | — | Telegram group chat ID |
338
389
  | `AEGIS_WEBHOOKS` | — | Webhook URLs (comma-separated) |
390
+ | `AEGIS_HOOK_SECRET_HEADER_ONLY` | false | Enforce `X-Hook-Secret` header and reject deprecated `?secret=` transport |
339
391
 
340
392
  ---
341
393
 
@@ -357,7 +409,7 @@ npx tsc --noEmit # type-check
357
409
 
358
410
  ```
359
411
  src/
360
- ├── cli.ts # CLI entry (npx aegis-bridge)
412
+ ├── cli.ts # CLI entry (npx @onestepat4time/aegis)
361
413
  ├── server.ts # Fastify HTTP server + routes
362
414
  ├── session.ts # Session lifecycle
363
415
  ├── tmux.ts # tmux operations
@@ -370,6 +422,8 @@ src/
370
422
  ├── channels/
371
423
  │ ├── manager.ts # Event fan-out
372
424
  │ ├── telegram.ts # Telegram channel
425
+ │ ├── slack.ts # Slack incoming webhook channel
426
+ │ ├── email.ts # SMTP email alert channel
373
427
  │ └── webhook.ts # Webhook channel
374
428
  └── __tests__/ # Vitest tests
375
429
  ```
@@ -378,11 +432,54 @@ src/
378
432
 
379
433
  ---
380
434
 
381
- ## API Reference
435
+ ## TypeScript Client SDK
382
436
 
383
- Full API documentation is auto-generated with TypeDoc and published to GitHub Pages:
437
+ Official `@onestepat4time/aegis-client` package for TypeScript/JavaScript applications.
384
438
 
385
- **<https://onestepat4time.github.io/aegis/>**
439
+ ```bash
440
+ npm install @onestepat4time/aegis-client
441
+ ```
442
+
443
+ ```typescript
444
+ import { AegisClient } from '@onestepat4time/aegis-client';
445
+
446
+ const client = new AegisClient('http://localhost:18792', process.env.AEGIS_AUTH_TOKEN);
447
+
448
+ // List sessions
449
+ const sessions = await client.listSessions();
450
+
451
+ // Create a session
452
+ const { id } = await client.createSession({ workDir: '/path/to/project' });
453
+
454
+ // Send a message
455
+ await client.sendMessage(id, 'Hello, Claude!');
456
+
457
+ // Approve a permission
458
+ await client.approvePermission(id);
459
+ ```
460
+
461
+ **What's included:**
462
+ - Full TypeScript types for all 30+ API endpoints
463
+ - Sessions, health, metrics, pipelines, memory, audit log
464
+ - Works in Node.js and browser
465
+ - `X-Aegis-API-Version: 1` header on all requests
466
+ - Configurable request timeouts
467
+
468
+ See [`packages/client/`](packages/client/) for the full SDK source.
469
+
470
+
471
+
472
+ ## Documentation
473
+
474
+ - **[Getting Started](docs/getting-started.md)** — Zero to first session in 5 minutes
475
+ - **[API Reference](docs/api-reference.md)** — Complete REST API documentation
476
+ - **[MCP Tools](docs/mcp-tools.md)** — 24 MCP tools and 3 prompts
477
+ - **[Notifications](docs/integrations/notifications.md)** — Telegram, Slack, Email, webhooks
478
+ - **[Advanced Features](docs/advanced.md)** — Pipelines, consensus, model router, templates
479
+ - **[Enterprise Deployment](docs/enterprise.md)** — Auth, rate limiting, security, production
480
+ - **[Migration Guide](docs/migration-guide.md)** — Upgrading from `aegis-bridge`
481
+ - **[Architecture](docs/architecture.md)** — Module overview and design
482
+ - **[TypeDoc API](https://onestepat4time.github.io/aegis/)** — Auto-generated TypeScript reference
386
483
 
387
484
  ---
388
485
 
@@ -402,3 +499,4 @@ Full API documentation is auto-generated with TypeDoc and published to GitHub Pa
402
499
  ## License
403
500
 
404
501
  MIT — [Emanuele Santonastaso](https://github.com/OneStepAt4time)
502
+
@@ -0,0 +1,16 @@
1
+ import{r as s,j as e}from"./react-vendor-D39sujLR.js";import{c as g,f as M,R as L,S as O,C as $,a as q}from"./index-B6Xt25Fx.js";import"./utils-vendor-Bk4NZbDs.js";import"./router-vendor-CSOqEeqr.js";/**
2
+ * @license lucide-react v0.474.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const K=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]],X=g("CircleAlert",K);/**
7
+ * @license lucide-react v0.474.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const G=[["polygon",{points:"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3",key:"1yg77f"}]],Z=g("Filter",G);/**
12
+ * @license lucide-react v0.474.0 - ISC
13
+ *
14
+ * This source code is licensed under the ISC license.
15
+ * See the LICENSE file in the root directory of this source tree.
16
+ */const B=[["path",{d:"m13.5 8.5-5 5",key:"1cs55j"}],["path",{d:"m8.5 8.5 5 5",key:"a8mexj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]],H=g("SearchX",B),J=[{value:"",label:"All actions"},{value:"create",label:"create"},{value:"kill",label:"kill"},{value:"send",label:"send"},{value:"approve",label:"approve"},{value:"reject",label:"reject"}],Q=[10,25,50];function U(a){try{return new Date(a).toLocaleString()}catch{return a}}function V({count:a}){return e.jsx(e.Fragment,{children:Array.from({length:a}).map((l,n)=>e.jsxs("tr",{className:"border-b border-zinc-800",children:[e.jsx("td",{className:"px-4 py-3",children:e.jsx("div",{className:"h-4 w-36 animate-pulse rounded bg-zinc-800"})}),e.jsx("td",{className:"px-4 py-3",children:e.jsx("div",{className:"h-4 w-24 animate-pulse rounded bg-zinc-800"})}),e.jsx("td",{className:"px-4 py-3",children:e.jsx("div",{className:"h-4 w-16 animate-pulse rounded bg-zinc-800"})}),e.jsx("td",{className:"px-4 py-3",children:e.jsx("div",{className:"h-4 w-28 animate-pulse rounded bg-zinc-800"})}),e.jsx("td",{className:"px-4 py-3",children:e.jsx("div",{className:"h-4 w-40 animate-pulse rounded bg-zinc-800"})})]},n))})}function W({record:a}){const n={create:"text-emerald-400 bg-emerald-400/10",kill:"text-red-400 bg-red-400/10",send:"text-blue-400 bg-blue-400/10",approve:"text-green-400 bg-green-400/10",reject:"text-amber-400 bg-amber-400/10"}[a.action]??"text-zinc-300 bg-zinc-700/50";return e.jsxs("tr",{className:"border-b border-zinc-800 hover:bg-zinc-800/40 transition-colors",children:[e.jsx("td",{className:"px-4 py-3 text-sm text-zinc-400 whitespace-nowrap",children:U(a.timestamp)}),e.jsx("td",{className:"px-4 py-3 text-sm text-zinc-200 font-mono",children:a.actor}),e.jsx("td",{className:"px-4 py-3",children:e.jsx("span",{className:`inline-block rounded px-2 py-0.5 text-xs font-medium ${n}`,children:a.action})}),e.jsx("td",{className:"px-4 py-3 text-sm text-zinc-300 font-mono",children:a.sessionId??"—"}),e.jsx("td",{className:"px-4 py-3 text-sm text-zinc-400 max-w-xs truncate",children:a.detail??"—"})]})}function ae(){const[a,l]=s.useState([]),[n,j]=s.useState(0),[i,r]=s.useState(1),[c,T]=s.useState(10),[h,N]=s.useState(!0),[y,z]=s.useState(null),[_,v]=s.useState(!1),[w,k]=s.useState(""),[A,S]=s.useState(""),[C,F]=s.useState(""),[o,I]=s.useState(""),[d,P]=s.useState(""),[x,D]=s.useState(""),m=s.useCallback(async t=>{N(!0),z(null),v(!1);const p={page:i,pageSize:c};o&&(p.actor=o),d&&(p.action=d),x&&(p.sessionId=x);try{const u=await M({...p,signal:t});l(u.records),j(u.total)}catch(u){const R=u;R.statusCode===404?(v(!0),l([]),j(0)):z(R.message??"Failed to fetch audit logs")}finally{N(!1)}},[i,c,o,d,x]);s.useEffect(()=>{const t=new AbortController;return m(t.signal),()=>t.abort()},[m]);const b=()=>{r(1),I(w),P(A),D(C)},E=()=>{k(""),S(""),F(""),r(1),I(""),P(""),D("")},f=Math.max(1,Math.ceil(n/c));return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold text-gray-100",children:"Audit Trail"}),e.jsx("p",{className:"mt-1 text-sm text-gray-500",children:"Review system actions and API key activity"})]}),e.jsxs("button",{onClick:()=>{m()},disabled:h,className:"flex items-center gap-1.5 px-3 py-2 text-xs font-medium rounded bg-[#00e5ff]/10 hover:bg-[#00e5ff]/20 text-[#00e5ff] border border-[#00e5ff]/30 transition-colors disabled:opacity-50",children:[e.jsx(L,{className:`h-3.5 w-3.5 ${h?"animate-spin":""}`}),"Refresh"]})]}),e.jsxs("div",{className:"rounded-lg border border-zinc-800 bg-zinc-900/50 p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(Z,{className:"h-4 w-4 text-zinc-400"}),e.jsx("span",{className:"text-sm font-medium text-zinc-300",children:"Filters"})]}),e.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{htmlFor:"filter-actor",className:"text-xs text-zinc-500",children:"Actor (Key ID)"}),e.jsx("input",{id:"filter-actor",type:"text",placeholder:"e.g. key-abc123",value:w,onChange:t=>k(t.target.value),onKeyDown:t=>{t.key==="Enter"&&b()},className:"rounded border border-zinc-700 bg-zinc-800 px-3 py-1.5 text-sm text-zinc-100 placeholder-zinc-600 focus:border-[#00e5ff]/50 focus:outline-none"})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{htmlFor:"filter-action",className:"text-xs text-zinc-500",children:"Action"}),e.jsx("select",{id:"filter-action",value:A,onChange:t=>S(t.target.value),className:"rounded border border-zinc-700 bg-zinc-800 px-3 py-1.5 text-sm text-zinc-100 focus:border-[#00e5ff]/50 focus:outline-none",children:J.map(t=>e.jsx("option",{value:t.value,children:t.label},t.value))})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{htmlFor:"filter-session",className:"text-xs text-zinc-500",children:"Session ID"}),e.jsx("input",{id:"filter-session",type:"text",placeholder:"e.g. sess-xyz",value:C,onChange:t=>F(t.target.value),onKeyDown:t=>{t.key==="Enter"&&b()},className:"rounded border border-zinc-700 bg-zinc-800 px-3 py-1.5 text-sm text-zinc-100 placeholder-zinc-600 focus:border-[#00e5ff]/50 focus:outline-none"})]}),e.jsx("button",{onClick:b,className:"rounded bg-[#00e5ff]/10 hover:bg-[#00e5ff]/20 px-3 py-1.5 text-xs font-medium text-[#00e5ff] border border-[#00e5ff]/30 transition-colors",children:"Apply"}),e.jsx("button",{onClick:E,className:"rounded bg-zinc-800 hover:bg-zinc-700 px-3 py-1.5 text-xs font-medium text-zinc-400 border border-zinc-700 transition-colors",children:"Clear"})]})]}),_?e.jsxs("div",{className:"rounded-lg border border-zinc-800 bg-[#111118] p-12 text-center",children:[e.jsx(O,{className:"mx-auto h-10 w-10 text-zinc-600 mb-3"}),e.jsx("p",{className:"text-zinc-400 font-medium",children:"Audit endpoint not available yet"}),e.jsx("p",{className:"mt-1 text-xs text-zinc-600",children:"The /v1/audit endpoint has not been implemented on the server."})]}):y?e.jsxs("div",{className:"rounded-lg border border-red-900/50 bg-red-950/20 p-12 text-center",children:[e.jsx(X,{className:"mx-auto h-10 w-10 text-red-500 mb-3"}),e.jsx("p",{className:"text-red-400 font-medium",children:"Failed to load audit logs"}),e.jsx("p",{className:"mt-1 text-xs text-zinc-500",children:y}),e.jsx("button",{onClick:()=>{m()},className:"mt-4 rounded bg-red-500/10 hover:bg-red-500/20 px-4 py-2 text-xs font-medium text-red-400 border border-red-500/30 transition-colors",children:"Retry"})]}):h?e.jsx("div",{className:"overflow-x-auto rounded-lg border border-zinc-800 bg-zinc-900/50",children:e.jsxs("table",{className:"w-full text-left",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-zinc-800",children:[e.jsx("th",{className:"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500",children:"Timestamp"}),e.jsx("th",{className:"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500",children:"Actor"}),e.jsx("th",{className:"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500",children:"Action"}),e.jsx("th",{className:"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500",children:"Session ID"}),e.jsx("th",{className:"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500",children:"Detail"})]})}),e.jsx("tbody",{children:e.jsx(V,{count:c})})]})}):a.length===0?e.jsxs("div",{className:"rounded-lg border border-zinc-800 bg-[#111118] p-12 text-center",children:[e.jsx(H,{className:"mx-auto h-10 w-10 text-zinc-600 mb-3"}),e.jsx("p",{className:"text-zinc-400 font-medium",children:"No audit records found"}),e.jsx("p",{className:"mt-1 text-xs text-zinc-600",children:o||d||x?"Try adjusting your filters.":"Audit records will appear here once actions are performed."})]}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"overflow-x-auto rounded-lg border border-zinc-800 bg-zinc-900/50",children:e.jsxs("table",{className:"w-full text-left",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-zinc-800",children:[e.jsx("th",{className:"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500",children:"Timestamp"}),e.jsx("th",{className:"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500",children:"Actor"}),e.jsx("th",{className:"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500",children:"Action"}),e.jsx("th",{className:"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500",children:"Session ID"}),e.jsx("th",{className:"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500",children:"Detail"})]})}),e.jsx("tbody",{children:a.map(t=>e.jsx(W,{record:t},t.id))})]})}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-zinc-500",children:[e.jsxs("span",{children:[n," record",n!==1?"s":""]}),e.jsx("span",{className:"text-zinc-700",children:"|"}),e.jsx("label",{htmlFor:"page-size",className:"sr-only",children:"Page size"}),e.jsx("select",{id:"page-size",value:c,onChange:t=>{T(Number(t.target.value)),r(1)},className:"rounded border border-zinc-700 bg-zinc-800 px-2 py-1 text-xs text-zinc-300 focus:border-[#00e5ff]/50 focus:outline-none",children:Q.map(t=>e.jsxs("option",{value:t,children:[t," / page"]},t))})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("span",{className:"text-xs text-zinc-500",children:["Page ",i," of ",f]}),e.jsx("button",{onClick:()=>r(t=>Math.max(1,t-1)),disabled:i<=1,className:"inline-flex items-center rounded border border-zinc-700 bg-zinc-800 px-2 py-1 text-xs text-zinc-300 hover:bg-zinc-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors","aria-label":"Previous page",children:e.jsx($,{className:"h-3.5 w-3.5"})}),e.jsx("button",{onClick:()=>r(t=>Math.min(f,t+1)),disabled:i>=f,className:"inline-flex items-center rounded border border-zinc-700 bg-zinc-800 px-2 py-1 text-xs text-zinc-300 hover:bg-zinc-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors","aria-label":"Next page",children:e.jsx(q,{className:"h-3.5 w-3.5"})})]})]})]})]})}export{ae as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuditPage-8FPmFJeT.js","sources":["../../node_modules/lucide-react/dist/esm/icons/circle-alert.js","../../node_modules/lucide-react/dist/esm/icons/filter.js","../../node_modules/lucide-react/dist/esm/icons/search-x.js","../../src/pages/AuditPage.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.474.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"8\", y2: \"12\", key: \"1pkeuh\" }],\n [\"line\", { x1: \"12\", x2: \"12.01\", y1: \"16\", y2: \"16\", key: \"4dfq90\" }]\n];\nconst CircleAlert = createLucideIcon(\"CircleAlert\", __iconNode);\n\nexport { __iconNode, CircleAlert as default };\n//# sourceMappingURL=circle-alert.js.map\n","/**\n * @license lucide-react v0.474.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"polygon\", { points: \"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\", key: \"1yg77f\" }]\n];\nconst Filter = createLucideIcon(\"Filter\", __iconNode);\n\nexport { __iconNode, Filter as default };\n//# sourceMappingURL=filter.js.map\n","/**\n * @license lucide-react v0.474.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m13.5 8.5-5 5\", key: \"1cs55j\" }],\n [\"path\", { d: \"m8.5 8.5 5 5\", key: \"a8mexj\" }],\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }],\n [\"path\", { d: \"m21 21-4.3-4.3\", key: \"1qie3q\" }]\n];\nconst SearchX = createLucideIcon(\"SearchX\", __iconNode);\n\nexport { __iconNode, SearchX as default };\n//# sourceMappingURL=search-x.js.map\n","/**\n * pages/AuditPage.tsx — Audit trail with paginated table, filters, and search.\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport {\n Shield,\n Filter,\n RefreshCw,\n ChevronLeft,\n ChevronRight,\n SearchX,\n AlertCircle,\n} from 'lucide-react';\nimport { fetchAuditLogs, type FetchAuditLogsParams } from '../api/client';\nimport type { AuditRecord } from '../types';\n\nconst ACTION_OPTIONS = [\n { value: '', label: 'All actions' },\n { value: 'create', label: 'create' },\n { value: 'kill', label: 'kill' },\n { value: 'send', label: 'send' },\n { value: 'approve', label: 'approve' },\n { value: 'reject', label: 'reject' },\n] as const;\n\nconst PAGE_SIZE_OPTIONS = [10, 25, 50] as const;\n\nfunction formatTimestamp(ts: string): string {\n try {\n return new Date(ts).toLocaleString();\n } catch {\n return ts;\n }\n}\n\nfunction SkeletonRows({ count }: { count: number }) {\n return (\n <>\n {Array.from({ length: count }).map((_, i) => (\n <tr key={i} className=\"border-b border-zinc-800\">\n <td className=\"px-4 py-3\"><div className=\"h-4 w-36 animate-pulse rounded bg-zinc-800\" /></td>\n <td className=\"px-4 py-3\"><div className=\"h-4 w-24 animate-pulse rounded bg-zinc-800\" /></td>\n <td className=\"px-4 py-3\"><div className=\"h-4 w-16 animate-pulse rounded bg-zinc-800\" /></td>\n <td className=\"px-4 py-3\"><div className=\"h-4 w-28 animate-pulse rounded bg-zinc-800\" /></td>\n <td className=\"px-4 py-3\"><div className=\"h-4 w-40 animate-pulse rounded bg-zinc-800\" /></td>\n </tr>\n ))}\n </>\n );\n}\n\nfunction AuditRow({ record }: { record: AuditRecord }) {\n const actionColor: Record<string, string> = {\n create: 'text-emerald-400 bg-emerald-400/10',\n kill: 'text-red-400 bg-red-400/10',\n send: 'text-blue-400 bg-blue-400/10',\n approve: 'text-green-400 bg-green-400/10',\n reject: 'text-amber-400 bg-amber-400/10',\n };\n\n const colorClass = actionColor[record.action] ?? 'text-zinc-300 bg-zinc-700/50';\n\n return (\n <tr className=\"border-b border-zinc-800 hover:bg-zinc-800/40 transition-colors\">\n <td className=\"px-4 py-3 text-sm text-zinc-400 whitespace-nowrap\">\n {formatTimestamp(record.timestamp)}\n </td>\n <td className=\"px-4 py-3 text-sm text-zinc-200 font-mono\">\n {record.actor}\n </td>\n <td className=\"px-4 py-3\">\n <span className={`inline-block rounded px-2 py-0.5 text-xs font-medium ${colorClass}`}>\n {record.action}\n </span>\n </td>\n <td className=\"px-4 py-3 text-sm text-zinc-300 font-mono\">\n {record.sessionId ?? '—'}\n </td>\n <td className=\"px-4 py-3 text-sm text-zinc-400 max-w-xs truncate\">\n {record.detail ?? '—'}\n </td>\n </tr>\n );\n}\n\nexport default function AuditPage() {\n const [records, setRecords] = useState<AuditRecord[]>([]);\n const [total, setTotal] = useState(0);\n const [page, setPage] = useState(1);\n const [pageSize, setPageSize] = useState(10);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [endpointMissing, setEndpointMissing] = useState(false);\n\n const [filterActor, setFilterActor] = useState('');\n const [filterAction, setFilterAction] = useState('');\n const [filterSessionId, setFilterSessionId] = useState('');\n\n const [appliedActor, setAppliedActor] = useState('');\n const [appliedAction, setAppliedAction] = useState('');\n const [appliedSessionId, setAppliedSessionId] = useState('');\n\n const fetchData = useCallback(async (signal?: AbortSignal) => {\n setLoading(true);\n setError(null);\n setEndpointMissing(false);\n\n const params: FetchAuditLogsParams = {\n page,\n pageSize,\n };\n if (appliedActor) params.actor = appliedActor;\n if (appliedAction) params.action = appliedAction;\n if (appliedSessionId) params.sessionId = appliedSessionId;\n\n try {\n const data = await fetchAuditLogs({ ...params, signal: signal as AbortSignal });\n setRecords(data.records);\n setTotal(data.total);\n } catch (e: unknown) {\n const err = e as Error & { statusCode?: number };\n if (err.statusCode === 404) {\n setEndpointMissing(true);\n setRecords([]);\n setTotal(0);\n } else {\n setError(err.message ?? 'Failed to fetch audit logs');\n }\n } finally {\n setLoading(false);\n }\n }, [page, pageSize, appliedActor, appliedAction, appliedSessionId]);\n\n useEffect(() => {\n const ac = new AbortController();\n void fetchData(ac.signal);\n return () => ac.abort();\n }, [fetchData]);\n\n const applyFilters = () => {\n setPage(1);\n setAppliedActor(filterActor);\n setAppliedAction(filterAction);\n setAppliedSessionId(filterSessionId);\n };\n\n const clearFilters = () => {\n setFilterActor('');\n setFilterAction('');\n setFilterSessionId('');\n setPage(1);\n setAppliedActor('');\n setAppliedAction('');\n setAppliedSessionId('');\n };\n\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n\n return (\n <div className=\"flex flex-col gap-6\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div>\n <h2 className=\"text-2xl font-bold text-gray-100\">Audit Trail</h2>\n <p className=\"mt-1 text-sm text-gray-500\">\n Review system actions and API key activity\n </p>\n </div>\n <button\n onClick={() => { void fetchData(); }}\n disabled={loading}\n className=\"flex items-center gap-1.5 px-3 py-2 text-xs font-medium rounded bg-[#00e5ff]/10 hover:bg-[#00e5ff]/20 text-[#00e5ff] border border-[#00e5ff]/30 transition-colors disabled:opacity-50\"\n >\n <RefreshCw className={`h-3.5 w-3.5 ${loading ? 'animate-spin' : ''}`} />\n Refresh\n </button>\n </div>\n\n {/* Filters */}\n <div className=\"rounded-lg border border-zinc-800 bg-zinc-900/50 p-4\">\n <div className=\"flex items-center gap-2 mb-3\">\n <Filter className=\"h-4 w-4 text-zinc-400\" />\n <span className=\"text-sm font-medium text-zinc-300\">Filters</span>\n </div>\n <div className=\"flex flex-wrap items-end gap-3\">\n <div className=\"flex flex-col gap-1\">\n <label htmlFor=\"filter-actor\" className=\"text-xs text-zinc-500\">Actor (Key ID)</label>\n <input\n id=\"filter-actor\"\n type=\"text\"\n placeholder=\"e.g. key-abc123\"\n value={filterActor}\n onChange={(e) => setFilterActor(e.target.value)}\n onKeyDown={(e) => { if (e.key === 'Enter') applyFilters(); }}\n className=\"rounded border border-zinc-700 bg-zinc-800 px-3 py-1.5 text-sm text-zinc-100 placeholder-zinc-600 focus:border-[#00e5ff]/50 focus:outline-none\"\n />\n </div>\n <div className=\"flex flex-col gap-1\">\n <label htmlFor=\"filter-action\" className=\"text-xs text-zinc-500\">Action</label>\n <select\n id=\"filter-action\"\n value={filterAction}\n onChange={(e) => setFilterAction(e.target.value)}\n className=\"rounded border border-zinc-700 bg-zinc-800 px-3 py-1.5 text-sm text-zinc-100 focus:border-[#00e5ff]/50 focus:outline-none\"\n >\n {ACTION_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n </div>\n <div className=\"flex flex-col gap-1\">\n <label htmlFor=\"filter-session\" className=\"text-xs text-zinc-500\">Session ID</label>\n <input\n id=\"filter-session\"\n type=\"text\"\n placeholder=\"e.g. sess-xyz\"\n value={filterSessionId}\n onChange={(e) => setFilterSessionId(e.target.value)}\n onKeyDown={(e) => { if (e.key === 'Enter') applyFilters(); }}\n className=\"rounded border border-zinc-700 bg-zinc-800 px-3 py-1.5 text-sm text-zinc-100 placeholder-zinc-600 focus:border-[#00e5ff]/50 focus:outline-none\"\n />\n </div>\n <button\n onClick={applyFilters}\n className=\"rounded bg-[#00e5ff]/10 hover:bg-[#00e5ff]/20 px-3 py-1.5 text-xs font-medium text-[#00e5ff] border border-[#00e5ff]/30 transition-colors\"\n >\n Apply\n </button>\n <button\n onClick={clearFilters}\n className=\"rounded bg-zinc-800 hover:bg-zinc-700 px-3 py-1.5 text-xs font-medium text-zinc-400 border border-zinc-700 transition-colors\"\n >\n Clear\n </button>\n </div>\n </div>\n\n {/* Content */}\n {endpointMissing ? (\n <div className=\"rounded-lg border border-zinc-800 bg-[#111118] p-12 text-center\">\n <Shield className=\"mx-auto h-10 w-10 text-zinc-600 mb-3\" />\n <p className=\"text-zinc-400 font-medium\">Audit endpoint not available yet</p>\n <p className=\"mt-1 text-xs text-zinc-600\">\n The /v1/audit endpoint has not been implemented on the server.\n </p>\n </div>\n ) : error ? (\n <div className=\"rounded-lg border border-red-900/50 bg-red-950/20 p-12 text-center\">\n <AlertCircle className=\"mx-auto h-10 w-10 text-red-500 mb-3\" />\n <p className=\"text-red-400 font-medium\">Failed to load audit logs</p>\n <p className=\"mt-1 text-xs text-zinc-500\">{error}</p>\n <button\n onClick={() => { void fetchData(); }}\n className=\"mt-4 rounded bg-red-500/10 hover:bg-red-500/20 px-4 py-2 text-xs font-medium text-red-400 border border-red-500/30 transition-colors\"\n >\n Retry\n </button>\n </div>\n ) : loading ? (\n <div className=\"overflow-x-auto rounded-lg border border-zinc-800 bg-zinc-900/50\">\n <table className=\"w-full text-left\">\n <thead>\n <tr className=\"border-b border-zinc-800\">\n <th className=\"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500\">Timestamp</th>\n <th className=\"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500\">Actor</th>\n <th className=\"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500\">Action</th>\n <th className=\"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500\">Session ID</th>\n <th className=\"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500\">Detail</th>\n </tr>\n </thead>\n <tbody>\n <SkeletonRows count={pageSize} />\n </tbody>\n </table>\n </div>\n ) : records.length === 0 ? (\n <div className=\"rounded-lg border border-zinc-800 bg-[#111118] p-12 text-center\">\n <SearchX className=\"mx-auto h-10 w-10 text-zinc-600 mb-3\" />\n <p className=\"text-zinc-400 font-medium\">No audit records found</p>\n <p className=\"mt-1 text-xs text-zinc-600\">\n {(appliedActor || appliedAction || appliedSessionId)\n ? 'Try adjusting your filters.'\n : 'Audit records will appear here once actions are performed.'}\n </p>\n </div>\n ) : (\n <>\n {/* Table */}\n <div className=\"overflow-x-auto rounded-lg border border-zinc-800 bg-zinc-900/50\">\n <table className=\"w-full text-left\">\n <thead>\n <tr className=\"border-b border-zinc-800\">\n <th className=\"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500\">Timestamp</th>\n <th className=\"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500\">Actor</th>\n <th className=\"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500\">Action</th>\n <th className=\"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500\">Session ID</th>\n <th className=\"px-4 py-3 text-xs font-medium uppercase tracking-wider text-zinc-500\">Detail</th>\n </tr>\n </thead>\n <tbody>\n {records.map((record) => (\n <AuditRow key={record.id} record={record} />\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Pagination */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2 text-sm text-zinc-500\">\n <span>{total} record{total !== 1 ? 's' : ''}</span>\n <span className=\"text-zinc-700\">|</span>\n <label htmlFor=\"page-size\" className=\"sr-only\">Page size</label>\n <select\n id=\"page-size\"\n value={pageSize}\n onChange={(e) => { setPageSize(Number(e.target.value)); setPage(1); }}\n className=\"rounded border border-zinc-700 bg-zinc-800 px-2 py-1 text-xs text-zinc-300 focus:border-[#00e5ff]/50 focus:outline-none\"\n >\n {PAGE_SIZE_OPTIONS.map((size) => (\n <option key={size} value={size}>{size} / page</option>\n ))}\n </select>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-zinc-500\">\n Page {page} of {totalPages}\n </span>\n <button\n onClick={() => setPage((p) => Math.max(1, p - 1))}\n disabled={page <= 1}\n className=\"inline-flex items-center rounded border border-zinc-700 bg-zinc-800 px-2 py-1 text-xs text-zinc-300 hover:bg-zinc-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n aria-label=\"Previous page\"\n >\n <ChevronLeft className=\"h-3.5 w-3.5\" />\n </button>\n <button\n onClick={() => setPage((p) => Math.min(totalPages, p + 1))}\n disabled={page >= totalPages}\n className=\"inline-flex items-center rounded border border-zinc-700 bg-zinc-800 px-2 py-1 text-xs text-zinc-300 hover:bg-zinc-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n aria-label=\"Next page\"\n >\n <ChevronRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n </>\n )}\n </div>\n );\n}\n"],"names":["__iconNode","CircleAlert","createLucideIcon","Filter","SearchX","ACTION_OPTIONS","PAGE_SIZE_OPTIONS","formatTimestamp","ts","SkeletonRows","count","jsx","Fragment","_","i","jsxs","AuditRow","record","colorClass","AuditPage","records","setRecords","useState","total","setTotal","page","setPage","pageSize","setPageSize","loading","setLoading","error","setError","endpointMissing","setEndpointMissing","filterActor","setFilterActor","filterAction","setFilterAction","filterSessionId","setFilterSessionId","appliedActor","setAppliedActor","appliedAction","setAppliedAction","appliedSessionId","setAppliedSessionId","fetchData","useCallback","signal","params","data","fetchAuditLogs","e","err","useEffect","ac","applyFilters","clearFilters","totalPages","RefreshCw","opt","Shield","AlertCircle","size","p","ChevronLeft","ChevronRight"],"mappings":"wMAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMA,EAAa,CACjB,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,KAAM,IAAK,SAAU,EACzD,CAAC,OAAQ,CAAE,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,GAAI,KAAM,IAAK,QAAQ,CAAE,EACjE,CAAC,OAAQ,CAAE,GAAI,KAAM,GAAI,QAAS,GAAI,KAAM,GAAI,KAAM,IAAK,QAAQ,CAAE,CACvE,EACMC,EAAcC,EAAiB,cAAeF,CAAU,ECd9D;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMA,EAAa,CACjB,CAAC,UAAW,CAAE,OAAQ,8CAA+C,IAAK,QAAQ,CAAE,CACtF,EACMG,EAASD,EAAiB,SAAUF,CAAU,ECZpD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMA,EAAa,CACjB,CAAC,OAAQ,CAAE,EAAG,gBAAiB,IAAK,QAAQ,CAAE,EAC9C,CAAC,OAAQ,CAAE,EAAG,eAAgB,IAAK,QAAQ,CAAE,EAC7C,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,CACjD,EACMI,EAAUF,EAAiB,UAAWF,CAAU,ECEhDK,EAAiB,CACrB,CAAE,MAAO,GAAI,MAAO,aAAA,EACpB,CAAE,MAAO,SAAU,MAAO,QAAA,EAC1B,CAAE,MAAO,OAAQ,MAAO,MAAA,EACxB,CAAE,MAAO,OAAQ,MAAO,MAAA,EACxB,CAAE,MAAO,UAAW,MAAO,SAAA,EAC3B,CAAE,MAAO,SAAU,MAAO,QAAA,CAC5B,EAEMC,EAAoB,CAAC,GAAI,GAAI,EAAE,EAErC,SAASC,EAAgBC,EAAoB,CAC3C,GAAI,CACF,OAAO,IAAI,KAAKA,CAAE,EAAE,eAAA,CACtB,MAAQ,CACN,OAAOA,CACT,CACF,CAEA,SAASC,EAAa,CAAE,MAAAC,GAA4B,CAClD,OACEC,EAAAA,IAAAC,EAAAA,SAAA,CACG,SAAA,MAAM,KAAK,CAAE,OAAQF,CAAA,CAAO,EAAE,IAAI,CAACG,EAAGC,IACrCC,EAAAA,KAAC,KAAA,CAAW,UAAU,2BACpB,SAAA,CAAAJ,EAAAA,IAAC,MAAG,UAAU,YAAY,eAAC,MAAA,CAAI,UAAU,6CAA6C,CAAA,CAAE,EACxFA,EAAAA,IAAC,MAAG,UAAU,YAAY,eAAC,MAAA,CAAI,UAAU,6CAA6C,CAAA,CAAE,EACxFA,EAAAA,IAAC,MAAG,UAAU,YAAY,eAAC,MAAA,CAAI,UAAU,6CAA6C,CAAA,CAAE,EACxFA,EAAAA,IAAC,MAAG,UAAU,YAAY,eAAC,MAAA,CAAI,UAAU,6CAA6C,CAAA,CAAE,EACxFA,EAAAA,IAAC,MAAG,UAAU,YAAY,eAAC,MAAA,CAAI,UAAU,6CAA6C,CAAA,CAAE,CAAA,GALjFG,CAMT,CACD,EACH,CAEJ,CAEA,SAASE,EAAS,CAAE,OAAAC,GAAmC,CASrD,MAAMC,EARsC,CAC1C,OAAQ,qCACR,KAAM,6BACN,KAAM,+BACN,QAAS,iCACT,OAAQ,gCAAA,EAGqBD,EAAO,MAAM,GAAK,+BAEjD,OACEF,EAAAA,KAAC,KAAA,CAAG,UAAU,kEACZ,SAAA,CAAAJ,MAAC,MAAG,UAAU,oDACX,SAAAJ,EAAgBU,EAAO,SAAS,EACnC,EACAN,EAAAA,IAAC,KAAA,CAAG,UAAU,4CACX,WAAO,MACV,EACAA,EAAAA,IAAC,KAAA,CAAG,UAAU,YACZ,SAAAA,EAAAA,IAAC,OAAA,CAAK,UAAW,wDAAwDO,CAAU,GAChF,SAAAD,EAAO,MAAA,CACV,EACF,QACC,KAAA,CAAG,UAAU,4CACX,SAAAA,EAAO,WAAa,IACvB,QACC,KAAA,CAAG,UAAU,oDACX,SAAAA,EAAO,QAAU,GAAA,CACpB,CAAA,EACF,CAEJ,CAEA,SAAwBE,IAAY,CAClC,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAAA,SAAwB,CAAA,CAAE,EAClD,CAACC,EAAOC,CAAQ,EAAIF,EAAAA,SAAS,CAAC,EAC9B,CAACG,EAAMC,CAAO,EAAIJ,EAAAA,SAAS,CAAC,EAC5B,CAACK,EAAUC,CAAW,EAAIN,EAAAA,SAAS,EAAE,EACrC,CAACO,EAASC,CAAU,EAAIR,EAAAA,SAAS,EAAI,EACrC,CAACS,EAAOC,CAAQ,EAAIV,EAAAA,SAAwB,IAAI,EAChD,CAACW,EAAiBC,CAAkB,EAAIZ,EAAAA,SAAS,EAAK,EAEtD,CAACa,EAAaC,CAAc,EAAId,EAAAA,SAAS,EAAE,EAC3C,CAACe,EAAcC,CAAe,EAAIhB,EAAAA,SAAS,EAAE,EAC7C,CAACiB,EAAiBC,CAAkB,EAAIlB,EAAAA,SAAS,EAAE,EAEnD,CAACmB,EAAcC,CAAe,EAAIpB,EAAAA,SAAS,EAAE,EAC7C,CAACqB,EAAeC,CAAgB,EAAItB,EAAAA,SAAS,EAAE,EAC/C,CAACuB,EAAkBC,CAAmB,EAAIxB,EAAAA,SAAS,EAAE,EAErDyB,EAAYC,cAAY,MAAOC,GAAyB,CAC5DnB,EAAW,EAAI,EACfE,EAAS,IAAI,EACbE,EAAmB,EAAK,EAExB,MAAMgB,EAA+B,CACnC,KAAAzB,EACA,SAAAE,CAAA,EAEEc,MAAqB,MAAQA,GAC7BE,MAAsB,OAASA,GAC/BE,MAAyB,UAAYA,GAEzC,GAAI,CACF,MAAMM,EAAO,MAAMC,EAAe,CAAE,GAAGF,EAAQ,OAAAD,EAA+B,EAC9E5B,EAAW8B,EAAK,OAAO,EACvB3B,EAAS2B,EAAK,KAAK,CACrB,OAASE,EAAY,CACnB,MAAMC,EAAMD,EACRC,EAAI,aAAe,KACrBpB,EAAmB,EAAI,EACvBb,EAAW,CAAA,CAAE,EACbG,EAAS,CAAC,GAEVQ,EAASsB,EAAI,SAAW,4BAA4B,CAExD,QAAA,CACExB,EAAW,EAAK,CAClB,CACF,EAAG,CAACL,EAAME,EAAUc,EAAcE,EAAeE,CAAgB,CAAC,EAElEU,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAK,IAAI,gBACf,OAAKT,EAAUS,EAAG,MAAM,EACjB,IAAMA,EAAG,MAAA,CAClB,EAAG,CAACT,CAAS,CAAC,EAEd,MAAMU,EAAe,IAAM,CACzB/B,EAAQ,CAAC,EACTgB,EAAgBP,CAAW,EAC3BS,EAAiBP,CAAY,EAC7BS,EAAoBP,CAAe,CACrC,EAEMmB,EAAe,IAAM,CACzBtB,EAAe,EAAE,EACjBE,EAAgB,EAAE,EAClBE,EAAmB,EAAE,EACrBd,EAAQ,CAAC,EACTgB,EAAgB,EAAE,EAClBE,EAAiB,EAAE,EACnBE,EAAoB,EAAE,CACxB,EAEMa,EAAa,KAAK,IAAI,EAAG,KAAK,KAAKpC,EAAQI,CAAQ,CAAC,EAE1D,OACEZ,EAAAA,KAAC,MAAA,CAAI,UAAU,sBAEb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAA,OAAC,MAAA,CACC,SAAA,CAAAJ,EAAAA,IAAC,KAAA,CAAG,UAAU,mCAAmC,SAAA,cAAW,EAC5DA,EAAAA,IAAC,IAAA,CAAE,UAAU,6BAA6B,SAAA,4CAAA,CAE1C,CAAA,EACF,EACAI,EAAAA,KAAC,SAAA,CACC,QAAS,IAAM,CAAOgC,EAAA,CAAa,EACnC,SAAUlB,EACV,UAAU,wLAEV,SAAA,CAAAlB,MAACiD,GAAU,UAAW,eAAe/B,EAAU,eAAiB,EAAE,GAAI,EAAE,SAAA,CAAA,CAAA,CAE1E,EACF,EAGAd,EAAAA,KAAC,MAAA,CAAI,UAAU,uDACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACb,SAAA,CAAAJ,EAAAA,IAACR,EAAA,CAAO,UAAU,uBAAA,CAAwB,EAC1CQ,EAAAA,IAAC,OAAA,CAAK,UAAU,oCAAoC,SAAA,SAAA,CAAO,CAAA,EAC7D,EACAI,EAAAA,KAAC,MAAA,CAAI,UAAU,iCACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAJ,MAAC,QAAA,CAAM,QAAQ,eAAe,UAAU,wBAAwB,SAAA,iBAAc,EAC9EA,EAAAA,IAAC,QAAA,CACC,GAAG,eACH,KAAK,OACL,YAAY,kBACZ,MAAOwB,EACP,SAAWkB,GAAMjB,EAAeiB,EAAE,OAAO,KAAK,EAC9C,UAAYA,GAAM,CAAMA,EAAE,MAAQ,SAASI,EAAA,CAAgB,EAC3D,UAAU,gJAAA,CAAA,CACZ,EACF,EACA1C,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAJ,MAAC,QAAA,CAAM,QAAQ,gBAAgB,UAAU,wBAAwB,SAAA,SAAM,EACvEA,EAAAA,IAAC,SAAA,CACC,GAAG,gBACH,MAAO0B,EACP,SAAWgB,GAAMf,EAAgBe,EAAE,OAAO,KAAK,EAC/C,UAAU,4HAET,SAAAhD,EAAe,IAAKwD,GACnBlD,EAAAA,IAAC,SAAA,CAAuB,MAAOkD,EAAI,MAAQ,SAAAA,EAAI,KAAA,EAAlCA,EAAI,KAAoC,CACtD,CAAA,CAAA,CACH,EACF,EACA9C,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAJ,MAAC,QAAA,CAAM,QAAQ,iBAAiB,UAAU,wBAAwB,SAAA,aAAU,EAC5EA,EAAAA,IAAC,QAAA,CACC,GAAG,iBACH,KAAK,OACL,YAAY,gBACZ,MAAO4B,EACP,SAAWc,GAAMb,EAAmBa,EAAE,OAAO,KAAK,EAClD,UAAYA,GAAM,CAAMA,EAAE,MAAQ,SAASI,EAAA,CAAgB,EAC3D,UAAU,gJAAA,CAAA,CACZ,EACF,EACA9C,EAAAA,IAAC,SAAA,CACC,QAAS8C,EACT,UAAU,4IACX,SAAA,OAAA,CAAA,EAGD9C,EAAAA,IAAC,SAAA,CACC,QAAS+C,EACT,UAAU,+HACX,SAAA,OAAA,CAAA,CAED,CAAA,CACF,CAAA,EACF,EAGCzB,EACClB,EAAAA,KAAC,MAAA,CAAI,UAAU,kEACb,SAAA,CAAAJ,EAAAA,IAACmD,EAAA,CAAO,UAAU,sCAAA,CAAuC,EACzDnD,EAAAA,IAAC,IAAA,CAAE,UAAU,4BAA4B,SAAA,mCAAgC,EACzEA,EAAAA,IAAC,IAAA,CAAE,UAAU,6BAA6B,SAAA,gEAAA,CAE1C,CAAA,CAAA,CACF,EACEoB,EACFhB,EAAAA,KAAC,MAAA,CAAI,UAAU,qEACb,SAAA,CAAAJ,EAAAA,IAACoD,EAAA,CAAY,UAAU,qCAAA,CAAsC,EAC7DpD,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,4BAAyB,EACjEA,EAAAA,IAAC,IAAA,CAAE,UAAU,6BAA8B,SAAAoB,EAAM,EACjDpB,EAAAA,IAAC,SAAA,CACC,QAAS,IAAM,CAAOoC,EAAA,CAAa,EACnC,UAAU,uIACX,SAAA,OAAA,CAAA,CAED,CAAA,CACF,EACElB,EACFlB,EAAAA,IAAC,MAAA,CAAI,UAAU,mEACb,SAAAI,EAAAA,KAAC,QAAA,CAAM,UAAU,mBACf,SAAA,CAAAJ,MAAC,QAAA,CACC,SAAAI,EAAAA,KAAC,KAAA,CAAG,UAAU,2BACZ,SAAA,CAAAJ,EAAAA,IAAC,KAAA,CAAG,UAAU,uEAAuE,SAAA,YAAS,EAC9FA,EAAAA,IAAC,KAAA,CAAG,UAAU,uEAAuE,SAAA,QAAK,EAC1FA,EAAAA,IAAC,KAAA,CAAG,UAAU,uEAAuE,SAAA,SAAM,EAC3FA,EAAAA,IAAC,KAAA,CAAG,UAAU,uEAAuE,SAAA,aAAU,EAC/FA,EAAAA,IAAC,KAAA,CAAG,UAAU,uEAAuE,SAAA,QAAA,CAAM,CAAA,CAAA,CAC7F,CAAA,CACF,QACC,QAAA,CACC,SAAAA,EAAAA,IAACF,EAAA,CAAa,MAAOkB,EAAU,CAAA,CACjC,CAAA,CAAA,CACF,CAAA,CACF,EACEP,EAAQ,SAAW,EACrBL,EAAAA,KAAC,MAAA,CAAI,UAAU,kEACb,SAAA,CAAAJ,EAAAA,IAACP,EAAA,CAAQ,UAAU,sCAAA,CAAuC,EAC1DO,EAAAA,IAAC,IAAA,CAAE,UAAU,4BAA4B,SAAA,yBAAsB,EAC/DA,EAAAA,IAAC,KAAE,UAAU,6BACT,YAAgBgC,GAAiBE,EAC/B,8BACA,4DAAA,CACN,CAAA,CAAA,CACF,EAEA9B,EAAAA,KAAAH,EAAAA,SAAA,CAEE,SAAA,CAAAD,EAAAA,IAAC,OAAI,UAAU,mEACb,SAAAI,EAAAA,KAAC,QAAA,CAAM,UAAU,mBACf,SAAA,CAAAJ,MAAC,QAAA,CACC,SAAAI,EAAAA,KAAC,KAAA,CAAG,UAAU,2BACZ,SAAA,CAAAJ,EAAAA,IAAC,KAAA,CAAG,UAAU,uEAAuE,SAAA,YAAS,EAC9FA,EAAAA,IAAC,KAAA,CAAG,UAAU,uEAAuE,SAAA,QAAK,EAC1FA,EAAAA,IAAC,KAAA,CAAG,UAAU,uEAAuE,SAAA,SAAM,EAC3FA,EAAAA,IAAC,KAAA,CAAG,UAAU,uEAAuE,SAAA,aAAU,EAC/FA,EAAAA,IAAC,KAAA,CAAG,UAAU,uEAAuE,SAAA,QAAA,CAAM,CAAA,CAAA,CAC7F,CAAA,CACF,EACAA,EAAAA,IAAC,QAAA,CACE,SAAAS,EAAQ,IAAKH,GACZN,EAAAA,IAACK,EAAA,CAAyB,OAAAC,CAAA,EAAXA,EAAO,EAAoB,CAC3C,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CACF,EAGAF,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,gDACb,SAAA,CAAAA,OAAC,OAAA,CAAM,SAAA,CAAAQ,EAAM,UAAQA,IAAU,EAAI,IAAM,EAAA,EAAG,EAC5CZ,EAAAA,IAAC,OAAA,CAAK,UAAU,gBAAgB,SAAA,IAAC,QAChC,QAAA,CAAM,QAAQ,YAAY,UAAU,UAAU,SAAA,YAAS,EACxDA,EAAAA,IAAC,SAAA,CACC,GAAG,YACH,MAAOgB,EACP,SAAW0B,GAAM,CAAEzB,EAAY,OAAOyB,EAAE,OAAO,KAAK,CAAC,EAAG3B,EAAQ,CAAC,CAAG,EACpE,UAAU,0HAET,WAAkB,IAAKsC,GACtBjD,OAAC,SAAA,CAAkB,MAAOiD,EAAO,SAAA,CAAAA,EAAK,SAAA,CAAA,EAAzBA,CAAgC,CAC9C,CAAA,CAAA,CACH,EACF,EACAjD,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAA,EAAAA,KAAC,OAAA,CAAK,UAAU,wBAAwB,SAAA,CAAA,QAChCU,EAAK,OAAKkC,CAAA,EAClB,EACAhD,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMe,EAASuC,GAAM,KAAK,IAAI,EAAGA,EAAI,CAAC,CAAC,EAChD,SAAUxC,GAAQ,EAClB,UAAU,0LACV,aAAW,gBAEX,SAAAd,EAAAA,IAACuD,EAAA,CAAY,UAAU,aAAA,CAAc,CAAA,CAAA,EAEvCvD,EAAAA,IAAC,SAAA,CACC,QAAS,IAAMe,EAASuC,GAAM,KAAK,IAAIN,EAAYM,EAAI,CAAC,CAAC,EACzD,SAAUxC,GAAQkC,EAClB,UAAU,0LACV,aAAW,YAEX,SAAAhD,EAAAA,IAACwD,EAAA,CAAa,UAAU,aAAA,CAAc,CAAA,CAAA,CACxC,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,EAEJ,CAEJ","x_google_ignoreList":[0,1,2]}
@@ -0,0 +1,6 @@
1
+ import{r as a,j as e}from"./react-vendor-D39sujLR.js";import{c as F,u as L,g as _,R as P,K as S,b as $,r as D}from"./index-B6Xt25Fx.js";import{C as M}from"./ConfirmDialog-COiUPUp_.js";import{f as V}from"./format-DhqF4LAD.js";import{P as H,T as z}from"./trash-2-DwBqM5Mz.js";import{E as O,a as U}from"./eye-BMuhGY5-.js";import"./utils-vendor-Bk4NZbDs.js";import"./router-vendor-CSOqEeqr.js";/**
2
+ * @license lucide-react v0.474.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const q=[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]],B=F("Copy",q),G=15e3,J=6e4;function Q(r){return new Date(r).toLocaleString()}function W(r){return r.length<=12?"•".repeat(r.length):`${r.slice(0,8)}${"•".repeat(Math.max(8,r.length-12))}${r.slice(-4)}`}function ne(){const[r,u]=a.useState([]),[A,g]=a.useState(!0),[y,f]=a.useState(null),[h,j]=a.useState(""),[v,N]=a.useState(!1),[w,k]=a.useState(!1),[C,R]=a.useState(null),[d,b]=a.useState(null),[n,m]=a.useState(null),[p,c]=a.useState(!1),i=L(t=>t.addToast),l=a.useCallback(async(t=!1)=>{t?k(!0):g(!0);try{const s=await _();u(s.slice().sort((o,x)=>x.createdAt-o.createdAt)),f(null)}catch(s){if(s.statusCode===403){u([]),f(null);return}const x=s instanceof Error?s.message:"Failed to load auth keys";f(x),i("error","Failed to load auth keys",x)}finally{t?k(!1):g(!1)}},[i]);a.useEffect(()=>{l();const t=setInterval(()=>{l(!0)},G);return()=>clearInterval(t)},[l]),a.useEffect(()=>{if(!n)return;const t=setTimeout(()=>{m(null),c(!1)},J);return()=>clearTimeout(t)},[n]);async function E(t){t.preventDefault();const s=h.trim();if(s){N(!0);try{const o=await $(s);m(o),c(!1),j(""),i("success","Auth key created","Store the secret now. It is only shown once."),await l(!0)}catch(o){i("error","Failed to create auth key",o instanceof Error?o.message:void 0)}finally{N(!1)}}}async function K(){var t;if(n)try{if(!((t=navigator.clipboard)!=null&&t.writeText))throw new Error("Clipboard access is unavailable in this browser");await navigator.clipboard.writeText(n.key),i("success","Auth key copied")}catch(s){i("warning","Failed to copy auth key",s instanceof Error?s.message:void 0)}}async function T(t,s){b({id:t,name:s})}async function I(t){R(t);try{await D(t),u(s=>s.filter(o=>o.id!==t)),(n==null?void 0:n.id)===t&&(m(null),c(!1)),i("success","Auth key revoked")}catch(s){i("error","Failed to revoke auth key",s instanceof Error?s.message:void 0)}finally{R(null)}}return e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsxs("div",{className:"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-2xl font-bold text-gray-100",children:"Auth Keys"}),e.jsx("p",{className:"mt-1 text-sm text-gray-500",children:"Create, review, and revoke dashboard API keys without exposing stored secrets."})]}),e.jsxs("button",{type:"button",onClick:()=>void l(!0),disabled:w,className:"flex min-h-[44px] items-center justify-center gap-2 rounded border border-[#1a1a2e] bg-[#111118] px-3 py-2 text-xs font-medium text-gray-300 transition-colors hover:border-[#00e5ff]/30 hover:text-[#00e5ff] disabled:cursor-not-allowed disabled:opacity-60",children:[e.jsx(P,{className:`h-3.5 w-3.5 ${w?"animate-spin":""}`}),"Refresh"]})]}),e.jsxs("div",{className:"grid gap-6 xl:grid-cols-[minmax(0,360px)_minmax(0,1fr)]",children:[e.jsxs("section",{className:"rounded-lg border border-[#1a1a2e] bg-[#111118] p-5",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm font-semibold text-gray-100",children:[e.jsx(H,{className:"h-4 w-4 text-[#00e5ff]"}),"Create Key"]}),e.jsx("p",{className:"mt-2 text-sm text-gray-500",children:"New secrets are never persisted in the dashboard and are cleared from view after one minute."}),e.jsxs("form",{className:"mt-4 space-y-4",onSubmit:E,children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1.5 block text-xs font-medium text-gray-400",htmlFor:"auth-key-name",children:"Key Name"}),e.jsx("input",{id:"auth-key-name",type:"text",value:h,onChange:t=>j(t.target.value),placeholder:"ops-primary",className:"min-h-[44px] w-full rounded border border-[#1a1a2e] bg-[#0a0a0f] px-3 py-2.5 text-sm text-gray-200 placeholder-gray-600 focus:border-[#00e5ff] focus:outline-none"})]}),e.jsxs("button",{type:"submit",disabled:v||!h.trim(),className:"flex min-h-[44px] w-full items-center justify-center gap-2 rounded border border-[#00e5ff]/30 bg-[#00e5ff]/10 px-3 py-2 text-sm font-medium text-[#00e5ff] transition-colors hover:bg-[#00e5ff]/20 disabled:cursor-not-allowed disabled:opacity-60",children:[e.jsx(S,{className:"h-4 w-4"}),v?"Creating…":"Create Auth Key"]})]}),n?e.jsxs("div",{className:"mt-5 rounded-lg border border-emerald-500/20 bg-emerald-500/5 p-4",role:"status",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold text-emerald-300",children:"Store this key now"}),e.jsx("p",{className:"mt-1 text-xs text-emerald-200/80",children:"This secret is shown once and is hidden by default."})]}),e.jsx("button",{type:"button",onClick:()=>{m(null),c(!1)},className:"text-xs font-medium text-emerald-200/80 transition-colors hover:text-emerald-200",children:"Dismiss"})]}),e.jsxs("dl",{className:"mt-4 space-y-3 text-sm text-gray-200",children:[e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs uppercase tracking-wide text-gray-500",children:"Name"}),e.jsx("dd",{className:"mt-1 font-medium text-gray-100",children:n.name})]}),e.jsxs("div",{children:[e.jsx("dt",{className:"text-xs uppercase tracking-wide text-gray-500",children:"Secret"}),e.jsx("dd",{className:"mt-1 rounded border border-[#1a1a2e] bg-[#0a0a0f] px-3 py-2 font-mono text-xs text-[#9af5ff]",children:p?n.key:W(n.key)})]})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsxs("button",{type:"button",onClick:()=>c(t=>!t),className:"flex min-h-[40px] items-center gap-2 rounded border border-[#1a1a2e] bg-[#0a0a0f] px-3 py-2 text-xs font-medium text-gray-300 transition-colors hover:border-[#00e5ff]/30 hover:text-[#00e5ff]",children:[p?e.jsx(O,{className:"h-3.5 w-3.5"}):e.jsx(U,{className:"h-3.5 w-3.5"}),p?"Hide secret":"Reveal secret"]}),e.jsxs("button",{type:"button",onClick:()=>void K(),className:"flex min-h-[40px] items-center gap-2 rounded border border-[#1a1a2e] bg-[#0a0a0f] px-3 py-2 text-xs font-medium text-gray-300 transition-colors hover:border-[#00e5ff]/30 hover:text-[#00e5ff]",children:[e.jsx(B,{className:"h-3.5 w-3.5"}),"Copy secret"]})]})]}):null]}),e.jsxs("section",{className:"rounded-lg border border-[#1a1a2e] bg-[#111118] p-5",children:[e.jsx("div",{className:"flex items-center justify-between gap-3 border-b border-[#1a1a2e] pb-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-100",children:"Existing Keys"}),e.jsxs("p",{className:"mt-1 text-xs text-gray-500",children:[r.length," key",r.length===1?"":"s"," configured"]})]})}),A?e.jsx("div",{className:"flex min-h-[240px] items-center justify-center text-sm text-gray-500",children:e.jsx("div",{className:"animate-pulse",children:"Loading auth keys…"})}):y?e.jsxs("div",{className:"mt-4 rounded-lg border border-amber-500/20 bg-amber-500/5 p-4 text-sm text-amber-200",children:[e.jsx("p",{className:"font-medium",children:"Unable to load auth keys"}),e.jsx("p",{className:"mt-1 text-amber-200/80",children:y}),e.jsx("button",{type:"button",onClick:()=>void l(),className:"mt-4 rounded border border-amber-500/30 px-3 py-2 text-xs font-medium text-amber-200 transition-colors hover:bg-amber-500/10",children:"Retry"})]}):r.length===0?e.jsxs("div",{className:"flex min-h-[240px] flex-col items-center justify-center rounded-lg border border-dashed border-[#1a1a2e] bg-[#0a0a0f] px-6 text-center",children:[e.jsx(S,{className:"h-8 w-8 text-gray-600"}),e.jsx("p",{className:"mt-4 text-sm font-medium text-gray-300",children:"No auth keys yet"}),e.jsx("p",{className:"mt-1 max-w-md text-sm text-gray-500",children:"Create a key to grant API access without sharing the dashboard bearer token."})]}):e.jsx("div",{className:"mt-4 space-y-3",children:r.map(t=>e.jsx("article",{className:"rounded-lg border border-[#1a1a2e] bg-[#0a0a0f] p-4",children:e.jsxs("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate font-medium text-gray-100",children:t.name}),e.jsx("span",{className:"rounded-full border border-[#1a1a2e] bg-[#111118] px-2 py-0.5 font-mono text-[11px] text-gray-500",children:t.id})]}),e.jsxs("p",{className:"mt-2 text-sm text-gray-400",children:["Created ",e.jsx("span",{title:Q(t.createdAt),children:V(t.createdAt)})]})]}),e.jsxs("button",{type:"button",onClick:()=>void T(t.id,t.name),disabled:C===t.id,className:"flex min-h-[40px] items-center justify-center gap-2 rounded border border-red-500/20 bg-red-500/5 px-3 py-2 text-xs font-medium text-red-300 transition-colors hover:bg-red-500/10 disabled:cursor-not-allowed disabled:opacity-60",children:[e.jsx(z,{className:"h-3.5 w-3.5"}),C===t.id?"Revoking…":"Revoke"]})]})},t.id))})]})]}),e.jsx(M,{open:d!==null,title:"Revoke Auth Key",message:d?`Revoke auth key "${d.name}"? This cannot be undone.`:"",confirmLabel:"Revoke",variant:"danger",onConfirm:()=>{d&&(I(d.id),b(null))},onCancel:()=>b(null)})]})}export{ne as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthKeysPage-B6MWGnkC.js","sources":["../../node_modules/lucide-react/dist/esm/icons/copy.js","../../src/pages/AuthKeysPage.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.474.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"14\", height: \"14\", x: \"8\", y: \"8\", rx: \"2\", ry: \"2\", key: \"17jyea\" }],\n [\"path\", { d: \"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\", key: \"zix9uf\" }]\n];\nconst Copy = createLucideIcon(\"Copy\", __iconNode);\n\nexport { __iconNode, Copy as default };\n//# sourceMappingURL=copy.js.map\n","import { useCallback, useEffect, useState } from 'react';\nimport {\n Copy,\n Eye,\n EyeOff,\n KeyRound,\n Plus,\n RefreshCw,\n Trash2,\n} from 'lucide-react';\nimport {\n createAuthKey,\n getAuthKeys,\n revokeAuthKey,\n type AuthKey,\n type CreatedAuthKey,\n} from '../api/client';\nimport { useToastStore } from '../store/useToastStore';\nimport { ConfirmDialog } from '../components/ConfirmDialog';\nimport { formatTimeAgo } from '../utils/format';\n\nconst REFRESH_INTERVAL_MS = 15_000;\nconst SECRET_CLEAR_MS = 60_000;\n\nfunction formatCreatedAt(timestamp: number): string {\n return new Date(timestamp).toLocaleString();\n}\n\nfunction maskKey(key: string): string {\n if (key.length <= 12) return '•'.repeat(key.length);\n return `${key.slice(0, 8)}${'•'.repeat(Math.max(8, key.length - 12))}${key.slice(-4)}`;\n}\n\nexport default function AuthKeysPage() {\n const [keys, setKeys] = useState<AuthKey[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [name, setName] = useState('');\n const [creating, setCreating] = useState(false);\n const [refreshing, setRefreshing] = useState(false);\n const [revokingId, setRevokingId] = useState<string | null>(null);\n const [revokeConfirm, setRevokeConfirm] = useState<{ id: string; name: string } | null>(null);\n const [createdKey, setCreatedKey] = useState<CreatedAuthKey | null>(null);\n const [secretVisible, setSecretVisible] = useState(false);\n const addToast = useToastStore((store) => store.addToast);\n\n const fetchKeys = useCallback(async (silent = false) => {\n if (silent) {\n setRefreshing(true);\n } else {\n setLoading(true);\n }\n\n try {\n const data = await getAuthKeys();\n setKeys(data.slice().sort((left, right) => right.createdAt - left.createdAt));\n setError(null);\n } catch (err) {\n // #1168: Suppress 403 noise - user simply lacks permission\n const statusCode = (err as Error & { statusCode?: number }).statusCode;\n if (statusCode === 403) {\n setKeys([]);\n setError(null);\n return;\n }\n const message = err instanceof Error ? err.message : 'Failed to load auth keys';\n setError(message);\n addToast('error', 'Failed to load auth keys', message);\n } finally {\n if (silent) {\n setRefreshing(false);\n } else {\n setLoading(false);\n }\n }\n }, [addToast]);\n\n useEffect(() => {\n fetchKeys();\n const interval = setInterval(() => {\n void fetchKeys(true);\n }, REFRESH_INTERVAL_MS);\n return () => clearInterval(interval);\n }, [fetchKeys]);\n\n useEffect(() => {\n if (!createdKey) return;\n const timer = setTimeout(() => {\n setCreatedKey(null);\n setSecretVisible(false);\n }, SECRET_CLEAR_MS);\n return () => clearTimeout(timer);\n }, [createdKey]);\n\n async function handleCreate(event: React.FormEvent<HTMLFormElement>): Promise<void> {\n event.preventDefault();\n const trimmedName = name.trim();\n if (!trimmedName) return;\n\n setCreating(true);\n try {\n const result = await createAuthKey(trimmedName);\n setCreatedKey(result);\n setSecretVisible(false);\n setName('');\n addToast('success', 'Auth key created', 'Store the secret now. It is only shown once.');\n await fetchKeys(true);\n } catch (err) {\n addToast(\n 'error',\n 'Failed to create auth key',\n err instanceof Error ? err.message : undefined,\n );\n } finally {\n setCreating(false);\n }\n }\n\n async function handleCopySecret(): Promise<void> {\n if (!createdKey) return;\n try {\n if (!navigator.clipboard?.writeText) {\n throw new Error('Clipboard access is unavailable in this browser');\n }\n await navigator.clipboard.writeText(createdKey.key);\n addToast('success', 'Auth key copied');\n } catch (err) {\n addToast('warning', 'Failed to copy auth key', err instanceof Error ? err.message : undefined);\n }\n }\n\n async function handleRevoke(id: string, keyName: string): Promise<void> {\n setRevokeConfirm({ id, name: keyName });\n }\n\n async function executeRevoke(id: string): Promise<void> {\n setRevokingId(id);\n try {\n await revokeAuthKey(id);\n setKeys((current) => current.filter((key) => key.id !== id));\n if (createdKey?.id === id) {\n setCreatedKey(null);\n setSecretVisible(false);\n }\n addToast('success', 'Auth key revoked');\n } catch (err) {\n addToast('error', 'Failed to revoke auth key', err instanceof Error ? err.message : undefined);\n } finally {\n setRevokingId(null);\n }\n }\n\n return (\n <div className=\"flex flex-col gap-6\">\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n <div>\n <h2 className=\"text-2xl font-bold text-gray-100\">Auth Keys</h2>\n <p className=\"mt-1 text-sm text-gray-500\">\n Create, review, and revoke dashboard API keys without exposing stored secrets.\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => void fetchKeys(true)}\n disabled={refreshing}\n className=\"flex min-h-[44px] items-center justify-center gap-2 rounded border border-[#1a1a2e] bg-[#111118] px-3 py-2 text-xs font-medium text-gray-300 transition-colors hover:border-[#00e5ff]/30 hover:text-[#00e5ff] disabled:cursor-not-allowed disabled:opacity-60\"\n >\n <RefreshCw className={`h-3.5 w-3.5 ${refreshing ? 'animate-spin' : ''}`} />\n Refresh\n </button>\n </div>\n\n <div className=\"grid gap-6 xl:grid-cols-[minmax(0,360px)_minmax(0,1fr)]\">\n <section className=\"rounded-lg border border-[#1a1a2e] bg-[#111118] p-5\">\n <div className=\"flex items-center gap-2 text-sm font-semibold text-gray-100\">\n <Plus className=\"h-4 w-4 text-[#00e5ff]\" />\n Create Key\n </div>\n <p className=\"mt-2 text-sm text-gray-500\">\n New secrets are never persisted in the dashboard and are cleared from view after one minute.\n </p>\n\n <form className=\"mt-4 space-y-4\" onSubmit={handleCreate}>\n <div>\n <label className=\"mb-1.5 block text-xs font-medium text-gray-400\" htmlFor=\"auth-key-name\">\n Key Name\n </label>\n <input\n id=\"auth-key-name\"\n type=\"text\"\n value={name}\n onChange={(event) => setName(event.target.value)}\n placeholder=\"ops-primary\"\n className=\"min-h-[44px] w-full rounded border border-[#1a1a2e] bg-[#0a0a0f] px-3 py-2.5 text-sm text-gray-200 placeholder-gray-600 focus:border-[#00e5ff] focus:outline-none\"\n />\n </div>\n\n <button\n type=\"submit\"\n disabled={creating || !name.trim()}\n className=\"flex min-h-[44px] w-full items-center justify-center gap-2 rounded border border-[#00e5ff]/30 bg-[#00e5ff]/10 px-3 py-2 text-sm font-medium text-[#00e5ff] transition-colors hover:bg-[#00e5ff]/20 disabled:cursor-not-allowed disabled:opacity-60\"\n >\n <KeyRound className=\"h-4 w-4\" />\n {creating ? 'Creating…' : 'Create Auth Key'}\n </button>\n </form>\n\n {createdKey ? (\n <div className=\"mt-5 rounded-lg border border-emerald-500/20 bg-emerald-500/5 p-4\" role=\"status\">\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <h3 className=\"text-sm font-semibold text-emerald-300\">Store this key now</h3>\n <p className=\"mt-1 text-xs text-emerald-200/80\">\n This secret is shown once and is hidden by default.\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => {\n setCreatedKey(null);\n setSecretVisible(false);\n }}\n className=\"text-xs font-medium text-emerald-200/80 transition-colors hover:text-emerald-200\"\n >\n Dismiss\n </button>\n </div>\n\n <dl className=\"mt-4 space-y-3 text-sm text-gray-200\">\n <div>\n <dt className=\"text-xs uppercase tracking-wide text-gray-500\">Name</dt>\n <dd className=\"mt-1 font-medium text-gray-100\">{createdKey.name}</dd>\n </div>\n <div>\n <dt className=\"text-xs uppercase tracking-wide text-gray-500\">Secret</dt>\n <dd className=\"mt-1 rounded border border-[#1a1a2e] bg-[#0a0a0f] px-3 py-2 font-mono text-xs text-[#9af5ff]\">\n {secretVisible ? createdKey.key : maskKey(createdKey.key)}\n </dd>\n </div>\n </dl>\n\n <div className=\"mt-4 flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => setSecretVisible((current) => !current)}\n className=\"flex min-h-[40px] items-center gap-2 rounded border border-[#1a1a2e] bg-[#0a0a0f] px-3 py-2 text-xs font-medium text-gray-300 transition-colors hover:border-[#00e5ff]/30 hover:text-[#00e5ff]\"\n >\n {secretVisible ? <EyeOff className=\"h-3.5 w-3.5\" /> : <Eye className=\"h-3.5 w-3.5\" />}\n {secretVisible ? 'Hide secret' : 'Reveal secret'}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleCopySecret()}\n className=\"flex min-h-[40px] items-center gap-2 rounded border border-[#1a1a2e] bg-[#0a0a0f] px-3 py-2 text-xs font-medium text-gray-300 transition-colors hover:border-[#00e5ff]/30 hover:text-[#00e5ff]\"\n >\n <Copy className=\"h-3.5 w-3.5\" />\n Copy secret\n </button>\n </div>\n </div>\n ) : null}\n </section>\n\n <section className=\"rounded-lg border border-[#1a1a2e] bg-[#111118] p-5\">\n <div className=\"flex items-center justify-between gap-3 border-b border-[#1a1a2e] pb-4\">\n <div>\n <h3 className=\"text-sm font-semibold text-gray-100\">Existing Keys</h3>\n <p className=\"mt-1 text-xs text-gray-500\">\n {keys.length} key{keys.length === 1 ? '' : 's'} configured\n </p>\n </div>\n </div>\n\n {loading ? (\n <div className=\"flex min-h-[240px] items-center justify-center text-sm text-gray-500\">\n <div className=\"animate-pulse\">Loading auth keys…</div>\n </div>\n ) : error ? (\n <div className=\"mt-4 rounded-lg border border-amber-500/20 bg-amber-500/5 p-4 text-sm text-amber-200\">\n <p className=\"font-medium\">Unable to load auth keys</p>\n <p className=\"mt-1 text-amber-200/80\">{error}</p>\n <button\n type=\"button\"\n onClick={() => void fetchKeys()}\n className=\"mt-4 rounded border border-amber-500/30 px-3 py-2 text-xs font-medium text-amber-200 transition-colors hover:bg-amber-500/10\"\n >\n Retry\n </button>\n </div>\n ) : keys.length === 0 ? (\n <div className=\"flex min-h-[240px] flex-col items-center justify-center rounded-lg border border-dashed border-[#1a1a2e] bg-[#0a0a0f] px-6 text-center\">\n <KeyRound className=\"h-8 w-8 text-gray-600\" />\n <p className=\"mt-4 text-sm font-medium text-gray-300\">No auth keys yet</p>\n <p className=\"mt-1 max-w-md text-sm text-gray-500\">\n Create a key to grant API access without sharing the dashboard bearer token.\n </p>\n </div>\n ) : (\n <div className=\"mt-4 space-y-3\">\n {keys.map((key) => (\n <article\n key={key.id}\n className=\"rounded-lg border border-[#1a1a2e] bg-[#0a0a0f] p-4\"\n >\n <div className=\"flex flex-col gap-4 md:flex-row md:items-center md:justify-between\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"truncate font-medium text-gray-100\">{key.name}</span>\n <span className=\"rounded-full border border-[#1a1a2e] bg-[#111118] px-2 py-0.5 font-mono text-[11px] text-gray-500\">\n {key.id}\n </span>\n </div>\n <p className=\"mt-2 text-sm text-gray-400\">\n Created <span title={formatCreatedAt(key.createdAt)}>{formatTimeAgo(key.createdAt)}</span>\n </p>\n </div>\n\n <button\n type=\"button\"\n onClick={() => void handleRevoke(key.id, key.name)}\n disabled={revokingId === key.id}\n className=\"flex min-h-[40px] items-center justify-center gap-2 rounded border border-red-500/20 bg-red-500/5 px-3 py-2 text-xs font-medium text-red-300 transition-colors hover:bg-red-500/10 disabled:cursor-not-allowed disabled:opacity-60\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n {revokingId === key.id ? 'Revoking…' : 'Revoke'}\n </button>\n </div>\n </article>\n ))}\n </div>\n )}\n </section>\n </div>\n\n <ConfirmDialog\n open={revokeConfirm !== null}\n title=\"Revoke Auth Key\"\n message={revokeConfirm ? `Revoke auth key \"${revokeConfirm.name}\"? This cannot be undone.` : ''}\n confirmLabel=\"Revoke\"\n variant=\"danger\"\n onConfirm={() => {\n if (revokeConfirm) {\n void executeRevoke(revokeConfirm.id);\n setRevokeConfirm(null);\n }\n }}\n onCancel={() => setRevokeConfirm(null)}\n />\n </div>\n );\n}"],"names":["__iconNode","Copy","createLucideIcon","REFRESH_INTERVAL_MS","SECRET_CLEAR_MS","formatCreatedAt","timestamp","maskKey","key","AuthKeysPage","keys","setKeys","useState","loading","setLoading","error","setError","name","setName","creating","setCreating","refreshing","setRefreshing","revokingId","setRevokingId","revokeConfirm","setRevokeConfirm","createdKey","setCreatedKey","secretVisible","setSecretVisible","addToast","useToastStore","store","fetchKeys","useCallback","silent","data","getAuthKeys","left","right","err","message","useEffect","interval","timer","handleCreate","event","trimmedName","result","createAuthKey","handleCopySecret","_a","handleRevoke","id","keyName","executeRevoke","revokeAuthKey","current","jsxs","jsx","RefreshCw","Plus","KeyRound","EyeOff","Eye","formatTimeAgo","Trash2","ConfirmDialog"],"mappings":"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","x_google_ignoreList":[0]}
@@ -0,0 +1 @@
1
+ import{r as s,j as t}from"./react-vendor-D39sujLR.js";const y={danger:{confirm:"bg-red-500/10 hover:bg-red-500/20 text-red-300 border border-red-500/30"},warning:{confirm:"bg-amber-500/10 hover:bg-amber-500/20 text-amber-300 border border-amber-500/30"},default:{confirm:"bg-[#3b82f6]/10 hover:bg-[#3b82f6]/20 text-[#3b82f6] border border-[#3b82f6]/30"}},E='input, textarea, select, button, [tabindex]:not([tabindex="-1"])';function w({open:n,title:u,message:b,confirmLabel:x="Confirm",cancelLabel:g="Cancel",variant:h="default",onConfirm:v,onCancel:o}){const l=s.useRef(null),d=s.useRef(null),c="confirm-dialog-title";if(s.useEffect(()=>{if(!n)return;const e=setTimeout(()=>{var r;return(r=l.current)==null?void 0:r.focus()},50);return()=>clearTimeout(e)},[n]),s.useEffect(()=>{if(!n)return;const e=r=>{r.key==="Escape"&&(r.preventDefault(),o())};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[n,o]),s.useEffect(()=>{if(!n)return;const e=d.current;if(!e)return;const r=a=>{if(a.key!=="Tab")return;const i=Array.from(e.querySelectorAll(E));if(i.length===0)return;const f=i[0],m=i[i.length-1];a.shiftKey?document.activeElement===f&&(a.preventDefault(),m.focus()):document.activeElement===m&&(a.preventDefault(),f.focus())};return e.addEventListener("keydown",r),()=>e.removeEventListener("keydown",r)},[n]),!n)return null;const p=y[h];return t.jsxs("div",{className:"fixed inset-0 z-50 flex items-center justify-center",children:[t.jsx("div",{className:"absolute inset-0 bg-black/60 backdrop-blur-sm",onClick:o}),t.jsxs("div",{ref:d,role:"alertdialog","aria-modal":"true","aria-labelledby":c,className:"relative w-full max-w-sm mx-4 bg-[#111118] border border-[#1a1a2e] rounded-lg shadow-2xl",children:[t.jsxs("div",{className:"p-4 sm:p-5 space-y-4",children:[t.jsx("h2",{id:c,className:"text-sm font-semibold text-gray-100",children:u}),t.jsx("p",{className:"text-sm text-gray-400",children:b})]}),t.jsxs("div",{className:"flex gap-2 px-4 sm:px-5 pb-4 sm:pb-5",children:[t.jsx("button",{type:"button",onClick:o,className:"flex-1 min-h-[44px] px-3 py-2 text-xs font-medium rounded bg-[#0a0a0f] border border-[#1a1a2e] text-gray-300 hover:text-gray-100 hover:border-[#333] transition-colors",children:g}),t.jsx("button",{ref:l,type:"button",onClick:v,className:`flex-1 min-h-[44px] px-3 py-2 text-xs font-medium rounded transition-colors ${p.confirm}`,children:x})]})]})]})}export{w as C};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmDialog-COiUPUp_.js","sources":["../../src/components/ConfirmDialog.tsx"],"sourcesContent":["/**\n * components/ConfirmDialog.tsx — Reusable confirmation modal dialog.\n */\n\nimport { useEffect, useRef } from 'react';\n\ninterface ConfirmDialogProps {\n open: boolean;\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n variant?: 'danger' | 'warning' | 'default';\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nconst VARIANT_STYLES = {\n danger: {\n confirm:\n 'bg-red-500/10 hover:bg-red-500/20 text-red-300 border border-red-500/30',\n },\n warning: {\n confirm:\n 'bg-amber-500/10 hover:bg-amber-500/20 text-amber-300 border border-amber-500/30',\n },\n default: {\n confirm:\n 'bg-[#3b82f6]/10 hover:bg-[#3b82f6]/20 text-[#3b82f6] border border-[#3b82f6]/30',\n },\n} as const;\n\nconst FOCUSABLE_SELECTOR =\n 'input, textarea, select, button, [tabindex]:not([tabindex=\"-1\"])';\n\nexport function ConfirmDialog({\n open,\n title,\n message,\n confirmLabel = 'Confirm',\n cancelLabel = 'Cancel',\n variant = 'default',\n onConfirm,\n onCancel,\n}: ConfirmDialogProps) {\n const confirmRef = useRef<HTMLButtonElement>(null);\n const modalRef = useRef<HTMLDivElement>(null);\n const titleId = 'confirm-dialog-title';\n\n // Auto-focus the confirm button when opened\n useEffect(() => {\n if (!open) return;\n const timer = setTimeout(() => confirmRef.current?.focus(), 50);\n return () => clearTimeout(timer);\n }, [open]);\n\n // Escape to cancel\n useEffect(() => {\n if (!open) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onCancel();\n }\n };\n window.addEventListener('keydown', handler);\n return () => window.removeEventListener('keydown', handler);\n }, [open, onCancel]);\n\n // Focus trap\n useEffect(() => {\n if (!open) return;\n const modal = modalRef.current;\n if (!modal) return;\n\n const handler = (e: KeyboardEvent) => {\n if (e.key !== 'Tab') return;\n const focusable = Array.from(\n modal.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n );\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n if (e.shiftKey) {\n if (document.activeElement === first) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n };\n modal.addEventListener('keydown', handler);\n return () => modal.removeEventListener('keydown', handler);\n }, [open]);\n\n if (!open) return null;\n\n const styles = VARIANT_STYLES[variant];\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-black/60 backdrop-blur-sm\"\n onClick={onCancel}\n />\n\n {/* Dialog */}\n <div\n ref={modalRef}\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n className=\"relative w-full max-w-sm mx-4 bg-[#111118] border border-[#1a1a2e] rounded-lg shadow-2xl\"\n >\n <div className=\"p-4 sm:p-5 space-y-4\">\n <h2\n id={titleId}\n className=\"text-sm font-semibold text-gray-100\"\n >\n {title}\n </h2>\n <p className=\"text-sm text-gray-400\">{message}</p>\n </div>\n\n <div className=\"flex gap-2 px-4 sm:px-5 pb-4 sm:pb-5\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"flex-1 min-h-[44px] px-3 py-2 text-xs font-medium rounded bg-[#0a0a0f] border border-[#1a1a2e] text-gray-300 hover:text-gray-100 hover:border-[#333] transition-colors\"\n >\n {cancelLabel}\n </button>\n <button\n ref={confirmRef}\n type=\"button\"\n onClick={onConfirm}\n className={`flex-1 min-h-[44px] px-3 py-2 text-xs font-medium rounded transition-colors ${styles.confirm}`}\n >\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>\n );\n}\n"],"names":["VARIANT_STYLES","FOCUSABLE_SELECTOR","ConfirmDialog","open","title","message","confirmLabel","cancelLabel","variant","onConfirm","onCancel","confirmRef","useRef","modalRef","titleId","useEffect","timer","_a","handler","e","modal","focusable","first","last","styles","jsxs","jsx"],"mappings":"sDAiBA,MAAMA,EAAiB,CACrB,OAAQ,CACN,QACE,yEAAA,EAEJ,QAAS,CACP,QACE,iFAAA,EAEJ,QAAS,CACP,QACE,iFAAA,CAEN,EAEMC,EACJ,mEAEK,SAASC,EAAc,CAC5B,KAAAC,EACA,MAAAC,EACA,QAAAC,EACA,aAAAC,EAAe,UACf,YAAAC,EAAc,SACd,QAAAC,EAAU,UACV,UAAAC,EACA,SAAAC,CACF,EAAuB,CACrB,MAAMC,EAAaC,EAAAA,OAA0B,IAAI,EAC3CC,EAAWD,EAAAA,OAAuB,IAAI,EACtCE,EAAU,uBAoDhB,GAjDAC,EAAAA,UAAU,IAAM,CACd,GAAI,CAACZ,EAAM,OACX,MAAMa,EAAQ,WAAW,IAAA,OAAM,OAAAC,EAAAN,EAAW,UAAX,YAAAM,EAAoB,SAAS,EAAE,EAC9D,MAAO,IAAM,aAAaD,CAAK,CACjC,EAAG,CAACb,CAAI,CAAC,EAGTY,EAAAA,UAAU,IAAM,CACd,GAAI,CAACZ,EAAM,OACX,MAAMe,EAAWC,GAAqB,CAChCA,EAAE,MAAQ,WACZA,EAAE,eAAA,EACFT,EAAA,EAEJ,EACA,cAAO,iBAAiB,UAAWQ,CAAO,EACnC,IAAM,OAAO,oBAAoB,UAAWA,CAAO,CAC5D,EAAG,CAACf,EAAMO,CAAQ,CAAC,EAGnBK,EAAAA,UAAU,IAAM,CACd,GAAI,CAACZ,EAAM,OACX,MAAMiB,EAAQP,EAAS,QACvB,GAAI,CAACO,EAAO,OAEZ,MAAMF,EAAWC,GAAqB,CACpC,GAAIA,EAAE,MAAQ,MAAO,OACrB,MAAME,EAAY,MAAM,KACtBD,EAAM,iBAA8BnB,CAAkB,CAAA,EAExD,GAAIoB,EAAU,SAAW,EAAG,OAC5B,MAAMC,EAAQD,EAAU,CAAC,EACnBE,EAAOF,EAAUA,EAAU,OAAS,CAAC,EACvCF,EAAE,SACA,SAAS,gBAAkBG,IAC7BH,EAAE,eAAA,EACFI,EAAK,MAAA,GAGH,SAAS,gBAAkBA,IAC7BJ,EAAE,eAAA,EACFG,EAAM,MAAA,EAGZ,EACA,OAAAF,EAAM,iBAAiB,UAAWF,CAAO,EAClC,IAAME,EAAM,oBAAoB,UAAWF,CAAO,CAC3D,EAAG,CAACf,CAAI,CAAC,EAEL,CAACA,EAAM,OAAO,KAElB,MAAMqB,EAASxB,EAAeQ,CAAO,EAErC,OACEiB,EAAAA,KAAC,MAAA,CAAI,UAAU,sDAEb,SAAA,CAAAC,EAAAA,IAAC,MAAA,CACC,UAAU,gDACV,QAAShB,CAAA,CAAA,EAIXe,EAAAA,KAAC,MAAA,CACC,IAAKZ,EACL,KAAK,cACL,aAAW,OACX,kBAAiBC,EACjB,UAAU,2FAEV,SAAA,CAAAW,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACb,SAAA,CAAAC,EAAAA,IAAC,KAAA,CACC,GAAIZ,EACJ,UAAU,sCAET,SAAAV,CAAA,CAAA,EAEHsB,EAAAA,IAAC,IAAA,CAAE,UAAU,wBAAyB,SAAArB,CAAA,CAAQ,CAAA,EAChD,EAEAoB,EAAAA,KAAC,MAAA,CAAI,UAAU,uCACb,SAAA,CAAAC,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAAShB,EACT,UAAU,yKAET,SAAAH,CAAA,CAAA,EAEHmB,EAAAA,IAAC,SAAA,CACC,IAAKf,EACL,KAAK,SACL,QAASF,EACT,UAAW,+EAA+Ee,EAAO,OAAO,GAEvG,SAAAlB,CAAA,CAAA,CACH,CAAA,CACF,CAAA,CAAA,CAAA,CACF,EACF,CAEJ"}
@@ -0,0 +1 @@
1
+ import{r as s,j as e}from"./react-vendor-D39sujLR.js";import{d as r,S as g}from"./index-B6Xt25Fx.js";import{E as y,a as j}from"./eye-BMuhGY5-.js";import{a as N}from"./router-vendor-CSOqEeqr.js";import"./utils-vendor-Bk4NZbDs.js";function E(){const m=r(t=>t.login),n=r(t=>t.init),x=r(t=>t.isAuthenticated),[o,f]=s.useState(""),[a,h]=s.useState(!1),[l,i]=s.useState(""),[c,d]=s.useState(!1);if(s.useEffect(()=>{n()},[n]),x)return e.jsx(N,{to:"/",replace:!0});async function p(t){t.preventDefault();const u=o.trim();if(!u)return;i(""),d(!0);const b=await m(u);d(!1),b||i("Invalid API token")}return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-[#0a0a0f]",children:e.jsxs("div",{className:"w-full max-w-sm rounded-xl border border-zinc-800 bg-zinc-900 p-8",children:[e.jsxs("div",{className:"mb-8 flex flex-col items-center gap-2",children:[e.jsx(g,{className:"h-10 w-10 text-blue-500"}),e.jsx("h1",{className:"text-xl font-semibold text-gray-100",children:"Aegis"}),e.jsx("p",{className:"text-sm text-gray-400",children:"Enter your API token to continue"})]}),e.jsxs("form",{onSubmit:p,className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"relative",children:[e.jsx("label",{htmlFor:"token",className:"sr-only",children:"API token"}),e.jsx("input",{id:"token",name:"token",type:a?"text":"password",value:o,onChange:t=>f(t.target.value),placeholder:"API token",autoFocus:!0,autoComplete:"current-password",className:"w-full rounded-lg border border-zinc-700 bg-zinc-800 px-3 py-2.5 pr-10 text-sm text-gray-200 placeholder-gray-500 focus:border-blue-500 focus:outline-none"}),e.jsx("button",{type:"button",onClick:()=>h(!a),className:"absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-200","aria-label":a?"Hide token":"Show token",children:a?e.jsx(y,{className:"h-4 w-4"}):e.jsx(j,{className:"h-4 w-4"})})]}),l&&e.jsx("p",{className:"text-sm text-red-400",children:l}),e.jsx("button",{type:"submit",disabled:c||!o.trim(),className:"rounded-lg bg-blue-600 px-4 py-2.5 text-sm font-medium text-white hover:bg-blue-500 disabled:cursor-not-allowed disabled:opacity-50",children:c?"Verifying...":"Sign in"})]})]})})}export{E as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoginPage-BRx1aLi6.js","sources":["../../src/pages/LoginPage.tsx"],"sourcesContent":["/**\n * pages/LoginPage.tsx — Full-screen login form for API token authentication.\n */\n\nimport { type FormEvent, useEffect, useState } from 'react';\nimport { Navigate } from 'react-router-dom';\nimport { Shield, Eye, EyeOff } from 'lucide-react';\nimport { useAuthStore } from '../store/useAuthStore.js';\n\nexport default function LoginPage() {\n const login = useAuthStore((s) => s.login);\n const init = useAuthStore((s) => s.init);\n const isAuthenticated = useAuthStore((s) => s.isAuthenticated);\n const [token, setToken] = useState('');\n const [showToken, setShowToken] = useState(false);\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n void init();\n }, [init]);\n\n if (isAuthenticated) {\n return <Navigate to=\"/\" replace />;\n }\n\n async function handleSubmit(e: FormEvent): Promise<void> {\n e.preventDefault();\n const trimmed = token.trim();\n if (!trimmed) return;\n\n setError('');\n setLoading(true);\n const success = await login(trimmed);\n setLoading(false);\n\n if (!success) {\n setError('Invalid API token');\n }\n // On success, the auth store sets isAuthenticated and ProtectedRoute redirects\n }\n\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-[#0a0a0f]\">\n <div className=\"w-full max-w-sm rounded-xl border border-zinc-800 bg-zinc-900 p-8\">\n {/* Logo / Title */}\n <div className=\"mb-8 flex flex-col items-center gap-2\">\n <Shield className=\"h-10 w-10 text-blue-500\" />\n <h1 className=\"text-xl font-semibold text-gray-100\">Aegis</h1>\n <p className=\"text-sm text-gray-400\">Enter your API token to continue</p>\n </div>\n\n {/* Form */}\n <form onSubmit={handleSubmit} className=\"flex flex-col gap-4\">\n <div className=\"relative\">\n <label htmlFor=\"token\" className=\"sr-only\">API token</label>\n <input\n id=\"token\"\n name=\"token\"\n type={showToken ? 'text' : 'password'}\n value={token}\n onChange={(e) => setToken(e.target.value)}\n placeholder=\"API token\"\n autoFocus\n autoComplete=\"current-password\"\n className=\"w-full rounded-lg border border-zinc-700 bg-zinc-800 px-3 py-2.5 pr-10 text-sm text-gray-200 placeholder-gray-500 focus:border-blue-500 focus:outline-none\"\n />\n <button\n type=\"button\"\n onClick={() => setShowToken(!showToken)}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-200\"\n aria-label={showToken ? 'Hide token' : 'Show token'}\n >\n {showToken ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\n </button>\n </div>\n\n {error && (\n <p className=\"text-sm text-red-400\">{error}</p>\n )}\n\n <button\n type=\"submit\"\n disabled={loading || !token.trim()}\n className=\"rounded-lg bg-blue-600 px-4 py-2.5 text-sm font-medium text-white hover:bg-blue-500 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {loading ? 'Verifying...' : 'Sign in'}\n </button>\n </form>\n </div>\n </div>\n );\n}\n"],"names":["LoginPage","login","useAuthStore","s","init","isAuthenticated","token","setToken","useState","showToken","setShowToken","error","setError","loading","setLoading","useEffect","jsx","Navigate","handleSubmit","e","trimmed","success","jsxs","Shield","EyeOff","Eye"],"mappings":"qOASA,SAAwBA,GAAY,CAClC,MAAMC,EAAQC,EAAcC,GAAMA,EAAE,KAAK,EACnCC,EAAOF,EAAcC,GAAMA,EAAE,IAAI,EACjCE,EAAkBH,EAAcC,GAAMA,EAAE,eAAe,EACvD,CAACG,EAAOC,CAAQ,EAAIC,EAAAA,SAAS,EAAE,EAC/B,CAACC,EAAWC,CAAY,EAAIF,EAAAA,SAAS,EAAK,EAC1C,CAACG,EAAOC,CAAQ,EAAIJ,EAAAA,SAAS,EAAE,EAC/B,CAACK,EAASC,CAAU,EAAIN,EAAAA,SAAS,EAAK,EAM5C,GAJAO,EAAAA,UAAU,IAAM,CACTX,EAAA,CACP,EAAG,CAACA,CAAI,CAAC,EAELC,EACF,OAAOW,EAAAA,IAACC,EAAA,CAAS,GAAG,IAAI,QAAO,GAAC,EAGlC,eAAeC,EAAaC,EAA6B,CACvDA,EAAE,eAAA,EACF,MAAMC,EAAUd,EAAM,KAAA,EACtB,GAAI,CAACc,EAAS,OAEdR,EAAS,EAAE,EACXE,EAAW,EAAI,EACf,MAAMO,EAAU,MAAMpB,EAAMmB,CAAO,EACnCN,EAAW,EAAK,EAEXO,GACHT,EAAS,mBAAmB,CAGhC,CAEA,aACG,MAAA,CAAI,UAAU,6DACb,SAAAU,EAAAA,KAAC,MAAA,CAAI,UAAU,oEAEb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAN,EAAAA,IAACO,EAAA,CAAO,UAAU,yBAAA,CAA0B,EAC5CP,EAAAA,IAAC,KAAA,CAAG,UAAU,sCAAsC,SAAA,QAAK,EACzDA,EAAAA,IAAC,IAAA,CAAE,UAAU,wBAAwB,SAAA,kCAAA,CAAgC,CAAA,EACvE,EAGAM,EAAAA,KAAC,OAAA,CAAK,SAAUJ,EAAc,UAAU,sBACtC,SAAA,CAAAI,EAAAA,KAAC,MAAA,CAAI,UAAU,WACb,SAAA,CAAAN,MAAC,QAAA,CAAM,QAAQ,QAAQ,UAAU,UAAU,SAAA,YAAS,EACpDA,EAAAA,IAAC,QAAA,CACC,GAAG,QACH,KAAK,QACL,KAAMP,EAAY,OAAS,WAC3B,MAAOH,EACP,SAAWa,GAAMZ,EAASY,EAAE,OAAO,KAAK,EACxC,YAAY,YACZ,UAAS,GACT,aAAa,mBACb,UAAU,4JAAA,CAAA,EAEZH,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAAS,IAAMN,EAAa,CAACD,CAAS,EACtC,UAAU,8EACV,aAAYA,EAAY,aAAe,aAEtC,SAAAA,QAAae,EAAA,CAAO,UAAU,UAAU,EAAKR,EAAAA,IAACS,EAAA,CAAI,UAAU,SAAA,CAAU,CAAA,CAAA,CACzE,EACF,EAECd,GACCK,EAAAA,IAAC,IAAA,CAAE,UAAU,uBAAwB,SAAAL,EAAM,EAG7CK,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,SAAUH,GAAW,CAACP,EAAM,KAAA,EAC5B,UAAU,sIAET,WAAU,eAAiB,SAAA,CAAA,CAC9B,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CACF,CAEJ"}
@@ -0,0 +1 @@
1
+ import{j as e}from"./react-vendor-D39sujLR.js";const n={blue:"text-[#3b82f6]",green:"text-[#22c55e]",amber:"text-[#f59e0b]",red:"text-[#ef4444]",purple:"text-[#a78bfa]"},o={blue:"bg-[#3b82f6]",green:"bg-[#22c55e]",amber:"bg-[#f59e0b]",red:"bg-[#ef4444]",purple:"bg-[#a78bfa]"};function c({label:r,value:a,icon:i,suffix:t,subLabel:l,color:s="blue",bar:d}){return e.jsxs("div",{role:"article","aria-label":`${r}: ${a}${t??""}`,className:"rounded-lg border border-void-lighter bg-[#111118] p-4",children:[e.jsxs("div",{className:"mb-2 flex items-center gap-2 text-sm text-[#888]",children:[i,r]}),e.jsxs("div",{className:`font-mono text-2xl ${n[s]}`,children:[a,t&&e.jsx("span",{className:"ml-1 text-base text-[#666]",children:t})]}),d!==void 0&&e.jsx("div",{className:"mt-2 h-1.5 w-full overflow-hidden rounded-full bg-[#1e1e2a]",children:e.jsx("div",{className:`h-full rounded-full transition-all duration-500 ${o[s]}`,style:{width:`${Math.min(100,Math.max(0,d))}%`}})}),l&&e.jsx("div",{className:"mt-1.5 text-xs text-[#666]",children:l})]})}export{c as M};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetricCard-CQ1XYP_b.js","sources":["../../src/components/overview/MetricCard.tsx"],"sourcesContent":["/**\n * components/overview/MetricCard.tsx — Dark card for a single metric.\n */\n\nimport type { ReactNode } from 'react';\n\ninterface MetricCardProps {\n label: string;\n value: string | number;\n icon?: ReactNode;\n suffix?: string;\n /** Secondary detail line below the value */\n subLabel?: string;\n /** Color variant for the value text */\n color?: 'blue' | 'green' | 'amber' | 'red' | 'purple';\n /** Optional progress bar (0–100) */\n bar?: number;\n}\n\nconst colorMap: Record<string, string> = {\n blue: 'text-[#3b82f6]',\n green: 'text-[#22c55e]',\n amber: 'text-[#f59e0b]',\n red: 'text-[#ef4444]',\n purple: 'text-[#a78bfa]',\n};\n\nconst barColorMap: Record<string, string> = {\n blue: 'bg-[#3b82f6]',\n green: 'bg-[#22c55e]',\n amber: 'bg-[#f59e0b]',\n red: 'bg-[#ef4444]',\n purple: 'bg-[#a78bfa]',\n};\n\nexport default function MetricCard({ label, value, icon, suffix, subLabel, color = 'blue', bar }: MetricCardProps) {\n return (\n <div\n role=\"article\"\n aria-label={`${label}: ${value}${suffix ?? ''}`}\n className=\"rounded-lg border border-void-lighter bg-[#111118] p-4\"\n >\n <div className=\"mb-2 flex items-center gap-2 text-sm text-[#888]\">\n {icon}\n {label}\n </div>\n <div className={`font-mono text-2xl ${colorMap[color]}`}>\n {value}\n {suffix && <span className=\"ml-1 text-base text-[#666]\">{suffix}</span>}\n </div>\n {bar !== undefined && (\n <div className=\"mt-2 h-1.5 w-full overflow-hidden rounded-full bg-[#1e1e2a]\">\n <div\n className={`h-full rounded-full transition-all duration-500 ${barColorMap[color]}`}\n style={{ width: `${Math.min(100, Math.max(0, bar))}%` }}\n />\n </div>\n )}\n {subLabel && (\n <div className=\"mt-1.5 text-xs text-[#666]\">{subLabel}</div>\n )}\n </div>\n );\n}\n"],"names":["colorMap","barColorMap","MetricCard","label","value","icon","suffix","subLabel","color","bar","jsxs","jsx"],"mappings":"+CAmBA,MAAMA,EAAmC,CACvC,KAAM,iBACN,MAAO,iBACP,MAAO,iBACP,IAAK,iBACL,OAAQ,gBACV,EAEMC,EAAsC,CAC1C,KAAM,eACN,MAAO,eACP,MAAO,eACP,IAAK,eACL,OAAQ,cACV,EAEA,SAAwBC,EAAW,CAAE,MAAAC,EAAO,MAAAC,EAAO,KAAAC,EAAM,OAAAC,EAAQ,SAAAC,EAAU,MAAAC,EAAQ,OAAQ,IAAAC,GAAwB,CACjH,OACEC,EAAAA,KAAC,MAAA,CACC,KAAK,UACL,aAAY,GAAGP,CAAK,KAAKC,CAAK,GAAGE,GAAU,EAAE,GAC7C,UAAU,yDAEV,SAAA,CAAAI,EAAAA,KAAC,MAAA,CAAI,UAAU,mDACZ,SAAA,CAAAL,EACAF,CAAA,EACH,SACC,MAAA,CAAI,UAAW,sBAAsBH,EAASQ,CAAK,CAAC,GAClD,SAAA,CAAAJ,EACAE,GAAUK,EAAAA,IAAC,OAAA,CAAK,UAAU,6BAA8B,SAAAL,CAAA,CAAO,CAAA,EAClE,EACCG,IAAQ,QACPE,MAAC,MAAA,CAAI,UAAU,8DACb,SAAAA,EAAAA,IAAC,MAAA,CACC,UAAW,mDAAmDV,EAAYO,CAAK,CAAC,GAChF,MAAO,CAAE,MAAO,GAAG,KAAK,IAAI,IAAK,KAAK,IAAI,EAAGC,CAAG,CAAC,CAAC,GAAA,CAAI,CAAA,EAE1D,EAEDF,GACCI,EAAAA,IAAC,MAAA,CAAI,UAAU,6BAA8B,SAAAJ,CAAA,CAAS,CAAA,CAAA,CAAA,CAI9D"}
@@ -0,0 +1 @@
1
+ import{j as t}from"./react-vendor-D39sujLR.js";import{L as e}from"./router-vendor-CSOqEeqr.js";function a(){return t.jsxs("div",{className:"flex flex-1 flex-col items-center justify-center gap-4 text-center",children:[t.jsx("h1",{className:"text-6xl font-bold text-gray-500",children:"404"}),t.jsx("p",{className:"text-lg text-gray-400",children:"Page not found"}),t.jsx(e,{to:"/",className:"mt-2 rounded-lg bg-cyan px-4 py-2 text-sm font-medium text-void transition-colors hover:bg-cyan/80",children:"Back to Dashboard"})]})}export{a as default};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotFoundPage-JmXHxvMq.js","sources":["../../src/pages/NotFoundPage.tsx"],"sourcesContent":["/**\n * NotFoundPage.tsx — 404 catch-all route (#646).\n *\n * Rendered when the user navigates to an undefined dashboard path.\n */\n\nimport { Link } from 'react-router-dom';\n\nexport default function NotFoundPage() {\n return (\n <div className=\"flex flex-1 flex-col items-center justify-center gap-4 text-center\">\n <h1 className=\"text-6xl font-bold text-gray-500\">404</h1>\n <p className=\"text-lg text-gray-400\">Page not found</p>\n <Link\n to=\"/\"\n className=\"mt-2 rounded-lg bg-cyan px-4 py-2 text-sm font-medium text-void transition-colors hover:bg-cyan/80\"\n >\n Back to Dashboard\n </Link>\n </div>\n );\n}\n"],"names":["NotFoundPage","jsxs","jsx","Link"],"mappings":"+FAQA,SAAwBA,GAAe,CACrC,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,qEACb,SAAA,CAAAC,EAAAA,IAAC,KAAA,CAAG,UAAU,mCAAmC,SAAA,MAAG,EACpDA,EAAAA,IAAC,IAAA,CAAE,UAAU,wBAAwB,SAAA,iBAAc,EACnDA,EAAAA,IAACC,EAAA,CACC,GAAG,IACH,UAAU,qGACX,SAAA,mBAAA,CAAA,CAED,EACF,CAEJ"}