@hed-hog/core 0.0.399 → 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 (668) 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 +29 -5
  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 +77 -3
  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 +386 -54
  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.service.d.ts +6 -2
  356. package/dist/pairing/pairing.service.d.ts.map +1 -1
  357. package/dist/profile/dto/change-password.dto.d.ts.map +1 -1
  358. package/dist/profile/dto/change-password.dto.js +4 -6
  359. package/dist/profile/dto/change-password.dto.js.map +1 -1
  360. package/dist/profile/profile.controller.d.ts +1 -1
  361. package/dist/profile/profile.service.d.ts +1 -1
  362. package/dist/profile/profile.service.d.ts.map +1 -1
  363. package/dist/profile/profile.service.js +9 -3
  364. package/dist/profile/profile.service.js.map +1 -1
  365. package/dist/realtime/realtime-tick.coalescer.d.ts +34 -0
  366. package/dist/realtime/realtime-tick.coalescer.d.ts.map +1 -0
  367. package/dist/realtime/realtime-tick.coalescer.js +60 -0
  368. package/dist/realtime/realtime-tick.coalescer.js.map +1 -0
  369. package/dist/realtime/realtime.service.d.ts +2 -0
  370. package/dist/realtime/realtime.service.d.ts.map +1 -1
  371. package/dist/realtime/realtime.service.js +22 -2
  372. package/dist/realtime/realtime.service.js.map +1 -1
  373. package/dist/redis/redis-kv.service.d.ts +90 -0
  374. package/dist/redis/redis-kv.service.d.ts.map +1 -0
  375. package/dist/redis/redis-kv.service.js +247 -0
  376. package/dist/redis/redis-kv.service.js.map +1 -0
  377. package/dist/redis/redis-master.d.ts +29 -0
  378. package/dist/redis/redis-master.d.ts.map +1 -0
  379. package/dist/redis/redis-master.js +81 -0
  380. package/dist/redis/redis-master.js.map +1 -0
  381. package/dist/redis/redis-pubsub.d.ts +12 -0
  382. package/dist/redis/redis-pubsub.d.ts.map +1 -1
  383. package/dist/redis/redis-pubsub.js +25 -2
  384. package/dist/redis/redis-pubsub.js.map +1 -1
  385. package/dist/redis/redis.module.d.ts +11 -0
  386. package/dist/redis/redis.module.d.ts.map +1 -0
  387. package/dist/redis/redis.module.js +30 -0
  388. package/dist/redis/redis.module.js.map +1 -0
  389. package/dist/session/session.controller.d.ts +6 -2
  390. package/dist/session/session.controller.d.ts.map +1 -1
  391. package/dist/session/session.service.d.ts +118 -15
  392. package/dist/session/session.service.d.ts.map +1 -1
  393. package/dist/session/session.service.js +251 -77
  394. package/dist/session/session.service.js.map +1 -1
  395. package/dist/setting/setting.controller.d.ts +5 -0
  396. package/dist/setting/setting.controller.d.ts.map +1 -1
  397. package/dist/setting/setting.service.d.ts +7 -0
  398. package/dist/setting/setting.service.d.ts.map +1 -1
  399. package/dist/setting/setting.service.js +38 -3
  400. package/dist/setting/setting.service.js.map +1 -1
  401. package/dist/task/task.service.d.ts +17 -0
  402. package/dist/task/task.service.d.ts.map +1 -1
  403. package/dist/task/task.service.js +48 -13
  404. package/dist/task/task.service.js.map +1 -1
  405. package/dist/token/token.service.d.ts +19 -1
  406. package/dist/token/token.service.d.ts.map +1 -1
  407. package/dist/token/token.service.js +39 -2
  408. package/dist/token/token.service.js.map +1 -1
  409. package/dist/user/user-credential.util.d.ts +10 -0
  410. package/dist/user/user-credential.util.d.ts.map +1 -1
  411. package/dist/user/user-credential.util.js +14 -1
  412. package/dist/user/user-credential.util.js.map +1 -1
  413. package/dist/user/user.service.d.ts +12 -4
  414. package/dist/user/user.service.d.ts.map +1 -1
  415. package/dist/user/user.service.js +2 -11
  416. package/dist/user/user.service.js.map +1 -1
  417. package/dist/user/user.sort.d.ts +16 -0
  418. package/dist/user/user.sort.d.ts.map +1 -0
  419. package/dist/user/user.sort.js +25 -0
  420. package/dist/user/user.sort.js.map +1 -0
  421. package/dist/utils/abbreviate-name.d.ts +13 -0
  422. package/dist/utils/abbreviate-name.d.ts.map +1 -0
  423. package/dist/utils/abbreviate-name.js +42 -0
  424. package/dist/utils/abbreviate-name.js.map +1 -0
  425. package/dist/utils/date-range-query.dto.d.ts +11 -0
  426. package/dist/utils/date-range-query.dto.d.ts.map +1 -0
  427. package/dist/utils/date-range-query.dto.js +63 -0
  428. package/dist/utils/date-range-query.dto.js.map +1 -0
  429. package/dist/utils/date-range.d.ts +96 -0
  430. package/dist/utils/date-range.d.ts.map +1 -0
  431. package/dist/utils/date-range.js +172 -0
  432. package/dist/utils/date-range.js.map +1 -0
  433. package/dist/webhook-integration/webhook-utils.d.ts.map +1 -1
  434. package/dist/webhook-integration/webhook-utils.js +24 -0
  435. package/dist/webhook-integration/webhook-utils.js.map +1 -1
  436. package/dist/whatsapp-sender/whatsapp-recipients.d.ts +49 -0
  437. package/dist/whatsapp-sender/whatsapp-recipients.d.ts.map +1 -0
  438. package/dist/whatsapp-sender/whatsapp-recipients.js +66 -0
  439. package/dist/whatsapp-sender/whatsapp-recipients.js.map +1 -0
  440. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +25 -0
  441. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -1
  442. package/dist/whatsapp-sender/whatsapp-sender.service.js +46 -5
  443. package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -1
  444. package/hedhog/data/integration_provider.yaml +9 -0
  445. package/hedhog/data/integration_type.yaml +6 -0
  446. package/hedhog/data/locale.yaml +0 -1
  447. package/hedhog/data/mail.yaml +2 -2
  448. package/hedhog/data/mail_layout.yaml +6 -3
  449. package/hedhog/data/menu.yaml +25 -5
  450. package/hedhog/data/route.yaml +140 -0
  451. package/hedhog/data/setting_group.yaml +137 -3
  452. package/hedhog/frontend/app/access-log/page.tsx.ejs +47 -53
  453. package/hedhog/frontend/app/account/components/active-sessions.tsx.ejs +33 -8
  454. package/hedhog/frontend/app/account/components/mcp-tokens.tsx.ejs +54 -13
  455. package/hedhog/frontend/app/account/components/mfa-method-card.tsx.ejs +7 -1
  456. package/hedhog/frontend/app/account/components/recovery-codes-dialog.tsx.ejs +1 -0
  457. package/hedhog/frontend/app/account/components/tokens.tsx.ejs +47 -17
  458. package/hedhog/frontend/app/ai_agent/page.tsx.ejs +46 -5
  459. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +101 -30
  460. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +24 -8
  461. package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +80 -15
  462. package/hedhog/frontend/app/configurations/[slug]/components/image-optimization-action.tsx.ejs +166 -0
  463. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.test.tsx.ejs +145 -45
  464. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +99 -219
  465. package/hedhog/frontend/app/configurations/[slug]/page.tsx.ejs +19 -1
  466. package/hedhog/frontend/app/configurations/layout.tsx.ejs +19 -5
  467. package/hedhog/frontend/app/dashboard/[slug]/widget-renderer.tsx.ejs +2 -8
  468. package/hedhog/frontend/app/dashboard/components/dynamic-widget.tsx.ejs +3 -0
  469. package/hedhog/frontend/app/dashboard/components/widget-wrapper.tsx.ejs +4 -0
  470. package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +43 -44
  471. package/hedhog/frontend/app/dashboard/management/tabs/component-roles-tab.tsx.ejs +41 -3
  472. package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +42 -2
  473. package/hedhog/frontend/app/dashboard/management/tabs/dashboard-roles-tab.tsx.ejs +41 -3
  474. package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +39 -4
  475. package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +42 -3
  476. package/hedhog/frontend/app/incidents/page.tsx.ejs +60 -31
  477. package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +45 -5
  478. package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +92 -15
  479. package/hedhog/frontend/app/mail/log/page.tsx.ejs +109 -61
  480. package/hedhog/frontend/app/mail/template/page.tsx.ejs +125 -23
  481. package/hedhog/frontend/app/mcp_chat/chat-components.tsx.ejs +13 -15
  482. package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +116 -110
  483. package/hedhog/frontend/app/message-templates/_components/message-template-sheet.tsx.ejs +245 -0
  484. package/hedhog/frontend/app/message-templates/_lib/types.ts.ejs +24 -0
  485. package/hedhog/frontend/app/message-templates/page.tsx.ejs +182 -0
  486. package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1 -0
  487. package/hedhog/frontend/app/pages/page.tsx.ejs +94 -9
  488. package/hedhog/frontend/app/roles/menus.tsx.ejs +4 -4
  489. package/hedhog/frontend/app/roles/routes.tsx.ejs +4 -4
  490. package/hedhog/frontend/app/roles/users.tsx.ejs +4 -4
  491. package/hedhog/frontend/app/setting-list/page.tsx.ejs +71 -9
  492. package/hedhog/frontend/app/users/page.tsx.ejs +77 -67
  493. package/hedhog/frontend/messages/en.json +183 -36
  494. package/hedhog/frontend/messages/pt.json +183 -36
  495. package/hedhog/table/cron_lock.yaml +17 -0
  496. package/hedhog/table/file.yaml +13 -1
  497. package/hedhog/table/file_upload_chunk.yaml +23 -0
  498. package/hedhog/table/file_upload_ticket.yaml +67 -0
  499. package/hedhog/table/mcp_tool_call_log.yaml +30 -22
  500. package/hedhog/table/message_template.yaml +33 -0
  501. package/hedhog/table/setting.yaml +8 -0
  502. package/hedhog/table/user_session.yaml +36 -1
  503. package/package.json +7 -5
  504. package/src/ai/ai-agent.sort.ts +21 -0
  505. package/src/ai/ai.service.spec.ts +173 -1
  506. package/src/ai/ai.service.ts +64 -193
  507. package/src/ai-instruction/ai-instruction.service.ts +32 -28
  508. package/src/ai-instruction/ai-instruction.sort.ts +32 -0
  509. package/src/auth/auth.module.ts +8 -1
  510. package/src/auth/auth.service.spec.ts +108 -1
  511. package/src/auth/auth.service.ts +59 -5
  512. package/src/auth/guards/auth.guard.ts +9 -1
  513. package/src/authorize/authorize.controller.ts +126 -11
  514. package/src/authorize/authorize.errors.ts +55 -0
  515. package/src/authorize/authorize.module.ts +6 -1
  516. package/src/authorize/authorize.service.spec.ts +379 -7
  517. package/src/authorize/authorize.service.ts +309 -23
  518. package/src/authorize/dto/authorize-info.dto.ts +21 -3
  519. package/src/authorize/dto/consent.dto.ts +21 -3
  520. package/src/authorize/dto/token.dto.ts +24 -2
  521. package/src/authorize/oauth-exception.filter.ts +58 -0
  522. package/src/authorize/oauth-metadata.service.ts +67 -0
  523. package/src/authorize/well-known.controller.spec.ts +84 -0
  524. package/src/authorize/well-known.controller.ts +96 -0
  525. package/src/captcha/captcha.service.spec.ts +211 -4
  526. package/src/captcha/captcha.service.ts +127 -10
  527. package/src/core.module.ts +6 -0
  528. package/src/dashboard/dashboard-component-role/dashboard-component-role.service.ts +2 -3
  529. package/src/dashboard/dashboard-component-role/dashboard-component-role.sort.ts +18 -0
  530. package/src/dashboard/dashboard-item/dashboard-item.service.ts +2 -3
  531. package/src/dashboard/dashboard-item/dashboard-item.sort.ts +19 -0
  532. package/src/dashboard/dashboard-role/dashboard-role.service.ts +2 -3
  533. package/src/dashboard/dashboard-role/dashboard-role.sort.ts +16 -0
  534. package/src/file/file-upload-ticket.service.spec.ts +422 -0
  535. package/src/file/file-upload-ticket.service.ts +513 -0
  536. package/src/file/file.controller.ts +65 -0
  537. package/src/file/file.module.ts +14 -2
  538. package/src/file/file.service.spec.ts +94 -0
  539. package/src/file/file.service.ts +433 -53
  540. package/src/file/filename-encoding.util.spec.ts +54 -0
  541. package/src/file/filename-encoding.util.ts +67 -0
  542. package/src/file/image-optimization.service.spec.ts +156 -19
  543. package/src/file/image-optimization.service.ts +106 -21
  544. package/src/file/mcp-file-source.schema.ts +83 -0
  545. package/src/file/mcp-file-source.service.spec.ts +473 -0
  546. package/src/file/mcp-file-source.service.ts +445 -0
  547. package/src/file/mimetype-sniff.util.spec.ts +126 -0
  548. package/src/file/mimetype-sniff.util.ts +265 -0
  549. package/src/file/remote-fetch.util.spec.ts +117 -0
  550. package/src/file/remote-fetch.util.ts +330 -0
  551. package/src/impersonation/dto/start-impersonation.dto.ts +5 -2
  552. package/src/impersonation/impersonation.service.spec.ts +24 -1
  553. package/src/impersonation/impersonation.service.ts +14 -4
  554. package/src/incident/incident.controller.ts +9 -1
  555. package/src/incident/incident.service.ts +7 -0
  556. package/src/index.ts +17 -0
  557. package/src/integration-profile/integration-profile.secrets.ts +7 -0
  558. package/src/integration-profile/integration-profile.service.ts +7 -64
  559. package/src/integration-profile/integration-profile.utils.spec.ts +9 -0
  560. package/src/integration-profile/integration-profile.utils.ts +5 -5
  561. package/src/integration-profile/testers/index.ts +2 -0
  562. package/src/integration-profile/testers/remaining.testers.spec.ts +79 -0
  563. package/src/integration-profile/testers/shipping.testers.ts +94 -0
  564. package/src/mail/dto/send.dto.ts +6 -1
  565. package/src/mail/mail-template.spec.ts +58 -1
  566. package/src/mail/mail.service.spec.ts +112 -0
  567. package/src/mail/mail.service.ts +42 -4
  568. package/src/mail-sent/mail-sent.service.ts +3 -0
  569. package/src/mail-sent/mail-sent.sort.ts +19 -0
  570. package/src/mcp/filters/mcp-challenge.filter.spec.ts +76 -0
  571. package/src/mcp/filters/mcp-challenge.filter.ts +70 -0
  572. package/src/mcp/guards/mcp-auth.guard.spec.ts +51 -2
  573. package/src/mcp/guards/mcp-auth.guard.ts +24 -1
  574. package/src/mcp/guards/mcp-permission.guard.spec.ts +109 -15
  575. package/src/mcp/guards/mcp-permission.guard.ts +76 -51
  576. package/src/mcp/mcp-audit.service.spec.ts +107 -0
  577. package/src/mcp/mcp-audit.service.ts +37 -1
  578. package/src/mcp/mcp-permission.service.spec.ts +197 -0
  579. package/src/mcp/mcp-permission.service.ts +184 -0
  580. package/src/mcp/mcp-server.service.spec.ts +84 -2
  581. package/src/mcp/mcp-server.service.ts +111 -87
  582. package/src/mcp/mcp.controller.ts +8 -1
  583. package/src/mcp/mcp.module.ts +5 -1
  584. package/src/mcp/tools/core-ai.mcp-tools.ts +1 -1
  585. package/src/mcp/tools/core-dashboard-items.mcp-tools.ts +1 -1
  586. package/src/mcp/tools/core-dashboard.mcp-tools.ts +1 -1
  587. package/src/mcp/tools/core-event-webhooks.mcp-tools.ts +1 -2
  588. package/src/mcp/tools/core-files.mcp-tools.ts +202 -22
  589. package/src/mcp/tools/core-integration-events.mcp-tools.ts +1 -1
  590. package/src/mcp/tools/core-mail-sent.mcp-tools.ts +1 -1
  591. package/src/mcp/tools/core-mail.mcp-tools.ts +1 -1
  592. package/src/mcp/tools/core-menus.mcp-tools.ts +1 -2
  593. package/src/mcp/tools/core-notifications.mcp-tools.ts +0 -1
  594. package/src/mcp/tools/core-roles.mcp-tools.ts +1 -5
  595. package/src/mcp/tools/core-routes.mcp-tools.ts +1 -3
  596. package/src/mcp/tools/core-screens.mcp-tools.ts +1 -3
  597. package/src/mcp/tools/core-sessions.mcp-tools.ts +0 -2
  598. package/src/mcp/tools/core-settings.mcp-tools.ts +1 -2
  599. package/src/mcp/tools/core-users.mcp-tools.ts +1 -1
  600. package/src/mcp/tools/core-webhooks.mcp-tools.ts +1 -2
  601. package/src/mcp/types/mcp-context.type.ts +15 -6
  602. package/src/mcp-chat/mcp-chat.service.ts +8 -0
  603. package/src/meeting/meeting-provider.registry.ts +121 -0
  604. package/src/meeting/meeting.constants.ts +74 -0
  605. package/src/menu/menu.service.spec.ts +89 -0
  606. package/src/menu/menu.service.ts +29 -11
  607. package/src/message-template/dto/update-message-template.dto.ts +22 -0
  608. package/src/message-template/message-template-admin.service.spec.ts +163 -0
  609. package/src/message-template/message-template-admin.service.ts +239 -0
  610. package/src/message-template/message-template.controller.ts +52 -0
  611. package/src/message-template/message-template.module.ts +21 -0
  612. package/src/message-template/message-template.registry.spec.ts +62 -0
  613. package/src/message-template/message-template.registry.ts +125 -0
  614. package/src/message-template/message-template.service.spec.ts +149 -0
  615. package/src/message-template/message-template.service.ts +149 -0
  616. package/src/notification/notification.constants.ts +10 -0
  617. package/src/notification/notification.module.ts +3 -0
  618. package/src/notification/notification.service.spec.ts +75 -1
  619. package/src/notification/notification.service.ts +39 -1
  620. package/src/oauth/oauth.controller.ts +0 -1
  621. package/src/oauth/oauth.errors.ts +7 -0
  622. package/src/oauth/oauth.module.ts +6 -1
  623. package/src/oauth/oauth.service.spec.ts +58 -7
  624. package/src/oauth/oauth.service.ts +71 -32
  625. package/src/oauth/providers/abstract.provider.spec.ts +192 -0
  626. package/src/oauth/providers/abstract.provider.ts +46 -14
  627. package/src/oauth/providers/github.provider.ts +57 -34
  628. package/src/oauth/providers/microsoft-entra-id.provider.ts +8 -1
  629. package/src/observability/monitored-cron.spec.ts +164 -31
  630. package/src/observability/monitored-cron.ts +154 -62
  631. package/src/profile/dto/change-password.dto.ts +25 -7
  632. package/src/profile/profile.service.spec.ts +97 -0
  633. package/src/profile/profile.service.ts +9 -3
  634. package/src/realtime/realtime-tick.coalescer.spec.ts +92 -0
  635. package/src/realtime/realtime-tick.coalescer.ts +60 -0
  636. package/src/realtime/realtime.service.spec.ts +33 -0
  637. package/src/realtime/realtime.service.ts +28 -2
  638. package/src/redis/redis-kv.service.ts +261 -0
  639. package/src/redis/redis-master.spec.ts +111 -0
  640. package/src/redis/redis-master.ts +86 -0
  641. package/src/redis/redis-pubsub.ts +27 -3
  642. package/src/redis/redis.module.ts +17 -0
  643. package/src/session/session.service.spec.ts +121 -42
  644. package/src/session/session.service.ts +279 -82
  645. package/src/setting/setting.service.ts +44 -3
  646. package/src/task/task.service.spec.ts +41 -0
  647. package/src/task/task.service.ts +53 -13
  648. package/src/token/token.service.spec.ts +90 -0
  649. package/src/token/token.service.ts +48 -2
  650. package/src/user/user-credential.util.ts +14 -5
  651. package/src/user/user.service.ts +2 -12
  652. package/src/user/user.sort.ts +25 -0
  653. package/src/utils/abbreviate-name.spec.ts +50 -0
  654. package/src/utils/abbreviate-name.ts +44 -0
  655. package/src/utils/date-range-query.dto.ts +56 -0
  656. package/src/utils/date-range.spec.ts +175 -0
  657. package/src/utils/date-range.ts +246 -0
  658. package/src/webhook-integration/webhook-utils.spec.ts +67 -0
  659. package/src/webhook-integration/webhook-utils.ts +26 -0
  660. package/src/whatsapp-sender/whatsapp-recipients.spec.ts +89 -0
  661. package/src/whatsapp-sender/whatsapp-recipients.ts +83 -0
  662. package/src/whatsapp-sender/whatsapp-sender.service.spec.ts +112 -0
  663. package/src/whatsapp-sender/whatsapp-sender.service.ts +58 -5
  664. package/hedhog/query/device_pairing_request.sql +0 -46
  665. package/hedhog/query/impersonation_grant.sql +0 -71
  666. package/hedhog/query/oauth_authorize_pkce.sql +0 -58
  667. package/hedhog/query/oauth_mobile_state_token.sql +0 -30
  668. package/hedhog/query/oauth_web_ref_token.sql +0 -25
@@ -0,0 +1,149 @@
1
+ import {
2
+ clearMessageTemplateRegistry,
3
+ registerMessageTemplates,
4
+ } from './message-template.registry';
5
+ import { MessageTemplateService } from './message-template.service';
6
+
7
+ /**
8
+ * O que estes testes protegem: o aviso nunca depender do texto editado dar certo.
9
+ *
10
+ * Portados do SAC, onde a regra era "todo caminho ruim devolve null e o chamador
11
+ * usa o texto embutido". Aqui a regra ficou mais forte: todo caminho ruim cai no
12
+ * `fallback` do registry, e o chamador não precisa mais manter texto nenhum.
13
+ */
14
+ describe('MessageTemplateService', () => {
15
+ let prisma: any;
16
+ let service: MessageTemplateService;
17
+
18
+ const SLUG = 'demo.aviso';
19
+ const PADRAO = 'Padrão: {{protocol}}';
20
+
21
+ const linha = (body: string, overrides: Record<string, unknown> = {}) => ({
22
+ is_active: true,
23
+ message_template_locale: [{ body, locale: { code: 'pt' } }],
24
+ ...overrides,
25
+ });
26
+
27
+ beforeEach(() => {
28
+ clearMessageTemplateRegistry();
29
+ registerMessageTemplates([
30
+ {
31
+ slug: SLUG,
32
+ moduleSlug: 'demo',
33
+ name: { pt: 'Aviso' },
34
+ fallback: { pt: PADRAO, en: 'Default: {{protocol}}' },
35
+ variables: { protocol: { sample: '202609-000045' } },
36
+ },
37
+ ]);
38
+
39
+ prisma = { message_template: { findUnique: jest.fn().mockResolvedValue(null) } };
40
+ service = new MessageTemplateService(prisma);
41
+ });
42
+
43
+ it('renderiza o texto editado quando existe', async () => {
44
+ prisma.message_template.findUnique.mockResolvedValue(
45
+ linha('Chamado {{protocol}} de {{requester_name}}'),
46
+ );
47
+
48
+ await expect(
49
+ service.render(SLUG, {
50
+ protocol: '202609-000045',
51
+ requester_name: 'João Rangel',
52
+ }),
53
+ ).resolves.toBe('Chamado 202609-000045 de João Rangel');
54
+ });
55
+
56
+ it('não escapa o texto, que vai puro para o WhatsApp', async () => {
57
+ // Com escape de HTML um apóstrofo viraria `&#x27;` na tela do celular.
58
+ prisma.message_template.findUnique.mockResolvedValue(linha('{{nome}}'));
59
+
60
+ await expect(service.render(SLUG, { nome: "Joao D'Avila" })).resolves.toBe(
61
+ "Joao D'Avila",
62
+ );
63
+ });
64
+
65
+ it('esconde a seção quando o campo vem vazio', async () => {
66
+ prisma.message_template.findUnique.mockResolvedValue(
67
+ linha('A\n{{#if contact}}\nContato: {{contact}}\n{{/if}}\nB'),
68
+ );
69
+
70
+ await expect(service.render(SLUG, { contact: '' })).resolves.toBe('A\nB');
71
+ });
72
+
73
+ describe('cai no texto padrão quando o editado não serve', () => {
74
+ const esperado = 'Padrão: 202609-000045';
75
+ const variaveis = { protocol: '202609-000045' };
76
+
77
+ it('não há linha no banco — o caso comum, antes de alguém editar', async () => {
78
+ prisma.message_template.findUnique.mockResolvedValue(null);
79
+ await expect(service.render(SLUG, variaveis)).resolves.toBe(esperado);
80
+ });
81
+
82
+ it('a linha está desligada', async () => {
83
+ prisma.message_template.findUnique.mockResolvedValue(
84
+ linha('Editado', { is_active: false }),
85
+ );
86
+ await expect(service.render(SLUG, variaveis)).resolves.toBe(esperado);
87
+ });
88
+
89
+ it('o corpo editado está em branco', async () => {
90
+ prisma.message_template.findUnique.mockResolvedValue(linha(' '));
91
+ await expect(service.render(SLUG, variaveis)).resolves.toBe(esperado);
92
+ });
93
+
94
+ it('o corpo editado tem sintaxe quebrada', async () => {
95
+ prisma.message_template.findUnique.mockResolvedValue(
96
+ linha('{{#if contact}}sem fechar'),
97
+ );
98
+ await expect(service.render(SLUG, variaveis)).resolves.toBe(esperado);
99
+ });
100
+
101
+ it('o corpo editado renderiza vazio', async () => {
102
+ // Template só com blocos que não casaram. Mandar mensagem em branco para o
103
+ // grupo é pior que mandar o texto padrão.
104
+ prisma.message_template.findUnique.mockResolvedValue(
105
+ linha('{{#if nada}}oi{{/if}}'),
106
+ );
107
+ await expect(service.render(SLUG, variaveis)).resolves.toBe(esperado);
108
+ });
109
+
110
+ it('o banco está fora do ar', async () => {
111
+ prisma.message_template.findUnique.mockRejectedValue(new Error('sem conexão'));
112
+ await expect(service.render(SLUG, variaveis)).resolves.toBe(esperado);
113
+ });
114
+ });
115
+
116
+ it('sem tradução no idioma pedido, usa a primeira que existir', async () => {
117
+ // Um texto escrito só em português continua valendo para quem abriu o painel
118
+ // em inglês; o contrário seria a equipe receber o padrão por causa do idioma
119
+ // da sessão.
120
+ prisma.message_template.findUnique.mockResolvedValue(
121
+ linha('Só em português'),
122
+ );
123
+
124
+ await expect(service.render(SLUG, {}, 'en')).resolves.toBe('Só em português');
125
+ });
126
+
127
+ it('sem texto padrão no idioma pedido, usa o português', async () => {
128
+ clearMessageTemplateRegistry();
129
+ registerMessageTemplates([
130
+ {
131
+ slug: SLUG,
132
+ moduleSlug: 'demo',
133
+ name: { pt: 'Aviso' },
134
+ fallback: { pt: PADRAO },
135
+ variables: {},
136
+ },
137
+ ]);
138
+
139
+ await expect(service.render(SLUG, { protocol: 'X' }, 'en')).resolves.toBe(
140
+ 'Padrão: X',
141
+ );
142
+ });
143
+
144
+ it('devolve null só quando o slug não está registrado', async () => {
145
+ // Nulo aqui é erro de programação — slug digitado errado, library não
146
+ // carregada —, não configuração. Por isso é o único caso.
147
+ await expect(service.render('demo.inexistente', {})).resolves.toBeNull();
148
+ });
149
+ });
@@ -0,0 +1,149 @@
1
+ import { PrismaService } from '@hed-hog/api-prisma';
2
+ import { Inject, Injectable, Logger, forwardRef } from '@nestjs/common';
3
+ import * as Handlebars from 'handlebars';
4
+
5
+ import {
6
+ MessageTemplateDefinition,
7
+ getMessageTemplateDefinition,
8
+ } from './message-template.registry';
9
+
10
+ /**
11
+ * Idioma em que a plataforma escreve para a própria equipe.
12
+ *
13
+ * O aviso interno não é mensagem ao cliente: quem lê é quem trabalha aqui, e o
14
+ * fato gerador pode ter chegado em qualquer idioma. Por isso o corpo sai no
15
+ * idioma do painel, e não no de quem comprou ou abriu o chamado.
16
+ */
17
+ export const DEFAULT_MESSAGE_LOCALE = 'pt';
18
+
19
+ /**
20
+ * Renderiza o texto das mensagens que saem por canal que não é e-mail.
21
+ *
22
+ * O corpo é texto puro com o markdown do WhatsApp, e não HTML: não dá para
23
+ * reusar o `MailService`, cujo render troca quebra de linha por `<br/>` — o que
24
+ * no WhatsApp apareceria literal na tela.
25
+ *
26
+ * **Nunca devolve nulo para um slug registrado.** Linha ausente, `is_active`
27
+ * desligado, corpo em branco, sintaxe quebrada ou banco fora do ar caem no texto
28
+ * canônico do registry. Isso é o que permite ao chamador parar de manter um
29
+ * construtor de texto em código só como rede: a rede é o `fallback`.
30
+ */
31
+ @Injectable()
32
+ export class MessageTemplateService {
33
+ private readonly logger = new Logger(MessageTemplateService.name);
34
+
35
+ constructor(
36
+ @Inject(forwardRef(() => PrismaService))
37
+ private readonly prisma: PrismaService,
38
+ ) {}
39
+
40
+ /**
41
+ * O texto pronto, ou `null` quando o slug não está registrado.
42
+ *
43
+ * Nulo aqui é erro de programação (slug digitado errado, library não
44
+ * carregada), não configuração — daí ser o único caso.
45
+ */
46
+ async render(
47
+ slug: string,
48
+ variables: Record<string, unknown>,
49
+ locale = DEFAULT_MESSAGE_LOCALE,
50
+ ): Promise<string | null> {
51
+ const definition = getMessageTemplateDefinition(slug);
52
+
53
+ if (!definition) {
54
+ this.logger.error(
55
+ `Modelo de mensagem "${slug}" não está registrado; nada a renderizar.`,
56
+ );
57
+ return null;
58
+ }
59
+
60
+ const edited = await this.readEditedBody(slug, locale);
61
+
62
+ if (edited) {
63
+ const rendered = MessageTemplateService.compile(edited, variables);
64
+ if (rendered) return rendered;
65
+
66
+ // Texto editado que não compila ou renderiza vazio não pode calar o aviso.
67
+ this.logger.warn(
68
+ `O texto editado do modelo "${slug}" não pôde ser usado; caindo no padrão.`,
69
+ );
70
+ }
71
+
72
+ return MessageTemplateService.renderFallback(definition, variables, locale);
73
+ }
74
+
75
+ /**
76
+ * Renderiza o texto canônico do registry.
77
+ *
78
+ * Estático e público porque o teste que varre o registry inteiro o usa para
79
+ * afirmar que todo modelo registrado compila com as suas amostras — é ele que
80
+ * substitui a manutenção do texto em dois lugares.
81
+ */
82
+ static renderFallback(
83
+ definition: MessageTemplateDefinition,
84
+ variables: Record<string, unknown>,
85
+ locale = DEFAULT_MESSAGE_LOCALE,
86
+ ): string | null {
87
+ const body =
88
+ definition.fallback[locale] ?? definition.fallback[DEFAULT_MESSAGE_LOCALE];
89
+
90
+ return body ? MessageTemplateService.compile(body, variables) : null;
91
+ }
92
+
93
+ /**
94
+ * Compila e renderiza, ou `null` em qualquer desfecho ruim.
95
+ *
96
+ * `noEscape` de propósito: escapar encheria o WhatsApp de `&#x27;`. Template
97
+ * preenchido só com blocos que não casaram renderiza vazio, e mandar mensagem
98
+ * em branco para o grupo é pior que mandar o texto padrão.
99
+ */
100
+ private static compile(
101
+ body: string,
102
+ variables: Record<string, unknown>,
103
+ ): string | null {
104
+ try {
105
+ const rendered = Handlebars.compile(body, { noEscape: true })(variables).trim();
106
+ return rendered || null;
107
+ } catch {
108
+ return null;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * O corpo editado no painel, ou `null` quando não há nada utilizável.
114
+ *
115
+ * Sem linha no idioma pedido, usa a primeira que existir: um texto escrito só
116
+ * em português continua valendo para quem abriu o painel em inglês — o
117
+ * contrário seria a equipe receber o padrão por causa do idioma da sessão.
118
+ */
119
+ private async readEditedBody(
120
+ slug: string,
121
+ locale: string,
122
+ ): Promise<string | null> {
123
+ try {
124
+ const template = await (this.prisma as any).message_template.findUnique({
125
+ where: { slug },
126
+ select: {
127
+ is_active: true,
128
+ message_template_locale: {
129
+ select: { body: true, locale: { select: { code: true } } },
130
+ },
131
+ },
132
+ });
133
+
134
+ if (!template?.is_active) return null;
135
+
136
+ const rows = template.message_template_locale ?? [];
137
+ const match = rows.find((row: any) => row.locale?.code === locale) ?? rows[0];
138
+
139
+ return String(match?.body ?? '').trim() || null;
140
+ } catch (error) {
141
+ this.logger.warn(
142
+ `Não foi possível ler o modelo "${slug}": ${
143
+ (error as Error)?.message ?? 'erro desconhecido'
144
+ }`,
145
+ );
146
+ return null;
147
+ }
148
+ }
149
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Nome do evento de notificação no WebSocket (`/realtime`).
3
+ *
4
+ * Segue a convenção `dominio:evento` dos outros produtores (`presence:update`,
5
+ * `lms:waiting-room:tick`). O payload é o mesmo `NotificationStreamEvent` que o
6
+ * SSE já entrega — os dois transportes convivem por tempo indeterminado (o
7
+ * class-app publicado nas lojas só fala SSE), e transporte que carrega dado
8
+ * diferente faz o comportamento do cliente depender de qual dos dois está vivo.
9
+ */
10
+ export const NOTIFICATION_REALTIME_EVENT = 'notification:event';
@@ -1,6 +1,7 @@
1
1
  import { PaginationModule } from '@hed-hog/api-pagination';
2
2
  import { PrismaModule } from '@hed-hog/api-prisma';
3
3
  import { forwardRef, Module } from '@nestjs/common';
4
+ import { RealtimeModule } from '../realtime/realtime.module';
4
5
  import { NotificationController } from './notification.controller';
5
6
  import { NotificationService } from './notification.service';
6
7
 
@@ -8,6 +9,8 @@ import { NotificationService } from './notification.service';
8
9
  imports: [
9
10
  forwardRef(() => PrismaModule),
10
11
  forwardRef(() => PaginationModule),
12
+ // O funil de eventos empurra a notificação pelo WebSocket além do SSE.
13
+ forwardRef(() => RealtimeModule),
11
14
  ],
12
15
  controllers: [NotificationController],
13
16
  providers: [NotificationService],
@@ -4,6 +4,7 @@ import {
4
4
  ForbiddenException,
5
5
  NotFoundException,
6
6
  } from '@nestjs/common';
7
+ import { NOTIFICATION_REALTIME_EVENT } from './notification.constants';
7
8
  import { NotificationService } from './notification.service';
8
9
 
9
10
  const makeDeps = () => {
@@ -22,7 +23,8 @@ const makeDeps = () => {
22
23
  };
23
24
  const pagination = { paginate: jest.fn().mockResolvedValue({ data: [] }) };
24
25
  const eventEmitter = { emitAsync: jest.fn().mockResolvedValue([]) };
25
- return { prisma, pagination, eventEmitter };
26
+ const realtime = { emitToUser: jest.fn() };
27
+ return { prisma, pagination, eventEmitter, realtime };
26
28
  };
27
29
 
28
30
  const makeService = (deps = makeDeps()) => ({
@@ -30,6 +32,7 @@ const makeService = (deps = makeDeps()) => ({
30
32
  deps.prisma as any,
31
33
  deps.pagination as any,
32
34
  deps.eventEmitter as any,
35
+ deps.realtime as any,
33
36
  ),
34
37
  deps,
35
38
  });
@@ -240,6 +243,77 @@ describe('NotificationService', () => {
240
243
  });
241
244
  expect(received).toHaveLength(1);
242
245
  });
246
+
247
+ // Os dois transportes convivem: o SSE (EventEmitter + pg_notify) ainda
248
+ // serve o class-app publicado, e o socket serve os apps web. Este teste
249
+ // trava a coexistência — derrubar um dos três é o jeito mais fácil de
250
+ // quebrar notificação em produção sem nenhum erro aparecer.
251
+ it('entrega nos três canais: local, socket e pg_notify', async () => {
252
+ const { service, deps } = makeService();
253
+ const received: any[] = [];
254
+ (service as any).notificationEvents.on('notification:7', (e: any) =>
255
+ received.push(e),
256
+ );
257
+ const event = { type: 'notification.created', notificationId: 3 };
258
+
259
+ await (service as any).broadcastNotificationEvent(7, event);
260
+
261
+ expect(received).toEqual([event]);
262
+ expect(deps.realtime.emitToUser).toHaveBeenCalledWith(
263
+ 7,
264
+ NOTIFICATION_REALTIME_EVENT,
265
+ event,
266
+ );
267
+ expect(deps.prisma.$executeRaw).toHaveBeenCalled();
268
+ });
269
+
270
+ it('emit do socket falhando não impede o pg_notify', async () => {
271
+ const { service, deps } = makeService();
272
+ deps.realtime.emitToUser.mockImplementation(() => {
273
+ throw new Error('socket down');
274
+ });
275
+
276
+ await expect(
277
+ (service as any).broadcastNotificationEvent(7, {
278
+ type: 'notification.updated',
279
+ }),
280
+ ).resolves.toBeUndefined();
281
+ expect(deps.prisma.$executeRaw).toHaveBeenCalled();
282
+ });
283
+ });
284
+
285
+ describe('notifyRewardGranted', () => {
286
+ it('emite sinal sem payload para o usuário', async () => {
287
+ const { service } = makeService();
288
+ const received: any[] = [];
289
+ (service as any).notificationEvents.on('notification:9', (e: any) =>
290
+ received.push(e),
291
+ );
292
+
293
+ await service.notifyRewardGranted(9);
294
+
295
+ // Só o tipo: a recompensa mora em `lms_student_reward`, e quem ouve refaz
296
+ // o GET da própria fila. Mandar o conteúdo aqui abriria caminho para
297
+ // comemorar duas vezes entre a web e o app.
298
+ expect(received).toEqual([{ type: 'reward.granted' }]);
299
+ });
300
+
301
+ it('atravessa o cluster pelo pg_notify', async () => {
302
+ const { service, deps } = makeService();
303
+
304
+ await service.notifyRewardGranted(9);
305
+
306
+ // O desbloqueio acontece no worker de fila, um processo separado de quem
307
+ // segura a conexão SSE — sem esta publicação o aviso morria no pod errado.
308
+ expect(deps.prisma.$executeRaw).toHaveBeenCalled();
309
+ });
310
+
311
+ it('não derruba o chamador quando o broadcast falha', async () => {
312
+ const { service, deps } = makeService();
313
+ deps.prisma.$executeRaw.mockRejectedValue(new Error('down'));
314
+
315
+ await expect(service.notifyRewardGranted(9)).resolves.toBeUndefined();
316
+ });
243
317
  });
244
318
 
245
319
  describe('handleClusterNotification', () => {
@@ -16,8 +16,10 @@ import type { Request, Response } from 'express';
16
16
  import { randomUUID } from 'node:crypto';
17
17
  import { EventEmitter } from 'node:events';
18
18
  import { Client, type Notification as PgNotification } from 'pg';
19
+ import { RealtimeService } from '../realtime/realtime.service';
19
20
  import { CreateNotificationDto } from './dto/create-notification.dto';
20
21
  import { UpdateProgressDto } from './dto/update-progress.dto';
22
+ import { NOTIFICATION_REALTIME_EVENT } from './notification.constants';
21
23
  import {
22
24
  NOTIFICATION_STALE_PROGRESS_CHECK,
23
25
  NotificationStaleProgressCheckEvent,
@@ -26,7 +28,11 @@ import {
26
28
  type NotificationStreamEventType =
27
29
  | 'ready'
28
30
  | 'notification.created'
29
- | 'notification.updated';
31
+ | 'notification.updated'
32
+ // Sinal de "acorda e busca", sem relação com a lista de notificações: quem
33
+ // ouve refaz o GET da própria fila. Anda por aqui porque este é o único
34
+ // stream que os apps do aluno já mantêm aberto e que alcança todos os pods.
35
+ | 'reward.granted';
30
36
 
31
37
  type NotificationStreamEvent = {
32
38
  type: NotificationStreamEventType;
@@ -53,6 +59,8 @@ export class NotificationService implements OnModuleInit, OnModuleDestroy {
53
59
  @Inject(forwardRef(() => PaginationService))
54
60
  private readonly pagination: PaginationService,
55
61
  private readonly eventEmitter: EventEmitter2,
62
+ @Inject(forwardRef(() => RealtimeService))
63
+ private readonly realtime: RealtimeService,
56
64
  ) {
57
65
  this.notificationEvents.setMaxListeners(0);
58
66
  }
@@ -122,6 +130,19 @@ export class NotificationService implements OnModuleInit, OnModuleDestroy {
122
130
  await this.broadcastNotificationEvent(userId, { type: 'notification.updated' });
123
131
  }
124
132
 
133
+ /**
134
+ * Avisa que o usuário ganhou uma recompensa de gamificação, para o cliente
135
+ * buscar a fila dele.
136
+ *
137
+ * Sem payload de propósito: a recompensa mora em `lms_student_reward` com o
138
+ * `seen_at` como fonte da verdade — mandar o conteúdo aqui abriria caminho
139
+ * para comemorar duas vezes entre a web e o app, e engordaria o `pg_notify`,
140
+ * cujo teto de 8000 bytes falha calado (ver `broadcastNotificationEvent`).
141
+ */
142
+ async notifyRewardGranted(userId: number) {
143
+ await this.broadcastNotificationEvent(userId, { type: 'reward.granted' });
144
+ }
145
+
125
146
  async unreadCount(userId: number) {
126
147
  const count = await this.prisma.notification.count({
127
148
  where: { user_id: userId, status: 'unread' },
@@ -330,6 +351,23 @@ export class NotificationService implements OnModuleInit, OnModuleDestroy {
330
351
  ) {
331
352
  this.emitLocalNotificationEvent(userId, event);
332
353
 
354
+ // WebSocket, antes do `pg_notify` abaixo: o emit é síncrono e o
355
+ // `$executeRaw` é aguardado, então empurrar primeiro tira o socket da
356
+ // latência do Postgres. Vai por `emitToUser` — a sala `user:{id}` só é
357
+ // entrada com o `sub` do JWT verificado, e o `subscribe` do gateway monta
358
+ // salas com o prefixo literal `channel:`, então ela não é assinável de
359
+ // fora. É o que torna seguro mandar a notificação inteira aqui; por
360
+ // `emitToChannel` o título e o corpo vazariam para qualquer conta.
361
+ //
362
+ // O try/catch existe porque este é o primeiro call-site de `emitToUser` em
363
+ // produção: um throw derrubaria `create`, `markRead` e o resto do funil, e
364
+ // a entrega pelo SSE (acima) já aconteceu.
365
+ try {
366
+ this.realtime.emitToUser(userId, NOTIFICATION_REALTIME_EVENT, event);
367
+ } catch (error) {
368
+ this.logger.warn('Failed to push notification over realtime', error as any);
369
+ }
370
+
333
371
  const payload: ClusterNotificationPayload = {
334
372
  ...event,
335
373
  userId,
@@ -290,7 +290,6 @@ export class OAuthController {
290
290
  state,
291
291
  type: 'login',
292
292
  redirectUri,
293
- includeRefreshTokenInBody: Boolean(redirectUri),
294
293
  requestOrigin: origin,
295
294
  requestReferer: referer,
296
295
  });
@@ -11,6 +11,13 @@ export class OAuthProviderException extends Error {
11
11
  public readonly status?: number,
12
12
  public readonly providerError?: string,
13
13
  public readonly providerErrorCode?: string,
14
+ /**
15
+ * Erro original do provider (tipicamente um AxiosError). Declarado como
16
+ * propriedade em vez de `super(message, { cause })` porque a library compila
17
+ * com `lib: es2021`, onde `ErrorOptions` ainda não existe — o que importa é a
18
+ * propriedade em runtime, que é o que o `linkedErrors` do Sentry encadeia.
19
+ */
20
+ public readonly cause?: unknown,
14
21
  ) {
15
22
  super(message);
16
23
  this.name = 'OAuthProviderException';
@@ -23,7 +23,12 @@ import { MicrosoftProvider } from './providers/microsoft.provider';
23
23
 
24
24
  @Module({
25
25
  imports: [
26
- forwardRef(() => HttpModule),
26
+ // O default do axios é `timeout: 0` — espera indefinidamente. Como a troca do
27
+ // código roda dentro da transação de 60s do OAuthCallbackCoordinatorService,
28
+ // uma conexão pendurada com o provider prendia uma conexão do pool até a
29
+ // transação estourar. 10s é folgado para um endpoint de token e falha como
30
+ // ECONNABORTED, que o mapProviderError classifica.
31
+ HttpModule.register({ timeout: 10_000, maxRedirects: 5 }),
27
32
  forwardRef(() => PrismaModule),
28
33
  forwardRef(() => MailSendModule),
29
34
  forwardRef(() => ConfigModule),
@@ -224,15 +224,13 @@ describe('OAuthService', () => {
224
224
  service = makeService().service;
225
225
  });
226
226
 
227
- it('inclui refresh quando solicitado', () => {
228
- expect((service as any).formatAuthResponse('a', 'r', true)).toEqual({
229
- accessToken: 'a',
230
- refreshToken: 'r',
231
- });
232
- });
233
- it('omite refresh por padrão', () => {
227
+ // O corpo carrega o par em TODO fluxo, web inclusive: o Class fala com a API
228
+ // por rewrite same-origin e nunca chega a ter o cookie `rt`, então omitir o
229
+ // refresh token aqui deixava o aluno sem nada para renovar.
230
+ it('inclui o refresh token', () => {
234
231
  expect((service as any).formatAuthResponse('a', 'r')).toEqual({
235
232
  accessToken: 'a',
233
+ refreshToken: 'r',
236
234
  });
237
235
  });
238
236
  });
@@ -288,6 +286,59 @@ describe('OAuthService', () => {
288
286
  it('mapeia erro genérico para ServiceUnavailable', () => {
289
287
  expect(map(new Error('boom'))).toBeInstanceOf(ServiceUnavailableException);
290
288
  });
289
+
290
+ // O frontend precisa reconhecer "código já usado" sem depender do idioma da
291
+ // mensagem — o match por substring só funcionava em inglês.
292
+ it.each([
293
+ ['callback_consumed', 'callback_consumed'],
294
+ ['invalid_callback', 'invalid_callback'],
295
+ ])('expõe oauthReason=%s no corpo do 400', (reason, expected) => {
296
+ const error = map(
297
+ new OAuthProviderException('google', reason as any, 'msg'),
298
+ ) as BadRequestException;
299
+
300
+ expect((error.getResponse() as any).oauthReason).toBe(expected);
301
+ });
302
+
303
+ it('expõe oauthReason=already_processed no callback repetido', () => {
304
+ const error = map(new OAuthCallbackAlreadyProcessedError()) as BadRequestException;
305
+
306
+ expect((error.getResponse() as any).oauthReason).toBe('already_processed');
307
+ });
308
+
309
+ it('mantém o envelope do 400 (statusCode/message/error)', () => {
310
+ const error = map(
311
+ new OAuthProviderException('google', 'invalid_callback', 'msg'),
312
+ ) as BadRequestException;
313
+ const body = error.getResponse() as any;
314
+
315
+ expect(body.statusCode).toBe(400);
316
+ expect(body.error).toBe('Bad Request');
317
+ expect(typeof body.message).toBe('string');
318
+ });
319
+
320
+ // Sem a causa encadeada o evento no Sentry chega sem status, sem corpo do
321
+ // provider e com o stack enraizado no próprio mapCallbackError.
322
+ it('preserva o erro original como cause nos dois ramos de 503', () => {
323
+ const generic = new Error('boom');
324
+ expect(map(generic).cause).toBe(generic);
325
+
326
+ const upstream = new OAuthProviderException('google', 'upstream_failure', 'msg', 500);
327
+ expect(map(upstream).cause).toBe(upstream);
328
+ });
329
+
330
+ // O Nest só aplica a description default quando o segundo argumento é ausente
331
+ // ou string, então passar `{ cause }` sozinho zeraria o campo `error`.
332
+ it.each([
333
+ ['genérico', new Error('boom')],
334
+ ['upstream', new OAuthProviderException('google', 'upstream_failure', 'msg', 500)],
335
+ ])('mantém o envelope do 503 no ramo %s', (_label, input) => {
336
+ const body = (map(input) as ServiceUnavailableException).getResponse() as any;
337
+
338
+ expect(body.statusCode).toBe(503);
339
+ expect(body.error).toBe('Service Unavailable');
340
+ expect(typeof body.message).toBe('string');
341
+ });
291
342
  });
292
343
 
293
344
  describe('consumeMobileState', () => {