@agenticmail/enterprise 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1106) hide show
  1. package/.github/CODEOWNERS +23 -0
  2. package/.github/workflows/publish-community-skills.yml +121 -0
  3. package/.github/workflows/validate-community-skills.yml +172 -0
  4. package/ARCHITECTURE.md +184 -167
  5. package/CLAUDE.md +40 -0
  6. package/CONTRIBUTING.md +254 -0
  7. package/DEPLOYMENT.md +1031 -0
  8. package/README.md +355 -174
  9. package/community-skills/_template/README.md +31 -0
  10. package/community-skills/_template/agenticmail-skill.json +48 -0
  11. package/community-skills/activecampaign/README.md +21 -0
  12. package/community-skills/activecampaign/agenticmail-skill.json +56 -0
  13. package/community-skills/adobe-sign/README.md +21 -0
  14. package/community-skills/adobe-sign/agenticmail-skill.json +72 -0
  15. package/community-skills/adp/README.md +21 -0
  16. package/community-skills/adp/agenticmail-skill.json +65 -0
  17. package/community-skills/airtable-bases/README.md +29 -0
  18. package/community-skills/airtable-bases/agenticmail-skill.json +69 -0
  19. package/community-skills/apollo-io/README.md +21 -0
  20. package/community-skills/apollo-io/agenticmail-skill.json +50 -0
  21. package/community-skills/asana-tasks/README.md +30 -0
  22. package/community-skills/asana-tasks/agenticmail-skill.json +70 -0
  23. package/community-skills/auth0/README.md +21 -0
  24. package/community-skills/auth0/agenticmail-skill.json +56 -0
  25. package/community-skills/aws-services/README.md +38 -0
  26. package/community-skills/aws-services/agenticmail-skill.json +70 -0
  27. package/community-skills/azure-devops/README.md +21 -0
  28. package/community-skills/azure-devops/agenticmail-skill.json +57 -0
  29. package/community-skills/bamboohr/README.md +21 -0
  30. package/community-skills/bamboohr/agenticmail-skill.json +56 -0
  31. package/community-skills/basecamp/README.md +21 -0
  32. package/community-skills/basecamp/agenticmail-skill.json +56 -0
  33. package/community-skills/bigcommerce/README.md +21 -0
  34. package/community-skills/bigcommerce/agenticmail-skill.json +55 -0
  35. package/community-skills/bitbucket-repos/README.md +29 -0
  36. package/community-skills/bitbucket-repos/agenticmail-skill.json +70 -0
  37. package/community-skills/box/README.md +21 -0
  38. package/community-skills/box/agenticmail-skill.json +48 -0
  39. package/community-skills/brex/README.md +21 -0
  40. package/community-skills/brex/agenticmail-skill.json +48 -0
  41. package/community-skills/buffer/README.md +21 -0
  42. package/community-skills/buffer/agenticmail-skill.json +50 -0
  43. package/community-skills/calendly/README.md +20 -0
  44. package/community-skills/calendly/agenticmail-skill.json +43 -0
  45. package/community-skills/canva-design/README.md +33 -0
  46. package/community-skills/canva-design/agenticmail-skill.json +60 -0
  47. package/community-skills/chargebee/README.md +21 -0
  48. package/community-skills/chargebee/agenticmail-skill.json +55 -0
  49. package/community-skills/circleci-pipelines/README.md +28 -0
  50. package/community-skills/circleci-pipelines/agenticmail-skill.json +66 -0
  51. package/community-skills/clickup/README.md +21 -0
  52. package/community-skills/clickup/agenticmail-skill.json +48 -0
  53. package/community-skills/close-crm/README.md +21 -0
  54. package/community-skills/close-crm/agenticmail-skill.json +49 -0
  55. package/community-skills/cloudflare-cdn/README.md +37 -0
  56. package/community-skills/cloudflare-cdn/agenticmail-skill.json +67 -0
  57. package/community-skills/confluence-wiki/README.md +31 -0
  58. package/community-skills/confluence-wiki/agenticmail-skill.json +74 -0
  59. package/community-skills/contentful/README.md +21 -0
  60. package/community-skills/contentful/agenticmail-skill.json +62 -0
  61. package/community-skills/copper-crm/README.md +21 -0
  62. package/community-skills/copper-crm/agenticmail-skill.json +56 -0
  63. package/community-skills/crisp/README.md +21 -0
  64. package/community-skills/crisp/agenticmail-skill.json +56 -0
  65. package/community-skills/crowdstrike/README.md +21 -0
  66. package/community-skills/crowdstrike/agenticmail-skill.json +69 -0
  67. package/community-skills/datadog-monitoring/README.md +37 -0
  68. package/community-skills/datadog-monitoring/agenticmail-skill.json +73 -0
  69. package/community-skills/digitalocean/README.md +21 -0
  70. package/community-skills/digitalocean/agenticmail-skill.json +48 -0
  71. package/community-skills/discord/README.md +45 -0
  72. package/community-skills/discord/agenticmail-skill.json +65 -0
  73. package/community-skills/docker-containers/README.md +38 -0
  74. package/community-skills/docker-containers/agenticmail-skill.json +70 -0
  75. package/community-skills/docusign-esign/README.md +35 -0
  76. package/community-skills/docusign-esign/agenticmail-skill.json +66 -0
  77. package/community-skills/drift/README.md +21 -0
  78. package/community-skills/drift/agenticmail-skill.json +50 -0
  79. package/community-skills/dropbox-storage/README.md +36 -0
  80. package/community-skills/dropbox-storage/agenticmail-skill.json +67 -0
  81. package/community-skills/figma-design/README.md +36 -0
  82. package/community-skills/figma-design/agenticmail-skill.json +66 -0
  83. package/community-skills/firebase/README.md +21 -0
  84. package/community-skills/firebase/agenticmail-skill.json +56 -0
  85. package/community-skills/flyio/README.md +21 -0
  86. package/community-skills/flyio/agenticmail-skill.json +56 -0
  87. package/community-skills/freshbooks/README.md +21 -0
  88. package/community-skills/freshbooks/agenticmail-skill.json +55 -0
  89. package/community-skills/freshdesk/README.md +21 -0
  90. package/community-skills/freshdesk/agenticmail-skill.json +57 -0
  91. package/community-skills/freshsales/README.md +21 -0
  92. package/community-skills/freshsales/agenticmail-skill.json +55 -0
  93. package/community-skills/freshservice/README.md +21 -0
  94. package/community-skills/freshservice/agenticmail-skill.json +56 -0
  95. package/community-skills/front/README.md +21 -0
  96. package/community-skills/front/agenticmail-skill.json +48 -0
  97. package/community-skills/github/README.md +49 -0
  98. package/community-skills/github/agenticmail-skill.json +73 -0
  99. package/community-skills/github-actions/README.md +29 -0
  100. package/community-skills/github-actions/agenticmail-skill.json +72 -0
  101. package/community-skills/gitlab-ci/README.md +51 -0
  102. package/community-skills/gitlab-ci/agenticmail-skill.json +66 -0
  103. package/community-skills/gong/README.md +21 -0
  104. package/community-skills/gong/agenticmail-skill.json +50 -0
  105. package/community-skills/google-ads/README.md +36 -0
  106. package/community-skills/google-ads/agenticmail-skill.json +58 -0
  107. package/community-skills/google-analytics/README.md +28 -0
  108. package/community-skills/google-analytics/agenticmail-skill.json +69 -0
  109. package/community-skills/google-cloud/README.md +33 -0
  110. package/community-skills/google-cloud/agenticmail-skill.json +59 -0
  111. package/community-skills/google-drive/README.md +36 -0
  112. package/community-skills/google-drive/agenticmail-skill.json +65 -0
  113. package/community-skills/gotomeeting/README.md +20 -0
  114. package/community-skills/gotomeeting/agenticmail-skill.json +45 -0
  115. package/community-skills/grafana/README.md +21 -0
  116. package/community-skills/grafana/agenticmail-skill.json +56 -0
  117. package/community-skills/greenhouse/README.md +21 -0
  118. package/community-skills/greenhouse/agenticmail-skill.json +49 -0
  119. package/community-skills/gusto/README.md +21 -0
  120. package/community-skills/gusto/agenticmail-skill.json +49 -0
  121. package/community-skills/hashicorp-vault/README.md +21 -0
  122. package/community-skills/hashicorp-vault/agenticmail-skill.json +58 -0
  123. package/community-skills/heroku/README.md +21 -0
  124. package/community-skills/heroku/agenticmail-skill.json +48 -0
  125. package/community-skills/hibob/README.md +21 -0
  126. package/community-skills/hibob/agenticmail-skill.json +48 -0
  127. package/community-skills/hootsuite/README.md +21 -0
  128. package/community-skills/hootsuite/agenticmail-skill.json +48 -0
  129. package/community-skills/hubspot-crm/README.md +36 -0
  130. package/community-skills/hubspot-crm/agenticmail-skill.json +70 -0
  131. package/community-skills/huggingface/README.md +21 -0
  132. package/community-skills/huggingface/agenticmail-skill.json +48 -0
  133. package/community-skills/index.json +1320 -0
  134. package/community-skills/intercom-support/README.md +36 -0
  135. package/community-skills/intercom-support/agenticmail-skill.json +64 -0
  136. package/community-skills/jira/README.md +53 -0
  137. package/community-skills/jira/agenticmail-skill.json +72 -0
  138. package/community-skills/klaviyo/README.md +21 -0
  139. package/community-skills/klaviyo/agenticmail-skill.json +48 -0
  140. package/community-skills/kubernetes-cluster/README.md +36 -0
  141. package/community-skills/kubernetes-cluster/agenticmail-skill.json +72 -0
  142. package/community-skills/lattice/README.md +21 -0
  143. package/community-skills/lattice/agenticmail-skill.json +49 -0
  144. package/community-skills/launchdarkly/README.md +21 -0
  145. package/community-skills/launchdarkly/agenticmail-skill.json +48 -0
  146. package/community-skills/lever/README.md +21 -0
  147. package/community-skills/lever/agenticmail-skill.json +49 -0
  148. package/community-skills/linear/README.md +29 -0
  149. package/community-skills/linear/agenticmail-skill.json +81 -0
  150. package/community-skills/linkedin/README.md +21 -0
  151. package/community-skills/linkedin/agenticmail-skill.json +48 -0
  152. package/community-skills/livechat/README.md +20 -0
  153. package/community-skills/livechat/agenticmail-skill.json +43 -0
  154. package/community-skills/loom-video/README.md +20 -0
  155. package/community-skills/loom-video/agenticmail-skill.json +44 -0
  156. package/community-skills/mailchimp-campaigns/README.md +37 -0
  157. package/community-skills/mailchimp-campaigns/agenticmail-skill.json +69 -0
  158. package/community-skills/mailgun/README.md +21 -0
  159. package/community-skills/mailgun/agenticmail-skill.json +71 -0
  160. package/community-skills/microsoft-teams/README.md +51 -0
  161. package/community-skills/microsoft-teams/agenticmail-skill.json +66 -0
  162. package/community-skills/miro-boards/README.md +20 -0
  163. package/community-skills/miro-boards/agenticmail-skill.json +44 -0
  164. package/community-skills/mixpanel-analytics/README.md +34 -0
  165. package/community-skills/mixpanel-analytics/agenticmail-skill.json +64 -0
  166. package/community-skills/monday-boards/README.md +28 -0
  167. package/community-skills/monday-boards/agenticmail-skill.json +68 -0
  168. package/community-skills/mongodb-atlas/README.md +21 -0
  169. package/community-skills/mongodb-atlas/agenticmail-skill.json +58 -0
  170. package/community-skills/neon/README.md +21 -0
  171. package/community-skills/neon/agenticmail-skill.json +50 -0
  172. package/community-skills/netlify/README.md +21 -0
  173. package/community-skills/netlify/agenticmail-skill.json +48 -0
  174. package/community-skills/netsuite/README.md +21 -0
  175. package/community-skills/netsuite/agenticmail-skill.json +57 -0
  176. package/community-skills/newrelic/README.md +21 -0
  177. package/community-skills/newrelic/agenticmail-skill.json +58 -0
  178. package/community-skills/notion/README.md +49 -0
  179. package/community-skills/notion/agenticmail-skill.json +72 -0
  180. package/community-skills/okta/README.md +21 -0
  181. package/community-skills/okta/agenticmail-skill.json +57 -0
  182. package/community-skills/openai/README.md +21 -0
  183. package/community-skills/openai/agenticmail-skill.json +48 -0
  184. package/community-skills/opsgenie/README.md +21 -0
  185. package/community-skills/opsgenie/agenticmail-skill.json +48 -0
  186. package/community-skills/outreach/README.md +21 -0
  187. package/community-skills/outreach/agenticmail-skill.json +50 -0
  188. package/community-skills/paddle/README.md +21 -0
  189. package/community-skills/paddle/agenticmail-skill.json +55 -0
  190. package/community-skills/pagerduty/README.md +21 -0
  191. package/community-skills/pagerduty/agenticmail-skill.json +48 -0
  192. package/community-skills/pandadoc/README.md +21 -0
  193. package/community-skills/pandadoc/agenticmail-skill.json +48 -0
  194. package/community-skills/paypal/README.md +21 -0
  195. package/community-skills/paypal/agenticmail-skill.json +55 -0
  196. package/community-skills/personio/README.md +21 -0
  197. package/community-skills/personio/agenticmail-skill.json +48 -0
  198. package/community-skills/pinecone/README.md +21 -0
  199. package/community-skills/pinecone/agenticmail-skill.json +48 -0
  200. package/community-skills/pipedrive-deals/README.md +33 -0
  201. package/community-skills/pipedrive-deals/agenticmail-skill.json +60 -0
  202. package/community-skills/plaid/README.md +21 -0
  203. package/community-skills/plaid/agenticmail-skill.json +65 -0
  204. package/community-skills/postmark/README.md +21 -0
  205. package/community-skills/postmark/agenticmail-skill.json +48 -0
  206. package/community-skills/power-automate/README.md +21 -0
  207. package/community-skills/power-automate/agenticmail-skill.json +59 -0
  208. package/community-skills/quickbooks-accounting/README.md +38 -0
  209. package/community-skills/quickbooks-accounting/agenticmail-skill.json +70 -0
  210. package/community-skills/recurly/README.md +21 -0
  211. package/community-skills/recurly/agenticmail-skill.json +48 -0
  212. package/community-skills/reddit/README.md +21 -0
  213. package/community-skills/reddit/agenticmail-skill.json +48 -0
  214. package/community-skills/render/README.md +21 -0
  215. package/community-skills/render/agenticmail-skill.json +48 -0
  216. package/community-skills/ringcentral/README.md +20 -0
  217. package/community-skills/ringcentral/agenticmail-skill.json +43 -0
  218. package/community-skills/rippling/README.md +21 -0
  219. package/community-skills/rippling/agenticmail-skill.json +48 -0
  220. package/community-skills/salesforce/README.md +53 -0
  221. package/community-skills/salesforce/agenticmail-skill.json +73 -0
  222. package/community-skills/salesloft/README.md +21 -0
  223. package/community-skills/salesloft/agenticmail-skill.json +48 -0
  224. package/community-skills/sanity/README.md +21 -0
  225. package/community-skills/sanity/agenticmail-skill.json +62 -0
  226. package/community-skills/sap/README.md +21 -0
  227. package/community-skills/sap/agenticmail-skill.json +63 -0
  228. package/community-skills/segment-cdp/README.md +37 -0
  229. package/community-skills/segment-cdp/agenticmail-skill.json +66 -0
  230. package/community-skills/sendgrid-email/README.md +51 -0
  231. package/community-skills/sendgrid-email/agenticmail-skill.json +71 -0
  232. package/community-skills/sentry/README.md +21 -0
  233. package/community-skills/sentry/agenticmail-skill.json +58 -0
  234. package/community-skills/servicenow/README.md +21 -0
  235. package/community-skills/servicenow/agenticmail-skill.json +56 -0
  236. package/community-skills/shopify/README.md +21 -0
  237. package/community-skills/shopify/agenticmail-skill.json +56 -0
  238. package/community-skills/shortcut/README.md +21 -0
  239. package/community-skills/shortcut/agenticmail-skill.json +48 -0
  240. package/community-skills/slack/README.md +45 -0
  241. package/community-skills/slack/agenticmail-skill.json +73 -0
  242. package/community-skills/smartsheet/README.md +21 -0
  243. package/community-skills/smartsheet/agenticmail-skill.json +48 -0
  244. package/community-skills/snowflake-warehouse/README.md +37 -0
  245. package/community-skills/snowflake-warehouse/agenticmail-skill.json +71 -0
  246. package/community-skills/snyk/README.md +21 -0
  247. package/community-skills/snyk/agenticmail-skill.json +48 -0
  248. package/community-skills/splunk/README.md +21 -0
  249. package/community-skills/splunk/agenticmail-skill.json +56 -0
  250. package/community-skills/square/README.md +21 -0
  251. package/community-skills/square/agenticmail-skill.json +55 -0
  252. package/community-skills/statuspage/README.md +21 -0
  253. package/community-skills/statuspage/agenticmail-skill.json +56 -0
  254. package/community-skills/stripe/README.md +45 -0
  255. package/community-skills/stripe/agenticmail-skill.json +66 -0
  256. package/community-skills/supabase/README.md +21 -0
  257. package/community-skills/supabase/agenticmail-skill.json +56 -0
  258. package/community-skills/teamwork/README.md +21 -0
  259. package/community-skills/teamwork/agenticmail-skill.json +56 -0
  260. package/community-skills/telegram-bot/README.md +20 -0
  261. package/community-skills/telegram-bot/agenticmail-skill.json +52 -0
  262. package/community-skills/terraform-iac/README.md +34 -0
  263. package/community-skills/terraform-iac/agenticmail-skill.json +66 -0
  264. package/community-skills/todoist-tasks/README.md +29 -0
  265. package/community-skills/todoist-tasks/agenticmail-skill.json +72 -0
  266. package/community-skills/trello-cards/README.md +30 -0
  267. package/community-skills/trello-cards/agenticmail-skill.json +72 -0
  268. package/community-skills/twilio-sms/README.md +47 -0
  269. package/community-skills/twilio-sms/agenticmail-skill.json +63 -0
  270. package/community-skills/twitter/README.md +21 -0
  271. package/community-skills/twitter/agenticmail-skill.json +48 -0
  272. package/community-skills/vercel-deployments/README.md +29 -0
  273. package/community-skills/vercel-deployments/agenticmail-skill.json +70 -0
  274. package/community-skills/weaviate/README.md +21 -0
  275. package/community-skills/weaviate/agenticmail-skill.json +56 -0
  276. package/community-skills/webex/README.md +20 -0
  277. package/community-skills/webex/agenticmail-skill.json +43 -0
  278. package/community-skills/webflow/README.md +21 -0
  279. package/community-skills/webflow/agenticmail-skill.json +48 -0
  280. package/community-skills/whatsapp-business/README.md +20 -0
  281. package/community-skills/whatsapp-business/agenticmail-skill.json +52 -0
  282. package/community-skills/whereby/README.md +20 -0
  283. package/community-skills/whereby/agenticmail-skill.json +43 -0
  284. package/community-skills/woocommerce/README.md +21 -0
  285. package/community-skills/woocommerce/agenticmail-skill.json +55 -0
  286. package/community-skills/wordpress/README.md +21 -0
  287. package/community-skills/wordpress/agenticmail-skill.json +56 -0
  288. package/community-skills/workday/README.md +21 -0
  289. package/community-skills/workday/agenticmail-skill.json +56 -0
  290. package/community-skills/wrike/README.md +21 -0
  291. package/community-skills/wrike/agenticmail-skill.json +48 -0
  292. package/community-skills/xero/README.md +21 -0
  293. package/community-skills/xero/agenticmail-skill.json +56 -0
  294. package/community-skills/youtube/README.md +21 -0
  295. package/community-skills/youtube/agenticmail-skill.json +52 -0
  296. package/community-skills/zendesk-tickets/README.md +37 -0
  297. package/community-skills/zendesk-tickets/agenticmail-skill.json +65 -0
  298. package/community-skills/zoho-crm/README.md +21 -0
  299. package/community-skills/zoho-crm/agenticmail-skill.json +74 -0
  300. package/community-skills/zoom-meetings/README.md +51 -0
  301. package/community-skills/zoom-meetings/agenticmail-skill.json +66 -0
  302. package/community-skills/zuora/README.md +21 -0
  303. package/community-skills/zuora/agenticmail-skill.json +55 -0
  304. package/dashboards/README.md +81 -70
  305. package/dashboards/django/app.py +117 -0
  306. package/dashboards/django/static/styles.css +284 -0
  307. package/dashboards/django/templates/agent_detail.html +501 -0
  308. package/dashboards/django/templates/agents.html +217 -0
  309. package/dashboards/django/templates/api_keys.html +41 -0
  310. package/dashboards/django/templates/audit.html +26 -0
  311. package/dashboards/django/templates/compliance.html +33 -0
  312. package/dashboards/django/templates/components/modal.html +6 -0
  313. package/dashboards/django/templates/components/pagination.html +9 -0
  314. package/dashboards/django/templates/components/stats.html +8 -0
  315. package/dashboards/django/templates/dashboard.html +24 -0
  316. package/dashboards/django/templates/dlp.html +70 -0
  317. package/dashboards/django/templates/guardrails.html +78 -0
  318. package/dashboards/django/templates/journal.html +39 -0
  319. package/dashboards/django/templates/layout.html +52 -0
  320. package/dashboards/django/templates/login.html +30 -0
  321. package/dashboards/django/templates/messages.html +38 -0
  322. package/dashboards/django/templates/settings.html +472 -0
  323. package/dashboards/django/templates/skills.html +66 -0
  324. package/dashboards/django/templates/users.html +34 -0
  325. package/dashboards/django/templates/vault.html +46 -0
  326. package/dashboards/django/utils/__init__.py +0 -0
  327. package/dashboards/django/utils/api.py +20 -0
  328. package/dashboards/django/utils/helpers.py +39 -0
  329. package/dashboards/django/views/__init__.py +38 -0
  330. package/dashboards/django/views/agents.py +343 -0
  331. package/dashboards/django/views/api_keys.py +47 -0
  332. package/dashboards/django/views/audit.py +35 -0
  333. package/dashboards/django/views/auth.py +34 -0
  334. package/dashboards/django/views/compliance.py +37 -0
  335. package/dashboards/django/views/dashboard.py +27 -0
  336. package/dashboards/django/views/dlp.py +53 -0
  337. package/dashboards/django/views/guardrails.py +61 -0
  338. package/dashboards/django/views/journal.py +41 -0
  339. package/dashboards/django/views/messages.py +65 -0
  340. package/dashboards/django/views/settings_view.py +335 -0
  341. package/dashboards/django/views/skills.py +50 -0
  342. package/dashboards/django/views/users.py +42 -0
  343. package/dashboards/django/views/vault.py +50 -0
  344. package/dashboards/dotnet/AgenticMailDashboard.csproj +10 -0
  345. package/dashboards/dotnet/Program.cs +53 -233
  346. package/dashboards/dotnet/Routes/AgentRoutes.cs +771 -0
  347. package/dashboards/dotnet/Routes/ApiKeyRoutes.cs +185 -0
  348. package/dashboards/dotnet/Routes/AuditRoutes.cs +86 -0
  349. package/dashboards/dotnet/Routes/AuthRoutes.cs +50 -0
  350. package/dashboards/dotnet/Routes/ComplianceRoutes.cs +143 -0
  351. package/dashboards/dotnet/Routes/DashboardRoutes.cs +81 -0
  352. package/dashboards/dotnet/Routes/DlpRoutes.cs +230 -0
  353. package/dashboards/dotnet/Routes/GuardrailRoutes.cs +285 -0
  354. package/dashboards/dotnet/Routes/JournalRoutes.cs +118 -0
  355. package/dashboards/dotnet/Routes/MessageRoutes.cs +167 -0
  356. package/dashboards/dotnet/Routes/SettingRoutes.cs +907 -0
  357. package/dashboards/dotnet/Routes/SkillRoutes.cs +198 -0
  358. package/dashboards/dotnet/Routes/UserRoutes.cs +111 -0
  359. package/dashboards/dotnet/Routes/VaultRoutes.cs +162 -0
  360. package/dashboards/dotnet/Services/ApiClient.cs +103 -0
  361. package/dashboards/dotnet/Services/HtmlBuilder.cs +249 -0
  362. package/dashboards/dotnet/wwwroot/styles.css +284 -0
  363. package/dashboards/express/app.js +37 -126
  364. package/dashboards/express/middleware/auth.js +10 -0
  365. package/dashboards/express/package-lock.json +922 -0
  366. package/dashboards/express/package.json +17 -0
  367. package/dashboards/express/public/styles.css +284 -0
  368. package/dashboards/express/routes/agents.js +771 -0
  369. package/dashboards/express/routes/apiKeys.js +107 -0
  370. package/dashboards/express/routes/audit.js +75 -0
  371. package/dashboards/express/routes/auth.js +38 -0
  372. package/dashboards/express/routes/compliance.js +93 -0
  373. package/dashboards/express/routes/dashboard.js +65 -0
  374. package/dashboards/express/routes/dlp.js +165 -0
  375. package/dashboards/express/routes/guardrails.js +195 -0
  376. package/dashboards/express/routes/journal.js +95 -0
  377. package/dashboards/express/routes/messages.js +97 -0
  378. package/dashboards/express/routes/settings.js +830 -0
  379. package/dashboards/express/routes/skills.js +141 -0
  380. package/dashboards/express/routes/users.js +69 -0
  381. package/dashboards/express/routes/vault.js +141 -0
  382. package/dashboards/express/utils/api.js +44 -0
  383. package/dashboards/express/utils/helpers.js +46 -0
  384. package/dashboards/express/views/components/modal.js +255 -0
  385. package/dashboards/express/views/components/stats.js +22 -0
  386. package/dashboards/express/views/components/table.js +31 -0
  387. package/dashboards/express/views/layout.js +73 -0
  388. package/dashboards/express/views/login.js +45 -0
  389. package/dashboards/go/go.mod +3 -0
  390. package/dashboards/go/handlers/agents.go +790 -0
  391. package/dashboards/go/handlers/apikeys.go +38 -0
  392. package/dashboards/go/handlers/audit.go +52 -0
  393. package/dashboards/go/handlers/auth.go +39 -0
  394. package/dashboards/go/handlers/compliance.go +58 -0
  395. package/dashboards/go/handlers/dashboard.go +43 -0
  396. package/dashboards/go/handlers/dlp.go +78 -0
  397. package/dashboards/go/handlers/guardrails.go +89 -0
  398. package/dashboards/go/handlers/journal.go +60 -0
  399. package/dashboards/go/handlers/messages.go +59 -0
  400. package/dashboards/go/handlers/settings.go +951 -0
  401. package/dashboards/go/handlers/skills.go +129 -0
  402. package/dashboards/go/handlers/users.go +54 -0
  403. package/dashboards/go/handlers/vault.go +85 -0
  404. package/dashboards/go/main.go +35 -485
  405. package/dashboards/go/middleware/auth.go +17 -0
  406. package/dashboards/go/services/api.go +38 -0
  407. package/dashboards/go/services/session.go +52 -0
  408. package/dashboards/go/static/styles.css +284 -0
  409. package/dashboards/go/templates/components.go +45 -0
  410. package/dashboards/go/templates/helpers.go +35 -0
  411. package/dashboards/go/templates/layout.go +59 -0
  412. package/dashboards/html/index.html +203 -450
  413. package/dashboards/html/package.json +11 -0
  414. package/dashboards/html/public/styles.css +149 -0
  415. package/dashboards/html/src/api.js +36 -0
  416. package/dashboards/html/src/components/badge.js +13 -0
  417. package/dashboards/html/src/components/layout.js +11 -0
  418. package/dashboards/html/src/components/modal.js +9 -0
  419. package/dashboards/html/src/components/pagination.js +12 -0
  420. package/dashboards/html/src/components/stat-card.js +14 -0
  421. package/dashboards/html/src/components/table.js +6 -0
  422. package/dashboards/html/src/main.js +83 -0
  423. package/dashboards/html/src/pages/agents.js +831 -0
  424. package/dashboards/html/src/pages/api-keys.js +80 -0
  425. package/dashboards/html/src/pages/audit.js +50 -0
  426. package/dashboards/html/src/pages/compliance.js +69 -0
  427. package/dashboards/html/src/pages/dashboard.js +25 -0
  428. package/dashboards/html/src/pages/dlp.js +112 -0
  429. package/dashboards/html/src/pages/guardrails.js +127 -0
  430. package/dashboards/html/src/pages/journal.js +54 -0
  431. package/dashboards/html/src/pages/login.js +84 -0
  432. package/dashboards/html/src/pages/messages.js +90 -0
  433. package/dashboards/html/src/pages/settings.js +656 -0
  434. package/dashboards/html/src/pages/skills.js +114 -0
  435. package/dashboards/html/src/pages/users.js +62 -0
  436. package/dashboards/html/src/pages/vault.js +105 -0
  437. package/dashboards/html/src/router.js +40 -0
  438. package/dashboards/html/src/utils/escape.js +7 -0
  439. package/dashboards/html/src/utils/time.js +16 -0
  440. package/dashboards/html/src/utils/toast.js +10 -0
  441. package/dashboards/java/AgenticMailDashboard.java +123 -346
  442. package/dashboards/java/handlers/AgentsHandler.java +807 -0
  443. package/dashboards/java/handlers/ApiKeysHandler.java +201 -0
  444. package/dashboards/java/handlers/AuditHandler.java +95 -0
  445. package/dashboards/java/handlers/AuthHandler.java +71 -0
  446. package/dashboards/java/handlers/ComplianceHandler.java +192 -0
  447. package/dashboards/java/handlers/DashboardHandler.java +98 -0
  448. package/dashboards/java/handlers/DlpHandler.java +230 -0
  449. package/dashboards/java/handlers/GuardrailsHandler.java +272 -0
  450. package/dashboards/java/handlers/JournalHandler.java +130 -0
  451. package/dashboards/java/handlers/MessagesHandler.java +168 -0
  452. package/dashboards/java/handlers/SettingsHandler.java +1017 -0
  453. package/dashboards/java/handlers/SkillsHandler.java +198 -0
  454. package/dashboards/java/handlers/UsersHandler.java +118 -0
  455. package/dashboards/java/handlers/VaultHandler.java +168 -0
  456. package/dashboards/java/services/ApiClient.java +233 -0
  457. package/dashboards/java/services/SessionManager.java +138 -0
  458. package/dashboards/java/static/styles.css +288 -0
  459. package/dashboards/java/templates/Components.java +142 -0
  460. package/dashboards/java/templates/Helpers.java +106 -0
  461. package/dashboards/java/templates/Layout.java +98 -0
  462. package/dashboards/laravel/controllers/AgentController.php +250 -0
  463. package/dashboards/laravel/controllers/ApiKeyController.php +73 -0
  464. package/dashboards/laravel/controllers/AuditController.php +31 -0
  465. package/dashboards/laravel/controllers/AuthController.php +44 -0
  466. package/dashboards/laravel/controllers/ComplianceController.php +55 -0
  467. package/dashboards/laravel/controllers/DashboardController.php +28 -0
  468. package/dashboards/laravel/controllers/DlpController.php +88 -0
  469. package/dashboards/laravel/controllers/GuardrailController.php +110 -0
  470. package/dashboards/laravel/controllers/JournalController.php +44 -0
  471. package/dashboards/laravel/controllers/MessageController.php +47 -0
  472. package/dashboards/laravel/controllers/SettingController.php +258 -0
  473. package/dashboards/laravel/controllers/SkillController.php +74 -0
  474. package/dashboards/laravel/controllers/UserController.php +47 -0
  475. package/dashboards/laravel/controllers/VaultController.php +94 -0
  476. package/dashboards/laravel/index.php +319 -0
  477. package/dashboards/laravel/lib/Api.php +73 -0
  478. package/dashboards/laravel/lib/Helpers.php +123 -0
  479. package/dashboards/laravel/public/styles.css +291 -0
  480. package/dashboards/laravel/views/agent-detail.php +534 -0
  481. package/dashboards/laravel/views/agents.php +204 -0
  482. package/dashboards/laravel/views/api-keys.php +55 -0
  483. package/dashboards/laravel/views/audit.php +30 -0
  484. package/dashboards/laravel/views/compliance.php +48 -0
  485. package/dashboards/laravel/views/components/modal.php +59 -0
  486. package/dashboards/laravel/views/components/stats.php +21 -0
  487. package/dashboards/laravel/views/components/table.php +35 -0
  488. package/dashboards/laravel/views/dashboard.php +31 -0
  489. package/dashboards/laravel/views/dlp.php +87 -0
  490. package/dashboards/laravel/views/guardrails.php +95 -0
  491. package/dashboards/laravel/views/journal.php +50 -0
  492. package/dashboards/laravel/views/layout.php +82 -0
  493. package/dashboards/laravel/views/login.php +45 -0
  494. package/dashboards/laravel/views/messages.php +60 -0
  495. package/dashboards/laravel/views/settings.php +622 -0
  496. package/dashboards/laravel/views/skills.php +74 -0
  497. package/dashboards/laravel/views/users.php +42 -0
  498. package/dashboards/laravel/views/vault.php +80 -0
  499. package/dashboards/php/components/layout.php +80 -0
  500. package/dashboards/php/components/modal.php +22 -0
  501. package/dashboards/php/components/stats.php +20 -0
  502. package/dashboards/php/components/table.php +33 -0
  503. package/dashboards/php/index.php +663 -381
  504. package/dashboards/php/lib/api.php +37 -0
  505. package/dashboards/php/lib/auth.php +47 -0
  506. package/dashboards/php/lib/helpers.php +69 -0
  507. package/dashboards/php/pages/agent-detail.php +552 -0
  508. package/dashboards/php/pages/agents.php +185 -0
  509. package/dashboards/php/pages/api-keys.php +34 -0
  510. package/dashboards/php/pages/audit.php +31 -0
  511. package/dashboards/php/pages/compliance.php +38 -0
  512. package/dashboards/php/pages/dashboard.php +29 -0
  513. package/dashboards/php/pages/dlp.php +65 -0
  514. package/dashboards/php/pages/guardrails.php +70 -0
  515. package/dashboards/php/pages/journal.php +53 -0
  516. package/dashboards/php/pages/login.php +34 -0
  517. package/dashboards/php/pages/messages.php +53 -0
  518. package/dashboards/php/pages/settings.php +687 -0
  519. package/dashboards/php/pages/skills.php +70 -0
  520. package/dashboards/php/pages/users.php +37 -0
  521. package/dashboards/php/pages/vault.php +70 -0
  522. package/dashboards/php/public/styles.css +81 -0
  523. package/dashboards/python/app.py +61 -259
  524. package/dashboards/python/routes/__init__.py +0 -0
  525. package/dashboards/python/routes/agents.py +296 -0
  526. package/dashboards/python/routes/api_keys.py +49 -0
  527. package/dashboards/python/routes/audit.py +33 -0
  528. package/dashboards/python/routes/auth.py +30 -0
  529. package/dashboards/python/routes/compliance.py +50 -0
  530. package/dashboards/python/routes/dashboard.py +32 -0
  531. package/dashboards/python/routes/dlp.py +64 -0
  532. package/dashboards/python/routes/guardrails.py +79 -0
  533. package/dashboards/python/routes/journal.py +40 -0
  534. package/dashboards/python/routes/messages.py +46 -0
  535. package/dashboards/python/routes/settings.py +260 -0
  536. package/dashboards/python/routes/skills.py +59 -0
  537. package/dashboards/python/routes/users.py +43 -0
  538. package/dashboards/python/routes/vault.py +59 -0
  539. package/dashboards/python/static/styles.css +288 -0
  540. package/dashboards/python/templates/agent_detail.html +552 -0
  541. package/dashboards/python/templates/agents.html +246 -0
  542. package/dashboards/python/templates/api_keys.html +64 -0
  543. package/dashboards/python/templates/audit.html +50 -0
  544. package/dashboards/python/templates/compliance.html +74 -0
  545. package/dashboards/python/templates/components/modal.html +43 -0
  546. package/dashboards/python/templates/components/stats.html +26 -0
  547. package/dashboards/python/templates/components/table.html +43 -0
  548. package/dashboards/python/templates/dashboard.html +34 -0
  549. package/dashboards/python/templates/dlp.html +159 -0
  550. package/dashboards/python/templates/guardrails.html +131 -0
  551. package/dashboards/python/templates/journal.html +66 -0
  552. package/dashboards/python/templates/layout.html +86 -0
  553. package/dashboards/python/templates/login.html +36 -0
  554. package/dashboards/python/templates/messages.html +90 -0
  555. package/dashboards/python/templates/settings.html +624 -0
  556. package/dashboards/python/templates/skills.html +89 -0
  557. package/dashboards/python/templates/users.html +70 -0
  558. package/dashboards/python/templates/vault.html +73 -0
  559. package/dashboards/python/utils/__init__.py +0 -0
  560. package/dashboards/python/utils/api.py +35 -0
  561. package/dashboards/python/utils/helpers.py +90 -0
  562. package/dashboards/rails/app.rb +56 -0
  563. package/dashboards/rails/helpers/api.rb +39 -0
  564. package/dashboards/rails/helpers/auth.rb +11 -0
  565. package/dashboards/rails/helpers/view.rb +95 -0
  566. package/dashboards/rails/public/styles.css +299 -0
  567. package/dashboards/rails/routes/agents.rb +173 -0
  568. package/dashboards/rails/routes/api_keys.rb +30 -0
  569. package/dashboards/rails/routes/audit.rb +15 -0
  570. package/dashboards/rails/routes/auth.rb +29 -0
  571. package/dashboards/rails/routes/compliance.rb +25 -0
  572. package/dashboards/rails/routes/dashboard.rb +13 -0
  573. package/dashboards/rails/routes/dlp.rb +40 -0
  574. package/dashboards/rails/routes/guardrails.rb +51 -0
  575. package/dashboards/rails/routes/journal.rb +24 -0
  576. package/dashboards/rails/routes/messages.rb +22 -0
  577. package/dashboards/rails/routes/settings.rb +196 -0
  578. package/dashboards/rails/routes/skills.rb +38 -0
  579. package/dashboards/rails/routes/users.rb +18 -0
  580. package/dashboards/rails/routes/vault.rb +37 -0
  581. package/dashboards/rails/views/agent_detail.erb +550 -0
  582. package/dashboards/rails/views/agents.erb +214 -0
  583. package/dashboards/rails/views/api_keys.erb +52 -0
  584. package/dashboards/rails/views/audit.erb +38 -0
  585. package/dashboards/rails/views/compliance.erb +69 -0
  586. package/dashboards/rails/views/dashboard.erb +46 -0
  587. package/dashboards/rails/views/dlp.erb +104 -0
  588. package/dashboards/rails/views/guardrails.erb +107 -0
  589. package/dashboards/rails/views/journal.erb +65 -0
  590. package/dashboards/rails/views/layout.erb +53 -0
  591. package/dashboards/rails/views/login.erb +47 -0
  592. package/dashboards/rails/views/messages.erb +62 -0
  593. package/dashboards/rails/views/settings.erb +578 -0
  594. package/dashboards/rails/views/skills.erb +66 -0
  595. package/dashboards/rails/views/users.erb +53 -0
  596. package/dashboards/rails/views/vault.erb +66 -0
  597. package/dashboards/ruby/app.rb +53 -182
  598. package/dashboards/ruby/helpers/api.rb +63 -0
  599. package/dashboards/ruby/helpers/auth.rb +20 -0
  600. package/dashboards/ruby/helpers/view.rb +91 -0
  601. package/dashboards/ruby/public/styles.css +294 -0
  602. package/dashboards/ruby/routes/agents.rb +197 -0
  603. package/dashboards/ruby/routes/api_keys.rb +43 -0
  604. package/dashboards/ruby/routes/audit.rb +15 -0
  605. package/dashboards/ruby/routes/auth.rb +29 -0
  606. package/dashboards/ruby/routes/compliance.rb +28 -0
  607. package/dashboards/ruby/routes/dashboard.rb +13 -0
  608. package/dashboards/ruby/routes/dlp.rb +55 -0
  609. package/dashboards/ruby/routes/guardrails.rb +77 -0
  610. package/dashboards/ruby/routes/journal.rb +24 -0
  611. package/dashboards/ruby/routes/messages.rb +27 -0
  612. package/dashboards/ruby/routes/settings.rb +214 -0
  613. package/dashboards/ruby/routes/skills.rb +50 -0
  614. package/dashboards/ruby/routes/users.rb +26 -0
  615. package/dashboards/ruby/routes/vault.rb +49 -0
  616. package/dashboards/ruby/views/agent_detail.erb +550 -0
  617. package/dashboards/ruby/views/agents.erb +214 -0
  618. package/dashboards/ruby/views/api_keys.erb +59 -0
  619. package/dashboards/ruby/views/audit.erb +38 -0
  620. package/dashboards/ruby/views/compliance.erb +45 -0
  621. package/dashboards/ruby/views/dashboard.erb +46 -0
  622. package/dashboards/ruby/views/dlp.erb +88 -0
  623. package/dashboards/ruby/views/guardrails.erb +103 -0
  624. package/dashboards/ruby/views/journal.erb +53 -0
  625. package/dashboards/ruby/views/layout.erb +52 -0
  626. package/dashboards/ruby/views/login.erb +31 -0
  627. package/dashboards/ruby/views/messages.erb +51 -0
  628. package/dashboards/ruby/views/settings.erb +579 -0
  629. package/dashboards/ruby/views/skills.erb +66 -0
  630. package/dashboards/ruby/views/users.erb +53 -0
  631. package/dashboards/ruby/views/vault.erb +66 -0
  632. package/dashboards/shared/styles.css +322 -0
  633. package/dist/{chunk-TVF23PUW.js → chunk-7FVRYOP4.js} +22 -7
  634. package/dist/chunk-DRXMYYKN.js +79 -0
  635. package/dist/chunk-E23VJ3QX.js +9427 -0
  636. package/dist/chunk-EOBN6RCA.js +12652 -0
  637. package/dist/chunk-FLRYMSKY.js +23 -0
  638. package/dist/chunk-HAUHDCUB.js +764 -0
  639. package/dist/chunk-HSF6OJ5Z.js +154 -0
  640. package/dist/{chunk-PNKVD2UK.js → chunk-KFQGP6VL.js} +7 -0
  641. package/dist/chunk-LKAFZ343.js +591 -0
  642. package/dist/{chunk-GXIEEA2T.js → chunk-NTVN3JHS.js} +10 -10
  643. package/dist/chunk-RO537U6H.js +70 -0
  644. package/dist/chunk-SGBTJHEF.js +2287 -0
  645. package/dist/chunk-SMUXH6FM.js +1943 -0
  646. package/dist/chunk-TY7NVD4U.js +275 -0
  647. package/dist/chunk-X6UVWFHW.js +3455 -0
  648. package/dist/{chunk-7RGCCHIT.js → chunk-XMDE2NGH.js} +2 -1
  649. package/dist/chunk-ZNR5DDTA.js +239 -0
  650. package/dist/cidr-LISVZSM2.js +17 -0
  651. package/dist/cli-build-skill-XOYECCLE.js +235 -0
  652. package/dist/cli-recover-SSGGSKZJ.js +97 -0
  653. package/dist/cli-submit-skill-RSBLF5XN.js +162 -0
  654. package/dist/cli-validate-WJBUOEGW.js +148 -0
  655. package/dist/cli-verify-V3GPFMWU.js +98 -0
  656. package/dist/cli.js +50 -376
  657. package/dist/config-store-CRMKWBON.js +58 -0
  658. package/dist/dashboard/app.js +246 -0
  659. package/dist/dashboard/assets/logo.png +0 -0
  660. package/dist/dashboard/components/error-boundary.js +21 -0
  661. package/dist/dashboard/components/help-button.js +34 -0
  662. package/dist/dashboard/components/icons.js +53 -0
  663. package/dist/dashboard/components/modal.js +124 -0
  664. package/dist/dashboard/components/persona-fields.js +271 -0
  665. package/dist/dashboard/components/settings-help.js +191 -0
  666. package/dist/dashboard/components/tag-input.js +96 -0
  667. package/dist/dashboard/components/utils.js +148 -0
  668. package/dist/dashboard/index.html +407 -874
  669. package/dist/dashboard/pages/activity.js +62 -0
  670. package/dist/dashboard/pages/agent-detail.js +3577 -0
  671. package/dist/dashboard/pages/agents.js +1072 -0
  672. package/dist/dashboard/pages/approvals.js +81 -0
  673. package/dist/dashboard/pages/audit.js +133 -0
  674. package/dist/dashboard/pages/community-skills.js +665 -0
  675. package/dist/dashboard/pages/compliance.js +81 -0
  676. package/dist/dashboard/pages/dashboard.js +150 -0
  677. package/dist/dashboard/pages/dlp.js +107 -0
  678. package/dist/dashboard/pages/domain-status.js +123 -0
  679. package/dist/dashboard/pages/guardrails.js +995 -0
  680. package/dist/dashboard/pages/journal.js +51 -0
  681. package/dist/dashboard/pages/knowledge-contributions.js +763 -0
  682. package/dist/dashboard/pages/knowledge.js +46 -0
  683. package/dist/dashboard/pages/login.js +491 -0
  684. package/dist/dashboard/pages/messages.js +274 -0
  685. package/dist/dashboard/pages/settings.js +1554 -0
  686. package/dist/dashboard/pages/skill-connections.js +452 -0
  687. package/dist/dashboard/pages/skills.js +433 -0
  688. package/dist/dashboard/pages/users.js +49 -0
  689. package/dist/dashboard/pages/vault.js +538 -0
  690. package/dist/dashboard/pages/workforce.js +569 -0
  691. package/dist/dashboard/vendor/react-dom.production.min.js +267 -0
  692. package/dist/dashboard/vendor/react.production.min.js +31 -0
  693. package/dist/db-adapter-5PWMLY67.js +7 -0
  694. package/dist/domain-lock-URIFILHB.js +7 -0
  695. package/dist/{dynamodb-CCGL2E77.js → dynamodb-CD3LREWD.js} +4 -4
  696. package/dist/{factory-HINWFYZ3.js → factory-FVJH5RRY.js} +2 -2
  697. package/dist/firewall-AHIRE6UB.js +10 -0
  698. package/dist/index.js +133 -448
  699. package/dist/{managed-RZITNPXG.js → managed-QVTONZ7E.js} +4 -2
  700. package/dist/{mongodb-ODTXIVPV.js → mongodb-73MGW7LD.js} +4 -4
  701. package/dist/{mysql-RM3S2FV5.js → mysql-A2RYNBQG.js} +59 -6
  702. package/dist/{postgres-LN7A6MGQ.js → postgres-OE23X46P.js} +63 -6
  703. package/dist/registry/cli.js +411 -0
  704. package/dist/routes-NJK5OI5N.js +5673 -0
  705. package/dist/runtime-SMA6JUMP.js +46 -0
  706. package/dist/server-ZT5NWHT4.js +11 -0
  707. package/dist/setup-RCYNX5NA.js +20 -0
  708. package/dist/skills-QNR3CCHA.js +14 -0
  709. package/dist/soul-templates.json +1525 -0
  710. package/dist/{sqlite-VLKVAJA4.js → sqlite-SFVNZPHX.js} +56 -8
  711. package/dist/{turso-LDWODSDI.js → turso-L6WQAY7U.js} +59 -6
  712. package/live-test.mjs +1 -1
  713. package/package.json +11 -10
  714. package/schemas/agenticmail-skill.v1.schema.json +180 -0
  715. package/serve.mjs +12 -2
  716. package/src/admin/routes.ts +536 -5
  717. package/src/agent-tools/common.ts +232 -0
  718. package/src/agent-tools/index.ts +246 -0
  719. package/src/agent-tools/merge.ts +62 -0
  720. package/src/agent-tools/middleware.ts +436 -0
  721. package/src/agent-tools/security.ts +352 -0
  722. package/src/agent-tools/tools/bash.ts +154 -0
  723. package/src/agent-tools/tools/browser.ts +236 -0
  724. package/src/agent-tools/tools/edit.ts +100 -0
  725. package/src/agent-tools/tools/enterprise-calendar.ts +561 -0
  726. package/src/agent-tools/tools/enterprise-code-sandbox.ts +395 -0
  727. package/src/agent-tools/tools/enterprise-database.ts +377 -0
  728. package/src/agent-tools/tools/enterprise-diff.ts +580 -0
  729. package/src/agent-tools/tools/enterprise-documents.ts +896 -0
  730. package/src/agent-tools/tools/enterprise-finance.ts +484 -0
  731. package/src/agent-tools/tools/enterprise-http.ts +477 -0
  732. package/src/agent-tools/tools/enterprise-knowledge-search.ts +369 -0
  733. package/src/agent-tools/tools/enterprise-logs.ts +479 -0
  734. package/src/agent-tools/tools/enterprise-notifications.ts +532 -0
  735. package/src/agent-tools/tools/enterprise-security-scan.ts +528 -0
  736. package/src/agent-tools/tools/enterprise-spreadsheet.ts +825 -0
  737. package/src/agent-tools/tools/enterprise-translation.ts +530 -0
  738. package/src/agent-tools/tools/enterprise-vision.ts +348 -0
  739. package/src/agent-tools/tools/enterprise-web-research.ts +422 -0
  740. package/src/agent-tools/tools/enterprise-workflow.ts +308 -0
  741. package/src/agent-tools/tools/glob.ts +129 -0
  742. package/src/agent-tools/tools/grep.ts +178 -0
  743. package/src/agent-tools/tools/memory.ts +194 -0
  744. package/src/agent-tools/tools/read.ts +160 -0
  745. package/src/agent-tools/tools/web-fetch-utils.ts +202 -0
  746. package/src/agent-tools/tools/web-fetch.ts +456 -0
  747. package/src/agent-tools/tools/web-search.ts +480 -0
  748. package/src/agent-tools/tools/web-shared.ts +232 -0
  749. package/src/agent-tools/tools/write.ts +68 -0
  750. package/src/agent-tools/types.ts +193 -0
  751. package/src/auth/routes.ts +916 -51
  752. package/src/cli.ts +74 -14
  753. package/src/dashboard/app.js +246 -0
  754. package/src/dashboard/assets/logo.png +0 -0
  755. package/src/dashboard/components/error-boundary.js +21 -0
  756. package/src/dashboard/components/help-button.js +34 -0
  757. package/src/dashboard/components/icons.js +53 -0
  758. package/src/dashboard/components/modal.js +124 -0
  759. package/src/dashboard/components/persona-fields.js +271 -0
  760. package/src/dashboard/components/settings-help.js +191 -0
  761. package/src/dashboard/components/tag-input.js +96 -0
  762. package/src/dashboard/components/utils.js +148 -0
  763. package/src/dashboard/index.html +407 -874
  764. package/src/dashboard/pages/activity.js +62 -0
  765. package/src/dashboard/pages/agent-detail.js +3577 -0
  766. package/src/dashboard/pages/agents.js +1072 -0
  767. package/src/dashboard/pages/approvals.js +81 -0
  768. package/src/dashboard/pages/audit.js +133 -0
  769. package/src/dashboard/pages/community-skills.js +665 -0
  770. package/src/dashboard/pages/compliance.js +81 -0
  771. package/src/dashboard/pages/dashboard.js +150 -0
  772. package/src/dashboard/pages/dlp.js +107 -0
  773. package/src/dashboard/pages/domain-status.js +123 -0
  774. package/src/dashboard/pages/guardrails.js +995 -0
  775. package/src/dashboard/pages/journal.js +51 -0
  776. package/src/dashboard/pages/knowledge-contributions.js +763 -0
  777. package/src/dashboard/pages/knowledge.js +46 -0
  778. package/src/dashboard/pages/login.js +491 -0
  779. package/src/dashboard/pages/messages.js +274 -0
  780. package/src/dashboard/pages/settings.js +1554 -0
  781. package/src/dashboard/pages/skill-connections.js +452 -0
  782. package/src/dashboard/pages/skills.js +433 -0
  783. package/src/dashboard/pages/users.js +49 -0
  784. package/src/dashboard/pages/vault.js +538 -0
  785. package/src/dashboard/pages/workforce.js +569 -0
  786. package/src/dashboard/vendor/react-dom.production.min.js +267 -0
  787. package/src/dashboard/vendor/react.production.min.js +31 -0
  788. package/src/db/adapter.ts +134 -1
  789. package/src/db/dynamodb.ts +2 -2
  790. package/src/db/mongodb.ts +2 -2
  791. package/src/db/mysql.ts +55 -1
  792. package/src/db/postgres.ts +59 -1
  793. package/src/db/proxy.ts +39 -0
  794. package/src/db/sql-schema.ts +2 -1
  795. package/src/db/sqlite.ts +51 -3
  796. package/src/db/turso.ts +55 -1
  797. package/src/deploy/fly.ts +2 -2
  798. package/src/deploy/managed.ts +32 -11
  799. package/src/domain-lock/cli-recover.ts +124 -0
  800. package/src/domain-lock/cli-verify.ts +122 -0
  801. package/src/domain-lock/index.ts +220 -0
  802. package/src/engine/activity-routes.ts +116 -0
  803. package/src/engine/activity.ts +62 -2
  804. package/src/engine/agent-config.ts +190 -24
  805. package/src/engine/agent-memory.ts +1062 -0
  806. package/src/engine/agent-routes.ts +379 -0
  807. package/src/engine/approvals.ts +309 -2
  808. package/src/engine/catalog-routes.ts +155 -0
  809. package/src/engine/cli-build-skill.ts +285 -0
  810. package/src/engine/cli-submit-skill.ts +200 -0
  811. package/src/engine/cli-validate.ts +188 -0
  812. package/src/engine/communication-routes.ts +139 -0
  813. package/src/engine/communication.ts +759 -0
  814. package/src/engine/community-registry.ts +1509 -0
  815. package/src/engine/community-routes.ts +233 -0
  816. package/src/engine/compliance-routes.ts +93 -0
  817. package/src/engine/compliance.ts +325 -0
  818. package/src/engine/db-adapter.ts +349 -1
  819. package/src/engine/db-schema.ts +971 -23
  820. package/src/engine/deploy-schema-routes.ts +176 -0
  821. package/src/engine/deployer.ts +6 -6
  822. package/src/engine/dlp-routes.ts +59 -0
  823. package/src/engine/dlp.ts +231 -0
  824. package/src/engine/guardrail-routes.ts +125 -0
  825. package/src/engine/guardrails.ts +403 -0
  826. package/src/engine/index.ts +131 -10
  827. package/src/engine/journal-routes.ts +56 -0
  828. package/src/engine/journal.ts +249 -0
  829. package/src/engine/knowledge-contribution-routes.ts +385 -0
  830. package/src/engine/knowledge-contribution.ts +1319 -0
  831. package/src/engine/knowledge-routes.ts +68 -0
  832. package/src/engine/knowledge.ts +73 -1
  833. package/src/engine/lifecycle.ts +487 -31
  834. package/src/engine/memory-routes.ts +142 -0
  835. package/src/engine/oauth-connect-routes.ts +366 -0
  836. package/src/engine/oauth-connect.ts +304 -0
  837. package/src/engine/onboarding-routes.ts +140 -0
  838. package/src/engine/onboarding.ts +574 -0
  839. package/src/engine/org-approval-routes.ts +146 -0
  840. package/src/engine/org-policies.ts +497 -0
  841. package/src/engine/policy-import-routes.ts +125 -0
  842. package/src/engine/policy-import.ts +1186 -0
  843. package/src/engine/policy-routes.ts +163 -0
  844. package/src/engine/routes.ts +239 -482
  845. package/src/engine/skill-updater-routes.ts +132 -0
  846. package/src/engine/skill-updater.ts +480 -0
  847. package/src/engine/skill-validator.ts +331 -0
  848. package/src/engine/skills/enterprise-calendar.ts +142 -0
  849. package/src/engine/skills/enterprise-code-sandbox.ts +112 -0
  850. package/src/engine/skills/enterprise-database.ts +122 -0
  851. package/src/engine/skills/enterprise-diff.ts +94 -0
  852. package/src/engine/skills/enterprise-documents.ts +161 -0
  853. package/src/engine/skills/enterprise-finance.ts +109 -0
  854. package/src/engine/skills/enterprise-http.ts +98 -0
  855. package/src/engine/skills/enterprise-knowledge-search.ts +106 -0
  856. package/src/engine/skills/enterprise-logs.ts +115 -0
  857. package/src/engine/skills/enterprise-notifications.ts +119 -0
  858. package/src/engine/skills/enterprise-security-scan.ts +124 -0
  859. package/src/engine/skills/enterprise-spreadsheet.ts +170 -0
  860. package/src/engine/skills/enterprise-translation.ts +111 -0
  861. package/src/engine/skills/enterprise-vision.ts +107 -0
  862. package/src/engine/skills/enterprise-web-research.ts +114 -0
  863. package/src/engine/skills/enterprise-workflow.ts +109 -0
  864. package/src/engine/skills/gws-admin.ts +17 -0
  865. package/src/engine/skills/gws-calendar.ts +19 -0
  866. package/src/engine/skills/gws-chat.ts +16 -0
  867. package/src/engine/skills/gws-docs.ts +17 -0
  868. package/src/engine/skills/gws-drive.ts +20 -0
  869. package/src/engine/skills/gws-forms.ts +16 -0
  870. package/src/engine/skills/gws-gmail.ts +20 -0
  871. package/src/engine/skills/gws-groups.ts +16 -0
  872. package/src/engine/skills/gws-keep.ts +16 -0
  873. package/src/engine/skills/gws-meet.ts +16 -0
  874. package/src/engine/skills/gws-sheets.ts +18 -0
  875. package/src/engine/skills/gws-sites.ts +15 -0
  876. package/src/engine/skills/gws-slides.ts +16 -0
  877. package/src/engine/skills/gws-vault.ts +16 -0
  878. package/src/engine/skills/index.ts +121 -0
  879. package/src/engine/skills/m365-admin.ts +17 -0
  880. package/src/engine/skills/m365-bookings.ts +16 -0
  881. package/src/engine/skills/m365-copilot.ts +16 -0
  882. package/src/engine/skills/m365-excel.ts +59 -0
  883. package/src/engine/skills/m365-forms.ts +16 -0
  884. package/src/engine/skills/m365-onedrive.ts +59 -0
  885. package/src/engine/skills/m365-onenote.ts +16 -0
  886. package/src/engine/skills/m365-outlook.ts +26 -0
  887. package/src/engine/skills/m365-planner.ts +17 -0
  888. package/src/engine/skills/m365-power-automate.ts +17 -0
  889. package/src/engine/skills/m365-power-bi.ts +18 -0
  890. package/src/engine/skills/m365-powerpoint.ts +32 -0
  891. package/src/engine/skills/m365-sharepoint.ts +19 -0
  892. package/src/engine/skills/m365-teams.ts +20 -0
  893. package/src/engine/skills/m365-todo.ts +16 -0
  894. package/src/engine/skills/m365-whiteboard.ts +15 -0
  895. package/src/engine/skills/m365-word.ts +41 -0
  896. package/src/engine/skills.ts +353 -17
  897. package/src/engine/soul-library.ts +142 -0
  898. package/src/engine/soul-templates.json +1525 -0
  899. package/src/engine/storage-manager.ts +252 -0
  900. package/src/engine/storage-routes.ts +113 -0
  901. package/src/engine/storage.ts +528 -0
  902. package/src/engine/tenant.ts +69 -5
  903. package/src/engine/tool-catalog.ts +177 -13
  904. package/src/engine/vault-routes.ts +130 -0
  905. package/src/engine/vault.ts +544 -0
  906. package/src/engine/workforce-routes.ts +282 -0
  907. package/src/engine/workforce.ts +957 -0
  908. package/src/index.ts +9 -1
  909. package/src/lib/cidr.ts +122 -0
  910. package/src/lib/config-store.ts +86 -0
  911. package/src/mcp/adapters/activecampaign.adapter.ts +391 -0
  912. package/src/mcp/adapters/adobe-sign.adapter.ts +469 -0
  913. package/src/mcp/adapters/adp.adapter.ts +358 -0
  914. package/src/mcp/adapters/airtable.adapter.ts +273 -0
  915. package/src/mcp/adapters/apollo.adapter.ts +420 -0
  916. package/src/mcp/adapters/asana.adapter.ts +315 -0
  917. package/src/mcp/adapters/auth0.adapter.ts +386 -0
  918. package/src/mcp/adapters/aws.adapter.ts +345 -0
  919. package/src/mcp/adapters/azure-devops.adapter.ts +389 -0
  920. package/src/mcp/adapters/bamboohr.adapter.ts +376 -0
  921. package/src/mcp/adapters/basecamp.adapter.ts +366 -0
  922. package/src/mcp/adapters/bigcommerce.adapter.ts +429 -0
  923. package/src/mcp/adapters/bitbucket.adapter.ts +260 -0
  924. package/src/mcp/adapters/box.adapter.ts +350 -0
  925. package/src/mcp/adapters/brex.adapter.ts +367 -0
  926. package/src/mcp/adapters/buffer.adapter.ts +303 -0
  927. package/src/mcp/adapters/calendly.adapter.ts +262 -0
  928. package/src/mcp/adapters/canva.adapter.ts +256 -0
  929. package/src/mcp/adapters/chargebee.adapter.ts +448 -0
  930. package/src/mcp/adapters/circleci.adapter.ts +216 -0
  931. package/src/mcp/adapters/clickup.adapter.ts +335 -0
  932. package/src/mcp/adapters/close.adapter.ts +390 -0
  933. package/src/mcp/adapters/cloudflare.adapter.ts +377 -0
  934. package/src/mcp/adapters/confluence.adapter.ts +301 -0
  935. package/src/mcp/adapters/contentful.adapter.ts +355 -0
  936. package/src/mcp/adapters/copper.adapter.ts +468 -0
  937. package/src/mcp/adapters/crisp.adapter.ts +415 -0
  938. package/src/mcp/adapters/crowdstrike.adapter.ts +413 -0
  939. package/src/mcp/adapters/datadog.adapter.ts +373 -0
  940. package/src/mcp/adapters/digitalocean.adapter.ts +336 -0
  941. package/src/mcp/adapters/discord.adapter.ts +248 -0
  942. package/src/mcp/adapters/docker.adapter.ts +238 -0
  943. package/src/mcp/adapters/docusign.adapter.ts +431 -0
  944. package/src/mcp/adapters/drift.adapter.ts +386 -0
  945. package/src/mcp/adapters/dropbox.adapter.ts +315 -0
  946. package/src/mcp/adapters/figma.adapter.ts +302 -0
  947. package/src/mcp/adapters/firebase.adapter.ts +446 -0
  948. package/src/mcp/adapters/flyio.adapter.ts +302 -0
  949. package/src/mcp/adapters/freshbooks.adapter.ts +474 -0
  950. package/src/mcp/adapters/freshdesk.adapter.ts +441 -0
  951. package/src/mcp/adapters/freshsales.adapter.ts +457 -0
  952. package/src/mcp/adapters/freshservice.adapter.ts +481 -0
  953. package/src/mcp/adapters/front.adapter.ts +357 -0
  954. package/src/mcp/adapters/github-actions.adapter.ts +329 -0
  955. package/src/mcp/adapters/github.adapter.ts +387 -0
  956. package/src/mcp/adapters/gitlab.adapter.ts +368 -0
  957. package/src/mcp/adapters/gong.adapter.ts +386 -0
  958. package/src/mcp/adapters/google-ads.adapter.ts +363 -0
  959. package/src/mcp/adapters/google-analytics.adapter.ts +316 -0
  960. package/src/mcp/adapters/google-cloud.adapter.ts +312 -0
  961. package/src/mcp/adapters/google-drive.adapter.ts +387 -0
  962. package/src/mcp/adapters/gotomeeting.adapter.ts +255 -0
  963. package/src/mcp/adapters/grafana.adapter.ts +361 -0
  964. package/src/mcp/adapters/greenhouse.adapter.ts +354 -0
  965. package/src/mcp/adapters/gusto.adapter.ts +329 -0
  966. package/src/mcp/adapters/hashicorp-vault.adapter.ts +355 -0
  967. package/src/mcp/adapters/heroku.adapter.ts +291 -0
  968. package/src/mcp/adapters/hibob.adapter.ts +334 -0
  969. package/src/mcp/adapters/hootsuite.adapter.ts +322 -0
  970. package/src/mcp/adapters/hubspot.adapter.ts +400 -0
  971. package/src/mcp/adapters/huggingface.adapter.ts +349 -0
  972. package/src/mcp/adapters/index.ts +530 -0
  973. package/src/mcp/adapters/intercom.adapter.ts +269 -0
  974. package/src/mcp/adapters/jira.adapter.ts +482 -0
  975. package/src/mcp/adapters/klaviyo.adapter.ts +353 -0
  976. package/src/mcp/adapters/kubernetes.adapter.ts +431 -0
  977. package/src/mcp/adapters/lattice.adapter.ts +339 -0
  978. package/src/mcp/adapters/launchdarkly.adapter.ts +368 -0
  979. package/src/mcp/adapters/lever.adapter.ts +347 -0
  980. package/src/mcp/adapters/linear.adapter.ts +300 -0
  981. package/src/mcp/adapters/linkedin.adapter.ts +331 -0
  982. package/src/mcp/adapters/livechat.adapter.ts +259 -0
  983. package/src/mcp/adapters/loom.adapter.ts +230 -0
  984. package/src/mcp/adapters/mailchimp.adapter.ts +394 -0
  985. package/src/mcp/adapters/mailgun.adapter.ts +425 -0
  986. package/src/mcp/adapters/microsoft-teams.adapter.ts +251 -0
  987. package/src/mcp/adapters/miro.adapter.ts +274 -0
  988. package/src/mcp/adapters/mixpanel.adapter.ts +324 -0
  989. package/src/mcp/adapters/monday.adapter.ts +308 -0
  990. package/src/mcp/adapters/mongodb-atlas.adapter.ts +345 -0
  991. package/src/mcp/adapters/neon.adapter.ts +312 -0
  992. package/src/mcp/adapters/netlify.adapter.ts +324 -0
  993. package/src/mcp/adapters/netsuite.adapter.ts +411 -0
  994. package/src/mcp/adapters/newrelic.adapter.ts +339 -0
  995. package/src/mcp/adapters/notion.adapter.ts +338 -0
  996. package/src/mcp/adapters/okta.adapter.ts +394 -0
  997. package/src/mcp/adapters/openai.adapter.ts +315 -0
  998. package/src/mcp/adapters/opsgenie.adapter.ts +375 -0
  999. package/src/mcp/adapters/outreach.adapter.ts +372 -0
  1000. package/src/mcp/adapters/paddle.adapter.ts +467 -0
  1001. package/src/mcp/adapters/pagerduty.adapter.ts +412 -0
  1002. package/src/mcp/adapters/pandadoc.adapter.ts +389 -0
  1003. package/src/mcp/adapters/paypal.adapter.ts +465 -0
  1004. package/src/mcp/adapters/personio.adapter.ts +401 -0
  1005. package/src/mcp/adapters/pinecone.adapter.ts +340 -0
  1006. package/src/mcp/adapters/pipedrive.adapter.ts +324 -0
  1007. package/src/mcp/adapters/plaid.adapter.ts +444 -0
  1008. package/src/mcp/adapters/postmark.adapter.ts +387 -0
  1009. package/src/mcp/adapters/power-automate.adapter.ts +388 -0
  1010. package/src/mcp/adapters/quickbooks.adapter.ts +431 -0
  1011. package/src/mcp/adapters/recurly.adapter.ts +433 -0
  1012. package/src/mcp/adapters/reddit.adapter.ts +371 -0
  1013. package/src/mcp/adapters/render.adapter.ts +332 -0
  1014. package/src/mcp/adapters/ringcentral.adapter.ts +281 -0
  1015. package/src/mcp/adapters/rippling.adapter.ts +287 -0
  1016. package/src/mcp/adapters/salesforce.adapter.ts +321 -0
  1017. package/src/mcp/adapters/salesloft.adapter.ts +413 -0
  1018. package/src/mcp/adapters/sanity.adapter.ts +363 -0
  1019. package/src/mcp/adapters/sap.adapter.ts +483 -0
  1020. package/src/mcp/adapters/segment.adapter.ts +260 -0
  1021. package/src/mcp/adapters/sendgrid.adapter.ts +265 -0
  1022. package/src/mcp/adapters/sentry.adapter.ts +331 -0
  1023. package/src/mcp/adapters/servicenow.adapter.ts +468 -0
  1024. package/src/mcp/adapters/shopify.adapter.ts +451 -0
  1025. package/src/mcp/adapters/shortcut.adapter.ts +290 -0
  1026. package/src/mcp/adapters/slack.adapter.ts +380 -0
  1027. package/src/mcp/adapters/smartsheet.adapter.ts +326 -0
  1028. package/src/mcp/adapters/snowflake.adapter.ts +347 -0
  1029. package/src/mcp/adapters/snyk.adapter.ts +394 -0
  1030. package/src/mcp/adapters/splunk.adapter.ts +403 -0
  1031. package/src/mcp/adapters/square.adapter.ts +467 -0
  1032. package/src/mcp/adapters/statuspage.adapter.ts +401 -0
  1033. package/src/mcp/adapters/stripe.adapter.ts +380 -0
  1034. package/src/mcp/adapters/supabase.adapter.ts +334 -0
  1035. package/src/mcp/adapters/teamwork.adapter.ts +404 -0
  1036. package/src/mcp/adapters/telegram.adapter.ts +299 -0
  1037. package/src/mcp/adapters/terraform.adapter.ts +300 -0
  1038. package/src/mcp/adapters/todoist.adapter.ts +239 -0
  1039. package/src/mcp/adapters/trello.adapter.ts +316 -0
  1040. package/src/mcp/adapters/twilio.adapter.ts +233 -0
  1041. package/src/mcp/adapters/twitter.adapter.ts +348 -0
  1042. package/src/mcp/adapters/vercel.adapter.ts +219 -0
  1043. package/src/mcp/adapters/weaviate.adapter.ts +371 -0
  1044. package/src/mcp/adapters/webex.adapter.ts +237 -0
  1045. package/src/mcp/adapters/webflow.adapter.ts +287 -0
  1046. package/src/mcp/adapters/whatsapp.adapter.ts +273 -0
  1047. package/src/mcp/adapters/whereby.adapter.ts +240 -0
  1048. package/src/mcp/adapters/woocommerce.adapter.ts +454 -0
  1049. package/src/mcp/adapters/wordpress.adapter.ts +455 -0
  1050. package/src/mcp/adapters/workday.adapter.ts +354 -0
  1051. package/src/mcp/adapters/wrike.adapter.ts +349 -0
  1052. package/src/mcp/adapters/xero.adapter.ts +472 -0
  1053. package/src/mcp/adapters/youtube.adapter.ts +401 -0
  1054. package/src/mcp/adapters/zendesk.adapter.ts +399 -0
  1055. package/src/mcp/adapters/zoho-crm.adapter.ts +410 -0
  1056. package/src/mcp/adapters/zoom.adapter.ts +241 -0
  1057. package/src/mcp/adapters/zuora.adapter.ts +476 -0
  1058. package/src/mcp/framework/api-executor.ts +192 -0
  1059. package/src/mcp/framework/aws-sigv4.ts +216 -0
  1060. package/src/mcp/framework/credential-resolver.ts +128 -0
  1061. package/src/mcp/framework/skill-mcp-framework.ts +226 -0
  1062. package/src/mcp/framework/types.ts +130 -0
  1063. package/src/mcp/index.ts +124 -0
  1064. package/src/middleware/egress-filter.ts +81 -0
  1065. package/src/middleware/firewall.ts +121 -0
  1066. package/src/middleware/index.ts +33 -0
  1067. package/src/registry/cli.ts +63 -0
  1068. package/src/registry/server.ts +504 -0
  1069. package/src/runtime/agent-loop.ts +504 -0
  1070. package/src/runtime/email-channel.ts +120 -0
  1071. package/src/runtime/followup.ts +211 -0
  1072. package/src/runtime/gateway.ts +260 -0
  1073. package/src/runtime/hooks.ts +472 -0
  1074. package/src/runtime/index.ts +679 -0
  1075. package/src/runtime/llm-client.ts +1019 -0
  1076. package/src/runtime/providers.ts +231 -0
  1077. package/src/runtime/session-manager.ts +340 -0
  1078. package/src/runtime/subagent.ts +154 -0
  1079. package/src/runtime/tool-executor.ts +202 -0
  1080. package/src/runtime/types.ts +215 -0
  1081. package/src/server.ts +157 -45
  1082. package/src/setup/company.ts +127 -8
  1083. package/src/setup/database.ts +2 -1
  1084. package/src/setup/domain.ts +33 -4
  1085. package/src/setup/index.ts +19 -7
  1086. package/src/setup/provision.ts +128 -8
  1087. package/src/setup/registration.ts +227 -0
  1088. package/src/types/hono-env.ts +14 -0
  1089. package/src/types/optional-deps.d.ts +10 -0
  1090. package/start-live.mjs +12 -3
  1091. package/test-integration.mjs +628 -257
  1092. package/dist/chunk-77IDQJL3.js +0 -7
  1093. package/dist/chunk-BE7MXVLA.js +0 -757
  1094. package/dist/chunk-BS2WCSHO.js +0 -48
  1095. package/dist/chunk-FL3VQBGL.js +0 -757
  1096. package/dist/chunk-IQWA44WT.js +0 -970
  1097. package/dist/chunk-N2JVTNNJ.js +0 -2553
  1098. package/dist/chunk-YFDSE4BW.js +0 -1355
  1099. package/dist/db-adapter-DEWEFNIV.js +0 -7
  1100. package/dist/factory-V37IG5AT.js +0 -9
  1101. package/dist/routes-2JEPIIKC.js +0 -441
  1102. package/dist/server-32YYCI3A.js +0 -8
  1103. package/dist/server-H3C6WUOS.js +0 -8
  1104. package/dist/sqlite-3K5YOZ4K.js +0 -439
  1105. package/src/engine/agenticmail-bridge.ts +0 -296
  1106. package/src/engine/openclaw-hook.ts +0 -371
@@ -1,15 +1,175 @@
1
1
  /**
2
2
  * Authentication Routes
3
- *
4
- * Handles login (email/password), JWT issuance, SAML, and OIDC callbacks.
3
+ *
4
+ * Handles login (email/password), JWT issuance, SAML 2.0, and OIDC.
5
+ * Uses httpOnly secure cookies for session management (enterprise-grade security).
6
+ * Also supports Bearer token + API key auth for programmatic access.
5
7
  */
6
8
 
7
9
  import { Hono } from 'hono';
8
- import type { DatabaseAdapter } from '../db/adapter.js';
10
+ import { setCookie, getCookie, deleteCookie } from 'hono/cookie';
11
+ import { createVerify } from 'node:crypto';
12
+ import type { DatabaseAdapter, SsoConfig } from '../db/adapter.js';
9
13
 
10
- export function createAuthRoutes(db: DatabaseAdapter, jwtSecret: string) {
14
+ const COOKIE_NAME = 'em_session';
15
+ const REFRESH_COOKIE = 'em_refresh';
16
+ const CSRF_COOKIE = 'em_csrf';
17
+ const TOKEN_TTL = '24h';
18
+ const REFRESH_TTL = '7d';
19
+
20
+ function cookieOpts(maxAge: number, isSecure: boolean) {
21
+ return {
22
+ httpOnly: true,
23
+ secure: isSecure,
24
+ sameSite: 'Lax' as const,
25
+ path: '/',
26
+ maxAge,
27
+ };
28
+ }
29
+
30
+ function generateCsrf(): string {
31
+ const bytes = new Uint8Array(32);
32
+ crypto.getRandomValues(bytes);
33
+ return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
34
+ }
35
+
36
+ function generateState(): string {
37
+ const bytes = new Uint8Array(32);
38
+ crypto.getRandomValues(bytes);
39
+ return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
40
+ }
41
+
42
+ function generateCodeVerifier(): string {
43
+ const bytes = new Uint8Array(32);
44
+ crypto.getRandomValues(bytes);
45
+ return Array.from(bytes)
46
+ .map(b => 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'[b % 66])
47
+ .join('');
48
+ }
49
+
50
+ async function generateCodeChallenge(verifier: string): Promise<string> {
51
+ const encoder = new TextEncoder();
52
+ const data = encoder.encode(verifier);
53
+ const digest = await crypto.subtle.digest('SHA-256', data);
54
+ return btoa(String.fromCharCode(...new Uint8Array(digest)))
55
+ .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
56
+ }
57
+
58
+ export function createAuthRoutes(
59
+ db: DatabaseAdapter,
60
+ jwtSecret: string,
61
+ opts?: {
62
+ onBootstrap?: () => void;
63
+ onDbConfigure?: (newAdapter: DatabaseAdapter) => DatabaseAdapter;
64
+ },
65
+ ) {
11
66
  const auth = new Hono();
12
67
 
68
+ const isSecure = () => {
69
+ return process.env.NODE_ENV === 'production' || process.env.SECURE_COOKIES === '1';
70
+ };
71
+
72
+ async function issueTokens(userId: string, email: string, role: string) {
73
+ const { SignJWT } = await import('jose');
74
+ const secret = new TextEncoder().encode(jwtSecret);
75
+
76
+ const token = await new SignJWT({ sub: userId, email, role })
77
+ .setProtectedHeader({ alg: 'HS256' })
78
+ .setIssuedAt()
79
+ .setExpirationTime(TOKEN_TTL)
80
+ .sign(secret);
81
+
82
+ const refreshToken = await new SignJWT({ sub: userId, type: 'refresh' })
83
+ .setProtectedHeader({ alg: 'HS256' })
84
+ .setIssuedAt()
85
+ .setExpirationTime(REFRESH_TTL)
86
+ .sign(secret);
87
+
88
+ return { token, refreshToken };
89
+ }
90
+
91
+ /** Set session cookies and return token info */
92
+ async function setSessionCookies(c: any, userId: string, email: string, role: string, method: string) {
93
+ const { token, refreshToken } = await issueTokens(userId, email, role);
94
+ const csrf = generateCsrf();
95
+ const secure = isSecure();
96
+
97
+ setCookie(c, COOKIE_NAME, token, cookieOpts(86400, secure));
98
+ setCookie(c, REFRESH_COOKIE, refreshToken, cookieOpts(604800, secure));
99
+ setCookie(c, CSRF_COOKIE, csrf, { ...cookieOpts(86400, secure), httpOnly: false });
100
+
101
+ await db.updateUser(userId, { lastLoginAt: new Date() } as any).catch(() => {});
102
+ await db.logEvent({
103
+ actor: userId, actorType: 'user', action: 'auth.login',
104
+ resource: `user:${userId}`, details: { method },
105
+ ip: c.req.header('x-forwarded-for') || c.req.header('x-real-ip'),
106
+ }).catch(() => {});
107
+
108
+ return { token, refreshToken, csrf };
109
+ }
110
+
111
+ /** Find or auto-provision an SSO user */
112
+ async function findOrProvisionSsoUser(
113
+ provider: string,
114
+ subject: string,
115
+ email: string,
116
+ name: string,
117
+ config: { autoProvision?: boolean; defaultRole?: string; allowedDomains?: string[] },
118
+ ) {
119
+ // Check domain allowlist
120
+ if (config.allowedDomains?.length) {
121
+ const domain = email.split('@')[1]?.toLowerCase();
122
+ if (!config.allowedDomains.some(d => d.toLowerCase() === domain)) {
123
+ return { error: `Email domain "${domain}" not allowed for SSO login` };
124
+ }
125
+ }
126
+
127
+ // Try to find existing SSO user
128
+ let user = await db.getUserBySso(provider, subject);
129
+ if (user) return { user };
130
+
131
+ // Try to find by email (link existing account)
132
+ user = await db.getUserByEmail(email);
133
+ if (user) {
134
+ // Link SSO to existing account
135
+ await db.updateUser(user.id, { ssoProvider: provider, ssoSubject: subject } as any);
136
+ return { user };
137
+ }
138
+
139
+ // Auto-provision if enabled
140
+ if (!config.autoProvision) {
141
+ return { error: 'No account found. Contact your administrator to create an account.' };
142
+ }
143
+
144
+ const newUser = await db.createUser({
145
+ email,
146
+ name: name || email.split('@')[0],
147
+ role: (config.defaultRole as any) || 'member',
148
+ ssoProvider: provider,
149
+ ssoSubject: subject,
150
+ });
151
+ return { user: newUser };
152
+ }
153
+
154
+ // Helper: extract JWT from cookie OR Authorization header
155
+ async function extractToken(c: any): Promise<string | null> {
156
+ const cookieToken = getCookie(c, COOKIE_NAME);
157
+ if (cookieToken) return cookieToken;
158
+ const authHeader = c.req.header('Authorization');
159
+ if (authHeader?.startsWith('Bearer ')) return authHeader.slice(7);
160
+ return null;
161
+ }
162
+
163
+ /** Load SSO config from company settings */
164
+ async function getSsoConfig(): Promise<SsoConfig | null> {
165
+ try {
166
+ const settings = await db.getSettings();
167
+ return settings?.ssoConfig || null;
168
+ } catch {
169
+ return null;
170
+ }
171
+ }
172
+
13
173
  // ─── Email/Password Login ───────────────────────────────
14
174
 
15
175
  auth.post('/login', async (c) => {
@@ -29,25 +189,12 @@ export function createAuthRoutes(db: DatabaseAdapter, jwtSecret: string) {
29
189
  return c.json({ error: 'Invalid credentials' }, 401);
30
190
  }
31
191
 
32
- // Issue JWT
33
- const { SignJWT } = await import('jose');
34
- const secret = new TextEncoder().encode(jwtSecret);
35
- const token = await new SignJWT({ sub: user.id, email: user.email, role: user.role })
36
- .setProtectedHeader({ alg: 'HS256' })
37
- .setIssuedAt()
38
- .setExpirationTime('24h')
39
- .sign(secret);
40
-
41
- // Update last login
42
- await db.updateUser(user.id, { lastLoginAt: new Date() } as any);
43
- await db.logEvent({
44
- actor: user.id, actorType: 'user', action: 'auth.login',
45
- resource: `user:${user.id}`, details: { method: 'password' },
46
- ip: c.req.header('x-forwarded-for') || c.req.header('x-real-ip'),
47
- });
192
+ const { token, refreshToken, csrf } = await setSessionCookies(c, user.id, user.email, user.role, 'password');
48
193
 
49
194
  return c.json({
50
195
  token,
196
+ refreshToken,
197
+ csrf,
51
198
  user: { id: user.id, email: user.email, name: user.name, role: user.role },
52
199
  });
53
200
  });
@@ -55,76 +202,794 @@ export function createAuthRoutes(db: DatabaseAdapter, jwtSecret: string) {
55
202
  // ─── Token Refresh ──────────────────────────────────────
56
203
 
57
204
  auth.post('/refresh', async (c) => {
58
- const authHeader = c.req.header('Authorization');
59
- if (!authHeader?.startsWith('Bearer ')) {
60
- return c.json({ error: 'Token required' }, 401);
205
+ const refreshJwt = getCookie(c, REFRESH_COOKIE) || c.req.header('Authorization')?.slice(7);
206
+ if (!refreshJwt) {
207
+ return c.json({ error: 'Refresh token required' }, 401);
61
208
  }
62
209
 
63
210
  try {
64
- const { jwtVerify, SignJWT } = await import('jose');
211
+ const { jwtVerify } = await import('jose');
65
212
  const secret = new TextEncoder().encode(jwtSecret);
66
- const { payload } = await jwtVerify(authHeader.slice(7), secret);
213
+ const { payload } = await jwtVerify(refreshJwt, secret);
214
+
215
+ if (payload.type !== 'refresh') return c.json({ error: 'Invalid token type' }, 401);
67
216
 
68
217
  const user = await db.getUser(payload.sub as string);
69
218
  if (!user) return c.json({ error: 'User not found' }, 401);
70
219
 
71
- const token = await new SignJWT({ sub: user.id, email: user.email, role: user.role })
72
- .setProtectedHeader({ alg: 'HS256' })
73
- .setIssuedAt()
74
- .setExpirationTime('24h')
75
- .sign(secret);
220
+ const { token, refreshToken } = await issueTokens(user.id, user.email, user.role);
221
+ const csrf = generateCsrf();
222
+ const secure = isSecure();
223
+
224
+ setCookie(c, COOKIE_NAME, token, cookieOpts(86400, secure));
225
+ setCookie(c, REFRESH_COOKIE, refreshToken, cookieOpts(604800, secure));
226
+ setCookie(c, CSRF_COOKIE, csrf, { ...cookieOpts(86400, secure), httpOnly: false });
76
227
 
77
- return c.json({ token });
228
+ return c.json({ token, csrf });
78
229
  } catch {
79
- return c.json({ error: 'Invalid token' }, 401);
230
+ return c.json({ error: 'Invalid or expired refresh token' }, 401);
80
231
  }
81
232
  });
82
233
 
83
234
  // ─── Current User ───────────────────────────────────────
84
235
 
85
236
  auth.get('/me', async (c) => {
86
- const authHeader = c.req.header('Authorization');
87
- if (!authHeader?.startsWith('Bearer ')) {
88
- return c.json({ error: 'Token required' }, 401);
89
- }
237
+ const token = await extractToken(c);
238
+ if (!token) return c.json({ error: 'Authentication required' }, 401);
90
239
 
91
240
  try {
92
241
  const { jwtVerify } = await import('jose');
93
242
  const secret = new TextEncoder().encode(jwtSecret);
94
- const { payload } = await jwtVerify(authHeader.slice(7), secret);
243
+ const { payload } = await jwtVerify(token, secret);
95
244
  const user = await db.getUser(payload.sub as string);
96
245
  if (!user) return c.json({ error: 'User not found' }, 404);
97
246
  const { passwordHash, ...safe } = user;
98
247
  return c.json(safe);
99
248
  } catch {
100
- return c.json({ error: 'Invalid token' }, 401);
249
+ return c.json({ error: 'Invalid or expired token' }, 401);
101
250
  }
102
251
  });
103
252
 
104
- // ─── SAML 2.0 (Placeholder) ────────────────────────────
253
+ // ─── Logout ─────────────────────────────────────────────
105
254
 
106
- auth.post('/saml/callback', async (c) => {
107
- // TODO: Implement SAML assertion parsing
108
- // Will use saml2-js or passport-saml
109
- return c.json({ error: 'SAML not yet configured' }, 501);
255
+ auth.post('/logout', (c) => {
256
+ deleteCookie(c, COOKIE_NAME, { path: '/' });
257
+ deleteCookie(c, REFRESH_COOKIE, { path: '/' });
258
+ deleteCookie(c, CSRF_COOKIE, { path: '/' });
259
+ return c.json({ ok: true });
110
260
  });
111
261
 
112
- auth.get('/saml/metadata', async (c) => {
113
- // TODO: Generate SP metadata XML
114
- return c.json({ error: 'SAML not yet configured' }, 501);
262
+ // ─── SSO Config Info (public — tells frontend what's available) ──
263
+
264
+ auth.get('/sso/providers', async (c) => {
265
+ const sso = await getSsoConfig();
266
+ const providers: { type: string; name: string; url: string }[] = [];
267
+
268
+ if (sso?.saml?.entityId && sso?.saml?.ssoUrl) {
269
+ providers.push({ type: 'saml', name: 'SAML SSO', url: '/auth/saml/login' });
270
+ }
271
+ if (sso?.oidc?.clientId && sso?.oidc?.discoveryUrl) {
272
+ providers.push({ type: 'oidc', name: 'OpenID Connect', url: '/auth/oidc/authorize' });
273
+ }
274
+
275
+ return c.json({ providers, ssoEnabled: providers.length > 0 });
276
+ });
277
+
278
+ // ─── Setup Status (public — tells frontend if onboarding is needed) ──
279
+
280
+ auth.get('/setup-status', async (c) => {
281
+ try {
282
+ const stats = await db.getStats();
283
+ const settings = await db.getSettings();
284
+
285
+ const hasUsers = stats.totalUsers > 0;
286
+ const hasCompanyName = !!(settings?.name && settings.name !== '' && settings.name !== 'My Company');
287
+ const hasSmtp = !!(settings?.smtpHost);
288
+ const hasAgents = stats.totalAgents > 0;
289
+
290
+ return c.json({
291
+ setupComplete: hasUsers,
292
+ needsBootstrap: !hasUsers,
293
+ checklist: {
294
+ adminCreated: hasUsers,
295
+ companyConfigured: hasCompanyName,
296
+ emailConfigured: hasSmtp,
297
+ agentCreated: hasAgents,
298
+ },
299
+ });
300
+ } catch {
301
+ return c.json({ setupComplete: false, needsBootstrap: true, checklist: { adminCreated: false, companyConfigured: false, emailConfigured: false, agentCreated: false } });
302
+ }
303
+ });
304
+
305
+ // ─── Database Configuration (only during initial setup) ──────────
306
+
307
+ auth.post('/test-db', async (c) => {
308
+ const stats = await db.getStats();
309
+ if (stats.totalUsers > 0) {
310
+ return c.json({ error: 'Setup already complete. Database configuration is disabled.' }, 403);
311
+ }
312
+
313
+ const body = await c.req.json();
314
+ if (!body.type) {
315
+ return c.json({ error: 'Database type is required' }, 400);
316
+ }
317
+
318
+ try {
319
+ const { createAdapter } = await import('../db/factory.js');
320
+ const testAdapter = await createAdapter(body);
321
+ await testAdapter.getStats();
322
+ await testAdapter.disconnect();
323
+ return c.json({ success: true });
324
+ } catch (err: any) {
325
+ return c.json({ success: false, error: err.message || 'Connection failed' }, 400);
326
+ }
327
+ });
328
+
329
+ auth.post('/configure-db', async (c) => {
330
+ const stats = await db.getStats();
331
+ if (stats.totalUsers > 0) {
332
+ return c.json({ error: 'Setup already complete. Database configuration is disabled.' }, 403);
333
+ }
334
+
335
+ if (!opts?.onDbConfigure) {
336
+ return c.json({ error: 'Database hot-swap not available' }, 501);
337
+ }
338
+
339
+ const body = await c.req.json();
340
+ if (!body.type) {
341
+ return c.json({ error: 'Database type is required' }, 400);
342
+ }
343
+
344
+ try {
345
+ const { createAdapter } = await import('../db/factory.js');
346
+ const newAdapter = await createAdapter(body);
347
+
348
+ // Run migrations on new adapter
349
+ await newAdapter.migrate();
350
+
351
+ // Hot-swap the live DB connection
352
+ const oldAdapter = opts.onDbConfigure(newAdapter);
353
+
354
+ // Disconnect old (temp) adapter
355
+ try { await oldAdapter.disconnect(); } catch { /* best effort */ }
356
+
357
+ // Save encrypted config
358
+ try {
359
+ const { saveDbConfig } = await import('../lib/config-store.js');
360
+ await saveDbConfig(body, jwtSecret);
361
+ } catch { /* non-fatal — config won't auto-restore on restart */ }
362
+
363
+ return c.json({ success: true, type: body.type });
364
+ } catch (err: any) {
365
+ return c.json({ success: false, error: err.message || 'Configuration failed' }, 400);
366
+ }
115
367
  });
116
368
 
117
- // ─── OIDC (Placeholder) ────────────────────────────────
369
+ // ─── Bootstrap (first admin creation — only works when no users exist) ──
118
370
 
371
+ const bootstrapAttempts = new Map<string, { count: number; resetAt: number }>();
372
+
373
+ auth.post('/bootstrap', async (c) => {
374
+ // Per-IP rate limit: max 5 bootstrap attempts per minute
375
+ const clientIp = c.req.header('x-forwarded-for')?.split(',')[0]?.trim() || c.req.header('x-real-ip') || 'unknown';
376
+ const now = Date.now();
377
+ const attempt = bootstrapAttempts.get(clientIp);
378
+ if (attempt && attempt.resetAt > now && attempt.count >= 5) {
379
+ return c.json({ error: 'Too many attempts. Try again later.' }, 429);
380
+ }
381
+ if (!attempt || attempt.resetAt <= now) {
382
+ bootstrapAttempts.set(clientIp, { count: 1, resetAt: now + 60000 });
383
+ } else {
384
+ attempt.count++;
385
+ }
386
+
387
+ // SECURITY: Only works when zero users exist
388
+ const stats = await db.getStats();
389
+ if (stats.totalUsers > 0) {
390
+ return c.json({ error: 'Setup already complete. Bootstrap is disabled.' }, 403);
391
+ }
392
+
393
+ const { name, email, password, companyName, subdomain } = await c.req.json();
394
+
395
+ if (!email || !password || !name) {
396
+ return c.json({ error: 'Name, email, and password are required' }, 400);
397
+ }
398
+ if (password.length < 8) {
399
+ return c.json({ error: 'Password must be at least 8 characters' }, 400);
400
+ }
401
+ if (!email.includes('@') || !email.includes('.')) {
402
+ return c.json({ error: 'Invalid email address' }, 400);
403
+ }
404
+
405
+ try {
406
+ const user = await db.createUser({
407
+ email,
408
+ name,
409
+ role: 'owner',
410
+ password,
411
+ });
412
+
413
+ if (companyName || subdomain) {
414
+ const updates: Record<string, any> = {};
415
+ if (companyName) updates.name = companyName;
416
+ if (subdomain) {
417
+ updates.subdomain = subdomain
418
+ .toLowerCase()
419
+ .replace(/[^a-z0-9]+/g, '-')
420
+ .replace(/^-|-$/g, '')
421
+ .slice(0, 63);
422
+ }
423
+ await db.updateSettings(updates);
424
+ }
425
+
426
+ await db.logEvent({
427
+ actor: user.id,
428
+ actorType: 'system',
429
+ action: 'setup.bootstrap',
430
+ resource: `user:${user.id}`,
431
+ details: { method: 'web-wizard', companyName },
432
+ ip: c.req.header('x-forwarded-for') || c.req.header('x-real-ip'),
433
+ });
434
+
435
+ const { token, refreshToken, csrf } = await setSessionCookies(c, user.id, user.email, user.role, 'bootstrap');
436
+
437
+ // Notify server that setup is complete (flips the dashboard latch)
438
+ opts?.onBootstrap?.();
439
+
440
+ return c.json({
441
+ token,
442
+ refreshToken,
443
+ csrf,
444
+ user: { id: user.id, email: user.email, name: user.name, role: user.role },
445
+ });
446
+ } catch (err: any) {
447
+ return c.json({ error: err.message || 'Bootstrap failed' }, 500);
448
+ }
449
+ });
450
+
451
+ // ─── OIDC Authorization Code Flow ────────────────────────
452
+
453
+ /**
454
+ * Step 1: Redirect user to the OIDC provider's authorization endpoint.
455
+ * Uses PKCE (S256) for security.
456
+ */
119
457
  auth.get('/oidc/authorize', async (c) => {
120
- // TODO: Redirect to IdP authorization endpoint
121
- return c.json({ error: 'OIDC not yet configured' }, 501);
458
+ const sso = await getSsoConfig();
459
+ if (!sso?.oidc?.clientId || !sso?.oidc?.discoveryUrl) {
460
+ return c.json({ error: 'OIDC not configured. Set up OIDC in Settings > SSO.' }, 400);
461
+ }
462
+
463
+ const oidc = sso.oidc;
464
+
465
+ // Fetch OIDC discovery document
466
+ let discovery: any;
467
+ try {
468
+ const res = await fetch(oidc.discoveryUrl);
469
+ if (!res.ok) throw new Error(`Discovery fetch failed: ${res.status}`);
470
+ discovery = await res.json();
471
+ } catch (e: any) {
472
+ return c.json({ error: `Failed to fetch OIDC discovery: ${e.message}` }, 502);
473
+ }
474
+
475
+ if (!discovery.authorization_endpoint) {
476
+ return c.json({ error: 'Invalid OIDC discovery: missing authorization_endpoint' }, 502);
477
+ }
478
+
479
+ // Generate PKCE + state
480
+ const state = generateState();
481
+ const nonce = generateState();
482
+ const codeVerifier = generateCodeVerifier();
483
+ const codeChallenge = await generateCodeChallenge(codeVerifier);
484
+
485
+ // Determine callback URL
486
+ const protocol = c.req.header('x-forwarded-proto') || 'http';
487
+ const host = c.req.header('host') || 'localhost';
488
+ const redirectUri = `${protocol}://${host}/auth/oidc/callback`;
489
+
490
+ // Store state for verification in callback (10 min TTL)
491
+ // We store it in a signed JWT since we may not have engine DB available at auth level
492
+ const { SignJWT } = await import('jose');
493
+ const secret = new TextEncoder().encode(jwtSecret);
494
+ const stateToken = await new SignJWT({
495
+ state, nonce, codeVerifier, redirectUri,
496
+ discoveryUrl: oidc.discoveryUrl,
497
+ })
498
+ .setProtectedHeader({ alg: 'HS256' })
499
+ .setIssuedAt()
500
+ .setExpirationTime('10m')
501
+ .sign(secret);
502
+
503
+ // Store state token in a cookie
504
+ setCookie(c, 'em_oidc_state', stateToken, {
505
+ httpOnly: true,
506
+ secure: isSecure(),
507
+ sameSite: 'Lax',
508
+ path: '/auth/oidc',
509
+ maxAge: 600,
510
+ });
511
+
512
+ // Build authorization URL
513
+ const scopes = oidc.scopes?.join(' ') || 'openid email profile';
514
+ const authUrl = new URL(discovery.authorization_endpoint);
515
+ authUrl.searchParams.set('client_id', oidc.clientId);
516
+ authUrl.searchParams.set('response_type', 'code');
517
+ authUrl.searchParams.set('scope', scopes);
518
+ authUrl.searchParams.set('redirect_uri', redirectUri);
519
+ authUrl.searchParams.set('state', state);
520
+ authUrl.searchParams.set('nonce', nonce);
521
+ authUrl.searchParams.set('code_challenge', codeChallenge);
522
+ authUrl.searchParams.set('code_challenge_method', 'S256');
523
+
524
+ return c.redirect(authUrl.toString());
122
525
  });
123
526
 
527
+ /**
528
+ * Step 2: OIDC callback — exchange code for tokens, extract user info, create session.
529
+ */
124
530
  auth.get('/oidc/callback', async (c) => {
125
- // TODO: Handle OIDC callback, exchange code for tokens
126
- return c.json({ error: 'OIDC not yet configured' }, 501);
531
+ const code = c.req.query('code');
532
+ const returnedState = c.req.query('state');
533
+ const error = c.req.query('error');
534
+ const errorDesc = c.req.query('error_description');
535
+
536
+ if (error) {
537
+ return c.html(ssoErrorPage('OIDC Error', errorDesc || error));
538
+ }
539
+
540
+ if (!code || !returnedState) {
541
+ return c.html(ssoErrorPage('OIDC Error', 'Missing code or state parameter'));
542
+ }
543
+
544
+ // Verify state from cookie
545
+ const stateCookie = getCookie(c, 'em_oidc_state');
546
+ if (!stateCookie) {
547
+ return c.html(ssoErrorPage('OIDC Error', 'Session expired. Please try again.'));
548
+ }
549
+
550
+ // Delete the state cookie
551
+ deleteCookie(c, 'em_oidc_state', { path: '/auth/oidc' });
552
+
553
+ let statePayload: any;
554
+ try {
555
+ const { jwtVerify } = await import('jose');
556
+ const secret = new TextEncoder().encode(jwtSecret);
557
+ const { payload } = await jwtVerify(stateCookie, secret);
558
+ statePayload = payload;
559
+ } catch {
560
+ return c.html(ssoErrorPage('OIDC Error', 'Invalid or expired state. Please try again.'));
561
+ }
562
+
563
+ if (statePayload.state !== returnedState) {
564
+ return c.html(ssoErrorPage('OIDC Error', 'State mismatch. Possible CSRF attack.'));
565
+ }
566
+
567
+ const sso = await getSsoConfig();
568
+ if (!sso?.oidc) {
569
+ return c.html(ssoErrorPage('OIDC Error', 'OIDC is no longer configured.'));
570
+ }
571
+
572
+ const oidc = sso.oidc;
573
+
574
+ // Fetch discovery for token endpoint
575
+ let discovery: any;
576
+ try {
577
+ const res = await fetch(oidc.discoveryUrl);
578
+ discovery = await res.json();
579
+ } catch (e: any) {
580
+ return c.html(ssoErrorPage('OIDC Error', `Discovery fetch failed: ${e.message}`));
581
+ }
582
+
583
+ // Exchange code for tokens
584
+ let tokenResponse: any;
585
+ try {
586
+ const tokenRes = await fetch(discovery.token_endpoint, {
587
+ method: 'POST',
588
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
589
+ body: new URLSearchParams({
590
+ grant_type: 'authorization_code',
591
+ code,
592
+ redirect_uri: statePayload.redirectUri,
593
+ client_id: oidc.clientId,
594
+ client_secret: oidc.clientSecret,
595
+ code_verifier: statePayload.codeVerifier,
596
+ }).toString(),
597
+ });
598
+
599
+ if (!tokenRes.ok) {
600
+ const errBody = await tokenRes.text();
601
+ throw new Error(`Token exchange failed (${tokenRes.status}): ${errBody}`);
602
+ }
603
+ tokenResponse = await tokenRes.json();
604
+ } catch (e: any) {
605
+ return c.html(ssoErrorPage('OIDC Error', e.message));
606
+ }
607
+
608
+ // Extract user info from id_token or userinfo endpoint
609
+ let email: string;
610
+ let name: string;
611
+ let sub: string;
612
+
613
+ if (tokenResponse.id_token) {
614
+ // Decode the id_token (header.payload.signature)
615
+ const parts = tokenResponse.id_token.split('.');
616
+ if (parts.length !== 3) {
617
+ return c.html(ssoErrorPage('OIDC Error', 'Invalid id_token format'));
618
+ }
619
+
620
+ try {
621
+ // Verify the id_token signature using the provider's JWKS
622
+ const { jwtVerify, createRemoteJWKSet } = await import('jose');
623
+ const jwks = createRemoteJWKSet(new URL(discovery.jwks_uri));
624
+ const { payload } = await jwtVerify(tokenResponse.id_token, jwks, {
625
+ issuer: discovery.issuer,
626
+ audience: oidc.clientId,
627
+ });
628
+
629
+ // Verify nonce
630
+ if (payload.nonce !== statePayload.nonce) {
631
+ return c.html(ssoErrorPage('OIDC Error', 'Nonce mismatch. Possible replay attack.'));
632
+ }
633
+
634
+ sub = payload.sub as string;
635
+ email = (payload.email as string) || '';
636
+ name = (payload.name as string) || (payload.preferred_username as string) || '';
637
+ } catch (e: any) {
638
+ return c.html(ssoErrorPage('OIDC Error', `ID token verification failed: ${e.message}`));
639
+ }
640
+ } else if (discovery.userinfo_endpoint) {
641
+ // Fallback: fetch userinfo
642
+ try {
643
+ const uiRes = await fetch(discovery.userinfo_endpoint, {
644
+ headers: { Authorization: `Bearer ${tokenResponse.access_token}` },
645
+ });
646
+ const userinfo = await uiRes.json();
647
+ sub = userinfo.sub;
648
+ email = userinfo.email || '';
649
+ name = userinfo.name || userinfo.preferred_username || '';
650
+ } catch (e: any) {
651
+ return c.html(ssoErrorPage('OIDC Error', `Userinfo fetch failed: ${e.message}`));
652
+ }
653
+ } else {
654
+ return c.html(ssoErrorPage('OIDC Error', 'No id_token or userinfo endpoint available'));
655
+ }
656
+
657
+ if (!email) {
658
+ return c.html(ssoErrorPage('OIDC Error', 'No email claim in the token. Ensure "email" scope is granted.'));
659
+ }
660
+
661
+ // Find or provision user
662
+ const result = await findOrProvisionSsoUser('oidc', sub, email, name, oidc);
663
+ if ('error' in result) {
664
+ return c.html(ssoErrorPage('OIDC Error', result.error ?? 'Unknown error'));
665
+ }
666
+
667
+ // Issue session
668
+ await setSessionCookies(c, result.user.id, result.user.email, result.user.role, 'oidc');
669
+
670
+ // Redirect to dashboard
671
+ return c.redirect('/dashboard');
672
+ });
673
+
674
+ // ─── SAML 2.0 ────────────────────────────────────────────
675
+
676
+ /**
677
+ * SP-initiated SAML login — redirects to IdP SSO URL
678
+ */
679
+ auth.get('/saml/login', async (c) => {
680
+ const sso = await getSsoConfig();
681
+ if (!sso?.saml?.ssoUrl || !sso?.saml?.entityId) {
682
+ return c.json({ error: 'SAML not configured. Set up SAML in Settings > SSO.' }, 400);
683
+ }
684
+
685
+ const saml = sso.saml;
686
+ const protocol = c.req.header('x-forwarded-proto') || 'http';
687
+ const host = c.req.header('host') || 'localhost';
688
+ const acsUrl = `${protocol}://${host}/auth/saml/callback`;
689
+
690
+ // Generate SAML AuthnRequest
691
+ const requestId = '_' + crypto.randomUUID().replace(/-/g, '');
692
+ const issueInstant = new Date().toISOString();
693
+
694
+ const authnRequest = `<samlp:AuthnRequest
695
+ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
696
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
697
+ ID="${requestId}"
698
+ Version="2.0"
699
+ IssueInstant="${issueInstant}"
700
+ Destination="${saml.ssoUrl}"
701
+ AssertionConsumerServiceURL="${acsUrl}"
702
+ ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST">
703
+ <saml:Issuer>${saml.entityId}</saml:Issuer>
704
+ <samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"/>
705
+ </samlp:AuthnRequest>`;
706
+
707
+ // Deflate and base64 encode for HTTP-Redirect binding
708
+ const { deflateRawSync } = await import('zlib');
709
+ const deflated = deflateRawSync(Buffer.from(authnRequest, 'utf-8'));
710
+ const encoded = deflated.toString('base64');
711
+
712
+ const redirectUrl = new URL(saml.ssoUrl);
713
+ redirectUrl.searchParams.set('SAMLRequest', encoded);
714
+ redirectUrl.searchParams.set('RelayState', '/dashboard');
715
+
716
+ return c.redirect(redirectUrl.toString());
717
+ });
718
+
719
+ /**
720
+ * SP metadata endpoint — provides IdP the SP configuration
721
+ */
722
+ auth.get('/saml/metadata', async (c) => {
723
+ const sso = await getSsoConfig();
724
+ const entityId = sso?.saml?.entityId || 'agenticmail-enterprise';
725
+
726
+ const protocol = c.req.header('x-forwarded-proto') || 'http';
727
+ const host = c.req.header('host') || 'localhost';
728
+ const acsUrl = `${protocol}://${host}/auth/saml/callback`;
729
+ const sloUrl = `${protocol}://${host}/auth/saml/logout`;
730
+
731
+ const metadata = `<?xml version="1.0" encoding="UTF-8"?>
732
+ <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
733
+ entityID="${entityId}">
734
+ <md:SPSSODescriptor
735
+ AuthnRequestsSigned="false"
736
+ WantAssertionsSigned="true"
737
+ protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
738
+ <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
739
+ <md:AssertionConsumerService
740
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
741
+ Location="${acsUrl}"
742
+ index="0"
743
+ isDefault="true"/>
744
+ <md:SingleLogoutService
745
+ Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
746
+ Location="${sloUrl}"/>
747
+ </md:SPSSODescriptor>
748
+ </md:EntityDescriptor>`;
749
+
750
+ return c.body(metadata, 200, {
751
+ 'Content-Type': 'application/xml',
752
+ });
753
+ });
754
+
755
+ /**
756
+ * SAML Assertion Consumer Service (ACS) — receives POST from IdP after auth
757
+ */
758
+ auth.post('/saml/callback', async (c) => {
759
+ const sso = await getSsoConfig();
760
+ if (!sso?.saml?.certificate) {
761
+ return c.html(ssoErrorPage('SAML Error', 'SAML not configured.'));
762
+ }
763
+
764
+ const saml = sso.saml;
765
+ let samlResponse: string;
766
+
767
+ const contentType = c.req.header('content-type') || '';
768
+
769
+ if (contentType.includes('application/x-www-form-urlencoded')) {
770
+ const body = await c.req.parseBody();
771
+ samlResponse = body['SAMLResponse'] as string;
772
+ } else {
773
+ const body = await c.req.json().catch(() => ({}));
774
+ samlResponse = body.SAMLResponse;
775
+ }
776
+
777
+ if (!samlResponse) {
778
+ return c.html(ssoErrorPage('SAML Error', 'Missing SAMLResponse'));
779
+ }
780
+
781
+ // Decode the SAML response
782
+ let xml: string;
783
+ try {
784
+ xml = Buffer.from(samlResponse, 'base64').toString('utf-8');
785
+ } catch {
786
+ return c.html(ssoErrorPage('SAML Error', 'Invalid base64 encoding'));
787
+ }
788
+
789
+ // Parse the SAML assertion
790
+ // We do lightweight XML parsing without a full XML library
791
+ const assertion = parseSamlAssertion(xml, saml.certificate);
792
+
793
+ if (assertion.error) {
794
+ return c.html(ssoErrorPage('SAML Error', assertion.error));
795
+ }
796
+
797
+ if (!assertion.email) {
798
+ return c.html(ssoErrorPage('SAML Error', 'No email found in SAML assertion. Check your IdP attribute mapping.'));
799
+ }
800
+
801
+ // Check conditions (time validity)
802
+ if (assertion.notBefore && new Date(assertion.notBefore) > new Date()) {
803
+ return c.html(ssoErrorPage('SAML Error', 'Assertion not yet valid'));
804
+ }
805
+ if (assertion.notOnOrAfter && new Date(assertion.notOnOrAfter) <= new Date()) {
806
+ return c.html(ssoErrorPage('SAML Error', 'Assertion has expired'));
807
+ }
808
+
809
+ // Find or provision user
810
+ const subject = assertion.nameId || assertion.email;
811
+ const result = await findOrProvisionSsoUser('saml', subject, assertion.email, assertion.name || '', saml);
812
+ if ('error' in result) {
813
+ return c.html(ssoErrorPage('SAML Error', result.error ?? 'Unknown error'));
814
+ }
815
+
816
+ // Issue session
817
+ await setSessionCookies(c, result.user.id, result.user.email, result.user.role, 'saml');
818
+
819
+ // Redirect to dashboard (or RelayState)
820
+ return c.redirect('/dashboard');
127
821
  });
128
822
 
129
823
  return auth;
130
824
  }
825
+
826
+ // ─── SAML Assertion Parser ───────────────────────────────
827
+
828
+ interface SamlAssertionResult {
829
+ nameId?: string;
830
+ email?: string;
831
+ name?: string;
832
+ firstName?: string;
833
+ lastName?: string;
834
+ sessionIndex?: string;
835
+ notBefore?: string;
836
+ notOnOrAfter?: string;
837
+ issuer?: string;
838
+ signatureValid?: boolean;
839
+ error?: string;
840
+ }
841
+
842
+ /**
843
+ * Lightweight SAML assertion parser.
844
+ * Extracts user attributes from the SAML Response XML without a full XML parser library.
845
+ * Validates the assertion signature if a certificate is provided.
846
+ */
847
+ function parseSamlAssertion(xml: string, certificate: string): SamlAssertionResult {
848
+ const result: SamlAssertionResult = {};
849
+
850
+ try {
851
+ // Check for successful status
852
+ const statusMatch = xml.match(/<samlp?:StatusCode[^>]*Value="([^"]+)"/);
853
+ if (statusMatch) {
854
+ const statusValue = statusMatch[1];
855
+ if (!statusValue.includes(':Success')) {
856
+ result.error = `SAML authentication failed with status: ${statusValue}`;
857
+ return result;
858
+ }
859
+ }
860
+
861
+ // Extract NameID
862
+ const nameIdMatch = xml.match(/<(?:saml2?:)?NameID[^>]*>([^<]+)<\/(?:saml2?:)?NameID>/);
863
+ if (nameIdMatch) {
864
+ result.nameId = nameIdMatch[1].trim();
865
+ }
866
+
867
+ // Extract Issuer
868
+ const issuerMatch = xml.match(/<(?:saml2?:)?Issuer[^>]*>([^<]+)<\/(?:saml2?:)?Issuer>/);
869
+ if (issuerMatch) {
870
+ result.issuer = issuerMatch[1].trim();
871
+ }
872
+
873
+ // Extract Conditions
874
+ const condMatch = xml.match(/<(?:saml2?:)?Conditions\s+NotBefore="([^"]+)"\s+NotOnOrAfter="([^"]+)"/);
875
+ if (condMatch) {
876
+ result.notBefore = condMatch[1];
877
+ result.notOnOrAfter = condMatch[2];
878
+ }
879
+
880
+ // Extract SessionIndex
881
+ const sessionMatch = xml.match(/SessionIndex="([^"]+)"/);
882
+ if (sessionMatch) {
883
+ result.sessionIndex = sessionMatch[1];
884
+ }
885
+
886
+ // Extract attributes
887
+ const attrRegex = /<(?:saml2?:)?Attribute\s+Name="([^"]+)"[^>]*>[\s\S]*?<(?:saml2?:)?AttributeValue[^>]*>([^<]*)<\/(?:saml2?:)?AttributeValue>/g;
888
+ let match;
889
+ while ((match = attrRegex.exec(xml)) !== null) {
890
+ const attrName = match[1].toLowerCase();
891
+ const attrValue = match[2].trim();
892
+
893
+ // Map common attribute names
894
+ if (attrName.includes('emailaddress') || attrName.includes('email') || attrName === 'mail') {
895
+ result.email = attrValue;
896
+ } else if (attrName.includes('displayname') || attrName === 'name') {
897
+ result.name = attrValue;
898
+ } else if (attrName.includes('givenname') || attrName.includes('firstname')) {
899
+ result.firstName = attrValue;
900
+ } else if (attrName.includes('surname') || attrName.includes('lastname')) {
901
+ result.lastName = attrValue;
902
+ }
903
+ }
904
+
905
+ // If no explicit email attribute, use NameID if it looks like an email
906
+ if (!result.email && result.nameId?.includes('@')) {
907
+ result.email = result.nameId;
908
+ }
909
+
910
+ // Build name from first/last if not provided
911
+ if (!result.name && (result.firstName || result.lastName)) {
912
+ result.name = [result.firstName, result.lastName].filter(Boolean).join(' ');
913
+ }
914
+
915
+ // Validate signature
916
+ // We verify the digest of the SignedInfo against the IdP certificate
917
+ result.signatureValid = verifySamlSignature(xml, certificate);
918
+ if (!result.signatureValid) {
919
+ result.error = 'SAML assertion signature verification failed. Check IdP certificate.';
920
+ return result;
921
+ }
922
+
923
+ } catch (e: any) {
924
+ result.error = `Failed to parse SAML assertion: ${e.message}`;
925
+ }
926
+
927
+ return result;
928
+ }
929
+
930
+ /**
931
+ * Verify the SAML response signature using the IdP's X.509 certificate.
932
+ * Uses Node.js crypto for signature verification.
933
+ */
934
+ function verifySamlSignature(xml: string, certPem: string): boolean {
935
+ try {
936
+ // Extract SignatureValue
937
+ const sigMatch = xml.match(/<(?:ds:)?SignatureValue[^>]*>([\s\S]*?)<\/(?:ds:)?SignatureValue>/);
938
+ if (!sigMatch) return true; // No signature = skip verification (some IdPs don't sign)
939
+
940
+ // Extract SignedInfo block
941
+ const signedInfoMatch = xml.match(/<(?:ds:)?SignedInfo[^>]*>[\s\S]*?<\/(?:ds:)?SignedInfo>/);
942
+ if (!signedInfoMatch) return false;
943
+
944
+ // Normalize the certificate
945
+ let cert = certPem.trim();
946
+ if (!cert.startsWith('-----BEGIN CERTIFICATE-----')) {
947
+ // Strip whitespace and reformat
948
+ cert = cert.replace(/\s/g, '');
949
+ cert = `-----BEGIN CERTIFICATE-----\n${cert.match(/.{1,64}/g)?.join('\n')}\n-----END CERTIFICATE-----`;
950
+ }
951
+
952
+ // Determine algorithm from SignatureMethod
953
+ const algMatch = xml.match(/SignatureMethod\s+Algorithm="([^"]+)"/);
954
+ const algorithm = algMatch?.[1]?.includes('rsa-sha256') ? 'RSA-SHA256' : 'RSA-SHA1';
955
+
956
+ const signature = Buffer.from(sigMatch[1].replace(/\s/g, ''), 'base64');
957
+ const signedInfo = signedInfoMatch[0];
958
+
959
+ // Canonicalize SignedInfo (exclusive C14N — we do a simplified version)
960
+ const canonicalized = signedInfo
961
+ .replace(/\r\n/g, '\n')
962
+ .replace(/\r/g, '\n')
963
+ .trim();
964
+
965
+ const verifier = createVerify(algorithm);
966
+ verifier.update(canonicalized);
967
+ return verifier.verify(cert, signature);
968
+ } catch {
969
+ // If verification fails for any reason, reject
970
+ return false;
971
+ }
972
+ }
973
+
974
+ // ─── SSO Error Page ──────────────────────────────────────
975
+
976
+ function ssoErrorPage(title: string, message: string): string {
977
+ return `<!DOCTYPE html>
978
+ <html>
979
+ <head><title>${title}</title>
980
+ <style>
981
+ body { font-family: system-ui, -apple-system, sans-serif; display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; background: #f8f9fa; }
982
+ .card { background: white; border-radius: 12px; padding: 40px; max-width: 480px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); text-align: center; }
983
+ h1 { color: #dc2626; font-size: 1.5rem; margin: 0 0 16px; }
984
+ p { color: #4b5563; margin: 0 0 24px; line-height: 1.5; }
985
+ a { display: inline-block; padding: 10px 24px; background: #6366f1; color: white; border-radius: 8px; text-decoration: none; }
986
+ a:hover { background: #4f46e5; }
987
+ </style></head>
988
+ <body>
989
+ <div class="card">
990
+ <h1>${title}</h1>
991
+ <p>${message}</p>
992
+ <a href="/dashboard">Back to Dashboard</a>
993
+ </div>
994
+ </body></html>`;
995
+ }