@hed-hog/core 0.0.398 → 0.0.400

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 (664) hide show
  1. package/dist/ai/ai-agent.sort.d.ts +6 -0
  2. package/dist/ai/ai-agent.sort.d.ts.map +1 -0
  3. package/dist/ai/ai-agent.sort.js +21 -0
  4. package/dist/ai/ai-agent.sort.js.map +1 -0
  5. package/dist/ai/ai.controller.d.ts +4 -4
  6. package/dist/ai/ai.service.d.ts +35 -4
  7. package/dist/ai/ai.service.d.ts.map +1 -1
  8. package/dist/ai/ai.service.js +51 -137
  9. package/dist/ai/ai.service.js.map +1 -1
  10. package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
  11. package/dist/ai-instruction/ai-instruction.service.js +26 -23
  12. package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
  13. package/dist/ai-instruction/ai-instruction.sort.d.ts +16 -0
  14. package/dist/ai-instruction/ai-instruction.sort.d.ts.map +1 -0
  15. package/dist/ai-instruction/ai-instruction.sort.js +32 -0
  16. package/dist/ai-instruction/ai-instruction.sort.js.map +1 -0
  17. package/dist/auth/auth.controller.d.ts +24 -8
  18. package/dist/auth/auth.controller.d.ts.map +1 -1
  19. package/dist/auth/auth.module.d.ts.map +1 -1
  20. package/dist/auth/auth.module.js +8 -1
  21. package/dist/auth/auth.module.js.map +1 -1
  22. package/dist/auth/auth.service.d.ts +72 -25
  23. package/dist/auth/auth.service.d.ts.map +1 -1
  24. package/dist/auth/auth.service.js +41 -4
  25. package/dist/auth/auth.service.js.map +1 -1
  26. package/dist/auth/guards/auth.guard.d.ts +3 -1
  27. package/dist/auth/guards/auth.guard.d.ts.map +1 -1
  28. package/dist/auth/guards/auth.guard.js +12 -3
  29. package/dist/auth/guards/auth.guard.js.map +1 -1
  30. package/dist/authorize/authorize.controller.d.ts +30 -6
  31. package/dist/authorize/authorize.controller.d.ts.map +1 -1
  32. package/dist/authorize/authorize.controller.js +120 -13
  33. package/dist/authorize/authorize.controller.js.map +1 -1
  34. package/dist/authorize/authorize.errors.d.ts +34 -0
  35. package/dist/authorize/authorize.errors.d.ts.map +1 -0
  36. package/dist/authorize/authorize.errors.js +37 -0
  37. package/dist/authorize/authorize.errors.js.map +1 -0
  38. package/dist/authorize/authorize.module.d.ts.map +1 -1
  39. package/dist/authorize/authorize.module.js +6 -1
  40. package/dist/authorize/authorize.module.js.map +1 -1
  41. package/dist/authorize/authorize.service.d.ts +78 -4
  42. package/dist/authorize/authorize.service.d.ts.map +1 -1
  43. package/dist/authorize/authorize.service.js +212 -21
  44. package/dist/authorize/authorize.service.js.map +1 -1
  45. package/dist/authorize/dto/authorize-info.dto.d.ts +10 -1
  46. package/dist/authorize/dto/authorize-info.dto.d.ts.map +1 -1
  47. package/dist/authorize/dto/authorize-info.dto.js +16 -1
  48. package/dist/authorize/dto/authorize-info.dto.js.map +1 -1
  49. package/dist/authorize/dto/consent.dto.d.ts +10 -1
  50. package/dist/authorize/dto/consent.dto.d.ts.map +1 -1
  51. package/dist/authorize/dto/consent.dto.js +16 -1
  52. package/dist/authorize/dto/consent.dto.js.map +1 -1
  53. package/dist/authorize/dto/token.dto.d.ts +12 -0
  54. package/dist/authorize/dto/token.dto.d.ts.map +1 -1
  55. package/dist/authorize/dto/token.dto.js +21 -1
  56. package/dist/authorize/dto/token.dto.js.map +1 -1
  57. package/dist/authorize/oauth-exception.filter.d.ts +17 -0
  58. package/dist/authorize/oauth-exception.filter.d.ts.map +1 -0
  59. package/dist/authorize/oauth-exception.filter.js +54 -0
  60. package/dist/authorize/oauth-exception.filter.js.map +1 -0
  61. package/dist/authorize/oauth-metadata.service.d.ts +39 -0
  62. package/dist/authorize/oauth-metadata.service.d.ts.map +1 -0
  63. package/dist/authorize/oauth-metadata.service.js +81 -0
  64. package/dist/authorize/oauth-metadata.service.js.map +1 -0
  65. package/dist/authorize/well-known.controller.d.ts +67 -0
  66. package/dist/authorize/well-known.controller.d.ts.map +1 -0
  67. package/dist/authorize/well-known.controller.js +126 -0
  68. package/dist/authorize/well-known.controller.js.map +1 -0
  69. package/dist/captcha/captcha.service.d.ts +32 -2
  70. package/dist/captcha/captcha.service.d.ts.map +1 -1
  71. package/dist/captcha/captcha.service.js +85 -12
  72. package/dist/captcha/captcha.service.js.map +1 -1
  73. package/dist/challenge/challenge.service.d.ts +2 -2
  74. package/dist/core.module.d.ts.map +1 -1
  75. package/dist/core.module.js +6 -0
  76. package/dist/core.module.js.map +1 -1
  77. package/dist/dashboard/dashboard/dashboard.controller.d.ts +9 -9
  78. package/dist/dashboard/dashboard/dashboard.service.d.ts +9 -9
  79. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +3 -3
  80. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +3 -3
  81. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +3 -3
  82. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +3 -3
  83. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts.map +1 -1
  84. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js +2 -4
  85. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js.map +1 -1
  86. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts +8 -0
  87. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts.map +1 -0
  88. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js +18 -0
  89. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js.map +1 -0
  90. package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts.map +1 -1
  91. package/dist/dashboard/dashboard-item/dashboard-item.service.js +2 -4
  92. package/dist/dashboard/dashboard-item/dashboard-item.service.js.map +1 -1
  93. package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts +9 -0
  94. package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts.map +1 -0
  95. package/dist/dashboard/dashboard-item/dashboard-item.sort.js +19 -0
  96. package/dist/dashboard/dashboard-item/dashboard-item.sort.js.map +1 -0
  97. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +3 -3
  98. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +3 -3
  99. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts.map +1 -1
  100. package/dist/dashboard/dashboard-role/dashboard-role.service.js +2 -4
  101. package/dist/dashboard/dashboard-role/dashboard-role.service.js.map +1 -1
  102. package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts +8 -0
  103. package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts.map +1 -0
  104. package/dist/dashboard/dashboard-role/dashboard-role.sort.js +16 -0
  105. package/dist/dashboard/dashboard-role/dashboard-role.sort.js.map +1 -0
  106. package/dist/file/file-upload-ticket.service.d.ts +160 -0
  107. package/dist/file/file-upload-ticket.service.d.ts.map +1 -0
  108. package/dist/file/file-upload-ticket.service.js +382 -0
  109. package/dist/file/file-upload-ticket.service.js.map +1 -0
  110. package/dist/file/file.controller.d.ts +24 -1
  111. package/dist/file/file.controller.d.ts.map +1 -1
  112. package/dist/file/file.controller.js +63 -2
  113. package/dist/file/file.controller.js.map +1 -1
  114. package/dist/file/file.module.d.ts.map +1 -1
  115. package/dist/file/file.module.js +14 -2
  116. package/dist/file/file.module.js.map +1 -1
  117. package/dist/file/file.service.d.ts +182 -6
  118. package/dist/file/file.service.d.ts.map +1 -1
  119. package/dist/file/file.service.js +385 -36
  120. package/dist/file/file.service.js.map +1 -1
  121. package/dist/file/filename-encoding.util.d.ts +24 -0
  122. package/dist/file/filename-encoding.util.d.ts.map +1 -0
  123. package/dist/file/filename-encoding.util.js +63 -0
  124. package/dist/file/filename-encoding.util.js.map +1 -0
  125. package/dist/file/image-optimization.service.d.ts +27 -0
  126. package/dist/file/image-optimization.service.d.ts.map +1 -1
  127. package/dist/file/image-optimization.service.js +63 -14
  128. package/dist/file/image-optimization.service.js.map +1 -1
  129. package/dist/file/mcp-file-source.schema.d.ts +33 -0
  130. package/dist/file/mcp-file-source.schema.d.ts.map +1 -0
  131. package/dist/file/mcp-file-source.schema.js +75 -0
  132. package/dist/file/mcp-file-source.schema.js.map +1 -0
  133. package/dist/file/mcp-file-source.service.d.ts +124 -0
  134. package/dist/file/mcp-file-source.service.d.ts.map +1 -0
  135. package/dist/file/mcp-file-source.service.js +262 -0
  136. package/dist/file/mcp-file-source.service.js.map +1 -0
  137. package/dist/file/mimetype-sniff.util.d.ts +62 -0
  138. package/dist/file/mimetype-sniff.util.d.ts.map +1 -0
  139. package/dist/file/mimetype-sniff.util.js +226 -0
  140. package/dist/file/mimetype-sniff.util.js.map +1 -0
  141. package/dist/file/remote-fetch.util.d.ts +35 -0
  142. package/dist/file/remote-fetch.util.d.ts.map +1 -0
  143. package/dist/file/remote-fetch.util.js +236 -0
  144. package/dist/file/remote-fetch.util.js.map +1 -0
  145. package/dist/impersonation/dto/start-impersonation.dto.d.ts +4 -1
  146. package/dist/impersonation/dto/start-impersonation.dto.d.ts.map +1 -1
  147. package/dist/impersonation/dto/start-impersonation.dto.js +1 -1
  148. package/dist/impersonation/dto/start-impersonation.dto.js.map +1 -1
  149. package/dist/impersonation/impersonation.service.d.ts +8 -3
  150. package/dist/impersonation/impersonation.service.d.ts.map +1 -1
  151. package/dist/impersonation/impersonation.service.js +14 -4
  152. package/dist/impersonation/impersonation.service.js.map +1 -1
  153. package/dist/incident/incident.controller.d.ts +2 -1
  154. package/dist/incident/incident.controller.d.ts.map +1 -1
  155. package/dist/incident/incident.controller.js +10 -6
  156. package/dist/incident/incident.controller.js.map +1 -1
  157. package/dist/incident/incident.service.d.ts +2 -0
  158. package/dist/incident/incident.service.d.ts.map +1 -1
  159. package/dist/incident/incident.service.js +4 -0
  160. package/dist/incident/incident.service.js.map +1 -1
  161. package/dist/index.d.ts +17 -0
  162. package/dist/index.d.ts.map +1 -1
  163. package/dist/index.js +17 -0
  164. package/dist/index.js.map +1 -1
  165. package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
  166. package/dist/integration-profile/integration-profile.secrets.js +7 -0
  167. package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
  168. package/dist/integration-profile/integration-profile.service.d.ts +0 -13
  169. package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
  170. package/dist/integration-profile/integration-profile.service.js +5 -40
  171. package/dist/integration-profile/integration-profile.service.js.map +1 -1
  172. package/dist/integration-profile/integration-profile.utils.js +5 -5
  173. package/dist/integration-profile/integration-profile.utils.js.map +1 -1
  174. package/dist/integration-profile/testers/index.d.ts.map +1 -1
  175. package/dist/integration-profile/testers/index.js +2 -0
  176. package/dist/integration-profile/testers/index.js.map +1 -1
  177. package/dist/integration-profile/testers/shipping.testers.d.ts +3 -0
  178. package/dist/integration-profile/testers/shipping.testers.d.ts.map +1 -0
  179. package/dist/integration-profile/testers/shipping.testers.js +71 -0
  180. package/dist/integration-profile/testers/shipping.testers.js.map +1 -0
  181. package/dist/locale/locale.controller.d.ts +1 -1
  182. package/dist/locale/locale.service.d.ts +1 -1
  183. package/dist/mail/dto/send.dto.d.ts +6 -1
  184. package/dist/mail/dto/send.dto.d.ts.map +1 -1
  185. package/dist/mail/dto/send.dto.js.map +1 -1
  186. package/dist/mail/mail.service.d.ts +9 -0
  187. package/dist/mail/mail.service.d.ts.map +1 -1
  188. package/dist/mail/mail.service.js +34 -14
  189. package/dist/mail/mail.service.js.map +1 -1
  190. package/dist/mail-sent/mail-sent.controller.d.ts +1 -1
  191. package/dist/mail-sent/mail-sent.service.d.ts +1 -1
  192. package/dist/mail-sent/mail-sent.service.d.ts.map +1 -1
  193. package/dist/mail-sent/mail-sent.service.js +2 -1
  194. package/dist/mail-sent/mail-sent.service.js.map +1 -1
  195. package/dist/mail-sent/mail-sent.sort.d.ts +9 -0
  196. package/dist/mail-sent/mail-sent.sort.d.ts.map +1 -0
  197. package/dist/mail-sent/mail-sent.sort.js +19 -0
  198. package/dist/mail-sent/mail-sent.sort.js.map +1 -0
  199. package/dist/mcp/filters/mcp-challenge.filter.d.ts +20 -0
  200. package/dist/mcp/filters/mcp-challenge.filter.d.ts.map +1 -0
  201. package/dist/mcp/filters/mcp-challenge.filter.js +69 -0
  202. package/dist/mcp/filters/mcp-challenge.filter.js.map +1 -0
  203. package/dist/mcp/guards/mcp-auth.guard.d.ts +4 -1
  204. package/dist/mcp/guards/mcp-auth.guard.d.ts.map +1 -1
  205. package/dist/mcp/guards/mcp-auth.guard.js +19 -5
  206. package/dist/mcp/guards/mcp-auth.guard.js.map +1 -1
  207. package/dist/mcp/guards/mcp-permission.guard.d.ts +25 -3
  208. package/dist/mcp/guards/mcp-permission.guard.d.ts.map +1 -1
  209. package/dist/mcp/guards/mcp-permission.guard.js +46 -26
  210. package/dist/mcp/guards/mcp-permission.guard.js.map +1 -1
  211. package/dist/mcp/mcp-audit.service.d.ts +17 -0
  212. package/dist/mcp/mcp-audit.service.d.ts.map +1 -1
  213. package/dist/mcp/mcp-audit.service.js +32 -3
  214. package/dist/mcp/mcp-audit.service.js.map +1 -1
  215. package/dist/mcp/mcp-permission.service.d.ts +64 -0
  216. package/dist/mcp/mcp-permission.service.d.ts.map +1 -0
  217. package/dist/mcp/mcp-permission.service.js +178 -0
  218. package/dist/mcp/mcp-permission.service.js.map +1 -0
  219. package/dist/mcp/mcp-server.service.d.ts +3 -1
  220. package/dist/mcp/mcp-server.service.d.ts.map +1 -1
  221. package/dist/mcp/mcp-server.service.js +36 -15
  222. package/dist/mcp/mcp-server.service.js.map +1 -1
  223. package/dist/mcp/mcp.controller.d.ts.map +1 -1
  224. package/dist/mcp/mcp.controller.js +10 -2
  225. package/dist/mcp/mcp.controller.js.map +1 -1
  226. package/dist/mcp/mcp.module.d.ts.map +1 -1
  227. package/dist/mcp/mcp.module.js +5 -1
  228. package/dist/mcp/mcp.module.js.map +1 -1
  229. package/dist/mcp/tools/core-ai.mcp-tools.js +2 -9
  230. package/dist/mcp/tools/core-ai.mcp-tools.js.map +1 -1
  231. package/dist/mcp/tools/core-dashboard-items.mcp-tools.js +1 -1
  232. package/dist/mcp/tools/core-dashboard-items.mcp-tools.js.map +1 -1
  233. package/dist/mcp/tools/core-dashboard.mcp-tools.js +2 -9
  234. package/dist/mcp/tools/core-dashboard.mcp-tools.js.map +1 -1
  235. package/dist/mcp/tools/core-event-webhooks.mcp-tools.d.ts.map +1 -1
  236. package/dist/mcp/tools/core-event-webhooks.mcp-tools.js +2 -10
  237. package/dist/mcp/tools/core-event-webhooks.mcp-tools.js.map +1 -1
  238. package/dist/mcp/tools/core-files.mcp-tools.d.ts +17 -5
  239. package/dist/mcp/tools/core-files.mcp-tools.d.ts.map +1 -1
  240. package/dist/mcp/tools/core-files.mcp-tools.js +186 -24
  241. package/dist/mcp/tools/core-files.mcp-tools.js.map +1 -1
  242. package/dist/mcp/tools/core-integration-events.mcp-tools.js +2 -9
  243. package/dist/mcp/tools/core-integration-events.mcp-tools.js.map +1 -1
  244. package/dist/mcp/tools/core-mail-sent.mcp-tools.js +2 -14
  245. package/dist/mcp/tools/core-mail-sent.mcp-tools.js.map +1 -1
  246. package/dist/mcp/tools/core-mail.mcp-tools.js +2 -9
  247. package/dist/mcp/tools/core-mail.mcp-tools.js.map +1 -1
  248. package/dist/mcp/tools/core-menus.mcp-tools.d.ts.map +1 -1
  249. package/dist/mcp/tools/core-menus.mcp-tools.js +2 -10
  250. package/dist/mcp/tools/core-menus.mcp-tools.js.map +1 -1
  251. package/dist/mcp/tools/core-notifications.mcp-tools.d.ts.map +1 -1
  252. package/dist/mcp/tools/core-notifications.mcp-tools.js +0 -1
  253. package/dist/mcp/tools/core-notifications.mcp-tools.js.map +1 -1
  254. package/dist/mcp/tools/core-roles.mcp-tools.d.ts.map +1 -1
  255. package/dist/mcp/tools/core-roles.mcp-tools.js +2 -13
  256. package/dist/mcp/tools/core-roles.mcp-tools.js.map +1 -1
  257. package/dist/mcp/tools/core-routes.mcp-tools.d.ts.map +1 -1
  258. package/dist/mcp/tools/core-routes.mcp-tools.js +2 -11
  259. package/dist/mcp/tools/core-routes.mcp-tools.js.map +1 -1
  260. package/dist/mcp/tools/core-screens.mcp-tools.d.ts.map +1 -1
  261. package/dist/mcp/tools/core-screens.mcp-tools.js +2 -11
  262. package/dist/mcp/tools/core-screens.mcp-tools.js.map +1 -1
  263. package/dist/mcp/tools/core-sessions.mcp-tools.d.ts.map +1 -1
  264. package/dist/mcp/tools/core-sessions.mcp-tools.js +0 -2
  265. package/dist/mcp/tools/core-sessions.mcp-tools.js.map +1 -1
  266. package/dist/mcp/tools/core-settings.mcp-tools.d.ts.map +1 -1
  267. package/dist/mcp/tools/core-settings.mcp-tools.js +2 -10
  268. package/dist/mcp/tools/core-settings.mcp-tools.js.map +1 -1
  269. package/dist/mcp/tools/core-users.mcp-tools.js +2 -9
  270. package/dist/mcp/tools/core-users.mcp-tools.js.map +1 -1
  271. package/dist/mcp/tools/core-webhooks.mcp-tools.d.ts.map +1 -1
  272. package/dist/mcp/tools/core-webhooks.mcp-tools.js +2 -10
  273. package/dist/mcp/tools/core-webhooks.mcp-tools.js.map +1 -1
  274. package/dist/mcp/types/mcp-context.type.d.ts +9 -0
  275. package/dist/mcp/types/mcp-context.type.d.ts.map +1 -1
  276. package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
  277. package/dist/mcp-chat/mcp-chat.service.js +8 -0
  278. package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
  279. package/dist/meeting/meeting-provider.registry.d.ts +115 -0
  280. package/dist/meeting/meeting-provider.registry.d.ts.map +1 -1
  281. package/dist/meeting/meeting-provider.registry.js.map +1 -1
  282. package/dist/meeting/meeting.constants.d.ts +70 -0
  283. package/dist/meeting/meeting.constants.d.ts.map +1 -1
  284. package/dist/meeting/meeting.constants.js +9 -1
  285. package/dist/meeting/meeting.constants.js.map +1 -1
  286. package/dist/menu/menu.service.d.ts.map +1 -1
  287. package/dist/menu/menu.service.js +29 -9
  288. package/dist/menu/menu.service.js.map +1 -1
  289. package/dist/message-template/dto/update-message-template.dto.d.ts +18 -0
  290. package/dist/message-template/dto/update-message-template.dto.d.ts.map +1 -0
  291. package/dist/message-template/dto/update-message-template.dto.js +38 -0
  292. package/dist/message-template/dto/update-message-template.dto.js.map +1 -0
  293. package/dist/message-template/message-template-admin.service.d.ts +70 -0
  294. package/dist/message-template/message-template-admin.service.d.ts.map +1 -0
  295. package/dist/message-template/message-template-admin.service.js +226 -0
  296. package/dist/message-template/message-template-admin.service.js.map +1 -0
  297. package/dist/message-template/message-template.controller.d.ts +29 -0
  298. package/dist/message-template/message-template.controller.d.ts.map +1 -0
  299. package/dist/message-template/message-template.controller.js +101 -0
  300. package/dist/message-template/message-template.controller.js.map +1 -0
  301. package/dist/message-template/message-template.module.d.ts +10 -0
  302. package/dist/message-template/message-template.module.d.ts.map +1 -0
  303. package/dist/message-template/message-template.module.js +33 -0
  304. package/dist/message-template/message-template.module.js.map +1 -0
  305. package/dist/message-template/message-template.registry.d.ts +55 -0
  306. package/dist/message-template/message-template.registry.d.ts.map +1 -0
  307. package/dist/message-template/message-template.registry.js +64 -0
  308. package/dist/message-template/message-template.registry.js.map +1 -0
  309. package/dist/message-template/message-template.service.d.ts +59 -0
  310. package/dist/message-template/message-template.service.d.ts.map +1 -0
  311. package/dist/message-template/message-template.service.js +166 -0
  312. package/dist/message-template/message-template.service.js.map +1 -0
  313. package/dist/notification/notification.constants.d.ts +11 -0
  314. package/dist/notification/notification.constants.d.ts.map +1 -0
  315. package/dist/notification/notification.constants.js +14 -0
  316. package/dist/notification/notification.constants.js.map +1 -0
  317. package/dist/notification/notification.controller.d.ts +20 -20
  318. package/dist/notification/notification.module.d.ts.map +1 -1
  319. package/dist/notification/notification.module.js +3 -0
  320. package/dist/notification/notification.module.js.map +1 -1
  321. package/dist/notification/notification.service.d.ts +33 -21
  322. package/dist/notification/notification.service.d.ts.map +1 -1
  323. package/dist/notification/notification.service.js +36 -2
  324. package/dist/notification/notification.service.js.map +1 -1
  325. package/dist/oauth/oauth.controller.d.ts +4 -6
  326. package/dist/oauth/oauth.controller.d.ts.map +1 -1
  327. package/dist/oauth/oauth.controller.js +0 -1
  328. package/dist/oauth/oauth.controller.js.map +1 -1
  329. package/dist/oauth/oauth.errors.d.ts +15 -1
  330. package/dist/oauth/oauth.errors.d.ts.map +1 -1
  331. package/dist/oauth/oauth.errors.js +9 -1
  332. package/dist/oauth/oauth.errors.js.map +1 -1
  333. package/dist/oauth/oauth.module.d.ts.map +1 -1
  334. package/dist/oauth/oauth.module.js +6 -1
  335. package/dist/oauth/oauth.module.js.map +1 -1
  336. package/dist/oauth/oauth.service.d.ts +25 -5
  337. package/dist/oauth/oauth.service.d.ts.map +1 -1
  338. package/dist/oauth/oauth.service.js +63 -27
  339. package/dist/oauth/oauth.service.js.map +1 -1
  340. package/dist/oauth/providers/abstract.provider.d.ts +10 -0
  341. package/dist/oauth/providers/abstract.provider.d.ts.map +1 -1
  342. package/dist/oauth/providers/abstract.provider.js +39 -12
  343. package/dist/oauth/providers/abstract.provider.js.map +1 -1
  344. package/dist/oauth/providers/github.provider.d.ts +1 -1
  345. package/dist/oauth/providers/github.provider.d.ts.map +1 -1
  346. package/dist/oauth/providers/github.provider.js +48 -22
  347. package/dist/oauth/providers/github.provider.js.map +1 -1
  348. package/dist/oauth/providers/microsoft-entra-id.provider.d.ts.map +1 -1
  349. package/dist/oauth/providers/microsoft-entra-id.provider.js +6 -0
  350. package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
  351. package/dist/observability/monitored-cron.d.ts +29 -12
  352. package/dist/observability/monitored-cron.d.ts.map +1 -1
  353. package/dist/observability/monitored-cron.js +131 -46
  354. package/dist/observability/monitored-cron.js.map +1 -1
  355. package/dist/pairing/pairing.controller.d.ts +9 -9
  356. package/dist/pairing/pairing.service.d.ts +15 -11
  357. package/dist/pairing/pairing.service.d.ts.map +1 -1
  358. package/dist/profile/dto/change-password.dto.d.ts.map +1 -1
  359. package/dist/profile/dto/change-password.dto.js +4 -6
  360. package/dist/profile/dto/change-password.dto.js.map +1 -1
  361. package/dist/profile/profile.controller.d.ts +1 -1
  362. package/dist/profile/profile.service.d.ts +1 -1
  363. package/dist/profile/profile.service.d.ts.map +1 -1
  364. package/dist/profile/profile.service.js +9 -3
  365. package/dist/profile/profile.service.js.map +1 -1
  366. package/dist/realtime/realtime-tick.coalescer.d.ts +34 -0
  367. package/dist/realtime/realtime-tick.coalescer.d.ts.map +1 -0
  368. package/dist/realtime/realtime-tick.coalescer.js +60 -0
  369. package/dist/realtime/realtime-tick.coalescer.js.map +1 -0
  370. package/dist/realtime/realtime.service.d.ts +2 -0
  371. package/dist/realtime/realtime.service.d.ts.map +1 -1
  372. package/dist/realtime/realtime.service.js +22 -2
  373. package/dist/realtime/realtime.service.js.map +1 -1
  374. package/dist/redis/redis-kv.service.d.ts +90 -0
  375. package/dist/redis/redis-kv.service.d.ts.map +1 -0
  376. package/dist/redis/redis-kv.service.js +247 -0
  377. package/dist/redis/redis-kv.service.js.map +1 -0
  378. package/dist/redis/redis-master.d.ts +29 -0
  379. package/dist/redis/redis-master.d.ts.map +1 -0
  380. package/dist/redis/redis-master.js +81 -0
  381. package/dist/redis/redis-master.js.map +1 -0
  382. package/dist/redis/redis-pubsub.d.ts +12 -0
  383. package/dist/redis/redis-pubsub.d.ts.map +1 -1
  384. package/dist/redis/redis-pubsub.js +25 -2
  385. package/dist/redis/redis-pubsub.js.map +1 -1
  386. package/dist/redis/redis.module.d.ts +11 -0
  387. package/dist/redis/redis.module.d.ts.map +1 -0
  388. package/dist/redis/redis.module.js +30 -0
  389. package/dist/redis/redis.module.js.map +1 -0
  390. package/dist/session/session.controller.d.ts +6 -2
  391. package/dist/session/session.controller.d.ts.map +1 -1
  392. package/dist/session/session.service.d.ts +118 -15
  393. package/dist/session/session.service.d.ts.map +1 -1
  394. package/dist/session/session.service.js +251 -77
  395. package/dist/session/session.service.js.map +1 -1
  396. package/dist/setting/setting.controller.d.ts +5 -0
  397. package/dist/setting/setting.controller.d.ts.map +1 -1
  398. package/dist/setting/setting.service.d.ts +7 -0
  399. package/dist/setting/setting.service.d.ts.map +1 -1
  400. package/dist/setting/setting.service.js +38 -3
  401. package/dist/setting/setting.service.js.map +1 -1
  402. package/dist/task/task.service.d.ts +17 -0
  403. package/dist/task/task.service.d.ts.map +1 -1
  404. package/dist/task/task.service.js +48 -13
  405. package/dist/task/task.service.js.map +1 -1
  406. package/dist/token/token.service.d.ts +19 -1
  407. package/dist/token/token.service.d.ts.map +1 -1
  408. package/dist/token/token.service.js +39 -2
  409. package/dist/token/token.service.js.map +1 -1
  410. package/dist/user/user-credential.util.d.ts +10 -0
  411. package/dist/user/user-credential.util.d.ts.map +1 -1
  412. package/dist/user/user-credential.util.js +14 -1
  413. package/dist/user/user-credential.util.js.map +1 -1
  414. package/dist/user/user.service.d.ts +12 -4
  415. package/dist/user/user.service.d.ts.map +1 -1
  416. package/dist/user/user.service.js +2 -11
  417. package/dist/user/user.service.js.map +1 -1
  418. package/dist/user/user.sort.d.ts +16 -0
  419. package/dist/user/user.sort.d.ts.map +1 -0
  420. package/dist/user/user.sort.js +25 -0
  421. package/dist/user/user.sort.js.map +1 -0
  422. package/dist/utils/abbreviate-name.d.ts +13 -0
  423. package/dist/utils/abbreviate-name.d.ts.map +1 -0
  424. package/dist/utils/abbreviate-name.js +42 -0
  425. package/dist/utils/abbreviate-name.js.map +1 -0
  426. package/dist/utils/date-range-query.dto.d.ts +11 -0
  427. package/dist/utils/date-range-query.dto.d.ts.map +1 -0
  428. package/dist/utils/date-range-query.dto.js +63 -0
  429. package/dist/utils/date-range-query.dto.js.map +1 -0
  430. package/dist/utils/date-range.d.ts +96 -0
  431. package/dist/utils/date-range.d.ts.map +1 -0
  432. package/dist/utils/date-range.js +172 -0
  433. package/dist/utils/date-range.js.map +1 -0
  434. package/dist/webhook-integration/webhook-utils.d.ts.map +1 -1
  435. package/dist/webhook-integration/webhook-utils.js +24 -0
  436. package/dist/webhook-integration/webhook-utils.js.map +1 -1
  437. package/dist/whatsapp-sender/whatsapp-recipients.d.ts +49 -0
  438. package/dist/whatsapp-sender/whatsapp-recipients.d.ts.map +1 -0
  439. package/dist/whatsapp-sender/whatsapp-recipients.js +66 -0
  440. package/dist/whatsapp-sender/whatsapp-recipients.js.map +1 -0
  441. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +25 -0
  442. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -1
  443. package/dist/whatsapp-sender/whatsapp-sender.service.js +46 -5
  444. package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -1
  445. package/hedhog/data/integration_provider.yaml +9 -0
  446. package/hedhog/data/integration_type.yaml +6 -0
  447. package/hedhog/data/locale.yaml +0 -1
  448. package/hedhog/data/mail.yaml +2 -2
  449. package/hedhog/data/mail_layout.yaml +6 -3
  450. package/hedhog/data/menu.yaml +25 -5
  451. package/hedhog/data/route.yaml +140 -0
  452. package/hedhog/data/setting_group.yaml +137 -3
  453. package/hedhog/frontend/app/access-log/page.tsx.ejs +47 -53
  454. package/hedhog/frontend/app/account/components/active-sessions.tsx.ejs +33 -8
  455. package/hedhog/frontend/app/account/components/mcp-tokens.tsx.ejs +54 -13
  456. package/hedhog/frontend/app/account/components/mfa-method-card.tsx.ejs +7 -1
  457. package/hedhog/frontend/app/account/components/recovery-codes-dialog.tsx.ejs +1 -0
  458. package/hedhog/frontend/app/account/components/tokens.tsx.ejs +47 -17
  459. package/hedhog/frontend/app/ai_agent/page.tsx.ejs +46 -5
  460. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +101 -30
  461. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +24 -8
  462. package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +80 -15
  463. package/hedhog/frontend/app/configurations/[slug]/components/image-optimization-action.tsx.ejs +166 -0
  464. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.test.tsx.ejs +145 -45
  465. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +99 -219
  466. package/hedhog/frontend/app/configurations/[slug]/page.tsx.ejs +19 -1
  467. package/hedhog/frontend/app/configurations/layout.tsx.ejs +19 -5
  468. package/hedhog/frontend/app/dashboard/[slug]/widget-renderer.tsx.ejs +2 -8
  469. package/hedhog/frontend/app/dashboard/components/dynamic-widget.tsx.ejs +3 -0
  470. package/hedhog/frontend/app/dashboard/components/widget-wrapper.tsx.ejs +4 -0
  471. package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +43 -44
  472. package/hedhog/frontend/app/dashboard/management/tabs/component-roles-tab.tsx.ejs +41 -3
  473. package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +42 -2
  474. package/hedhog/frontend/app/dashboard/management/tabs/dashboard-roles-tab.tsx.ejs +41 -3
  475. package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +39 -4
  476. package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +42 -3
  477. package/hedhog/frontend/app/incidents/page.tsx.ejs +60 -31
  478. package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +45 -5
  479. package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +92 -15
  480. package/hedhog/frontend/app/mail/log/page.tsx.ejs +109 -61
  481. package/hedhog/frontend/app/mail/template/page.tsx.ejs +125 -23
  482. package/hedhog/frontend/app/mcp_chat/chat-components.tsx.ejs +13 -15
  483. package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +116 -110
  484. package/hedhog/frontend/app/message-templates/_components/message-template-sheet.tsx.ejs +245 -0
  485. package/hedhog/frontend/app/message-templates/_lib/types.ts.ejs +24 -0
  486. package/hedhog/frontend/app/message-templates/page.tsx.ejs +182 -0
  487. package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1 -0
  488. package/hedhog/frontend/app/pages/page.tsx.ejs +94 -9
  489. package/hedhog/frontend/app/roles/menus.tsx.ejs +4 -4
  490. package/hedhog/frontend/app/roles/routes.tsx.ejs +4 -4
  491. package/hedhog/frontend/app/roles/users.tsx.ejs +4 -4
  492. package/hedhog/frontend/app/setting-list/page.tsx.ejs +71 -9
  493. package/hedhog/frontend/app/users/page.tsx.ejs +77 -67
  494. package/hedhog/frontend/messages/en.json +183 -36
  495. package/hedhog/frontend/messages/pt.json +183 -36
  496. package/hedhog/table/cron_lock.yaml +17 -0
  497. package/hedhog/table/file.yaml +13 -1
  498. package/hedhog/table/file_upload_chunk.yaml +23 -0
  499. package/hedhog/table/file_upload_ticket.yaml +67 -0
  500. package/hedhog/table/mcp_tool_call_log.yaml +30 -22
  501. package/hedhog/table/message_template.yaml +33 -0
  502. package/hedhog/table/setting.yaml +8 -0
  503. package/hedhog/table/user_session.yaml +36 -1
  504. package/package.json +8 -6
  505. package/src/ai/ai-agent.sort.ts +21 -0
  506. package/src/ai/ai.service.spec.ts +173 -1
  507. package/src/ai/ai.service.ts +64 -193
  508. package/src/ai-instruction/ai-instruction.service.ts +32 -28
  509. package/src/ai-instruction/ai-instruction.sort.ts +32 -0
  510. package/src/auth/auth.module.ts +8 -1
  511. package/src/auth/auth.service.spec.ts +108 -1
  512. package/src/auth/auth.service.ts +59 -5
  513. package/src/auth/guards/auth.guard.ts +9 -1
  514. package/src/authorize/authorize.controller.ts +126 -11
  515. package/src/authorize/authorize.errors.ts +55 -0
  516. package/src/authorize/authorize.module.ts +6 -1
  517. package/src/authorize/authorize.service.spec.ts +379 -7
  518. package/src/authorize/authorize.service.ts +309 -23
  519. package/src/authorize/dto/authorize-info.dto.ts +21 -3
  520. package/src/authorize/dto/consent.dto.ts +21 -3
  521. package/src/authorize/dto/token.dto.ts +24 -2
  522. package/src/authorize/oauth-exception.filter.ts +58 -0
  523. package/src/authorize/oauth-metadata.service.ts +67 -0
  524. package/src/authorize/well-known.controller.spec.ts +84 -0
  525. package/src/authorize/well-known.controller.ts +96 -0
  526. package/src/captcha/captcha.service.spec.ts +211 -4
  527. package/src/captcha/captcha.service.ts +127 -10
  528. package/src/core.module.ts +6 -0
  529. package/src/dashboard/dashboard-component-role/dashboard-component-role.service.ts +2 -3
  530. package/src/dashboard/dashboard-component-role/dashboard-component-role.sort.ts +18 -0
  531. package/src/dashboard/dashboard-item/dashboard-item.service.ts +2 -3
  532. package/src/dashboard/dashboard-item/dashboard-item.sort.ts +19 -0
  533. package/src/dashboard/dashboard-role/dashboard-role.service.ts +2 -3
  534. package/src/dashboard/dashboard-role/dashboard-role.sort.ts +16 -0
  535. package/src/file/file-upload-ticket.service.spec.ts +422 -0
  536. package/src/file/file-upload-ticket.service.ts +513 -0
  537. package/src/file/file.controller.ts +65 -0
  538. package/src/file/file.module.ts +14 -2
  539. package/src/file/file.service.spec.ts +94 -0
  540. package/src/file/file.service.ts +432 -30
  541. package/src/file/filename-encoding.util.spec.ts +54 -0
  542. package/src/file/filename-encoding.util.ts +67 -0
  543. package/src/file/image-optimization.service.spec.ts +156 -19
  544. package/src/file/image-optimization.service.ts +106 -21
  545. package/src/file/mcp-file-source.schema.ts +83 -0
  546. package/src/file/mcp-file-source.service.spec.ts +473 -0
  547. package/src/file/mcp-file-source.service.ts +445 -0
  548. package/src/file/mimetype-sniff.util.spec.ts +126 -0
  549. package/src/file/mimetype-sniff.util.ts +265 -0
  550. package/src/file/remote-fetch.util.spec.ts +117 -0
  551. package/src/file/remote-fetch.util.ts +330 -0
  552. package/src/impersonation/dto/start-impersonation.dto.ts +5 -2
  553. package/src/impersonation/impersonation.service.spec.ts +24 -1
  554. package/src/impersonation/impersonation.service.ts +14 -4
  555. package/src/incident/incident.controller.ts +9 -1
  556. package/src/incident/incident.service.ts +7 -0
  557. package/src/index.ts +17 -0
  558. package/src/integration-profile/integration-profile.secrets.ts +7 -0
  559. package/src/integration-profile/integration-profile.service.ts +7 -64
  560. package/src/integration-profile/integration-profile.utils.spec.ts +9 -0
  561. package/src/integration-profile/integration-profile.utils.ts +5 -5
  562. package/src/integration-profile/testers/index.ts +2 -0
  563. package/src/integration-profile/testers/remaining.testers.spec.ts +79 -0
  564. package/src/integration-profile/testers/shipping.testers.ts +94 -0
  565. package/src/mail/dto/send.dto.ts +6 -1
  566. package/src/mail/mail-template.spec.ts +58 -1
  567. package/src/mail/mail.service.spec.ts +112 -0
  568. package/src/mail/mail.service.ts +42 -4
  569. package/src/mail-sent/mail-sent.service.ts +3 -0
  570. package/src/mail-sent/mail-sent.sort.ts +19 -0
  571. package/src/mcp/filters/mcp-challenge.filter.spec.ts +76 -0
  572. package/src/mcp/filters/mcp-challenge.filter.ts +70 -0
  573. package/src/mcp/guards/mcp-auth.guard.spec.ts +51 -2
  574. package/src/mcp/guards/mcp-auth.guard.ts +24 -1
  575. package/src/mcp/guards/mcp-permission.guard.spec.ts +109 -15
  576. package/src/mcp/guards/mcp-permission.guard.ts +76 -51
  577. package/src/mcp/mcp-audit.service.spec.ts +107 -0
  578. package/src/mcp/mcp-audit.service.ts +37 -1
  579. package/src/mcp/mcp-permission.service.spec.ts +197 -0
  580. package/src/mcp/mcp-permission.service.ts +184 -0
  581. package/src/mcp/mcp-server.service.spec.ts +84 -2
  582. package/src/mcp/mcp-server.service.ts +111 -87
  583. package/src/mcp/mcp.controller.ts +8 -1
  584. package/src/mcp/mcp.module.ts +5 -1
  585. package/src/mcp/tools/core-ai.mcp-tools.ts +1 -1
  586. package/src/mcp/tools/core-dashboard-items.mcp-tools.ts +1 -1
  587. package/src/mcp/tools/core-dashboard.mcp-tools.ts +1 -1
  588. package/src/mcp/tools/core-event-webhooks.mcp-tools.ts +1 -2
  589. package/src/mcp/tools/core-files.mcp-tools.ts +202 -22
  590. package/src/mcp/tools/core-integration-events.mcp-tools.ts +1 -1
  591. package/src/mcp/tools/core-mail-sent.mcp-tools.ts +1 -1
  592. package/src/mcp/tools/core-mail.mcp-tools.ts +1 -1
  593. package/src/mcp/tools/core-menus.mcp-tools.ts +1 -2
  594. package/src/mcp/tools/core-notifications.mcp-tools.ts +0 -1
  595. package/src/mcp/tools/core-roles.mcp-tools.ts +1 -5
  596. package/src/mcp/tools/core-routes.mcp-tools.ts +1 -3
  597. package/src/mcp/tools/core-screens.mcp-tools.ts +1 -3
  598. package/src/mcp/tools/core-sessions.mcp-tools.ts +0 -2
  599. package/src/mcp/tools/core-settings.mcp-tools.ts +1 -2
  600. package/src/mcp/tools/core-users.mcp-tools.ts +1 -1
  601. package/src/mcp/tools/core-webhooks.mcp-tools.ts +1 -2
  602. package/src/mcp/types/mcp-context.type.ts +15 -6
  603. package/src/mcp-chat/mcp-chat.service.ts +8 -0
  604. package/src/meeting/meeting-provider.registry.ts +121 -0
  605. package/src/meeting/meeting.constants.ts +74 -0
  606. package/src/menu/menu.service.spec.ts +89 -0
  607. package/src/menu/menu.service.ts +29 -11
  608. package/src/message-template/dto/update-message-template.dto.ts +22 -0
  609. package/src/message-template/message-template-admin.service.spec.ts +163 -0
  610. package/src/message-template/message-template-admin.service.ts +239 -0
  611. package/src/message-template/message-template.controller.ts +52 -0
  612. package/src/message-template/message-template.module.ts +21 -0
  613. package/src/message-template/message-template.registry.spec.ts +62 -0
  614. package/src/message-template/message-template.registry.ts +125 -0
  615. package/src/message-template/message-template.service.spec.ts +149 -0
  616. package/src/message-template/message-template.service.ts +149 -0
  617. package/src/notification/notification.constants.ts +10 -0
  618. package/src/notification/notification.module.ts +3 -0
  619. package/src/notification/notification.service.spec.ts +75 -1
  620. package/src/notification/notification.service.ts +39 -1
  621. package/src/oauth/oauth.controller.ts +0 -1
  622. package/src/oauth/oauth.errors.ts +7 -0
  623. package/src/oauth/oauth.module.ts +6 -1
  624. package/src/oauth/oauth.service.spec.ts +58 -7
  625. package/src/oauth/oauth.service.ts +71 -32
  626. package/src/oauth/providers/abstract.provider.spec.ts +192 -0
  627. package/src/oauth/providers/abstract.provider.ts +46 -14
  628. package/src/oauth/providers/github.provider.ts +57 -34
  629. package/src/oauth/providers/microsoft-entra-id.provider.ts +8 -1
  630. package/src/observability/monitored-cron.spec.ts +164 -31
  631. package/src/observability/monitored-cron.ts +154 -62
  632. package/src/profile/dto/change-password.dto.ts +25 -7
  633. package/src/profile/profile.service.spec.ts +97 -0
  634. package/src/profile/profile.service.ts +9 -3
  635. package/src/realtime/realtime-tick.coalescer.spec.ts +92 -0
  636. package/src/realtime/realtime-tick.coalescer.ts +60 -0
  637. package/src/realtime/realtime.service.spec.ts +33 -0
  638. package/src/realtime/realtime.service.ts +28 -2
  639. package/src/redis/redis-kv.service.ts +261 -0
  640. package/src/redis/redis-master.spec.ts +111 -0
  641. package/src/redis/redis-master.ts +86 -0
  642. package/src/redis/redis-pubsub.ts +27 -3
  643. package/src/redis/redis.module.ts +17 -0
  644. package/src/session/session.service.spec.ts +121 -42
  645. package/src/session/session.service.ts +279 -82
  646. package/src/setting/setting.service.ts +44 -3
  647. package/src/task/task.service.spec.ts +41 -0
  648. package/src/task/task.service.ts +53 -13
  649. package/src/token/token.service.spec.ts +90 -0
  650. package/src/token/token.service.ts +48 -2
  651. package/src/user/user-credential.util.ts +14 -5
  652. package/src/user/user.service.ts +2 -12
  653. package/src/user/user.sort.ts +25 -0
  654. package/src/utils/abbreviate-name.spec.ts +50 -0
  655. package/src/utils/abbreviate-name.ts +44 -0
  656. package/src/utils/date-range-query.dto.ts +56 -0
  657. package/src/utils/date-range.spec.ts +175 -0
  658. package/src/utils/date-range.ts +246 -0
  659. package/src/webhook-integration/webhook-utils.spec.ts +67 -0
  660. package/src/webhook-integration/webhook-utils.ts +26 -0
  661. package/src/whatsapp-sender/whatsapp-recipients.spec.ts +89 -0
  662. package/src/whatsapp-sender/whatsapp-recipients.ts +83 -0
  663. package/src/whatsapp-sender/whatsapp-sender.service.spec.ts +112 -0
  664. package/src/whatsapp-sender/whatsapp-sender.service.ts +58 -5
@@ -0,0 +1,76 @@
1
+ import { afterEach, describe, expect, it, jest } from '@jest/globals';
2
+ import {
3
+ ForbiddenException,
4
+ UnauthorizedException,
5
+ } from '@nestjs/common';
6
+ import { McpChallengeFilter } from './mcp-challenge.filter';
7
+
8
+ const ISSUER = 'https://hub-api.example.com';
9
+ const METADATA_URL = `${ISSUER}/.well-known/oauth-protected-resource/mcp`;
10
+
11
+ const makeFilter = () => {
12
+ const metadata = { getIssuer: jest.fn<any>().mockResolvedValue(ISSUER) };
13
+ const response: any = {
14
+ setHeader: jest.fn(),
15
+ status: jest.fn().mockReturnThis(),
16
+ json: jest.fn().mockReturnThis(),
17
+ };
18
+ const host: any = { switchToHttp: () => ({ getResponse: () => response }) };
19
+ return { filter: new McpChallengeFilter(metadata as any), response, host };
20
+ };
21
+
22
+ describe('McpChallengeFilter', () => {
23
+ afterEach(() => jest.clearAllMocks());
24
+
25
+ // O passo 1 de todo fluxo OAuth de cliente MCP: bater sem token e ler daqui
26
+ // onde estao os metadados do recurso.
27
+ it('desafia o 401 com resource_metadata', async () => {
28
+ const { filter, response, host } = makeFilter();
29
+
30
+ await filter.catch(new UnauthorizedException('Access denied.'), host);
31
+
32
+ expect(response.setHeader).toHaveBeenCalledWith(
33
+ 'WWW-Authenticate',
34
+ `Bearer resource_metadata="${METADATA_URL}", error="invalid_token"`,
35
+ );
36
+ expect(response.status).toHaveBeenCalledWith(401);
37
+ });
38
+
39
+ it('pede reautorizacao quando falta o escopo mcp', async () => {
40
+ const { filter, response, host } = makeFilter();
41
+
42
+ await filter.catch(
43
+ new ForbiddenException("MCP: token is missing the 'mcp' scope"),
44
+ host,
45
+ );
46
+
47
+ const [, value] = response.setHeader.mock.calls[0];
48
+ expect(value).toContain('error="insufficient_scope"');
49
+ expect(value).toContain('scope="mcp"');
50
+ expect(response.status).toHaveBeenCalledWith(403);
51
+ });
52
+
53
+ // 403 por falta de papel numa tool nao se resolve reautorizando: mandar
54
+ // insufficient_scope poria o cliente num laco de reautorizacao sem fim.
55
+ it('nao desafia 403 de permissao de tool', async () => {
56
+ const { filter, response, host } = makeFilter();
57
+
58
+ await filter.catch(
59
+ new ForbiddenException("Access denied to MCP tool 'core.users.list'"),
60
+ host,
61
+ );
62
+
63
+ expect(response.setHeader).not.toHaveBeenCalled();
64
+ expect(response.status).toHaveBeenCalledWith(403);
65
+ });
66
+
67
+ it('preserva o corpo original da excecao', async () => {
68
+ const { filter, response, host } = makeFilter();
69
+
70
+ await filter.catch(new UnauthorizedException('Access denied.'), host);
71
+
72
+ expect(response.json).toHaveBeenCalledWith(
73
+ expect.objectContaining({ message: 'Access denied.' }),
74
+ );
75
+ });
76
+ });
@@ -0,0 +1,70 @@
1
+ import {
2
+ ArgumentsHost,
3
+ Catch,
4
+ ExceptionFilter,
5
+ HttpException,
6
+ HttpStatus,
7
+ } from '@nestjs/common';
8
+ import { Response } from 'express';
9
+ import { OAuthMetadataService } from '../../authorize/oauth-metadata.service';
10
+ import { MCP_SCOPE } from '../guards/mcp-auth.guard';
11
+
12
+ /**
13
+ * O desafio `WWW-Authenticate` do /mcp — o primeiro passo de todo fluxo OAuth de
14
+ * um cliente MCP (RFC 9728 §5.1): ele bate sem token, lê deste cabeçalho onde
15
+ * estão os metadados do recurso, e só então sabe a quem pedir autorização.
16
+ *
17
+ * Precisa ser um ExceptionFilter, e não um trecho dentro do McpAuthGuard, porque
18
+ * o caso que mais importa nem chega ao McpAuthGuard: numa requisição SEM token,
19
+ * quem lança o 401 é o AuthGuard global, que roda antes. Um filtro declarado no
20
+ * controller captura tambem o que os guards lançam, e por isso cobre os dois.
21
+ */
22
+ @Catch(HttpException)
23
+ export class McpChallengeFilter implements ExceptionFilter {
24
+ constructor(private readonly metadata: OAuthMetadataService) {}
25
+
26
+ async catch(exception: HttpException, host: ArgumentsHost): Promise<void> {
27
+ const ctx = host.switchToHttp();
28
+ const response = ctx.getResponse<Response>();
29
+ const status = exception.getStatus();
30
+
31
+ if (status === HttpStatus.UNAUTHORIZED) {
32
+ response.setHeader(
33
+ 'WWW-Authenticate',
34
+ `Bearer resource_metadata="${await this.resourceMetadataUrl()}", error="invalid_token"`,
35
+ );
36
+ } else if (status === HttpStatus.FORBIDDEN) {
37
+ // 403 aqui pode ser falta de escopo (o token não foi autorizado para o MCP)
38
+ // ou falta de papel numa tool específica. Só o primeiro é recuperável por
39
+ // uma nova autorização, e é o único que ganha o desafio de escopo — mandar
40
+ // `insufficient_scope` no segundo caso faria o cliente entrar num laço de
41
+ // reautorização que nunca resolve.
42
+ if (this.isScopeError(exception)) {
43
+ response.setHeader(
44
+ 'WWW-Authenticate',
45
+ `Bearer error="insufficient_scope", scope="${MCP_SCOPE}", resource_metadata="${await this.resourceMetadataUrl()}"`,
46
+ );
47
+ }
48
+ }
49
+
50
+ const body = exception.getResponse();
51
+ response
52
+ .status(status)
53
+ .json(
54
+ typeof body === 'string'
55
+ ? { statusCode: status, message: body }
56
+ : body,
57
+ );
58
+ }
59
+
60
+ private isScopeError(exception: HttpException): boolean {
61
+ const body = exception.getResponse() as any;
62
+ const message =
63
+ typeof body === 'string' ? body : String(body?.message ?? '');
64
+ return message.includes(`'${MCP_SCOPE}' scope`);
65
+ }
66
+
67
+ private async resourceMetadataUrl(): Promise<string> {
68
+ return `${await this.metadata.getIssuer()}/.well-known/oauth-protected-resource/mcp`;
69
+ }
70
+ }
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals';
2
- import { UnauthorizedException } from '@nestjs/common';
2
+ import { ForbiddenException, UnauthorizedException } from '@nestjs/common';
3
3
  import { McpAuthGuard } from './mcp-auth.guard';
4
4
 
5
5
  const makeContext = (request: any) => ({
@@ -10,14 +10,20 @@ const makeDeps = () => {
10
10
  const tokenService = { verify: jest.fn() };
11
11
  const prisma = { mcp_api_key: { findFirst: jest.fn(), update: jest.fn() } };
12
12
  const security = { hashWithPepper: jest.fn().mockReturnValue('hash') };
13
- return { tokenService, prisma, security };
13
+ const oauthMetadata = {
14
+ getMcpResource: jest.fn<any>().mockResolvedValue(MCP_RESOURCE),
15
+ };
16
+ return { tokenService, prisma, security, oauthMetadata };
14
17
  };
15
18
 
19
+ const MCP_RESOURCE = 'https://hub-api.example.com/mcp';
20
+
16
21
  const makeService = (deps = makeDeps()) => ({
17
22
  guard: new McpAuthGuard(
18
23
  deps.tokenService as any,
19
24
  deps.prisma as any,
20
25
  deps.security as any,
26
+ deps.oauthMetadata as any,
21
27
  ),
22
28
  deps,
23
29
  });
@@ -40,6 +46,49 @@ describe('McpAuthGuard', () => {
40
46
  true,
41
47
  );
42
48
  expect(request.auth).toEqual({ sub: 4 });
49
+ // O recurso e passado para o verify — e dele que sai a recusa de um token
50
+ // emitido para outra audiencia.
51
+ expect(deps.tokenService.verify).toHaveBeenCalledWith(
52
+ expect.anything(),
53
+ 'tok',
54
+ MCP_RESOURCE,
55
+ );
56
+ });
57
+
58
+ it('aceita token OAuth que traz o escopo mcp', async () => {
59
+ const { guard, deps } = makeService();
60
+ deps.tokenService.verify.mockResolvedValue({
61
+ sub: 4,
62
+ aud: MCP_RESOURCE,
63
+ scope: 'mcp',
64
+ });
65
+ const request: any = { headers: { authorization: 'Bearer tok' } };
66
+ await expect(guard.canActivate(makeContext(request) as any)).resolves.toBe(
67
+ true,
68
+ );
69
+ });
70
+
71
+ it('nega token OAuth sem o escopo mcp', async () => {
72
+ const { guard, deps } = makeService();
73
+ deps.tokenService.verify.mockResolvedValue({
74
+ sub: 4,
75
+ aud: MCP_RESOURCE,
76
+ scope: 'profile',
77
+ });
78
+ const request: any = { headers: { authorization: 'Bearer tok' } };
79
+ await expect(
80
+ guard.canActivate(makeContext(request) as any),
81
+ ).rejects.toThrow(ForbiddenException);
82
+ });
83
+
84
+ // O JWT de login nunca teve `scope`; exigi-lo quebraria o uso interno do /mcp.
85
+ it('nao exige escopo de token sem audiencia', async () => {
86
+ const { guard, deps } = makeService();
87
+ deps.tokenService.verify.mockResolvedValue({ sub: 4 });
88
+ const request: any = { headers: { authorization: 'Bearer tok' } };
89
+ await expect(guard.canActivate(makeContext(request) as any)).resolves.toBe(
90
+ true,
91
+ );
43
92
  });
44
93
 
45
94
  it('autentica com api key mcp válida', async () => {
@@ -2,19 +2,24 @@ import { PrismaService } from '@hed-hog/api-prisma';
2
2
  import {
3
3
  CanActivate,
4
4
  ExecutionContext,
5
+ ForbiddenException,
5
6
  Injectable,
6
7
  UnauthorizedException,
7
8
  } from '@nestjs/common';
8
9
  import { Request } from 'express';
10
+ import { MCP_SCOPE, OAuthMetadataService } from '../../authorize/oauth-metadata.service';
9
11
  import { SecurityService } from '../../security/security.service';
10
12
  import { TokenService } from '../../token/token.service';
11
13
 
14
+ export { MCP_SCOPE };
15
+
12
16
  @Injectable()
13
17
  export class McpAuthGuard implements CanActivate {
14
18
  constructor(
15
19
  private readonly tokenService: TokenService,
16
20
  private readonly prisma: PrismaService,
17
21
  private readonly security: SecurityService,
22
+ private readonly oauthMetadata: OAuthMetadataService,
18
23
  ) {}
19
24
 
20
25
  async canActivate(context: ExecutionContext): Promise<boolean> {
@@ -31,7 +36,25 @@ export class McpAuthGuard implements CanActivate {
31
36
  return this.verifyApiKey(request, token);
32
37
  }
33
38
 
34
- request['auth'] = await this.tokenService.verify(locale, token);
39
+ const payload = await this.tokenService.verify(
40
+ locale,
41
+ token,
42
+ await this.oauthMetadata.getMcpResource(),
43
+ );
44
+
45
+ // Token emitido pelo fluxo OAuth carrega `scope`; o JWT de login, nao. So o
46
+ // primeiro precisa provar que o usuario consentiu com o acesso ao MCP — exigir
47
+ // escopo de um token de sessao quebraria o uso interno, que nunca teve escopo.
48
+ if (payload.aud !== undefined) {
49
+ const scopes = String(payload.scope ?? '').split(/\s+/).filter(Boolean);
50
+ if (!scopes.includes(MCP_SCOPE)) {
51
+ throw new ForbiddenException(
52
+ `MCP: token is missing the '${MCP_SCOPE}' scope`,
53
+ );
54
+ }
55
+ }
56
+
57
+ request['auth'] = payload;
35
58
  return true;
36
59
  }
37
60
 
@@ -1,4 +1,4 @@
1
- import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals';
1
+ import { afterEach, describe, expect, it, jest } from '@jest/globals';
2
2
  import { ForbiddenException } from '@nestjs/common';
3
3
  import { McpPermissionGuard } from './mcp-permission.guard';
4
4
 
@@ -6,9 +6,11 @@ const makeContext = (request: any) => ({
6
6
  switchToHttp: () => ({ getRequest: () => request }),
7
7
  });
8
8
 
9
- const makeService = () => {
10
- const prisma = { route: { count: jest.fn() } };
11
- return { guard: new McpPermissionGuard(prisma as any), prisma };
9
+ const makeService = (allowed: string[] = []) => {
10
+ const permissions = {
11
+ getAllowedToolNames: jest.fn<any>().mockResolvedValue(new Set(allowed)),
12
+ };
13
+ return { guard: new McpPermissionGuard(permissions as any), permissions };
12
14
  };
13
15
 
14
16
  describe('McpPermissionGuard', () => {
@@ -22,18 +24,17 @@ describe('McpPermissionGuard', () => {
22
24
  });
23
25
 
24
26
  it('permite POST sem tools/call (ex.: tools/list)', async () => {
25
- const { guard, prisma } = makeService();
27
+ const { guard, permissions } = makeService();
26
28
  await expect(
27
29
  guard.canActivate(
28
30
  makeContext({ method: 'POST', body: { method: 'tools/list' } }) as any,
29
31
  ),
30
32
  ).resolves.toBe(true);
31
- expect(prisma.route.count).not.toHaveBeenCalled();
33
+ expect(permissions.getAllowedToolNames).not.toHaveBeenCalled();
32
34
  });
33
35
 
34
36
  it('permite tools/call quando usuário tem permissão', async () => {
35
- const { guard, prisma } = makeService();
36
- prisma.route.count.mockResolvedValue(1);
37
+ const { guard, permissions } = makeService(['my_tool']);
37
38
  const request = {
38
39
  method: 'POST',
39
40
  body: { method: 'tools/call', params: { name: 'my_tool' } },
@@ -42,16 +43,11 @@ describe('McpPermissionGuard', () => {
42
43
  await expect(guard.canActivate(makeContext(request) as any)).resolves.toBe(
43
44
  true,
44
45
  );
45
- expect(prisma.route.count).toHaveBeenCalledWith(
46
- expect.objectContaining({
47
- where: expect.objectContaining({ tool_name: 'my_tool' }),
48
- }),
49
- );
46
+ expect(permissions.getAllowedToolNames).toHaveBeenCalledWith(2, false);
50
47
  });
51
48
 
52
49
  it('nega tools/call sem permissão', async () => {
53
- const { guard, prisma } = makeService();
54
- prisma.route.count.mockResolvedValue(0);
50
+ const { guard } = makeService([]);
55
51
  const request = {
56
52
  method: 'POST',
57
53
  body: { method: 'tools/call', params: { name: 'secret_tool' } },
@@ -61,4 +57,102 @@ describe('McpPermissionGuard', () => {
61
57
  ForbiddenException,
62
58
  );
63
59
  });
60
+
61
+ /**
62
+ * O teto so vale para cliente OAuth externo. O token interno (chave
63
+ * hedhog_mcp_, JWT de login) nao tem `aud`, e ali quem chama e o proprio
64
+ * operador, com a tela na frente.
65
+ */
66
+ describe('origem da chamada', () => {
67
+ it('marca como conector quando o token tem aud', async () => {
68
+ const { guard, permissions } = makeService(['my_tool']);
69
+ const request = {
70
+ method: 'POST',
71
+ body: { method: 'tools/call', params: { name: 'my_tool' } },
72
+ auth: { sub: 2, aud: 'https://hub-api.example.com/mcp' },
73
+ };
74
+ await guard.canActivate(makeContext(request) as any);
75
+ expect(permissions.getAllowedToolNames).toHaveBeenCalledWith(2, true);
76
+ });
77
+
78
+ it('nao marca como conector sem aud', async () => {
79
+ const { guard, permissions } = makeService(['my_tool']);
80
+ const request = {
81
+ method: 'POST',
82
+ body: { method: 'tools/call', params: { name: 'my_tool' } },
83
+ auth: { sub: 2 },
84
+ };
85
+ await guard.canActivate(makeContext(request) as any);
86
+ expect(permissions.getAllowedToolNames).toHaveBeenCalledWith(2, false);
87
+ });
88
+ });
89
+
90
+ /**
91
+ * REGRESSAO: o transporte do SDK aceita batch JSON-RPC (corpo array) e despacha
92
+ * cada mensagem para o mesmo handler. Lendo so `body.method`, um `tools/call`
93
+ * envolvido em colchetes fazia `toolName` virar undefined, o guard liberava, e
94
+ * o handler executava a tool sem checar papel nenhum — bypass completo da
95
+ * autorizacao, reproduzido com o SDK instalado.
96
+ */
97
+ describe('batch JSON-RPC (corpo array)', () => {
98
+ it('nega tool sem permissão dentro de um lote', async () => {
99
+ const { guard } = makeService(['permitida']);
100
+ const request = {
101
+ method: 'POST',
102
+ body: [
103
+ { jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: 'proibida' } },
104
+ ],
105
+ auth: { sub: 2 },
106
+ };
107
+ await expect(
108
+ guard.canActivate(makeContext(request) as any),
109
+ ).rejects.toThrow(ForbiddenException);
110
+ });
111
+
112
+ it('nega o lote inteiro se UMA das mensagens não é permitida', async () => {
113
+ const { guard } = makeService(['permitida']);
114
+ const request = {
115
+ method: 'POST',
116
+ body: [
117
+ { method: 'tools/call', params: { name: 'permitida' } },
118
+ { method: 'tools/list' },
119
+ { method: 'tools/call', params: { name: 'proibida' } },
120
+ ],
121
+ auth: { sub: 2 },
122
+ };
123
+ await expect(
124
+ guard.canActivate(makeContext(request) as any),
125
+ ).rejects.toThrow(/proibida/);
126
+ });
127
+
128
+ it('permite lote em que toda tool é concedida', async () => {
129
+ const { guard, permissions } = makeService(['a', 'b']);
130
+ const request = {
131
+ method: 'POST',
132
+ body: [
133
+ { method: 'tools/call', params: { name: 'a' } },
134
+ { method: 'tools/call', params: { name: 'b' } },
135
+ ],
136
+ auth: { sub: 2 },
137
+ };
138
+ await expect(guard.canActivate(makeContext(request) as any)).resolves.toBe(
139
+ true,
140
+ );
141
+ // Uma consulta so para o lote inteiro.
142
+ expect(permissions.getAllowedToolNames).toHaveBeenCalledTimes(1);
143
+ });
144
+
145
+ it('lote sem nenhum tools/call passa sem consultar permissão', async () => {
146
+ const { guard, permissions } = makeService();
147
+ const request = {
148
+ method: 'POST',
149
+ body: [{ method: 'initialize' }, { method: 'tools/list' }],
150
+ auth: { sub: 2 },
151
+ };
152
+ await expect(guard.canActivate(makeContext(request) as any)).resolves.toBe(
153
+ true,
154
+ );
155
+ expect(permissions.getAllowedToolNames).not.toHaveBeenCalled();
156
+ });
157
+ });
64
158
  });
@@ -1,51 +1,76 @@
1
- import { PrismaService } from '@hed-hog/api-prisma';
2
- import {
3
- CanActivate,
4
- ExecutionContext,
5
- ForbiddenException,
6
- Injectable,
7
- } from '@nestjs/common';
8
- import { Request } from 'express';
9
-
10
- @Injectable()
11
- export class McpPermissionGuard implements CanActivate {
12
- constructor(private readonly prisma: PrismaService) {}
13
-
14
- async canActivate(context: ExecutionContext): Promise<boolean> {
15
- const request = context.switchToHttp().getRequest<Request>();
16
-
17
- // Only POST requests carry tool invocations
18
- if (request.method !== 'POST') return true;
19
-
20
- const body = request.body as any;
21
- const toolName: string | undefined =
22
- body?.method === 'tools/call' ? body?.params?.name : undefined;
23
-
24
- // tools/list, initialize, ping, etc. — no per-tool permission check needed
25
- if (!toolName) return true;
26
-
27
- const userId = (request as any)?.auth?.sub;
28
-
29
- const count = await this.prisma.route.count({
30
- where: {
31
- type: 'MCP' as any,
32
- tool_name: toolName,
33
- role_route: {
34
- some: {
35
- role: {
36
- role_user: {
37
- some: { user_id: userId },
38
- },
39
- },
40
- },
41
- },
42
- },
43
- });
44
-
45
- if (count === 0) {
46
- throw new ForbiddenException(`Access denied to MCP tool '${toolName}'`);
47
- }
48
-
49
- return true;
50
- }
51
- }
1
+ import {
2
+ CanActivate,
3
+ ExecutionContext,
4
+ ForbiddenException,
5
+ Injectable,
6
+ } from '@nestjs/common';
7
+ import { Request } from 'express';
8
+ import { McpPermissionService } from '../mcp-permission.service';
9
+
10
+ /**
11
+ * A trava de verdade do `tools/call`.
12
+ *
13
+ * O `tools/list` também filtra pelas mesmas permissões, mas aquilo é
14
+ * apresentação: nada impede um cliente de chamar uma tool que ele nunca viu na
15
+ * lista. Por isso os dois consultam o mesmo `McpPermissionService` e este guard
16
+ * continua existindo.
17
+ *
18
+ * O corpo pode ser UM objeto JSON-RPC ou um ARRAY deles — o transporte do SDK
19
+ * aceita batch (`if (Array.isArray(rawMessage))`) e despacha cada mensagem para o
20
+ * mesmo handler. Ler só `body.method` deixava passar qualquer chamada envolvida em
21
+ * colchetes: `body.method` fica `undefined`, o guard liberava, e o handler de
22
+ * `CallToolRequestSchema` executa sem olhar papel nenhum. Toda mensagem do lote
23
+ * precisa ser inspecionada.
24
+ */
25
+ @Injectable()
26
+ export class McpPermissionGuard implements CanActivate {
27
+ constructor(private readonly permissions: McpPermissionService) {}
28
+
29
+ async canActivate(context: ExecutionContext): Promise<boolean> {
30
+ const request = context.switchToHttp().getRequest<Request>();
31
+
32
+ // Only POST requests carry tool invocations
33
+ if (request.method !== 'POST') return true;
34
+
35
+ const toolNames = this.extractToolNames(request.body);
36
+
37
+ // tools/list, initialize, ping, etc. — no per-tool permission check needed
38
+ if (toolNames.length === 0) return true;
39
+
40
+ const auth = (request as any)?.auth;
41
+ const userId = auth?.sub;
42
+ // Token de cliente OAuth externo carrega `aud`; o interno, nao. O teto de
43
+ // permissao so vale para o primeiro.
44
+ const viaConnector = auth?.aud !== undefined;
45
+
46
+ // Uma consulta só: o service resolve o conjunto inteiro de uma vez e o cache
47
+ // atende as demais mensagens do lote.
48
+ const allowed = await this.permissions.getAllowedToolNames(
49
+ userId,
50
+ viaConnector,
51
+ );
52
+
53
+ for (const toolName of toolNames) {
54
+ if (!allowed.has(toolName)) {
55
+ throw new ForbiddenException(`Access denied to MCP tool '${toolName}'`);
56
+ }
57
+ }
58
+
59
+ return true;
60
+ }
61
+
62
+ /**
63
+ * Nomes de tool de toda mensagem `tools/call` do corpo, seja ele um objeto ou
64
+ * um lote. Mensagem malformada é ignorada aqui de propósito — quem a rejeita é
65
+ * o parser do SDK, e inventar um nome a partir dela só produziria um 403 com
66
+ * mensagem enganosa.
67
+ */
68
+ private extractToolNames(body: unknown): string[] {
69
+ const messages = Array.isArray(body) ? body : [body];
70
+
71
+ return messages
72
+ .filter((m: any) => m?.method === 'tools/call')
73
+ .map((m: any) => m?.params?.name)
74
+ .filter((name: unknown): name is string => typeof name === 'string' && name.length > 0);
75
+ }
76
+ }
@@ -0,0 +1,107 @@
1
+ import { describe, expect, it, jest } from '@jest/globals';
2
+
3
+ jest.mock('@hed-hog/api-prisma', () => ({
4
+ __esModule: true,
5
+ PrismaService: class {},
6
+ Prisma: {},
7
+ }));
8
+
9
+ import { McpAuditService } from './mcp-audit.service';
10
+
11
+ const makeService = () => {
12
+ const rows: any[] = [];
13
+
14
+ const prisma: any = {
15
+ mcp_tool_call_log: {
16
+ create: jest.fn(async ({ data }: any) => {
17
+ rows.push(data);
18
+ return data;
19
+ }),
20
+ },
21
+ };
22
+
23
+ const accessLogService: any = { recordMcp: jest.fn() };
24
+ const service = new McpAuditService(prisma, accessLogService);
25
+
26
+ return { service, rows, accessLogService };
27
+ };
28
+
29
+ const base = {
30
+ userId: 7,
31
+ toolName: 'finance.titles.attachments.add',
32
+ success: true,
33
+ durationMs: 12,
34
+ };
35
+
36
+ describe('McpAuditService.record', () => {
37
+ it('redige o conteúdo do arquivo e preserva o resto dos argumentos', async () => {
38
+ const { service, rows } = makeService();
39
+ const base64 = 'A'.repeat(50_000);
40
+
41
+ await service.record({
42
+ ...base,
43
+ input: { titleId: 42, fileName: 'nota.pdf', fileBase64: base64 },
44
+ });
45
+
46
+ const logged = JSON.parse(rows[0].input);
47
+
48
+ // O que a auditoria quer é o id do título e a modalidade, não mil caracteres de
49
+ // base64 — que é tudo o que sobrava do slice(0, 1000).
50
+ expect(logged.titleId).toBe(42);
51
+ expect(logged.fileName).toBe('nota.pdf');
52
+ expect(logged.fileBase64).toBe('<redacted: 50000 chars>');
53
+ expect(rows[0].input).not.toContain('AAAA');
54
+ });
55
+
56
+ it('redige também a parte do upload em partes', async () => {
57
+ const { service, rows } = makeService();
58
+
59
+ await service.record({
60
+ ...base,
61
+ toolName: 'core.files.upload.append',
62
+ input: { uploadId: 3, index: 0, chunkBase64: 'B'.repeat(1000) },
63
+ });
64
+
65
+ const logged = JSON.parse(rows[0].input);
66
+ expect(logged.uploadId).toBe(3);
67
+ expect(logged.chunkBase64).toBe('<redacted: 1000 chars>');
68
+ });
69
+
70
+ it('mantém a entrada intacta quando não há conteúdo de arquivo', async () => {
71
+ const { service, rows } = makeService();
72
+
73
+ await service.record({ ...base, input: { titleId: 42, fileId: 10 } });
74
+
75
+ expect(JSON.parse(rows[0].input)).toEqual({ titleId: 42, fileId: 10 });
76
+ });
77
+
78
+ it('não modifica o objeto de entrada do chamador', async () => {
79
+ // O mesmo objeto segue para o handler da tool; redigir no lugar apagaria o arquivo.
80
+ const { service } = makeService();
81
+ const input = { fileBase64: 'AAAA' };
82
+
83
+ await service.record({ ...base, input });
84
+
85
+ expect(input.fileBase64).toBe('AAAA');
86
+ });
87
+
88
+ it('continua cortando em 1000 caracteres o que sobra', async () => {
89
+ const { service, rows } = makeService();
90
+
91
+ await service.record({ ...base, input: { note: 'x'.repeat(5000) } });
92
+
93
+ expect(rows[0].input.length).toBe(1000);
94
+ });
95
+
96
+ it('não deixa a falha da auditoria derrubar a chamada', async () => {
97
+ const { service, rows } = makeService();
98
+ (service as any).prisma.mcp_tool_call_log.create.mockRejectedValue(
99
+ new Error('banco fora'),
100
+ );
101
+
102
+ await expect(
103
+ service.record({ ...base, input: { titleId: 1 } }),
104
+ ).resolves.toBeUndefined();
105
+ expect(rows).toHaveLength(0);
106
+ });
107
+ });