@hed-hog/core 0.0.399 → 0.0.401

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 (815) 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 +6 -4
  6. package/dist/ai/ai.controller.d.ts.map +1 -1
  7. package/dist/ai/ai.service.d.ts +121 -6
  8. package/dist/ai/ai.service.d.ts.map +1 -1
  9. package/dist/ai/ai.service.js +355 -160
  10. package/dist/ai/ai.service.js.map +1 -1
  11. package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
  12. package/dist/ai-instruction/ai-instruction.service.js +26 -23
  13. package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
  14. package/dist/ai-instruction/ai-instruction.sort.d.ts +16 -0
  15. package/dist/ai-instruction/ai-instruction.sort.d.ts.map +1 -0
  16. package/dist/ai-instruction/ai-instruction.sort.js +32 -0
  17. package/dist/ai-instruction/ai-instruction.sort.js.map +1 -0
  18. package/dist/ai-instruction/ai-prompt-resolver.service.d.ts +12 -0
  19. package/dist/ai-instruction/ai-prompt-resolver.service.d.ts.map +1 -1
  20. package/dist/ai-instruction/ai-prompt-resolver.service.js +26 -0
  21. package/dist/ai-instruction/ai-prompt-resolver.service.js.map +1 -1
  22. package/dist/auth/auth.controller.d.ts +24 -8
  23. package/dist/auth/auth.controller.d.ts.map +1 -1
  24. package/dist/auth/auth.module.d.ts.map +1 -1
  25. package/dist/auth/auth.module.js +8 -1
  26. package/dist/auth/auth.module.js.map +1 -1
  27. package/dist/auth/auth.service.d.ts +72 -25
  28. package/dist/auth/auth.service.d.ts.map +1 -1
  29. package/dist/auth/auth.service.js +41 -4
  30. package/dist/auth/auth.service.js.map +1 -1
  31. package/dist/auth/guards/auth.guard.d.ts +3 -1
  32. package/dist/auth/guards/auth.guard.d.ts.map +1 -1
  33. package/dist/auth/guards/auth.guard.js +12 -3
  34. package/dist/auth/guards/auth.guard.js.map +1 -1
  35. package/dist/authorize/authorize.controller.d.ts +29 -5
  36. package/dist/authorize/authorize.controller.d.ts.map +1 -1
  37. package/dist/authorize/authorize.controller.js +120 -13
  38. package/dist/authorize/authorize.controller.js.map +1 -1
  39. package/dist/authorize/authorize.errors.d.ts +34 -0
  40. package/dist/authorize/authorize.errors.d.ts.map +1 -0
  41. package/dist/authorize/authorize.errors.js +37 -0
  42. package/dist/authorize/authorize.errors.js.map +1 -0
  43. package/dist/authorize/authorize.module.d.ts.map +1 -1
  44. package/dist/authorize/authorize.module.js +6 -1
  45. package/dist/authorize/authorize.module.js.map +1 -1
  46. package/dist/authorize/authorize.service.d.ts +77 -3
  47. package/dist/authorize/authorize.service.d.ts.map +1 -1
  48. package/dist/authorize/authorize.service.js +212 -21
  49. package/dist/authorize/authorize.service.js.map +1 -1
  50. package/dist/authorize/dto/authorize-info.dto.d.ts +10 -1
  51. package/dist/authorize/dto/authorize-info.dto.d.ts.map +1 -1
  52. package/dist/authorize/dto/authorize-info.dto.js +16 -1
  53. package/dist/authorize/dto/authorize-info.dto.js.map +1 -1
  54. package/dist/authorize/dto/consent.dto.d.ts +10 -1
  55. package/dist/authorize/dto/consent.dto.d.ts.map +1 -1
  56. package/dist/authorize/dto/consent.dto.js +16 -1
  57. package/dist/authorize/dto/consent.dto.js.map +1 -1
  58. package/dist/authorize/dto/token.dto.d.ts +12 -0
  59. package/dist/authorize/dto/token.dto.d.ts.map +1 -1
  60. package/dist/authorize/dto/token.dto.js +21 -1
  61. package/dist/authorize/dto/token.dto.js.map +1 -1
  62. package/dist/authorize/oauth-exception.filter.d.ts +17 -0
  63. package/dist/authorize/oauth-exception.filter.d.ts.map +1 -0
  64. package/dist/authorize/oauth-exception.filter.js +54 -0
  65. package/dist/authorize/oauth-exception.filter.js.map +1 -0
  66. package/dist/authorize/oauth-metadata.service.d.ts +39 -0
  67. package/dist/authorize/oauth-metadata.service.d.ts.map +1 -0
  68. package/dist/authorize/oauth-metadata.service.js +81 -0
  69. package/dist/authorize/oauth-metadata.service.js.map +1 -0
  70. package/dist/authorize/well-known.controller.d.ts +67 -0
  71. package/dist/authorize/well-known.controller.d.ts.map +1 -0
  72. package/dist/authorize/well-known.controller.js +126 -0
  73. package/dist/authorize/well-known.controller.js.map +1 -0
  74. package/dist/captcha/captcha.service.d.ts +32 -2
  75. package/dist/captcha/captcha.service.d.ts.map +1 -1
  76. package/dist/captcha/captcha.service.js +85 -12
  77. package/dist/captcha/captcha.service.js.map +1 -1
  78. package/dist/challenge/challenge.service.d.ts +2 -2
  79. package/dist/core.module.d.ts.map +1 -1
  80. package/dist/core.module.js +9 -0
  81. package/dist/core.module.js.map +1 -1
  82. package/dist/dashboard/dashboard/dashboard.controller.d.ts +9 -9
  83. package/dist/dashboard/dashboard/dashboard.service.d.ts +9 -9
  84. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +3 -3
  85. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +3 -3
  86. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +3 -3
  87. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +3 -3
  88. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts.map +1 -1
  89. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js +2 -4
  90. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.js.map +1 -1
  91. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts +8 -0
  92. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.d.ts.map +1 -0
  93. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js +18 -0
  94. package/dist/dashboard/dashboard-component-role/dashboard-component-role.sort.js.map +1 -0
  95. package/dist/dashboard/dashboard-item/dashboard-item.service.d.ts.map +1 -1
  96. package/dist/dashboard/dashboard-item/dashboard-item.service.js +2 -4
  97. package/dist/dashboard/dashboard-item/dashboard-item.service.js.map +1 -1
  98. package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts +9 -0
  99. package/dist/dashboard/dashboard-item/dashboard-item.sort.d.ts.map +1 -0
  100. package/dist/dashboard/dashboard-item/dashboard-item.sort.js +19 -0
  101. package/dist/dashboard/dashboard-item/dashboard-item.sort.js.map +1 -0
  102. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +3 -3
  103. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +3 -3
  104. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts.map +1 -1
  105. package/dist/dashboard/dashboard-role/dashboard-role.service.js +2 -4
  106. package/dist/dashboard/dashboard-role/dashboard-role.service.js.map +1 -1
  107. package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts +8 -0
  108. package/dist/dashboard/dashboard-role/dashboard-role.sort.d.ts.map +1 -0
  109. package/dist/dashboard/dashboard-role/dashboard-role.sort.js +16 -0
  110. package/dist/dashboard/dashboard-role/dashboard-role.sort.js.map +1 -0
  111. package/dist/document-kit/document-kit.module.d.ts +3 -0
  112. package/dist/document-kit/document-kit.module.d.ts.map +1 -0
  113. package/dist/document-kit/document-kit.module.js +24 -0
  114. package/dist/document-kit/document-kit.module.js.map +1 -0
  115. package/dist/document-kit/document-kit.registry.d.ts +55 -0
  116. package/dist/document-kit/document-kit.registry.d.ts.map +1 -0
  117. package/dist/document-kit/document-kit.registry.js +91 -0
  118. package/dist/document-kit/document-kit.registry.js.map +1 -0
  119. package/dist/document-kit/document-kit.service.d.ts +49 -0
  120. package/dist/document-kit/document-kit.service.d.ts.map +1 -0
  121. package/dist/document-kit/document-kit.service.js +135 -0
  122. package/dist/document-kit/document-kit.service.js.map +1 -0
  123. package/dist/file/file-upload-ticket.service.d.ts +160 -0
  124. package/dist/file/file-upload-ticket.service.d.ts.map +1 -0
  125. package/dist/file/file-upload-ticket.service.js +382 -0
  126. package/dist/file/file-upload-ticket.service.js.map +1 -0
  127. package/dist/file/file.controller.d.ts +24 -1
  128. package/dist/file/file.controller.d.ts.map +1 -1
  129. package/dist/file/file.controller.js +63 -2
  130. package/dist/file/file.controller.js.map +1 -1
  131. package/dist/file/file.module.d.ts.map +1 -1
  132. package/dist/file/file.module.js +14 -2
  133. package/dist/file/file.module.js.map +1 -1
  134. package/dist/file/file.service.d.ts +197 -7
  135. package/dist/file/file.service.d.ts.map +1 -1
  136. package/dist/file/file.service.js +438 -78
  137. package/dist/file/file.service.js.map +1 -1
  138. package/dist/file/filename-encoding.util.d.ts +24 -0
  139. package/dist/file/filename-encoding.util.d.ts.map +1 -0
  140. package/dist/file/filename-encoding.util.js +63 -0
  141. package/dist/file/filename-encoding.util.js.map +1 -0
  142. package/dist/file/image-optimization.service.d.ts +27 -0
  143. package/dist/file/image-optimization.service.d.ts.map +1 -1
  144. package/dist/file/image-optimization.service.js +63 -14
  145. package/dist/file/image-optimization.service.js.map +1 -1
  146. package/dist/file/mcp-file-source.schema.d.ts +33 -0
  147. package/dist/file/mcp-file-source.schema.d.ts.map +1 -0
  148. package/dist/file/mcp-file-source.schema.js +78 -0
  149. package/dist/file/mcp-file-source.schema.js.map +1 -0
  150. package/dist/file/mcp-file-source.service.d.ts +124 -0
  151. package/dist/file/mcp-file-source.service.d.ts.map +1 -0
  152. package/dist/file/mcp-file-source.service.js +262 -0
  153. package/dist/file/mcp-file-source.service.js.map +1 -0
  154. package/dist/file/mimetype-sniff.util.d.ts +62 -0
  155. package/dist/file/mimetype-sniff.util.d.ts.map +1 -0
  156. package/dist/file/mimetype-sniff.util.js +226 -0
  157. package/dist/file/mimetype-sniff.util.js.map +1 -0
  158. package/dist/file/remote-fetch.util.d.ts +35 -0
  159. package/dist/file/remote-fetch.util.d.ts.map +1 -0
  160. package/dist/file/remote-fetch.util.js +236 -0
  161. package/dist/file/remote-fetch.util.js.map +1 -0
  162. package/dist/impersonation/dto/start-impersonation.dto.d.ts +4 -1
  163. package/dist/impersonation/dto/start-impersonation.dto.d.ts.map +1 -1
  164. package/dist/impersonation/dto/start-impersonation.dto.js +1 -1
  165. package/dist/impersonation/dto/start-impersonation.dto.js.map +1 -1
  166. package/dist/impersonation/impersonation.service.d.ts +8 -3
  167. package/dist/impersonation/impersonation.service.d.ts.map +1 -1
  168. package/dist/impersonation/impersonation.service.js +14 -4
  169. package/dist/impersonation/impersonation.service.js.map +1 -1
  170. package/dist/incident/incident.controller.d.ts +2 -1
  171. package/dist/incident/incident.controller.d.ts.map +1 -1
  172. package/dist/incident/incident.controller.js +10 -6
  173. package/dist/incident/incident.controller.js.map +1 -1
  174. package/dist/incident/incident.service.d.ts +2 -0
  175. package/dist/incident/incident.service.d.ts.map +1 -1
  176. package/dist/incident/incident.service.js +4 -0
  177. package/dist/incident/incident.service.js.map +1 -1
  178. package/dist/index.d.ts +22 -0
  179. package/dist/index.d.ts.map +1 -1
  180. package/dist/index.js +22 -0
  181. package/dist/index.js.map +1 -1
  182. package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
  183. package/dist/integration-profile/integration-profile.secrets.js +28 -0
  184. package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
  185. package/dist/integration-profile/integration-profile.service.d.ts +0 -13
  186. package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
  187. package/dist/integration-profile/integration-profile.service.js +5 -40
  188. package/dist/integration-profile/integration-profile.service.js.map +1 -1
  189. package/dist/integration-profile/integration-profile.utils.js +5 -5
  190. package/dist/integration-profile/integration-profile.utils.js.map +1 -1
  191. package/dist/integration-profile/testers/ai.testers.d.ts.map +1 -1
  192. package/dist/integration-profile/testers/ai.testers.js +46 -8
  193. package/dist/integration-profile/testers/ai.testers.js.map +1 -1
  194. package/dist/integration-profile/testers/index.d.ts.map +1 -1
  195. package/dist/integration-profile/testers/index.js +2 -0
  196. package/dist/integration-profile/testers/index.js.map +1 -1
  197. package/dist/integration-profile/testers/shipping.testers.d.ts +3 -0
  198. package/dist/integration-profile/testers/shipping.testers.d.ts.map +1 -0
  199. package/dist/integration-profile/testers/shipping.testers.js +71 -0
  200. package/dist/integration-profile/testers/shipping.testers.js.map +1 -0
  201. package/dist/locale/locale.controller.d.ts +1 -1
  202. package/dist/locale/locale.service.d.ts +1 -1
  203. package/dist/mail/dto/send.dto.d.ts +6 -1
  204. package/dist/mail/dto/send.dto.d.ts.map +1 -1
  205. package/dist/mail/dto/send.dto.js.map +1 -1
  206. package/dist/mail/mail.service.d.ts +9 -0
  207. package/dist/mail/mail.service.d.ts.map +1 -1
  208. package/dist/mail/mail.service.js +34 -14
  209. package/dist/mail/mail.service.js.map +1 -1
  210. package/dist/mail-sent/mail-sent.controller.d.ts +1 -1
  211. package/dist/mail-sent/mail-sent.service.d.ts +1 -1
  212. package/dist/mail-sent/mail-sent.service.d.ts.map +1 -1
  213. package/dist/mail-sent/mail-sent.service.js +2 -1
  214. package/dist/mail-sent/mail-sent.service.js.map +1 -1
  215. package/dist/mail-sent/mail-sent.sort.d.ts +9 -0
  216. package/dist/mail-sent/mail-sent.sort.d.ts.map +1 -0
  217. package/dist/mail-sent/mail-sent.sort.js +19 -0
  218. package/dist/mail-sent/mail-sent.sort.js.map +1 -0
  219. package/dist/mcp/filters/mcp-challenge.filter.d.ts +20 -0
  220. package/dist/mcp/filters/mcp-challenge.filter.d.ts.map +1 -0
  221. package/dist/mcp/filters/mcp-challenge.filter.js +69 -0
  222. package/dist/mcp/filters/mcp-challenge.filter.js.map +1 -0
  223. package/dist/mcp/guards/mcp-auth.guard.d.ts +4 -1
  224. package/dist/mcp/guards/mcp-auth.guard.d.ts.map +1 -1
  225. package/dist/mcp/guards/mcp-auth.guard.js +19 -5
  226. package/dist/mcp/guards/mcp-auth.guard.js.map +1 -1
  227. package/dist/mcp/guards/mcp-permission.guard.d.ts +25 -3
  228. package/dist/mcp/guards/mcp-permission.guard.d.ts.map +1 -1
  229. package/dist/mcp/guards/mcp-permission.guard.js +46 -26
  230. package/dist/mcp/guards/mcp-permission.guard.js.map +1 -1
  231. package/dist/mcp/mcp-audit.service.d.ts +17 -0
  232. package/dist/mcp/mcp-audit.service.d.ts.map +1 -1
  233. package/dist/mcp/mcp-audit.service.js +32 -3
  234. package/dist/mcp/mcp-audit.service.js.map +1 -1
  235. package/dist/mcp/mcp-permission.service.d.ts +64 -0
  236. package/dist/mcp/mcp-permission.service.d.ts.map +1 -0
  237. package/dist/mcp/mcp-permission.service.js +178 -0
  238. package/dist/mcp/mcp-permission.service.js.map +1 -0
  239. package/dist/mcp/mcp-server.service.d.ts +3 -1
  240. package/dist/mcp/mcp-server.service.d.ts.map +1 -1
  241. package/dist/mcp/mcp-server.service.js +36 -15
  242. package/dist/mcp/mcp-server.service.js.map +1 -1
  243. package/dist/mcp/mcp.controller.d.ts.map +1 -1
  244. package/dist/mcp/mcp.controller.js +10 -2
  245. package/dist/mcp/mcp.controller.js.map +1 -1
  246. package/dist/mcp/mcp.module.d.ts.map +1 -1
  247. package/dist/mcp/mcp.module.js +7 -1
  248. package/dist/mcp/mcp.module.js.map +1 -1
  249. package/dist/mcp/tools/core-access-log.mcp-tools.d.ts +17 -0
  250. package/dist/mcp/tools/core-access-log.mcp-tools.d.ts.map +1 -0
  251. package/dist/mcp/tools/core-access-log.mcp-tools.js +74 -0
  252. package/dist/mcp/tools/core-access-log.mcp-tools.js.map +1 -0
  253. package/dist/mcp/tools/core-ai.mcp-tools.js +2 -9
  254. package/dist/mcp/tools/core-ai.mcp-tools.js.map +1 -1
  255. package/dist/mcp/tools/core-dashboard-items.mcp-tools.js +1 -1
  256. package/dist/mcp/tools/core-dashboard-items.mcp-tools.js.map +1 -1
  257. package/dist/mcp/tools/core-dashboard.mcp-tools.js +2 -9
  258. package/dist/mcp/tools/core-dashboard.mcp-tools.js.map +1 -1
  259. package/dist/mcp/tools/core-event-webhooks.mcp-tools.d.ts.map +1 -1
  260. package/dist/mcp/tools/core-event-webhooks.mcp-tools.js +2 -10
  261. package/dist/mcp/tools/core-event-webhooks.mcp-tools.js.map +1 -1
  262. package/dist/mcp/tools/core-files.mcp-tools.d.ts +17 -5
  263. package/dist/mcp/tools/core-files.mcp-tools.d.ts.map +1 -1
  264. package/dist/mcp/tools/core-files.mcp-tools.js +186 -24
  265. package/dist/mcp/tools/core-files.mcp-tools.js.map +1 -1
  266. package/dist/mcp/tools/core-integration-events.mcp-tools.js +2 -9
  267. package/dist/mcp/tools/core-integration-events.mcp-tools.js.map +1 -1
  268. package/dist/mcp/tools/core-mail-sent.mcp-tools.js +2 -14
  269. package/dist/mcp/tools/core-mail-sent.mcp-tools.js.map +1 -1
  270. package/dist/mcp/tools/core-mail.mcp-tools.js +2 -9
  271. package/dist/mcp/tools/core-mail.mcp-tools.js.map +1 -1
  272. package/dist/mcp/tools/core-menus.mcp-tools.d.ts.map +1 -1
  273. package/dist/mcp/tools/core-menus.mcp-tools.js +2 -10
  274. package/dist/mcp/tools/core-menus.mcp-tools.js.map +1 -1
  275. package/dist/mcp/tools/core-notifications.mcp-tools.d.ts.map +1 -1
  276. package/dist/mcp/tools/core-notifications.mcp-tools.js +0 -1
  277. package/dist/mcp/tools/core-notifications.mcp-tools.js.map +1 -1
  278. package/dist/mcp/tools/core-roles.mcp-tools.d.ts.map +1 -1
  279. package/dist/mcp/tools/core-roles.mcp-tools.js +2 -13
  280. package/dist/mcp/tools/core-roles.mcp-tools.js.map +1 -1
  281. package/dist/mcp/tools/core-routes.mcp-tools.d.ts.map +1 -1
  282. package/dist/mcp/tools/core-routes.mcp-tools.js +2 -11
  283. package/dist/mcp/tools/core-routes.mcp-tools.js.map +1 -1
  284. package/dist/mcp/tools/core-screens.mcp-tools.d.ts.map +1 -1
  285. package/dist/mcp/tools/core-screens.mcp-tools.js +2 -11
  286. package/dist/mcp/tools/core-screens.mcp-tools.js.map +1 -1
  287. package/dist/mcp/tools/core-sessions.mcp-tools.d.ts.map +1 -1
  288. package/dist/mcp/tools/core-sessions.mcp-tools.js +0 -2
  289. package/dist/mcp/tools/core-sessions.mcp-tools.js.map +1 -1
  290. package/dist/mcp/tools/core-settings.mcp-tools.d.ts.map +1 -1
  291. package/dist/mcp/tools/core-settings.mcp-tools.js +2 -10
  292. package/dist/mcp/tools/core-settings.mcp-tools.js.map +1 -1
  293. package/dist/mcp/tools/core-users.mcp-tools.js +2 -9
  294. package/dist/mcp/tools/core-users.mcp-tools.js.map +1 -1
  295. package/dist/mcp/tools/core-webhooks.mcp-tools.d.ts.map +1 -1
  296. package/dist/mcp/tools/core-webhooks.mcp-tools.js +2 -10
  297. package/dist/mcp/tools/core-webhooks.mcp-tools.js.map +1 -1
  298. package/dist/mcp/types/mcp-context.type.d.ts +9 -0
  299. package/dist/mcp/types/mcp-context.type.d.ts.map +1 -1
  300. package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
  301. package/dist/mcp-chat/mcp-chat.service.js +8 -0
  302. package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
  303. package/dist/meeting/meeting-provider.registry.d.ts +187 -0
  304. package/dist/meeting/meeting-provider.registry.d.ts.map +1 -1
  305. package/dist/meeting/meeting-provider.registry.js.map +1 -1
  306. package/dist/meeting/meeting.constants.d.ts +70 -0
  307. package/dist/meeting/meeting.constants.d.ts.map +1 -1
  308. package/dist/meeting/meeting.constants.js +9 -1
  309. package/dist/meeting/meeting.constants.js.map +1 -1
  310. package/dist/menu/menu.service.d.ts.map +1 -1
  311. package/dist/menu/menu.service.js +29 -9
  312. package/dist/menu/menu.service.js.map +1 -1
  313. package/dist/message-template/dto/update-message-template.dto.d.ts +18 -0
  314. package/dist/message-template/dto/update-message-template.dto.d.ts.map +1 -0
  315. package/dist/message-template/dto/update-message-template.dto.js +38 -0
  316. package/dist/message-template/dto/update-message-template.dto.js.map +1 -0
  317. package/dist/message-template/message-template-admin.service.d.ts +70 -0
  318. package/dist/message-template/message-template-admin.service.d.ts.map +1 -0
  319. package/dist/message-template/message-template-admin.service.js +226 -0
  320. package/dist/message-template/message-template-admin.service.js.map +1 -0
  321. package/dist/message-template/message-template.controller.d.ts +29 -0
  322. package/dist/message-template/message-template.controller.d.ts.map +1 -0
  323. package/dist/message-template/message-template.controller.js +101 -0
  324. package/dist/message-template/message-template.controller.js.map +1 -0
  325. package/dist/message-template/message-template.module.d.ts +10 -0
  326. package/dist/message-template/message-template.module.d.ts.map +1 -0
  327. package/dist/message-template/message-template.module.js +33 -0
  328. package/dist/message-template/message-template.module.js.map +1 -0
  329. package/dist/message-template/message-template.registry.d.ts +55 -0
  330. package/dist/message-template/message-template.registry.d.ts.map +1 -0
  331. package/dist/message-template/message-template.registry.js +64 -0
  332. package/dist/message-template/message-template.registry.js.map +1 -0
  333. package/dist/message-template/message-template.service.d.ts +59 -0
  334. package/dist/message-template/message-template.service.d.ts.map +1 -0
  335. package/dist/message-template/message-template.service.js +166 -0
  336. package/dist/message-template/message-template.service.js.map +1 -0
  337. package/dist/notification/notification.constants.d.ts +11 -0
  338. package/dist/notification/notification.constants.d.ts.map +1 -0
  339. package/dist/notification/notification.constants.js +14 -0
  340. package/dist/notification/notification.constants.js.map +1 -0
  341. package/dist/notification/notification.controller.d.ts +20 -20
  342. package/dist/notification/notification.module.d.ts.map +1 -1
  343. package/dist/notification/notification.module.js +3 -0
  344. package/dist/notification/notification.module.js.map +1 -1
  345. package/dist/notification/notification.service.d.ts +33 -21
  346. package/dist/notification/notification.service.d.ts.map +1 -1
  347. package/dist/notification/notification.service.js +36 -2
  348. package/dist/notification/notification.service.js.map +1 -1
  349. package/dist/oauth/oauth-token-broker.service.d.ts +50 -1
  350. package/dist/oauth/oauth-token-broker.service.d.ts.map +1 -1
  351. package/dist/oauth/oauth-token-broker.service.js +105 -3
  352. package/dist/oauth/oauth-token-broker.service.js.map +1 -1
  353. package/dist/oauth/oauth.controller.d.ts +4 -6
  354. package/dist/oauth/oauth.controller.d.ts.map +1 -1
  355. package/dist/oauth/oauth.controller.js +0 -1
  356. package/dist/oauth/oauth.controller.js.map +1 -1
  357. package/dist/oauth/oauth.errors.d.ts +15 -1
  358. package/dist/oauth/oauth.errors.d.ts.map +1 -1
  359. package/dist/oauth/oauth.errors.js +9 -1
  360. package/dist/oauth/oauth.errors.js.map +1 -1
  361. package/dist/oauth/oauth.module.d.ts.map +1 -1
  362. package/dist/oauth/oauth.module.js +6 -1
  363. package/dist/oauth/oauth.module.js.map +1 -1
  364. package/dist/oauth/oauth.service.d.ts +25 -5
  365. package/dist/oauth/oauth.service.d.ts.map +1 -1
  366. package/dist/oauth/oauth.service.js +63 -27
  367. package/dist/oauth/oauth.service.js.map +1 -1
  368. package/dist/oauth/providers/abstract.provider.d.ts +10 -0
  369. package/dist/oauth/providers/abstract.provider.d.ts.map +1 -1
  370. package/dist/oauth/providers/abstract.provider.js +39 -12
  371. package/dist/oauth/providers/abstract.provider.js.map +1 -1
  372. package/dist/oauth/providers/github.provider.d.ts +1 -1
  373. package/dist/oauth/providers/github.provider.d.ts.map +1 -1
  374. package/dist/oauth/providers/github.provider.js +48 -22
  375. package/dist/oauth/providers/github.provider.js.map +1 -1
  376. package/dist/oauth/providers/microsoft-entra-id.provider.d.ts +6 -0
  377. package/dist/oauth/providers/microsoft-entra-id.provider.d.ts.map +1 -1
  378. package/dist/oauth/providers/microsoft-entra-id.provider.js +36 -4
  379. package/dist/oauth/providers/microsoft-entra-id.provider.js.map +1 -1
  380. package/dist/observability/monitored-cron.d.ts +29 -12
  381. package/dist/observability/monitored-cron.d.ts.map +1 -1
  382. package/dist/observability/monitored-cron.js +131 -46
  383. package/dist/observability/monitored-cron.js.map +1 -1
  384. package/dist/pairing/pairing.service.d.ts +6 -2
  385. package/dist/pairing/pairing.service.d.ts.map +1 -1
  386. package/dist/pdf/document/charts/chart-bar.d.ts +24 -0
  387. package/dist/pdf/document/charts/chart-bar.d.ts.map +1 -0
  388. package/dist/pdf/document/charts/chart-bar.js +117 -0
  389. package/dist/pdf/document/charts/chart-bar.js.map +1 -0
  390. package/dist/pdf/document/charts/chart-donut.d.ts +16 -0
  391. package/dist/pdf/document/charts/chart-donut.d.ts.map +1 -0
  392. package/dist/pdf/document/charts/chart-donut.js +89 -0
  393. package/dist/pdf/document/charts/chart-donut.js.map +1 -0
  394. package/dist/pdf/document/charts/chart-gauge.d.ts +15 -0
  395. package/dist/pdf/document/charts/chart-gauge.d.ts.map +1 -0
  396. package/dist/pdf/document/charts/chart-gauge.js +60 -0
  397. package/dist/pdf/document/charts/chart-gauge.js.map +1 -0
  398. package/dist/pdf/document/charts/chart-line.d.ts +29 -0
  399. package/dist/pdf/document/charts/chart-line.d.ts.map +1 -0
  400. package/dist/pdf/document/charts/chart-line.js +89 -0
  401. package/dist/pdf/document/charts/chart-line.js.map +1 -0
  402. package/dist/pdf/document/charts/chart-primitives.d.ts +64 -0
  403. package/dist/pdf/document/charts/chart-primitives.d.ts.map +1 -0
  404. package/dist/pdf/document/charts/chart-primitives.js +110 -0
  405. package/dist/pdf/document/charts/chart-primitives.js.map +1 -0
  406. package/dist/pdf/document/charts/chart-radar.d.ts +13 -0
  407. package/dist/pdf/document/charts/chart-radar.d.ts.map +1 -0
  408. package/dist/pdf/document/charts/chart-radar.js +83 -0
  409. package/dist/pdf/document/charts/chart-radar.js.map +1 -0
  410. package/dist/pdf/document/charts/chart-scale.d.ts +39 -0
  411. package/dist/pdf/document/charts/chart-scale.d.ts.map +1 -0
  412. package/dist/pdf/document/charts/chart-scale.js +118 -0
  413. package/dist/pdf/document/charts/chart-scale.js.map +1 -0
  414. package/dist/pdf/document/charts/index.d.ts +8 -0
  415. package/dist/pdf/document/charts/index.d.ts.map +1 -0
  416. package/dist/pdf/document/charts/index.js +24 -0
  417. package/dist/pdf/document/charts/index.js.map +1 -0
  418. package/dist/pdf/document/index.d.ts +8 -0
  419. package/dist/pdf/document/index.d.ts.map +1 -0
  420. package/dist/pdf/document/index.js +24 -0
  421. package/dist/pdf/document/index.js.map +1 -0
  422. package/dist/pdf/document/pdf-document.chrome.d.ts +20 -0
  423. package/dist/pdf/document/pdf-document.chrome.d.ts.map +1 -0
  424. package/dist/pdf/document/pdf-document.chrome.js +36 -0
  425. package/dist/pdf/document/pdf-document.chrome.js.map +1 -0
  426. package/dist/pdf/document/pdf-document.css.d.ts +20 -0
  427. package/dist/pdf/document/pdf-document.css.d.ts.map +1 -0
  428. package/dist/pdf/document/pdf-document.css.js +239 -0
  429. package/dist/pdf/document/pdf-document.css.js.map +1 -0
  430. package/dist/pdf/document/pdf-document.renderer.d.ts +10 -0
  431. package/dist/pdf/document/pdf-document.renderer.d.ts.map +1 -0
  432. package/dist/pdf/document/pdf-document.renderer.js +153 -0
  433. package/dist/pdf/document/pdf-document.renderer.js.map +1 -0
  434. package/dist/pdf/document/pdf-document.service.d.ts +27 -0
  435. package/dist/pdf/document/pdf-document.service.d.ts.map +1 -0
  436. package/dist/pdf/document/pdf-document.service.js +81 -0
  437. package/dist/pdf/document/pdf-document.service.js.map +1 -0
  438. package/dist/pdf/document/pdf-document.theme.d.ts +41 -0
  439. package/dist/pdf/document/pdf-document.theme.d.ts.map +1 -0
  440. package/dist/pdf/document/pdf-document.theme.js +105 -0
  441. package/dist/pdf/document/pdf-document.theme.js.map +1 -0
  442. package/dist/pdf/document/pdf-document.types.d.ts +108 -0
  443. package/dist/pdf/document/pdf-document.types.d.ts.map +1 -0
  444. package/dist/pdf/document/pdf-document.types.js +18 -0
  445. package/dist/pdf/document/pdf-document.types.js.map +1 -0
  446. package/dist/pdf/pdf.module.d.ts.map +1 -1
  447. package/dist/pdf/pdf.module.js +3 -2
  448. package/dist/pdf/pdf.module.js.map +1 -1
  449. package/dist/pdf/pdf.service.d.ts +69 -1
  450. package/dist/pdf/pdf.service.d.ts.map +1 -1
  451. package/dist/pdf/pdf.service.js +164 -63
  452. package/dist/pdf/pdf.service.js.map +1 -1
  453. package/dist/pdf/templates/commercial-proposal.template.d.ts +96 -0
  454. package/dist/pdf/templates/commercial-proposal.template.d.ts.map +1 -0
  455. package/dist/pdf/templates/commercial-proposal.template.js +276 -0
  456. package/dist/pdf/templates/commercial-proposal.template.js.map +1 -0
  457. package/dist/profile/dto/change-password.dto.d.ts.map +1 -1
  458. package/dist/profile/dto/change-password.dto.js +4 -6
  459. package/dist/profile/dto/change-password.dto.js.map +1 -1
  460. package/dist/profile/profile.controller.d.ts +1 -1
  461. package/dist/profile/profile.service.d.ts +1 -1
  462. package/dist/profile/profile.service.d.ts.map +1 -1
  463. package/dist/profile/profile.service.js +9 -3
  464. package/dist/profile/profile.service.js.map +1 -1
  465. package/dist/realtime/realtime-tick.coalescer.d.ts +34 -0
  466. package/dist/realtime/realtime-tick.coalescer.d.ts.map +1 -0
  467. package/dist/realtime/realtime-tick.coalescer.js +60 -0
  468. package/dist/realtime/realtime-tick.coalescer.js.map +1 -0
  469. package/dist/realtime/realtime.service.d.ts +2 -0
  470. package/dist/realtime/realtime.service.d.ts.map +1 -1
  471. package/dist/realtime/realtime.service.js +22 -2
  472. package/dist/realtime/realtime.service.js.map +1 -1
  473. package/dist/redis/redis-kv.service.d.ts +90 -0
  474. package/dist/redis/redis-kv.service.d.ts.map +1 -0
  475. package/dist/redis/redis-kv.service.js +247 -0
  476. package/dist/redis/redis-kv.service.js.map +1 -0
  477. package/dist/redis/redis-master.d.ts +29 -0
  478. package/dist/redis/redis-master.d.ts.map +1 -0
  479. package/dist/redis/redis-master.js +81 -0
  480. package/dist/redis/redis-master.js.map +1 -0
  481. package/dist/redis/redis-pubsub.d.ts +12 -0
  482. package/dist/redis/redis-pubsub.d.ts.map +1 -1
  483. package/dist/redis/redis-pubsub.js +25 -2
  484. package/dist/redis/redis-pubsub.js.map +1 -1
  485. package/dist/redis/redis.module.d.ts +11 -0
  486. package/dist/redis/redis.module.d.ts.map +1 -0
  487. package/dist/redis/redis.module.js +30 -0
  488. package/dist/redis/redis.module.js.map +1 -0
  489. package/dist/session/session.controller.d.ts +6 -2
  490. package/dist/session/session.controller.d.ts.map +1 -1
  491. package/dist/session/session.service.d.ts +118 -15
  492. package/dist/session/session.service.d.ts.map +1 -1
  493. package/dist/session/session.service.js +251 -77
  494. package/dist/session/session.service.js.map +1 -1
  495. package/dist/setting/favicon.controller.d.ts +26 -0
  496. package/dist/setting/favicon.controller.d.ts.map +1 -0
  497. package/dist/setting/favicon.controller.js +130 -0
  498. package/dist/setting/favicon.controller.js.map +1 -0
  499. package/dist/setting/setting.controller.d.ts +5 -0
  500. package/dist/setting/setting.controller.d.ts.map +1 -1
  501. package/dist/setting/setting.module.d.ts.map +1 -1
  502. package/dist/setting/setting.module.js +2 -1
  503. package/dist/setting/setting.module.js.map +1 -1
  504. package/dist/setting/setting.service.d.ts +7 -0
  505. package/dist/setting/setting.service.d.ts.map +1 -1
  506. package/dist/setting/setting.service.js +38 -3
  507. package/dist/setting/setting.service.js.map +1 -1
  508. package/dist/task/task.service.d.ts +17 -0
  509. package/dist/task/task.service.d.ts.map +1 -1
  510. package/dist/task/task.service.js +48 -13
  511. package/dist/task/task.service.js.map +1 -1
  512. package/dist/token/token.service.d.ts +19 -1
  513. package/dist/token/token.service.d.ts.map +1 -1
  514. package/dist/token/token.service.js +39 -2
  515. package/dist/token/token.service.js.map +1 -1
  516. package/dist/user/user-credential.util.d.ts +10 -0
  517. package/dist/user/user-credential.util.d.ts.map +1 -1
  518. package/dist/user/user-credential.util.js +14 -1
  519. package/dist/user/user-credential.util.js.map +1 -1
  520. package/dist/user/user.service.d.ts +12 -4
  521. package/dist/user/user.service.d.ts.map +1 -1
  522. package/dist/user/user.service.js +2 -11
  523. package/dist/user/user.service.js.map +1 -1
  524. package/dist/user/user.sort.d.ts +16 -0
  525. package/dist/user/user.sort.d.ts.map +1 -0
  526. package/dist/user/user.sort.js +25 -0
  527. package/dist/user/user.sort.js.map +1 -0
  528. package/dist/utils/abbreviate-name.d.ts +13 -0
  529. package/dist/utils/abbreviate-name.d.ts.map +1 -0
  530. package/dist/utils/abbreviate-name.js +42 -0
  531. package/dist/utils/abbreviate-name.js.map +1 -0
  532. package/dist/utils/date-range-query.dto.d.ts +11 -0
  533. package/dist/utils/date-range-query.dto.d.ts.map +1 -0
  534. package/dist/utils/date-range-query.dto.js +63 -0
  535. package/dist/utils/date-range-query.dto.js.map +1 -0
  536. package/dist/utils/date-range.d.ts +96 -0
  537. package/dist/utils/date-range.d.ts.map +1 -0
  538. package/dist/utils/date-range.js +172 -0
  539. package/dist/utils/date-range.js.map +1 -0
  540. package/dist/webhook-integration/webhook-utils.d.ts.map +1 -1
  541. package/dist/webhook-integration/webhook-utils.js +24 -0
  542. package/dist/webhook-integration/webhook-utils.js.map +1 -1
  543. package/dist/whatsapp-sender/whatsapp-recipients.d.ts +49 -0
  544. package/dist/whatsapp-sender/whatsapp-recipients.d.ts.map +1 -0
  545. package/dist/whatsapp-sender/whatsapp-recipients.js +66 -0
  546. package/dist/whatsapp-sender/whatsapp-recipients.js.map +1 -0
  547. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +25 -0
  548. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -1
  549. package/dist/whatsapp-sender/whatsapp-sender.service.js +71 -7
  550. package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -1
  551. package/hedhog/data/integration_provider.yaml +9 -0
  552. package/hedhog/data/integration_type.yaml +12 -0
  553. package/hedhog/data/locale.yaml +0 -1
  554. package/hedhog/data/mail.yaml +2 -2
  555. package/hedhog/data/mail_layout.yaml +6 -3
  556. package/hedhog/data/menu.yaml +25 -5
  557. package/hedhog/data/route.yaml +148 -0
  558. package/hedhog/data/setting_group.yaml +189 -3
  559. package/hedhog/frontend/app/access-log/page.tsx.ejs +47 -53
  560. package/hedhog/frontend/app/account/components/active-sessions.tsx.ejs +33 -8
  561. package/hedhog/frontend/app/account/components/mcp-tokens.tsx.ejs +54 -13
  562. package/hedhog/frontend/app/account/components/mfa-method-card.tsx.ejs +7 -1
  563. package/hedhog/frontend/app/account/components/recovery-codes-dialog.tsx.ejs +1 -0
  564. package/hedhog/frontend/app/account/components/tokens.tsx.ejs +47 -17
  565. package/hedhog/frontend/app/ai_agent/page.tsx.ejs +46 -5
  566. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +101 -30
  567. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +24 -8
  568. package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +80 -15
  569. package/hedhog/frontend/app/configurations/[slug]/components/image-optimization-action.tsx.ejs +166 -0
  570. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.test.tsx.ejs +145 -45
  571. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +99 -219
  572. package/hedhog/frontend/app/configurations/[slug]/page.tsx.ejs +19 -1
  573. package/hedhog/frontend/app/configurations/layout.tsx.ejs +19 -5
  574. package/hedhog/frontend/app/dashboard/[slug]/widget-renderer.tsx.ejs +2 -8
  575. package/hedhog/frontend/app/dashboard/components/dynamic-widget.tsx.ejs +3 -0
  576. package/hedhog/frontend/app/dashboard/components/widget-wrapper.tsx.ejs +4 -0
  577. package/hedhog/frontend/app/dashboard/dashboard-home-tabs.tsx.ejs +43 -44
  578. package/hedhog/frontend/app/dashboard/management/tabs/component-roles-tab.tsx.ejs +41 -3
  579. package/hedhog/frontend/app/dashboard/management/tabs/components-tab.tsx.ejs +42 -2
  580. package/hedhog/frontend/app/dashboard/management/tabs/dashboard-roles-tab.tsx.ejs +41 -3
  581. package/hedhog/frontend/app/dashboard/management/tabs/dashboards-tab.tsx.ejs +39 -4
  582. package/hedhog/frontend/app/dashboard/management/tabs/items-tab.tsx.ejs +42 -3
  583. package/hedhog/frontend/app/incidents/page.tsx.ejs +60 -31
  584. package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +45 -5
  585. package/hedhog/frontend/app/integrations-webhooks/page.tsx.ejs +92 -15
  586. package/hedhog/frontend/app/mail/log/page.tsx.ejs +109 -61
  587. package/hedhog/frontend/app/mail/template/page.tsx.ejs +125 -23
  588. package/hedhog/frontend/app/mcp_chat/chat-components.tsx.ejs +13 -15
  589. package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +116 -110
  590. package/hedhog/frontend/app/message-templates/_components/message-template-sheet.tsx.ejs +245 -0
  591. package/hedhog/frontend/app/message-templates/_lib/types.ts.ejs +24 -0
  592. package/hedhog/frontend/app/message-templates/page.tsx.ejs +182 -0
  593. package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1 -0
  594. package/hedhog/frontend/app/pages/page.tsx.ejs +94 -9
  595. package/hedhog/frontend/app/roles/menus.tsx.ejs +4 -4
  596. package/hedhog/frontend/app/roles/routes.tsx.ejs +4 -4
  597. package/hedhog/frontend/app/roles/users.tsx.ejs +4 -4
  598. package/hedhog/frontend/app/setting-list/page.tsx.ejs +71 -9
  599. package/hedhog/frontend/app/users/page.tsx.ejs +77 -67
  600. package/hedhog/frontend/messages/en.json +237 -37
  601. package/hedhog/frontend/messages/pt.json +237 -37
  602. package/hedhog/table/cron_lock.yaml +17 -0
  603. package/hedhog/table/file.yaml +13 -1
  604. package/hedhog/table/file_upload_chunk.yaml +23 -0
  605. package/hedhog/table/file_upload_ticket.yaml +67 -0
  606. package/hedhog/table/mcp_tool_call_log.yaml +30 -22
  607. package/hedhog/table/message_template.yaml +33 -0
  608. package/hedhog/table/setting.yaml +8 -0
  609. package/hedhog/table/user_session.yaml +36 -1
  610. package/package.json +5 -3
  611. package/src/ai/ai-agent.sort.ts +21 -0
  612. package/src/ai/ai-attachment.fragments.spec.ts +56 -3
  613. package/src/ai/ai.service.responses.spec.ts +429 -0
  614. package/src/ai/ai.service.spec.ts +173 -1
  615. package/src/ai/ai.service.ts +473 -220
  616. package/src/ai-instruction/ai-instruction.service.ts +32 -28
  617. package/src/ai-instruction/ai-instruction.sort.ts +32 -0
  618. package/src/ai-instruction/ai-prompt-resolver.service.spec.ts +44 -0
  619. package/src/ai-instruction/ai-prompt-resolver.service.ts +29 -0
  620. package/src/auth/auth.module.ts +8 -1
  621. package/src/auth/auth.service.spec.ts +108 -1
  622. package/src/auth/auth.service.ts +59 -5
  623. package/src/auth/guards/auth.guard.ts +9 -1
  624. package/src/authorize/authorize.controller.ts +126 -11
  625. package/src/authorize/authorize.errors.ts +55 -0
  626. package/src/authorize/authorize.module.ts +6 -1
  627. package/src/authorize/authorize.service.spec.ts +379 -7
  628. package/src/authorize/authorize.service.ts +309 -23
  629. package/src/authorize/dto/authorize-info.dto.ts +21 -3
  630. package/src/authorize/dto/consent.dto.ts +21 -3
  631. package/src/authorize/dto/token.dto.ts +24 -2
  632. package/src/authorize/oauth-exception.filter.ts +58 -0
  633. package/src/authorize/oauth-metadata.service.ts +67 -0
  634. package/src/authorize/well-known.controller.spec.ts +84 -0
  635. package/src/authorize/well-known.controller.ts +96 -0
  636. package/src/captcha/captcha.service.spec.ts +211 -4
  637. package/src/captcha/captcha.service.ts +127 -10
  638. package/src/core.module.ts +9 -0
  639. package/src/dashboard/dashboard-component-role/dashboard-component-role.service.ts +2 -3
  640. package/src/dashboard/dashboard-component-role/dashboard-component-role.sort.ts +18 -0
  641. package/src/dashboard/dashboard-item/dashboard-item.service.ts +2 -3
  642. package/src/dashboard/dashboard-item/dashboard-item.sort.ts +19 -0
  643. package/src/dashboard/dashboard-role/dashboard-role.service.ts +2 -3
  644. package/src/dashboard/dashboard-role/dashboard-role.sort.ts +16 -0
  645. package/src/document-kit/document-kit.module.ts +12 -0
  646. package/src/document-kit/document-kit.registry.ts +125 -0
  647. package/src/document-kit/document-kit.service.spec.ts +156 -0
  648. package/src/document-kit/document-kit.service.ts +173 -0
  649. package/src/file/file-upload-ticket.service.spec.ts +422 -0
  650. package/src/file/file-upload-ticket.service.ts +513 -0
  651. package/src/file/file.controller.ts +65 -0
  652. package/src/file/file.module.ts +14 -2
  653. package/src/file/file.service.spec.ts +262 -1
  654. package/src/file/file.service.ts +505 -87
  655. package/src/file/filename-encoding.util.spec.ts +54 -0
  656. package/src/file/filename-encoding.util.ts +67 -0
  657. package/src/file/image-optimization.service.spec.ts +156 -19
  658. package/src/file/image-optimization.service.ts +106 -21
  659. package/src/file/mcp-file-source.schema.ts +86 -0
  660. package/src/file/mcp-file-source.service.spec.ts +473 -0
  661. package/src/file/mcp-file-source.service.ts +445 -0
  662. package/src/file/mimetype-sniff.util.spec.ts +126 -0
  663. package/src/file/mimetype-sniff.util.ts +265 -0
  664. package/src/file/remote-fetch.util.spec.ts +117 -0
  665. package/src/file/remote-fetch.util.ts +330 -0
  666. package/src/impersonation/dto/start-impersonation.dto.ts +5 -2
  667. package/src/impersonation/impersonation.service.spec.ts +24 -1
  668. package/src/impersonation/impersonation.service.ts +14 -4
  669. package/src/incident/incident.controller.ts +9 -1
  670. package/src/incident/incident.service.ts +7 -0
  671. package/src/index.ts +23 -1
  672. package/src/integration-profile/integration-profile.secrets.ts +28 -0
  673. package/src/integration-profile/integration-profile.service.ts +7 -64
  674. package/src/integration-profile/integration-profile.utils.spec.ts +9 -0
  675. package/src/integration-profile/integration-profile.utils.ts +5 -5
  676. package/src/integration-profile/testers/ai.testers.ts +70 -5
  677. package/src/integration-profile/testers/index.ts +2 -0
  678. package/src/integration-profile/testers/remaining.testers.spec.ts +144 -1
  679. package/src/integration-profile/testers/shipping.testers.ts +94 -0
  680. package/src/integration-profile/testers/tester-coverage.spec.ts +10 -0
  681. package/src/mail/dto/send.dto.ts +6 -1
  682. package/src/mail/mail-template.spec.ts +58 -1
  683. package/src/mail/mail.service.spec.ts +112 -0
  684. package/src/mail/mail.service.ts +42 -4
  685. package/src/mail-sent/mail-sent.service.ts +3 -0
  686. package/src/mail-sent/mail-sent.sort.ts +19 -0
  687. package/src/mcp/filters/mcp-challenge.filter.spec.ts +76 -0
  688. package/src/mcp/filters/mcp-challenge.filter.ts +70 -0
  689. package/src/mcp/guards/mcp-auth.guard.spec.ts +51 -2
  690. package/src/mcp/guards/mcp-auth.guard.ts +24 -1
  691. package/src/mcp/guards/mcp-permission.guard.spec.ts +109 -15
  692. package/src/mcp/guards/mcp-permission.guard.ts +76 -51
  693. package/src/mcp/mcp-audit.service.spec.ts +107 -0
  694. package/src/mcp/mcp-audit.service.ts +37 -1
  695. package/src/mcp/mcp-permission.service.spec.ts +197 -0
  696. package/src/mcp/mcp-permission.service.ts +184 -0
  697. package/src/mcp/mcp-server.service.spec.ts +84 -2
  698. package/src/mcp/mcp-server.service.ts +111 -87
  699. package/src/mcp/mcp.controller.ts +8 -1
  700. package/src/mcp/mcp.module.ts +7 -1
  701. package/src/mcp/tools/core-access-log.mcp-tools.ts +66 -0
  702. package/src/mcp/tools/core-ai.mcp-tools.ts +1 -1
  703. package/src/mcp/tools/core-dashboard-items.mcp-tools.ts +1 -1
  704. package/src/mcp/tools/core-dashboard.mcp-tools.ts +1 -1
  705. package/src/mcp/tools/core-event-webhooks.mcp-tools.ts +1 -2
  706. package/src/mcp/tools/core-files.mcp-tools.ts +202 -22
  707. package/src/mcp/tools/core-integration-events.mcp-tools.ts +1 -1
  708. package/src/mcp/tools/core-mail-sent.mcp-tools.ts +1 -1
  709. package/src/mcp/tools/core-mail.mcp-tools.ts +1 -1
  710. package/src/mcp/tools/core-menus.mcp-tools.ts +1 -2
  711. package/src/mcp/tools/core-notifications.mcp-tools.ts +0 -1
  712. package/src/mcp/tools/core-roles.mcp-tools.ts +1 -5
  713. package/src/mcp/tools/core-routes.mcp-tools.ts +1 -3
  714. package/src/mcp/tools/core-screens.mcp-tools.ts +1 -3
  715. package/src/mcp/tools/core-sessions.mcp-tools.ts +0 -2
  716. package/src/mcp/tools/core-settings.mcp-tools.ts +1 -2
  717. package/src/mcp/tools/core-users.mcp-tools.ts +1 -1
  718. package/src/mcp/tools/core-webhooks.mcp-tools.ts +1 -2
  719. package/src/mcp/types/mcp-context.type.ts +15 -6
  720. package/src/mcp-chat/mcp-chat.service.ts +8 -0
  721. package/src/meeting/meeting-provider.registry.ts +201 -0
  722. package/src/meeting/meeting.constants.ts +74 -0
  723. package/src/menu/menu.service.spec.ts +89 -0
  724. package/src/menu/menu.service.ts +29 -11
  725. package/src/message-template/dto/update-message-template.dto.ts +22 -0
  726. package/src/message-template/message-template-admin.service.spec.ts +163 -0
  727. package/src/message-template/message-template-admin.service.ts +239 -0
  728. package/src/message-template/message-template.controller.ts +52 -0
  729. package/src/message-template/message-template.module.ts +21 -0
  730. package/src/message-template/message-template.registry.spec.ts +62 -0
  731. package/src/message-template/message-template.registry.ts +125 -0
  732. package/src/message-template/message-template.service.spec.ts +149 -0
  733. package/src/message-template/message-template.service.ts +149 -0
  734. package/src/notification/notification.constants.ts +10 -0
  735. package/src/notification/notification.module.ts +3 -0
  736. package/src/notification/notification.service.spec.ts +75 -1
  737. package/src/notification/notification.service.ts +39 -1
  738. package/src/oauth/oauth-token-broker.service.spec.ts +108 -0
  739. package/src/oauth/oauth-token-broker.service.ts +129 -2
  740. package/src/oauth/oauth.controller.ts +0 -1
  741. package/src/oauth/oauth.errors.ts +7 -0
  742. package/src/oauth/oauth.module.ts +6 -1
  743. package/src/oauth/oauth.service.spec.ts +58 -7
  744. package/src/oauth/oauth.service.ts +71 -32
  745. package/src/oauth/providers/abstract.provider.spec.ts +192 -0
  746. package/src/oauth/providers/abstract.provider.ts +46 -14
  747. package/src/oauth/providers/github.provider.ts +57 -34
  748. package/src/oauth/providers/microsoft-entra-id.provider.spec.ts +133 -0
  749. package/src/oauth/providers/microsoft-entra-id.provider.ts +37 -3
  750. package/src/observability/monitored-cron.spec.ts +164 -31
  751. package/src/observability/monitored-cron.ts +154 -62
  752. package/src/pdf/document/charts/chart-bar.ts +217 -0
  753. package/src/pdf/document/charts/chart-donut.ts +163 -0
  754. package/src/pdf/document/charts/chart-gauge.ts +94 -0
  755. package/src/pdf/document/charts/chart-line.ts +159 -0
  756. package/src/pdf/document/charts/chart-primitives.ts +188 -0
  757. package/src/pdf/document/charts/chart-radar.ts +136 -0
  758. package/src/pdf/document/charts/chart-scale.spec.ts +93 -0
  759. package/src/pdf/document/charts/chart-scale.ts +141 -0
  760. package/src/pdf/document/charts/charts.spec.ts +157 -0
  761. package/src/pdf/document/charts/index.ts +7 -0
  762. package/src/pdf/document/index.ts +7 -0
  763. package/src/pdf/document/pdf-document.chrome.ts +38 -0
  764. package/src/pdf/document/pdf-document.css.ts +238 -0
  765. package/src/pdf/document/pdf-document.renderer.spec.ts +129 -0
  766. package/src/pdf/document/pdf-document.renderer.ts +215 -0
  767. package/src/pdf/document/pdf-document.service.ts +77 -0
  768. package/src/pdf/document/pdf-document.theme.ts +146 -0
  769. package/src/pdf/document/pdf-document.types.ts +97 -0
  770. package/src/pdf/pdf.module.ts +3 -2
  771. package/src/pdf/pdf.service.spec.ts +131 -0
  772. package/src/pdf/pdf.service.ts +245 -82
  773. package/src/pdf/templates/commercial-proposal.template.spec.ts +177 -0
  774. package/src/pdf/templates/commercial-proposal.template.ts +400 -0
  775. package/src/profile/dto/change-password.dto.ts +25 -7
  776. package/src/profile/profile.service.spec.ts +97 -0
  777. package/src/profile/profile.service.ts +9 -3
  778. package/src/realtime/realtime-tick.coalescer.spec.ts +92 -0
  779. package/src/realtime/realtime-tick.coalescer.ts +60 -0
  780. package/src/realtime/realtime.service.spec.ts +33 -0
  781. package/src/realtime/realtime.service.ts +28 -2
  782. package/src/redis/redis-kv.service.ts +261 -0
  783. package/src/redis/redis-master.spec.ts +111 -0
  784. package/src/redis/redis-master.ts +86 -0
  785. package/src/redis/redis-pubsub.ts +27 -3
  786. package/src/redis/redis.module.ts +17 -0
  787. package/src/session/session.service.spec.ts +121 -42
  788. package/src/session/session.service.ts +279 -82
  789. package/src/setting/favicon.controller.spec.ts +92 -0
  790. package/src/setting/favicon.controller.ts +135 -0
  791. package/src/setting/setting.module.ts +2 -1
  792. package/src/setting/setting.service.ts +44 -3
  793. package/src/task/task.service.spec.ts +41 -0
  794. package/src/task/task.service.ts +53 -13
  795. package/src/token/token.service.spec.ts +90 -0
  796. package/src/token/token.service.ts +48 -2
  797. package/src/user/user-credential.util.ts +14 -5
  798. package/src/user/user.service.ts +2 -12
  799. package/src/user/user.sort.ts +25 -0
  800. package/src/utils/abbreviate-name.spec.ts +50 -0
  801. package/src/utils/abbreviate-name.ts +44 -0
  802. package/src/utils/date-range-query.dto.ts +56 -0
  803. package/src/utils/date-range.spec.ts +175 -0
  804. package/src/utils/date-range.ts +246 -0
  805. package/src/webhook-integration/webhook-utils.spec.ts +67 -0
  806. package/src/webhook-integration/webhook-utils.ts +26 -0
  807. package/src/whatsapp-sender/whatsapp-recipients.spec.ts +89 -0
  808. package/src/whatsapp-sender/whatsapp-recipients.ts +83 -0
  809. package/src/whatsapp-sender/whatsapp-sender.service.spec.ts +185 -0
  810. package/src/whatsapp-sender/whatsapp-sender.service.ts +90 -7
  811. package/hedhog/query/device_pairing_request.sql +0 -46
  812. package/hedhog/query/impersonation_grant.sql +0 -71
  813. package/hedhog/query/oauth_authorize_pkce.sql +0 -58
  814. package/hedhog/query/oauth_mobile_state_token.sql +0 -30
  815. package/hedhog/query/oauth_web_ref_token.sql +0 -25
@@ -18,11 +18,25 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
18
18
  function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
19
19
  function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
20
20
  };
21
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
22
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
23
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
24
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
25
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
26
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
27
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
28
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
29
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
30
+ function fulfill(value) { resume("next", value); }
31
+ function reject(value) { resume("throw", value); }
32
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
33
+ };
21
34
  var _a;
22
35
  var FileService_1;
23
36
  Object.defineProperty(exports, "__esModule", { value: true });
24
37
  exports.FileService = void 0;
25
38
  const client_s3_1 = require("@aws-sdk/client-s3");
39
+ const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
26
40
  const client_lambda_1 = require("@aws-sdk/client-lambda");
27
41
  const client_sts_1 = require("@aws-sdk/client-sts");
28
42
  const api_locale_1 = require("@hed-hog/api-locale");
@@ -30,6 +44,7 @@ const api_pagination_1 = require("@hed-hog/api-pagination");
30
44
  const api_prisma_1 = require("@hed-hog/api-prisma");
31
45
  const common_1 = require("@nestjs/common");
32
46
  const jwt_1 = require("@nestjs/jwt");
47
+ const crypto_1 = require("crypto");
33
48
  const fs_1 = require("fs");
34
49
  const os_1 = require("os");
35
50
  const path_1 = require("path");
@@ -37,9 +52,13 @@ const promises_1 = require("stream/promises");
37
52
  const uuid_1 = require("uuid");
38
53
  const integration_profile_utils_1 = require("../integration-profile/integration-profile.utils");
39
54
  const setting_service_1 = require("../setting/setting.service");
55
+ const filename_encoding_util_1 = require("./filename-encoding.util");
56
+ const mimetype_sniff_util_1 = require("./mimetype-sniff.util");
40
57
  const image_optimization_service_1 = require("./image-optimization.service");
41
58
  const abstract_provider_1 = require("./provider/abstract.provider");
42
59
  const provider_factory_1 = require("./provider/provider.factory");
60
+ /** Códigos de erro do S3/Spaces que indicam indisponibilidade passageira, não arquivo ruim. */
61
+ const STORAGE_UNAVAILABLE_CODES = ['SlowDown', 'ServiceUnavailable', 'InternalError', 'RequestTimeout'];
43
62
  /**
44
63
  * Resolver o provider custa 3 queries (setting + integration_profile, que ainda decifra o
45
64
  * config, + file_provider) e reconstrói o client de storage a cada arquivo. Em upload em
@@ -56,18 +75,13 @@ let FileService = FileService_1 = class FileService {
56
75
  }
57
76
  return `${file.location}/${file.path}`;
58
77
  }
59
- hasMojibake(value) {
60
- return /Ã.|Â.|â[\u0080-\u00BF]/.test(value);
61
- }
78
+ /**
79
+ * Nome que chegou com o encoding trocado (busboy entrega `originalname` em
80
+ * latin1, e a base ainda recebe nome importado com o mesmo defeito). A lógica
81
+ * mora no util porque a migration de backfill a reproduz em plpgsql.
82
+ */
62
83
  normalizeUploadedFilename(filename) {
63
- if (!filename) {
64
- return filename;
65
- }
66
- if (!this.hasMojibake(filename)) {
67
- return filename;
68
- }
69
- const decoded = Buffer.from(filename, 'latin1').toString('utf8');
70
- return this.hasMojibake(decoded) ? filename : decoded;
84
+ return filename ? (0, filename_encoding_util_1.fixMojibake)(filename) : filename;
71
85
  }
72
86
  constructor(prismaService, paginationService, settingService, jwtService, imageOptimizationService) {
73
87
  this.prismaService = prismaService;
@@ -79,6 +93,8 @@ let FileService = FileService_1 = class FileService {
79
93
  this.mimetypes = {};
80
94
  this.cachedProvider = null;
81
95
  this.providerResolution = null;
96
+ /** Cache curto de papéis, no mesmo espírito do McpPermissionService. */
97
+ this.fileAdminCache = new Map();
82
98
  }
83
99
  async onModuleInit() {
84
100
  try {
@@ -212,14 +228,30 @@ let FileService = FileService_1 = class FileService {
212
228
  });
213
229
  return file;
214
230
  }
215
- mapStorageNotFoundError(error, fileId) {
216
- var _a;
217
- const missingInStorage = (error === null || error === void 0 ? void 0 : error.name) === 'NoSuchKey' ||
218
- (error === null || error === void 0 ? void 0 : error.Code) === 'NoSuchKey' ||
219
- ((_a = error === null || error === void 0 ? void 0 : error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) === 404;
220
- if (missingInStorage) {
231
+ /**
232
+ * Traduz a falha do provider de storage para a resposta HTTP certa.
233
+ *
234
+ * 5xx e throttle do S3/Spaces são indisponibilidade passageira, não defeito:
235
+ * viram 503 com `code: STORAGE_UNAVAILABLE`, que o HttpExceptionFilter da API
236
+ * responde com `Retry-After` e reporta deduplicado. Sem isso, um 503 do Spaces
237
+ * com corpo que não é XML (ex.: `upstream connect error` do balanceador)
238
+ * estourava no parse do SDK como `char 'u' is not expected` e virava 500.
239
+ *
240
+ * O status vem de `$metadata.httpStatusCode`, que o SDK carimba mesmo quando a
241
+ * desserialização do erro falha; `$response.statusCode` cobre o resto.
242
+ */
243
+ mapStorageError(error, fileId) {
244
+ var _a, _b, _c;
245
+ const status = (_b = (_a = error === null || error === void 0 ? void 0 : error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) !== null && _b !== void 0 ? _b : (_c = error === null || error === void 0 ? void 0 : error.$response) === null || _c === void 0 ? void 0 : _c.statusCode;
246
+ const codes = [error === null || error === void 0 ? void 0 : error.name, error === null || error === void 0 ? void 0 : error.Code];
247
+ if (codes.includes('NoSuchKey') || status === 404) {
221
248
  throw new common_1.NotFoundException(`File not found in storage: ${fileId}`);
222
249
  }
250
+ const unavailable = (typeof status === 'number' && status >= 500) ||
251
+ codes.some((c) => STORAGE_UNAVAILABLE_CODES.includes(c));
252
+ if (unavailable) {
253
+ throw new common_1.ServiceUnavailableException({ message: 'Storage temporarily unavailable', code: 'STORAGE_UNAVAILABLE' }, { cause: error });
254
+ }
223
255
  throw error;
224
256
  }
225
257
  async openReadStreamById(fileId) {
@@ -240,12 +272,16 @@ let FileService = FileService_1 = class FileService {
240
272
  }
241
273
  const provider = await this.getProvider();
242
274
  const providerPath = this.resolveProviderPath(file);
275
+ // O HEAD só serve para descobrir o tamanho quando a tabela não o tem. Feito
276
+ // sempre, dobrava as requisições ao storage em cada segmento HLS.
243
277
  let metadata;
244
- try {
245
- metadata = await provider.metaData(providerPath);
246
- }
247
- catch (_b) {
248
- metadata = undefined;
278
+ if (file.size == null) {
279
+ try {
280
+ metadata = await provider.metaData(providerPath);
281
+ }
282
+ catch (_b) {
283
+ metadata = undefined;
284
+ }
249
285
  }
250
286
  try {
251
287
  const stream = await provider.readStream(providerPath);
@@ -256,7 +292,7 @@ let FileService = FileService_1 = class FileService {
256
292
  };
257
293
  }
258
294
  catch (error) {
259
- this.mapStorageNotFoundError(error, fileId);
295
+ this.mapStorageError(error, fileId);
260
296
  }
261
297
  }
262
298
  async openReadStreamWithRange(fileId, start, end) {
@@ -275,7 +311,13 @@ let FileService = FileService_1 = class FileService {
275
311
  const resolvedStart = start !== null && start !== void 0 ? start : 0;
276
312
  const resolvedEnd = end !== undefined ? end : totalSize > 0 ? totalSize - 1 : undefined;
277
313
  const hasRange = start !== undefined;
278
- const stream = await provider.readStream(providerPath, hasRange ? { start: resolvedStart, end: resolvedEnd } : undefined);
314
+ let stream;
315
+ try {
316
+ stream = await provider.readStream(providerPath, hasRange ? { start: resolvedStart, end: resolvedEnd } : undefined);
317
+ }
318
+ catch (error) {
319
+ this.mapStorageError(error, fileId);
320
+ }
279
321
  const contentLength = resolvedEnd !== undefined ? resolvedEnd - resolvedStart + 1 : totalSize;
280
322
  return {
281
323
  file,
@@ -315,7 +357,6 @@ let FileService = FileService_1 = class FileService {
315
357
  }
316
358
  }
317
359
  async getBuffer(fileId) {
318
- var _a;
319
360
  if (!fileId) {
320
361
  throw new common_1.BadRequestException(`No file ID provided`);
321
362
  }
@@ -337,13 +378,7 @@ let FileService = FileService_1 = class FileService {
337
378
  providerBuffer = await provider.buffer(providerPath);
338
379
  }
339
380
  catch (error) {
340
- const missingInStorage = (error === null || error === void 0 ? void 0 : error.name) === 'NoSuchKey' ||
341
- (error === null || error === void 0 ? void 0 : error.Code) === 'NoSuchKey' ||
342
- ((_a = error === null || error === void 0 ? void 0 : error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) === 404;
343
- if (missingInStorage) {
344
- throw new common_1.NotFoundException(`File not found in storage: ${fileId}`);
345
- }
346
- throw error;
381
+ this.mapStorageError(error, fileId);
347
382
  }
348
383
  const buffer = Buffer.from(providerBuffer);
349
384
  return {
@@ -397,7 +432,7 @@ let FileService = FileService_1 = class FileService {
397
432
  // repassa este argumento, então não há como acioná-lo por HTTP.
398
433
  // `isPrivate` tira o arquivo das rotas que servem por id sem autenticação.
399
434
  options) {
400
- var _a;
435
+ var _a, _b;
401
436
  if (!fileBuffer) {
402
437
  throw new common_1.BadRequestException(`No file provided`);
403
438
  }
@@ -414,7 +449,13 @@ let FileService = FileService_1 = class FileService {
414
449
  }
415
450
  const normalizedFilename = this.normalizeUploadedFilename(fileBuffer.originalname);
416
451
  const effectiveMimetype = await this.resolveEffectiveMimetype(fileBuffer.mimetype, normalizedFilename, fileBuffer.buffer);
417
- const optimized = await this.imageOptimizationService.optimizeBuffer(fileBuffer.buffer, effectiveMimetype, normalizedFilename, { maxWidth: resize === null || resize === void 0 ? void 0 : resize.maxWidth, maxHeight: resize === null || resize === void 0 ? void 0 : resize.maxHeight });
452
+ const optimized = (options === null || options === void 0 ? void 0 : options.skipImageOptimization)
453
+ ? {
454
+ buffer: fileBuffer.buffer,
455
+ mimetype: effectiveMimetype,
456
+ originalname: normalizedFilename,
457
+ }
458
+ : await this.imageOptimizationService.optimizeBuffer(fileBuffer.buffer, effectiveMimetype, normalizedFilename, { maxWidth: resize === null || resize === void 0 ? void 0 : resize.maxWidth, maxHeight: resize === null || resize === void 0 ? void 0 : resize.maxHeight });
418
459
  const normalizedFile = Object.assign(Object.assign({}, fileBuffer), { buffer: optimized.buffer, mimetype: optimized.mimetype, originalname: optimized.originalname, size: optimized.buffer.length });
419
460
  const url = await provider.upload(destination, normalizedFile);
420
461
  const file = await this.prismaService.file.create({
@@ -426,12 +467,13 @@ let FileService = FileService_1 = class FileService {
426
467
  mimetype_id: await this.getMimeType(optimized.mimetype),
427
468
  size: optimized.buffer.length,
428
469
  is_private: (_a = options === null || options === void 0 ? void 0 : options.isPrivate) !== null && _a !== void 0 ? _a : false,
470
+ created_by_user_id: (_b = options === null || options === void 0 ? void 0 : options.createdByUserId) !== null && _b !== void 0 ? _b : null,
429
471
  },
430
472
  });
431
473
  return file;
432
474
  }
433
475
  async uploadFromPath(destination, filePath, metadata) {
434
- var _a, _b, _c, _d, _e, _f, _g, _h;
476
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
435
477
  if (!filePath) {
436
478
  throw new common_1.BadRequestException(`No file path provided`);
437
479
  }
@@ -446,7 +488,14 @@ let FileService = FileService_1 = class FileService {
446
488
  const originalname = this.normalizeUploadedFilename((_c = (_b = metadata === null || metadata === void 0 ? void 0 : metadata.originalname) !== null && _b !== void 0 ? _b : metadata === null || metadata === void 0 ? void 0 : metadata.filename) !== null && _c !== void 0 ? _c : (0, path_1.basename)(filePath));
447
489
  // Recupera o tipo real quando o caller não informou o mimetype (default antigo era
448
490
  // application/octet-stream, que fazia imagens caírem fora da otimização e do serve).
449
- const mimetype = await this.resolveEffectiveMimetype(metadata === null || metadata === void 0 ? void 0 : metadata.mimetype, originalname);
491
+ // Diferente de `upload`, aqui só existe um caminho no disco — e ler o arquivo inteiro
492
+ // é justamente o que o branch de streaming abaixo evita para SCORM/vídeo de vários GB.
493
+ // Por isso o sniffing recebe só o cabeçalho, e apenas quando o caller não declarou um
494
+ // tipo concreto: sem isso, uma imagem enviada como application/octet-stream sem
495
+ // extensão no nome escapava da otimização e era gravada byte a byte.
496
+ const declaredMimetype = metadata === null || metadata === void 0 ? void 0 : metadata.mimetype;
497
+ const isGenericMimetype = !declaredMimetype || declaredMimetype === 'application/octet-stream';
498
+ const mimetype = await this.resolveEffectiveMimetype(declaredMimetype, originalname, isGenericMimetype ? await this.readFileHeader(filePath) : undefined);
450
499
  if (!(metadata === null || metadata === void 0 ? void 0 : metadata.skipMimeValidation) && !(await this.acceptMimetypes(mimetype))) {
451
500
  throw new common_1.BadRequestException(`Invalid file type: ${mimetype}`);
452
501
  }
@@ -458,8 +507,9 @@ let FileService = FileService_1 = class FileService {
458
507
  // streaming direto do disco via provider.uploadFromPath. Isso evita carregar
459
508
  // o arquivo inteiro na RAM (fs.readFile estoura o limite de Buffer / causa OOM)
460
509
  // e habilita upload multipart no S3. A otimização de imagem só se aplica a
461
- // image/*, então não há perda nesse caminho.
462
- if (!mimetype.startsWith('image/')) {
510
+ // image/*, então não há perda nesse caminho. `skipImageOptimization` manda a
511
+ // imagem pelo mesmo caminho: o chamador quer os bytes exatamente como estão.
512
+ if (!mimetype.startsWith('image/') || (metadata === null || metadata === void 0 ? void 0 : metadata.skipImageOptimization)) {
463
513
  const url = await provider.uploadFromPath(destination, filePath, {
464
514
  filename: originalname,
465
515
  mimetype,
@@ -473,19 +523,20 @@ let FileService = FileService_1 = class FileService {
473
523
  mimetype_id: await this.getMimeType(mimetype),
474
524
  size,
475
525
  is_private: (_d = metadata === null || metadata === void 0 ? void 0 : metadata.isPrivate) !== null && _d !== void 0 ? _d : false,
526
+ created_by_user_id: (_e = metadata === null || metadata === void 0 ? void 0 : metadata.createdByUserId) !== null && _e !== void 0 ? _e : null,
476
527
  },
477
528
  });
478
529
  }
479
530
  // Read buffer to allow image optimization regardless of provider support
480
531
  const rawBuffer = await fs_1.promises.readFile(filePath);
481
532
  const optimized = await this.imageOptimizationService.optimizeBuffer(rawBuffer, mimetype, originalname, {
482
- maxWidth: (_e = metadata === null || metadata === void 0 ? void 0 : metadata.resize) === null || _e === void 0 ? void 0 : _e.maxWidth,
483
- maxHeight: (_f = metadata === null || metadata === void 0 ? void 0 : metadata.resize) === null || _f === void 0 ? void 0 : _f.maxHeight,
533
+ maxWidth: (_f = metadata === null || metadata === void 0 ? void 0 : metadata.resize) === null || _f === void 0 ? void 0 : _f.maxWidth,
534
+ maxHeight: (_g = metadata === null || metadata === void 0 ? void 0 : metadata.resize) === null || _g === void 0 ? void 0 : _g.maxHeight,
484
535
  });
485
536
  const url = await provider.upload(destination, {
486
537
  fieldname: 'file',
487
538
  originalname: optimized.originalname,
488
- encoding: (_g = metadata === null || metadata === void 0 ? void 0 : metadata.encoding) !== null && _g !== void 0 ? _g : '7bit',
539
+ encoding: (_h = metadata === null || metadata === void 0 ? void 0 : metadata.encoding) !== null && _h !== void 0 ? _h : '7bit',
489
540
  mimetype: optimized.mimetype,
490
541
  size: optimized.buffer.length,
491
542
  destination: '',
@@ -501,19 +552,68 @@ let FileService = FileService_1 = class FileService {
501
552
  location: destination,
502
553
  mimetype_id: await this.getMimeType(optimized.mimetype),
503
554
  size: optimized.buffer.length,
504
- is_private: (_h = metadata === null || metadata === void 0 ? void 0 : metadata.isPrivate) !== null && _h !== void 0 ? _h : false,
555
+ is_private: (_j = metadata === null || metadata === void 0 ? void 0 : metadata.isPrivate) !== null && _j !== void 0 ? _j : false,
556
+ created_by_user_id: (_k = metadata === null || metadata === void 0 ? void 0 : metadata.createdByUserId) !== null && _k !== void 0 ? _k : null,
505
557
  },
506
558
  });
507
559
  return file;
508
560
  }
561
+ /**
562
+ * Lista as imagens armazenadas que valem uma passada por `reoptimizeFile`, para a
563
+ * operação em massa de reprocessamento do acervo.
564
+ *
565
+ * Devolve junto o total e a soma de bytes do filtro inteiro (não só da página), que é
566
+ * o que permite mostrar uma prévia antes de enfileirar dezenas de milhares de jobs.
567
+ * O core não conhece a fila — quem enfileira é a library `queue`, que depende deste
568
+ * pacote e não o contrário.
569
+ */
570
+ async findOptimizableImages(params) {
571
+ var _a, _b, _c;
572
+ const minSize = Math.max(0, Math.trunc(Number(params === null || params === void 0 ? void 0 : params.minSize) || 0));
573
+ const locations = ((_a = params === null || params === void 0 ? void 0 : params.locations) !== null && _a !== void 0 ? _a : [])
574
+ .map((location) => String(location).trim())
575
+ .filter(Boolean);
576
+ const where = {
577
+ size: { gte: minSize },
578
+ file_mimetype: {
579
+ name: {
580
+ startsWith: 'image/',
581
+ notIn: FileService_1.NON_OPTIMIZABLE_IMAGE_MIMETYPES,
582
+ },
583
+ },
584
+ };
585
+ if (locations.length) {
586
+ where.location = { in: locations };
587
+ }
588
+ const [aggregate, rows] = await Promise.all([
589
+ this.prismaService.file.aggregate({
590
+ where,
591
+ _count: { _all: true },
592
+ _sum: { size: true },
593
+ }),
594
+ this.prismaService.file.findMany({
595
+ where,
596
+ select: { id: true },
597
+ // Ordem estável para que o enfileiramento paginado não pule nem repita linhas.
598
+ orderBy: { id: 'asc' },
599
+ skip: Math.max(0, Math.trunc(Number(params === null || params === void 0 ? void 0 : params.offset) || 0)),
600
+ take: Math.min(5000, Math.max(1, Math.trunc(Number(params === null || params === void 0 ? void 0 : params.limit) || 1000))),
601
+ }),
602
+ ]);
603
+ return {
604
+ ids: rows.map((row) => row.id),
605
+ total: (_b = aggregate._count._all) !== null && _b !== void 0 ? _b : 0,
606
+ totalBytes: Number((_c = aggregate._sum.size) !== null && _c !== void 0 ? _c : 0),
607
+ };
608
+ }
509
609
  /**
510
610
  * Re-applies the current image-optimization settings to an already-stored file,
511
611
  * rewriting it in place: the `file` record keeps the same id, so every row that
512
612
  * references it (course_image, course_lesson_video_frame, ...) stays valid without
513
- * any FK juggling. Only replaces the stored object when the optimized result is
514
- * strictly smaller or the mimetype changed (e.g. PNG → WebP) — this keeps the
515
- * operation idempotent and avoids repeated lossy recompression. Non-image files are
516
- * left untouched.
613
+ * any FK juggling. Only replaces the stored object when the mimetype changed
614
+ * (e.g. PNG → WebP) or the result is smaller by a margin that justifies the rewrite —
615
+ * that margin is what actually makes the operation idempotent and avoids repeated
616
+ * lossy recompression. Non-image files are left untouched.
517
617
  */
518
618
  async reoptimizeFile(fileId) {
519
619
  var _a;
@@ -525,8 +625,13 @@ let FileService = FileService_1 = class FileService {
525
625
  }
526
626
  const optimized = await this.imageOptimizationService.optimizeBuffer(buffer, currentMimetype, file.filename);
527
627
  const mimetypeChanged = optimized.mimetype !== currentMimetype;
528
- const smaller = optimized.buffer.length < oldSize;
529
- if (!mimetypeChanged && !smaller) {
628
+ // Mudança de formato é o ganho principal (PNG → WebP) e vale por si; sem ela, só
629
+ // regrava quando a economia passa do limiar. `optimizeBuffer` já garante que o
630
+ // resultado nunca é maior que a entrada neste caminho (sem crop de alvo exato).
631
+ const worthRewriting = oldSize > 0 &&
632
+ (oldSize - optimized.buffer.length) / oldSize >=
633
+ FileService_1.REOPTIMIZE_MIN_GAIN_RATIO;
634
+ if (!mimetypeChanged && !worthRewriting) {
530
635
  return {
531
636
  changed: false,
532
637
  oldSize,
@@ -602,14 +707,181 @@ let FileService = FileService_1 = class FileService {
602
707
  }
603
708
  return files.map((file) => file.id);
604
709
  }
605
- async getFiles(paginationParams) {
710
+ /**
711
+ * `ownerUserId` restringe a listagem aos arquivos enviados por aquele usuário.
712
+ *
713
+ * Existe para as tools MCP: sem ele, `core.files.list` é um índice de tudo o que
714
+ * qualquer empresa já subiu, incluindo o que está gravado como `is_private`. O
715
+ * controller REST continua chamando sem o parâmetro, porque ali a rota já é `admin`
716
+ * e a tela de arquivos é justamente a visão global.
717
+ */
718
+ /**
719
+ * Grava um stream em disco medindo, hasheando e guardando o cabeçalho de uma vez só.
720
+ *
721
+ * O upload assinado recebe o binário cru no corpo do PUT, e nada garante que venha com
722
+ * `Content-Length` — sem o contador abaixo, um corpo aberto encheria o disco do pod. O
723
+ * corte é feito em pleno voo, antes de o excedente chegar ao arquivo.
724
+ *
725
+ * Passa o cabeçalho adiante porque conferir o tipo real é obrigatório nesse caminho, e
726
+ * reler o arquivo depois seria uma segunda passada por nada.
727
+ */
728
+ async writeStreamToPath(source, targetPath, maxBytes) {
729
+ const hash = (0, crypto_1.createHash)('sha256');
730
+ const headerChunks = [];
731
+ let headerLength = 0;
732
+ let bytes = 0;
733
+ const target = (0, fs_1.createWriteStream)(targetPath);
734
+ await (0, promises_1.pipeline)(source, function (chunks) {
735
+ return __asyncGenerator(this, arguments, function* () {
736
+ var _a, e_1, _b, _c;
737
+ try {
738
+ for (var _d = true, chunks_1 = __asyncValues(chunks), chunks_1_1; chunks_1_1 = yield __await(chunks_1.next()), _a = chunks_1_1.done, !_a; _d = true) {
739
+ _c = chunks_1_1.value;
740
+ _d = false;
741
+ const chunk = _c;
742
+ const buffer = Buffer.from(chunk);
743
+ bytes += buffer.length;
744
+ if (bytes > maxBytes) {
745
+ throw new common_1.BadRequestException(`Upload exceeds the declared size of ${maxBytes} bytes`);
746
+ }
747
+ hash.update(buffer);
748
+ if (headerLength < mimetype_sniff_util_1.MIMETYPE_SNIFF_BYTES) {
749
+ const slice = buffer.subarray(0, mimetype_sniff_util_1.MIMETYPE_SNIFF_BYTES - headerLength);
750
+ headerChunks.push(slice);
751
+ headerLength += slice.length;
752
+ }
753
+ yield yield __await(buffer);
754
+ }
755
+ }
756
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
757
+ finally {
758
+ try {
759
+ if (!_d && !_a && (_b = chunks_1.return)) yield __await(_b.call(chunks_1));
760
+ }
761
+ finally { if (e_1) throw e_1.error; }
762
+ }
763
+ });
764
+ }, target);
765
+ return {
766
+ bytes,
767
+ sha256: hash.digest('hex'),
768
+ header: Buffer.concat(headerChunks),
769
+ };
770
+ }
771
+ /**
772
+ * Conteúdo de um arquivo já armazenado, em memória.
773
+ *
774
+ * Existe para as tools que consomem os bytes sem persistir nada (importar extrato,
775
+ * extrair dados de uma nota com IA): elas recebem um `fileId` e precisam do arquivo,
776
+ * não de um stream. O teto evita que um `fileId` apontando para um SCORM de vários GB
777
+ * derrube o pod — quem serve arquivo grande usa `openReadStream` e não passa por aqui.
778
+ */
779
+ async bufferById(fileId, maxBytes) {
780
+ var _a, e_2, _b, _c;
781
+ var _d, _e;
782
+ const { stream } = await this.openReadStreamById(fileId);
783
+ const chunks = [];
784
+ let total = 0;
785
+ try {
786
+ for (var _f = true, _g = __asyncValues(stream), _h; _h = await _g.next(), _a = _h.done, !_a; _f = true) {
787
+ _c = _h.value;
788
+ _f = false;
789
+ const chunk = _c;
790
+ total += chunk.length;
791
+ if (total > maxBytes) {
792
+ (_e = (_d = stream).destroy) === null || _e === void 0 ? void 0 : _e.call(_d);
793
+ throw new common_1.BadRequestException(`File ${fileId} is larger than the ${maxBytes} bytes this operation can load`);
794
+ }
795
+ chunks.push(Buffer.from(chunk));
796
+ }
797
+ }
798
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
799
+ finally {
800
+ try {
801
+ if (!_f && !_a && (_b = _g.return)) await _b.call(_g);
802
+ }
803
+ finally { if (e_2) throw e_2.error; }
804
+ }
805
+ return Buffer.concat(chunks);
806
+ }
807
+ /**
808
+ * Nome do mimetype de um arquivo.
809
+ *
810
+ * `get()` e `upload()` devolvem a linha crua, sem a relação, e cada chamador que
811
+ * precisava do tipo vinha refazendo o `include` por conta. Como o cache de
812
+ * `getMimeType` é id-por-nome, este é o inverso dele e sai do mesmo mapa quando já
813
+ * tiver sido consultado.
814
+ */
815
+ async mimetypeNameById(mimetypeId) {
816
+ const cached = Object.entries(this.mimetypes).find(([, id]) => id === mimetypeId);
817
+ if (cached) {
818
+ return cached[0];
819
+ }
820
+ const row = await this.prismaService.file_mimetype.findUnique({
821
+ where: { id: mimetypeId },
822
+ select: { name: true },
823
+ });
824
+ if (row === null || row === void 0 ? void 0 : row.name) {
825
+ this.mimetypes[row.name] = mimetypeId;
826
+ return row.name;
827
+ }
828
+ return 'application/octet-stream';
829
+ }
830
+ async getFiles(paginationParams, ownerUserId) {
606
831
  const fields = ['filename', 'path'];
607
832
  const OR = this.prismaService.createInsensitiveSearch(fields, paginationParams);
608
833
  return this.paginationService.paginate(this.prismaService.file, paginationParams, {
834
+ where: Object.assign({ OR }, (ownerUserId ? { created_by_user_id: ownerUserId } : {})),
835
+ });
836
+ }
837
+ async isFileAdmin(userId) {
838
+ const cached = this.fileAdminCache.get(userId);
839
+ if (cached && Date.now() - cached.at < FileService_1.FILE_ADMIN_CACHE_TTL_MS) {
840
+ return cached.value;
841
+ }
842
+ const found = await this.prismaService.role_user.findFirst({
609
843
  where: {
610
- OR,
844
+ user_id: userId,
845
+ role: { slug: { in: FileService_1.FILE_ADMIN_ROLES } },
611
846
  },
847
+ select: { role_id: true },
848
+ });
849
+ const value = Boolean(found);
850
+ this.fileAdminCache.set(userId, { value, at: Date.now() });
851
+ return value;
852
+ }
853
+ /**
854
+ * Porteiro do `fileId` vindo de fora: só o dono usa um arquivo, e quem administra o
855
+ * acervo usa qualquer um.
856
+ *
857
+ * Sem isto, apontar um `fileId` numa tool seria enumerar — id de arquivo é sequencial,
858
+ * exatamente o motivo pelo qual `is_private` existe. Arquivo anterior a esta coluna
859
+ * (ou gravado por cron/seed/webhook) fica com dono nulo e só o admin alcança: não dá
860
+ * para provar de quem ele é, e adivinhar a favor do chamador seria abrir a porta que
861
+ * este método fecha.
862
+ */
863
+ async assertFileUsable(fileId, userId) {
864
+ if (!Number.isInteger(fileId) || fileId <= 0) {
865
+ throw new common_1.BadRequestException(`Invalid file id: ${fileId}`);
866
+ }
867
+ const file = await this.prismaService.file.findUnique({
868
+ where: { id: fileId },
869
+ include: { file_mimetype: true },
612
870
  });
871
+ // Mesma resposta para inexistente e para alheio seria o ideal contra enumeração, mas
872
+ // `get()` já responde 404 com o id, e divergir aqui só confundiria quem integra.
873
+ if (!file) {
874
+ throw new common_1.NotFoundException(`File not found: ${fileId}`);
875
+ }
876
+ if (file.created_by_user_id === userId) {
877
+ return file;
878
+ }
879
+ if (await this.isFileAdmin(userId)) {
880
+ return file;
881
+ }
882
+ throw new common_1.ForbiddenException(file.created_by_user_id === null
883
+ ? `File ${fileId} has no recorded owner and can only be used by an administrator`
884
+ : `File ${fileId} belongs to another user`);
613
885
  }
614
886
  async get(fileId) {
615
887
  const file = await this.prismaService.file.findUnique({
@@ -743,19 +1015,44 @@ let FileService = FileService_1 = class FileService {
743
1015
  }
744
1016
  return undefined;
745
1017
  }
1018
+ /**
1019
+ * Resolve o `file` cujo `resolveProviderPath` (location + path, ou path já combinado) bate com
1020
+ * o `filepath` embutido no token de download — é o inverso de `resolveProviderPath`.
1021
+ *
1022
+ * Bug corrigido (relatado como "Token de download inválido ou expirado" no storage local):
1023
+ * `tempURLById` assina o token com `resolveProviderPath(file)` (ex.:
1024
+ * "class-assignment-tasks/abc123.pdf", já com o prefixo de `location`), mas o upload local/S3
1025
+ * grava só o basename em `file.path` ("abc123.pdf") e o `location` separado em outra coluna.
1026
+ * Um `findFirst({ where: { path: filepath } })` direto nunca batia para esses arquivos — sempre
1027
+ * caía no `catch` abaixo e mostrava a mensagem genérica de token inválido, mesmo com o token
1028
+ * (e o arquivo) perfeitamente válidos. S3 mascarava isso porque `S3Provider.tempURL` devolve uma
1029
+ * URL assinada direto do bucket, sem passar por este método.
1030
+ */
1031
+ async findFileByResolvedPath(filepath) {
1032
+ const bySameValue = await this.prismaService.file.findFirst({
1033
+ where: { path: filepath },
1034
+ include: { file_mimetype: true },
1035
+ });
1036
+ if (bySameValue)
1037
+ return bySameValue;
1038
+ const slashIndex = filepath.lastIndexOf('/');
1039
+ if (slashIndex === -1)
1040
+ return null;
1041
+ return this.prismaService.file.findFirst({
1042
+ where: {
1043
+ location: filepath.slice(0, slashIndex),
1044
+ path: filepath.slice(slashIndex + 1),
1045
+ },
1046
+ include: { file_mimetype: true },
1047
+ });
1048
+ }
746
1049
  async download(locale, token) {
747
1050
  var _a;
748
1051
  try {
749
1052
  const { filepath } = this.jwtService.verify(token, {
750
1053
  secret: process.env.JWT_SECRET,
751
1054
  });
752
- // Buscar o arquivo no banco para pegar nome original e mimetype
753
- const file = await this.prismaService.file.findFirst({
754
- where: { path: filepath },
755
- include: {
756
- file_mimetype: true,
757
- },
758
- });
1055
+ const file = await this.findFileByResolvedPath(filepath);
759
1056
  if (!file) {
760
1057
  throw new common_1.NotFoundException((0, api_locale_1.getLocaleText)('file.download.not_found', locale, `Not found: ${filepath}`));
761
1058
  }
@@ -879,6 +1176,28 @@ let FileService = FileService_1 = class FileService {
879
1176
  };
880
1177
  return (_a = map[ext]) !== null && _a !== void 0 ? _a : null;
881
1178
  }
1179
+ /**
1180
+ * Lê só o começo do arquivo, o bastante para o sharp reconhecer o formato pelo
1181
+ * cabeçalho. Existe para o sniffing de `uploadFromPath`, que não pode chamar
1182
+ * `fs.readFile`: o mesmo caminho recebe pacotes SCORM e vídeos de vários GB, e
1183
+ * carregá-los inteiros estoura o limite de Buffer. Devolve `undefined` em qualquer
1184
+ * falha de leitura — quem chama já trata a ausência do buffer.
1185
+ */
1186
+ async readFileHeader(filePath, bytes = 64 * 1024) {
1187
+ let handle;
1188
+ try {
1189
+ handle = await fs_1.promises.open(filePath, 'r');
1190
+ const buffer = Buffer.alloc(bytes);
1191
+ const { bytesRead } = await handle.read(buffer, 0, bytes, 0);
1192
+ return bytesRead > 0 ? buffer.subarray(0, bytesRead) : undefined;
1193
+ }
1194
+ catch (_a) {
1195
+ return undefined;
1196
+ }
1197
+ finally {
1198
+ await (handle === null || handle === void 0 ? void 0 : handle.close().catch(() => undefined));
1199
+ }
1200
+ }
882
1201
  /**
883
1202
  * Resolves the MIME type to persist for an upload. When the incoming mimetype is
884
1203
  * generic (application/octet-stream or empty), recovers the real image type from
@@ -886,25 +1205,8 @@ let FileService = FileService_1 = class FileService {
886
1205
  * Concrete non-image types (video, pdf, ...) are returned unchanged.
887
1206
  */
888
1207
  async resolveEffectiveMimetype(mimetype, name, buffer) {
889
- if (mimetype && mimetype.startsWith('image/')) {
890
- // O mimetype que chega do navegador vem da EXTENSÃO do arquivo, não do
891
- // conteúdo: um PNG renomeado para `.svg` é anunciado como `image/svg+xml`.
892
- // Gravar isso faz o endpoint de imagem servir bytes PNG sob Content-Type
893
- // de SVG e, com o `nosniff` que a API envia, o navegador não corrige
894
- // sozinho — a imagem simplesmente não renderiza, sem erro nenhum.
895
- // Com os bytes em mãos, quem decide é a assinatura do arquivo.
896
- if (buffer) {
897
- const sniffed = await this.imageOptimizationService.detectImageMimetype(buffer);
898
- // Só sobrepõe quando o sniffing reconheceu o formato: um `null` significa
899
- // que o sharp não entendeu o buffer, e aí o declarado ainda é o melhor
900
- // palpite disponível.
901
- if (sniffed && sniffed !== mimetype) {
902
- this.logger.warn(`Upload "${name}" foi anunciado como ${mimetype}, mas os bytes são ${sniffed}. Persistindo o tipo real.`);
903
- return sniffed;
904
- }
905
- }
1208
+ if (mimetype && mimetype.startsWith('image/'))
906
1209
  return mimetype;
907
- }
908
1210
  // Tipos concretos não-imagem (video, pdf, ...) são mantidos como estão.
909
1211
  if (mimetype && mimetype !== 'application/octet-stream')
910
1212
  return mimetype;
@@ -1017,7 +1319,7 @@ let FileService = FileService_1 = class FileService {
1017
1319
  * which the storage layer does not normally do — cannot serve stale bytes.
1018
1320
  */
1019
1321
  async renderImageVariant(provider, providerPath, contentType, id, size, variant) {
1020
- var _a, e_1, _b, _c;
1322
+ var _a, e_3, _b, _c;
1021
1323
  var _d;
1022
1324
  const format = (_d = variant.format) !== null && _d !== void 0 ? _d : (contentType === 'image/png'
1023
1325
  ? 'png'
@@ -1045,12 +1347,12 @@ let FileService = FileService_1 = class FileService {
1045
1347
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
1046
1348
  }
1047
1349
  }
1048
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
1350
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
1049
1351
  finally {
1050
1352
  try {
1051
1353
  if (!_f && !_a && (_b = stream_1.return)) await _b.call(stream_1);
1052
1354
  }
1053
- finally { if (e_1) throw e_1.error; }
1355
+ finally { if (e_3) throw e_3.error; }
1054
1356
  }
1055
1357
  const original = Buffer.concat(chunks);
1056
1358
  const rendered = await this.imageOptimizationService.resizeBuffer(original, contentType, { width: variant.width, format: variant.format, quality: variant.quality });
@@ -1113,6 +1415,14 @@ let FileService = FileService_1 = class FileService {
1113
1415
  }
1114
1416
  return url;
1115
1417
  }
1418
+ /** Par de `tempURLById`, pela mesma razão: `path` cru resolve para NoSuchKey no S3. */
1419
+ async tempOpenURLById(fileId, expires = 3600) {
1420
+ const url = await this.tempURLById(fileId, expires);
1421
+ if (typeof url === 'string') {
1422
+ return url.replace('/file/download/', '/file/open/');
1423
+ }
1424
+ return url;
1425
+ }
1116
1426
  async getTemporaryCredentials(params) {
1117
1427
  const stsClient = new client_sts_1.STSClient({
1118
1428
  region: params.region,
@@ -1148,6 +1458,30 @@ let FileService = FileService_1 = class FileService {
1148
1458
  ETag: result.ETag,
1149
1459
  };
1150
1460
  }
1461
+ /**
1462
+ * URL assinada de um objeto em bucket avulso.
1463
+ *
1464
+ * O `getFileUrl` do provider resolve arquivos do acervo, que vivem no destino
1465
+ * ativo do core. Este metodo serve para os buckets que outras libraries
1466
+ * configuram por conta propria — o Studio grava no perfil de armazenamento
1467
+ * dele, que pode nao ser o mesmo — e por isso recebe as credenciais e o bucket
1468
+ * de fora, como o `headS3Object` ao lado.
1469
+ */
1470
+ async signS3Object(params) {
1471
+ var _a;
1472
+ const s3 = new client_s3_1.S3Client({
1473
+ region: params.region,
1474
+ credentials: Object.assign({ accessKeyId: params.accessKeyId, secretAccessKey: params.secretAccessKey }, (params.sessionToken ? { sessionToken: params.sessionToken } : {})),
1475
+ });
1476
+ const command = new client_s3_1.GetObjectCommand(Object.assign({ Bucket: params.bucket, Key: params.key }, (params.downloadFileName
1477
+ ? {
1478
+ ResponseContentDisposition: `attachment; filename="${params.downloadFileName.replace(/"/g, '')}"`,
1479
+ }
1480
+ : {})));
1481
+ return (0, s3_request_presigner_1.getSignedUrl)(s3, command, {
1482
+ expiresIn: (_a = params.expiresInSeconds) !== null && _a !== void 0 ? _a : 900,
1483
+ });
1484
+ }
1151
1485
  async headS3Bucket(params) {
1152
1486
  const s3 = new client_s3_1.S3Client({
1153
1487
  region: params.region,
@@ -1399,6 +1733,32 @@ let FileService = FileService_1 = class FileService {
1399
1733
  }
1400
1734
  };
1401
1735
  exports.FileService = FileService;
1736
+ /**
1737
+ * Mimetypes de imagem que `optimizeBuffer` devolve intactos por decisão de projeto
1738
+ * (vetor não vira bitmap, GIF animado não vira quadro único). Enfileirá-los para
1739
+ * reotimização seria custo de download e reprocessamento com resultado garantidamente
1740
+ * nulo, então ficam fora da varredura.
1741
+ */
1742
+ FileService.NON_OPTIMIZABLE_IMAGE_MIMETYPES = [
1743
+ 'image/svg+xml',
1744
+ 'image/gif',
1745
+ ];
1746
+ /**
1747
+ * Ganho mínimo para valer a regravação de um arquivo que já está no formato final.
1748
+ *
1749
+ * Recomprimir WebP sobre WebP sempre devolve alguns bytes a menos, então um limiar de
1750
+ * "estritamente menor" nunca converge: cada passada da varredura trocaria o arquivo
1751
+ * por um ganho irrisório e mais uma geração de perda de qualidade. Medido aqui, três
1752
+ * passadas seguidas rendiam 10926 → 10664 → 10662 bytes — a última custou uma
1753
+ * recompressão inteira para economizar 2 bytes.
1754
+ */
1755
+ FileService.REOPTIMIZE_MIN_GAIN_RATIO = 0.1;
1756
+ /**
1757
+ * Papéis que enxergam qualquer arquivo. Os mesmos que já governam as rotas de arquivo
1758
+ * em `route.yaml` — quem administra o acervo pela tela também o administra pelo MCP.
1759
+ */
1760
+ FileService.FILE_ADMIN_ROLES = ['admin', 'admin-access'];
1761
+ FileService.FILE_ADMIN_CACHE_TTL_MS = 30000;
1402
1762
  exports.FileService = FileService = FileService_1 = __decorate([
1403
1763
  (0, common_1.Injectable)(),
1404
1764
  __param(0, (0, common_1.Inject)((0, common_1.forwardRef)(() => api_prisma_1.PrismaService))),