@omnizap-system/omnizap 2.6.0 → 2.6.2

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 (261) hide show
  1. package/.env.example +58 -13
  2. package/.github/workflows/ci.yml +5 -5
  3. package/.github/workflows/codeql.yml +1 -1
  4. package/.github/workflows/db-migration-check.yml +2 -2
  5. package/.github/workflows/dependency-review.yml +1 -1
  6. package/.github/workflows/deploy.yml +2 -2
  7. package/.github/workflows/release.yml +2 -2
  8. package/.github/workflows/security-attest-provenance.yml +2 -2
  9. package/.github/workflows/security-gitleaks.yml +13 -4
  10. package/.github/workflows/security-runner-hardening.yml +2 -2
  11. package/.github/workflows/security-scorecard.yml +1 -1
  12. package/.github/workflows/security-zap-baseline.yml +1 -1
  13. package/.github/workflows/security-zap-full-scan.yml +2 -1
  14. package/.github/workflows/security-zizmor.yml +1 -1
  15. package/.github/workflows/wiki-sync.yml +1 -1
  16. package/.gitleaksignore +9 -0
  17. package/CODE_OF_CONDUCT.md +2 -2
  18. package/GEMINI.md +64 -0
  19. package/README.md +52 -82
  20. package/SECURITY.md +1 -1
  21. package/app/config/index.js +2 -0
  22. package/app/configParts/adminIdentity.js +5 -5
  23. package/app/configParts/baileysConfig.js +230 -58
  24. package/app/configParts/groupUtils.js +5 -0
  25. package/app/configParts/messagePersistenceService.js +145 -4
  26. package/app/configParts/sessionConfig.js +157 -0
  27. package/app/connection/baileysCompatibility.test.js +1 -1
  28. package/app/connection/groupOwnerWriteStateResolver.js +109 -0
  29. package/app/connection/socketController.js +660 -158
  30. package/app/connection/socketController.multiSession.test.js +108 -0
  31. package/app/controllers/messageController.js +1 -1
  32. package/app/controllers/messagePipeline/commandMiddleware.js +12 -10
  33. package/app/controllers/messagePipeline/conversationMiddleware.js +2 -1
  34. package/app/controllers/messagePipeline/messagePipelineMiddlewares.test.js +104 -0
  35. package/app/controllers/messagePipeline/preProcessingMiddlewares.js +80 -2
  36. package/app/controllers/messageProcessingPipeline.js +93 -13
  37. package/app/controllers/messageProcessingPipeline.test.js +200 -0
  38. package/app/modules/adminModule/AGENT.md +1 -1
  39. package/app/modules/adminModule/commandConfig.json +3318 -1347
  40. package/app/modules/adminModule/groupCommandHandlers.js +858 -15
  41. package/app/modules/adminModule/groupCommandHandlers.test.js +378 -11
  42. package/app/modules/adminModule/groupWarningRepository.js +152 -0
  43. package/app/modules/aiModule/AGENT.md +47 -30
  44. package/app/modules/aiModule/aiConfigRuntime.js +1 -0
  45. package/app/modules/aiModule/catCommand.js +135 -27
  46. package/app/modules/aiModule/commandConfig.json +114 -28
  47. package/app/modules/analyticsModule/messageAnalysisEventRepository.js +54 -6
  48. package/app/modules/gameModule/AGENT.md +1 -1
  49. package/app/modules/gameModule/commandConfig.json +29 -0
  50. package/app/modules/menuModule/AGENT.md +1 -1
  51. package/app/modules/menuModule/commandConfig.json +45 -10
  52. package/app/modules/menuModule/menuCatalogService.js +190 -0
  53. package/app/modules/menuModule/menuCommandUsageRepository.js +109 -0
  54. package/app/modules/menuModule/menuDynamicService.js +511 -0
  55. package/app/modules/menuModule/menuDynamicService.test.js +141 -0
  56. package/app/modules/menuModule/menus.js +36 -5
  57. package/app/modules/playModule/AGENT.md +10 -5
  58. package/app/modules/playModule/commandConfig.json +140 -12
  59. package/app/modules/playModule/playCommand.js +1 -1417
  60. package/app/modules/playModule/playCommandConstants.js +80 -0
  61. package/app/modules/playModule/playCommandCore.js +361 -0
  62. package/app/modules/playModule/playCommandHandlers.js +41 -0
  63. package/app/modules/playModule/playCommandMediaClient.js +1872 -0
  64. package/app/modules/playModule/playConfigRuntime.js +245 -4
  65. package/app/modules/playModule/playModuleCriticalFlows.test.js +152 -0
  66. package/app/modules/quoteModule/AGENT.md +1 -1
  67. package/app/modules/quoteModule/commandConfig.json +29 -0
  68. package/app/modules/quoteModule/quoteCommand.js +3 -2
  69. package/app/modules/rpgPokemonModule/AGENT.md +1 -1
  70. package/app/modules/rpgPokemonModule/commandConfig.json +29 -0
  71. package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +5 -4
  72. package/app/modules/rpgPokemonModule/rpgBattleService.test.js +2 -1
  73. package/app/modules/rpgPokemonModule/rpgPokemonDomain.js +2 -1
  74. package/app/modules/rpgPokemonModule/rpgPokemonService.js +38 -37
  75. package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +4 -3
  76. package/app/modules/statsModule/AGENT.md +1 -1
  77. package/app/modules/statsModule/commandConfig.json +58 -0
  78. package/app/modules/statsModule/rankingCommon.js +5 -4
  79. package/app/modules/stickerModule/AGENT.md +1 -1
  80. package/app/modules/stickerModule/addStickerMetadata.js +4 -3
  81. package/app/modules/stickerModule/commandConfig.json +145 -0
  82. package/app/modules/stickerModule/stickerCommand.js +1 -1
  83. package/app/modules/stickerPackModule/AGENT.md +1 -1
  84. package/app/modules/stickerPackModule/autoPackCollectorService.js +5 -1
  85. package/app/modules/stickerPackModule/commandConfig.json +29 -0
  86. package/app/modules/stickerPackModule/semanticThemeClusterService.js +7 -6
  87. package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +10 -9
  88. package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +9 -8
  89. package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +3 -2
  90. package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +2 -1
  91. package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +80 -58
  92. package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +2 -1
  93. package/app/modules/stickerPackModule/stickerPackRepository.js +2 -1
  94. package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +5 -4
  95. package/app/modules/stickerPackModule/stickerPackService.js +13 -6
  96. package/app/modules/stickerPackModule/stickerStorageService.js +3 -2
  97. package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +2 -1
  98. package/app/modules/systemMetricsModule/AGENT.md +1 -1
  99. package/app/modules/systemMetricsModule/commandConfig.json +29 -0
  100. package/app/modules/systemMetricsModule/pingCommand.js +6 -5
  101. package/app/modules/tiktokModule/AGENT.md +1 -1
  102. package/app/modules/tiktokModule/commandConfig.json +29 -0
  103. package/app/modules/tiktokModule/tiktokCommand.js +2 -1
  104. package/app/modules/userModule/AGENT.md +1 -1
  105. package/app/modules/userModule/commandConfig.json +29 -0
  106. package/app/modules/userModule/userCommand.js +72 -23
  107. package/app/modules/waifuPicsModule/AGENT.md +57 -27
  108. package/app/modules/waifuPicsModule/commandConfig.json +87 -0
  109. package/app/modules/waifuPicsModule/waifuPicsCommand.js +3 -2
  110. package/app/observability/metrics.js +136 -0
  111. package/app/services/ai/commandConfigEnrichmentService.js +229 -47
  112. package/app/services/ai/conversationRouterService.js +4 -3
  113. package/app/services/ai/geminiService.js +132 -7
  114. package/app/services/ai/geminiService.test.js +59 -2
  115. package/app/services/ai/globalModuleAiHelpService.js +3 -2
  116. package/app/services/ai/messageCommandExecutionService.js +2 -1
  117. package/app/services/ai/moduleAiHelpCoreService.js +45 -14
  118. package/app/services/ai/moduleToolExecutorService.js +3 -2
  119. package/app/services/ai/moduleToolRegistryService.js +2 -1
  120. package/app/services/ai/toolCandidateSelectorService.js +6 -5
  121. package/app/services/auth/googleWebLinkService.js +3 -2
  122. package/app/services/auth/whatsappLoginLinkService.js +3 -2
  123. package/app/services/external/pokeApiService.js +4 -3
  124. package/app/services/group/groupMetadataService.js +24 -1
  125. package/app/services/infra/dbWriteQueue.js +57 -26
  126. package/app/services/infra/featureFlagService.js +2 -1
  127. package/app/services/messaging/captchaService.js +3 -2
  128. package/app/services/messaging/newsBroadcastService.js +846 -29
  129. package/app/services/multiSession/assignmentBalancerService.js +457 -0
  130. package/app/services/multiSession/groupOwnershipRepository.js +381 -0
  131. package/app/services/multiSession/groupOwnershipService.js +890 -0
  132. package/app/services/multiSession/groupOwnershipService.test.js +309 -0
  133. package/app/services/multiSession/sessionRegistryService.js +293 -0
  134. package/app/services/sticker/stickerFocusService.js +11 -10
  135. package/app/store/aiPromptStore.js +36 -19
  136. package/app/store/conversationSessionStore.js +7 -6
  137. package/app/store/groupConfigStore.js +41 -5
  138. package/app/store/premiumUserStore.js +21 -7
  139. package/app/utils/antiLink/antiLinkModule.js +352 -16
  140. package/app/workers/aiHelperContinuousLearningWorker.js +512 -0
  141. package/app/workers/aiLearningWorker.js +6 -5
  142. package/app/workers/commandConfigEnrichmentWorker.js +4 -3
  143. package/database/index.js +14 -8
  144. package/database/migrations/20260307_d0_hardening_down.sql +1 -1
  145. package/database/migrations/20260314_d7_canonical_sender_down.sql +1 -1
  146. package/database/migrations/20260406_d30_security_analytics_down.sql +1 -1
  147. package/database/migrations/20260411_d35_group_community_metadata_down.sql +59 -0
  148. package/database/migrations/20260411_d35_group_community_metadata_up.sql +62 -0
  149. package/database/migrations/20260412_d36_system_config_tables_down.sql +32 -0
  150. package/database/migrations/20260412_d36_system_config_tables_up.sql +66 -0
  151. package/database/migrations/20260413_d37_group_user_warnings_down.sql +11 -0
  152. package/database/migrations/20260413_d37_group_user_warnings_up.sql +24 -0
  153. package/database/migrations/20260414_d38_multi_session_foundation_down.sql +72 -0
  154. package/database/migrations/20260414_d38_multi_session_foundation_up.sql +125 -0
  155. package/database/migrations/20260414_d39_multi_session_cutover_down.sql +103 -0
  156. package/database/migrations/20260414_d39_multi_session_cutover_up.sql +83 -0
  157. package/database/schema.sql +102 -1
  158. package/docker-compose.yml +4 -1
  159. package/docs/compliance/acceptable-use-policy-2026-03-07.md +1 -1
  160. package/docs/compliance/dpa-b2b-standard-2026-03-07.md +1 -1
  161. package/docs/compliance/privacy-policy-2026-03-07.md +4 -4
  162. package/docs/security/dsar-lgpd-runbook-2026-03-07.md +1 -1
  163. package/docs/security/incident-response-lgpd-anpd-runbook-2026-03-07.md +1 -1
  164. package/docs/security/network-hardening-runbook-2026-03-07.md +53 -0
  165. package/docs/security/omnizap-static-security-headers.conf +25 -0
  166. package/docs/wiki/Home.md +1 -1
  167. package/ecosystem.prod.config.cjs +32 -12
  168. package/index.js +57 -23
  169. package/observability/alert-rules.yml +20 -0
  170. package/observability/grafana/dashboards/omnizap-system-admin.json +229 -0
  171. package/observability/mysql-setup.sql +4 -4
  172. package/observability/system-admin-observability.md +26 -0
  173. package/package.json +20 -6
  174. package/public/apple-touch-icon.png +0 -0
  175. package/public/comandos/commands-catalog.json +2853 -3326
  176. package/public/favicon-16x16.png +0 -0
  177. package/public/favicon-32x32.png +0 -0
  178. package/public/favicon.ico +0 -0
  179. package/public/js/apps/apiDocsApp.js +3 -2
  180. package/public/js/apps/commandsReactApp.js +280 -99
  181. package/public/js/apps/createPackApp.js +11 -10
  182. package/public/js/apps/homeReactApp.js +181 -130
  183. package/public/js/apps/loginReactApp.js +1 -1
  184. package/public/js/apps/stickersApp.js +263 -110
  185. package/public/js/apps/termsReactApp.js +73 -24
  186. package/public/js/apps/userApp.js +4 -3
  187. package/public/js/apps/userPasswordResetReactApp.js +406 -0
  188. package/public/js/apps/userReactApp.js +355 -280
  189. package/public/js/apps/userSystemAdmReactApp.js +1506 -0
  190. package/public/pages/api-docs.html +1 -1
  191. package/public/pages/aup.html +2 -2
  192. package/public/pages/dpa.html +3 -3
  193. package/public/pages/licenca.html +4 -4
  194. package/public/pages/login.html +1 -1
  195. package/public/pages/notice-and-takedown.html +2 -2
  196. package/public/pages/politica-de-privacidade.html +6 -6
  197. package/public/pages/seo-bot-whatsapp-para-grupo.html +3 -3
  198. package/public/pages/seo-bot-whatsapp-sem-programar.html +3 -3
  199. package/public/pages/seo-como-automatizar-avisos-no-whatsapp.html +3 -3
  200. package/public/pages/seo-como-criar-comandos-whatsapp.html +3 -3
  201. package/public/pages/seo-como-evitar-spam-no-whatsapp.html +3 -3
  202. package/public/pages/seo-como-moderar-grupo-whatsapp.html +3 -3
  203. package/public/pages/seo-como-organizar-comunidade-whatsapp.html +3 -3
  204. package/public/pages/seo-melhor-bot-whatsapp-para-grupos.html +3 -3
  205. package/public/pages/stickers-admin.html +1 -1
  206. package/public/pages/stickers-create.html +1 -1
  207. package/public/pages/stickers.html +6 -6
  208. package/public/pages/suboperadores.html +2 -2
  209. package/public/pages/termos-de-uso-texto-integral.html +6 -6
  210. package/public/pages/termos-de-uso.html +3 -3
  211. package/public/pages/user-password-reset.html +4 -5
  212. package/public/pages/user-systemadm.html +9 -463
  213. package/public/pages/user.html +2 -2
  214. package/scripts/clear-whatsapp-session.sh +123 -0
  215. package/scripts/core-ai-mode.mjs +163 -0
  216. package/scripts/deploy.sh +11 -1
  217. package/scripts/email-broadcast-terms-update.mjs +2 -1
  218. package/scripts/enrich-command-config-ux-openai.mjs +492 -0
  219. package/scripts/generate-commands-catalog.mjs +166 -2
  220. package/scripts/generate-module-agents.mjs +2 -1
  221. package/scripts/generate-seo-satellite-pages.mjs +5 -4
  222. package/scripts/github-deploy-notify.mjs +2 -1
  223. package/scripts/github-release-notify.mjs +25 -10
  224. package/scripts/new-whatsapp-session.sh +317 -0
  225. package/scripts/release.sh +2 -19
  226. package/scripts/security-smoketest.mjs +6 -5
  227. package/scripts/security-web-surface-check.mjs +218 -0
  228. package/scripts/sticker-catalog-loadtest.mjs +5 -4
  229. package/server/auth/googleWebAuth/googleWebAuthService.js +8 -7
  230. package/server/auth/jwt/webJwtService.js +1 -1
  231. package/server/auth/stickerCatalogAuthContext.js +2 -1
  232. package/server/auth/termsAcceptance/termsAcceptanceHandler.js +2 -1
  233. package/server/auth/userPassword/userPasswordAuthService.js +2 -1
  234. package/server/auth/userPassword/userPasswordRecoveryService.js +4 -3
  235. package/server/auth/webAccount/webAccountHandlers.js +9 -10
  236. package/server/controllers/admin/adminPanelHandlers.js +267 -16
  237. package/server/controllers/admin/systemAdminController.js +267 -0
  238. package/server/controllers/seo/stickerCatalogSeoContext.js +10 -9
  239. package/server/controllers/sticker/nonCatalogHandlers.js +2 -1
  240. package/server/controllers/sticker/stickerCatalogController.js +23 -36
  241. package/server/controllers/system/contactController.js +9 -17
  242. package/server/controllers/system/githubController.js +3 -2
  243. package/server/controllers/system/stickerCatalogSystemContext.js +41 -19
  244. package/server/controllers/system/systemController.js +254 -1
  245. package/server/controllers/system/systemMetricsController.js +2 -1
  246. package/server/controllers/userController.js +6 -0
  247. package/server/email/emailTemplateService.js +5 -3
  248. package/server/http/httpServer.js +11 -6
  249. package/server/middleware/rateLimit.js +2 -1
  250. package/server/middleware/securityHeaders.js +20 -1
  251. package/server/routes/admin/systemAdminRouter.js +6 -0
  252. package/server/routes/indexRouter.js +30 -6
  253. package/server/routes/observability/grafanaProxyRouter.js +254 -0
  254. package/server/routes/static/staticPageRouter.js +27 -1
  255. package/server/utils/publicContact.js +31 -0
  256. package/utils/time/timeModule.js +135 -0
  257. package/utils/time/timeModule.test.js +65 -0
  258. package/utils/whatsapp/contactEnv.js +39 -0
  259. package/vite.config.mjs +7 -1
  260. package/public/assets/images/brand-icon-192.png +0 -0
  261. package/scripts/sync-readme-snapshot.mjs +0 -133
@@ -0,0 +1,200 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+
4
+ import { createPreProcessingMiddlewares } from './messagePipeline/preProcessingMiddlewares.js';
5
+ import { createCommandMiddleware } from './messagePipeline/commandMiddleware.js';
6
+
7
+ const createContext = (overrides = {}) => ({
8
+ sock: {},
9
+ messageInfo: { key: { id: 'msg-1' }, message: { conversation: '/menu' } },
10
+ key: { id: 'msg-1' },
11
+ remoteJid: '120363111111111111@g.us',
12
+ isGroupMessage: true,
13
+ extractedText: '/menu',
14
+ senderJid: '5511999999999@s.whatsapp.net',
15
+ senderIdentity: '5511999999999@s.whatsapp.net',
16
+ senderName: 'Tester',
17
+ expirationMessage: 0,
18
+ botJid: '5511888888888@s.whatsapp.net',
19
+ isMessageFromBot: false,
20
+ commandPrefix: '/',
21
+ mediaEntries: [],
22
+ upsertType: 'notify',
23
+ isNotifyUpsert: true,
24
+ sessionId: 'session-a',
25
+ ownerSessionId: null,
26
+ isCommandMessage: false,
27
+ hasCommandPrefix: false,
28
+ pipelineStopped: false,
29
+ analysisPayload: {
30
+ processingResult: 'processed',
31
+ errorCode: null,
32
+ metadata: {},
33
+ isCommand: false,
34
+ commandPrefix: '/',
35
+ commandName: null,
36
+ commandArgsCount: 0,
37
+ commandKnown: null,
38
+ },
39
+ ...overrides,
40
+ });
41
+
42
+ const createStopMessagePipeline = () => (ctx, processingResult = '', metadataPatch = null) => {
43
+ if (processingResult) {
44
+ ctx.analysisPayload.processingResult = processingResult;
45
+ }
46
+ if (metadataPatch) {
47
+ ctx.analysisPayload.metadata = {
48
+ ...(ctx.analysisPayload.metadata || {}),
49
+ ...(metadataPatch || {}),
50
+ };
51
+ }
52
+ ctx.pipelineStopped = true;
53
+ return { stop: true };
54
+ };
55
+
56
+ const mergeAnalysisMetadata = (analysisPayload, patch) => {
57
+ analysisPayload.metadata = {
58
+ ...(analysisPayload.metadata || {}),
59
+ ...(patch || {}),
60
+ };
61
+ };
62
+
63
+ const createSharedCommandDedupe = () => {
64
+ const cache = new Map();
65
+ return {
66
+ isDuplicateCommandExecution: (chatId, messageId) => cache.has(`${chatId}:${messageId}`),
67
+ markCommandExecution: (chatId, messageId) => {
68
+ cache.set(`${chatId}:${messageId}`, true);
69
+ },
70
+ };
71
+ };
72
+
73
+ const createCommandMiddlewareForTest = ({ executeRouteSpy, dedupe }) =>
74
+ createCommandMiddleware({
75
+ isAdminCommand: () => false,
76
+ isKnownNonAdminCommand: () => true,
77
+ isDuplicateCommandExecution: dedupe.isDuplicateCommandExecution,
78
+ markCommandExecution: dedupe.markCommandExecution,
79
+ MESSAGE_COMMAND_DEDUPE_TTL_MS: 120_000,
80
+ stopMessagePipeline: createStopMessagePipeline(),
81
+ WHATSAPP_COMMAND_REQUIRES_GOOGLE_LOGIN: false,
82
+ resolveCanonicalSenderJidForContext: async () => '5511999999999@s.whatsapp.net',
83
+ ensureUserHasGoogleWebLoginForCommand: async () => ({ allowed: true }),
84
+ SITE_LOGIN_URL: 'https://omnizap.shop/login',
85
+ COMMAND_REACT_EMOJI: '',
86
+ sendAndStore: async () => {},
87
+ executeMessageCommandRoute: async (payload) => {
88
+ executeRouteSpy.push(payload);
89
+ return {
90
+ commandRoute: payload.command || 'menu',
91
+ commandResult: { ok: true },
92
+ };
93
+ },
94
+ runCommand: async (_label, handler) => {
95
+ try {
96
+ await handler();
97
+ return { ok: true };
98
+ } catch (error) {
99
+ return { ok: false, error };
100
+ }
101
+ },
102
+ sendReply: async () => {},
103
+ registerGlobalHelpCommandExecution: async () => {},
104
+ logger: { warn: () => {} },
105
+ normalizeAnalysisErrorCode: () => 'processing_error',
106
+ resolveSenderAdminForContext: async () => false,
107
+ isUserAdmin: async () => false,
108
+ buildCommandErrorHelpText: async () => '',
109
+ mergeAnalysisMetadata,
110
+ });
111
+
112
+ test('messageProcessingPipeline: com owner enforcement ativo, apenas owner executa comando no grupo', async () => {
113
+ const pre = createPreProcessingMiddlewares({
114
+ executeQuery: async () => [],
115
+ TABLES: { RPG_PLAYER: 'rpg_player' },
116
+ isStatusJid: () => false,
117
+ stopMessagePipeline: createStopMessagePipeline(),
118
+ handleAntiLink: async () => false,
119
+ ensureCommandPrefixForContext: async () => '/',
120
+ resolveCaptchaByMessage: async () => {},
121
+ maybeHandleStartLoginMessage: async () => false,
122
+ mergeAnalysisMetadata,
123
+ ensureGroupConfigForContext: async () => ({}),
124
+ resolveStickerFocusState: () => ({ enabled: false }),
125
+ resolveStickerFocusMessageClassification: () => ({ isThrottleCandidate: false }),
126
+ resolveGroupOwnerForContext: async (ctx) => {
127
+ ctx.ownerSessionId = 'session-a';
128
+ return { ownerSessionId: 'session-a', assignmentVersion: 7 };
129
+ },
130
+ ownerEnforcementMode: 'enforce',
131
+ primarySessionId: 'session-a',
132
+ resolveSenderAdminForContext: async () => false,
133
+ isUserAdmin: async () => false,
134
+ canSendMessageInStickerFocus: () => ({ allowed: true, remainingMs: 0 }),
135
+ registerMessageUsageInStickerFocus: () => {},
136
+ shouldSendStickerFocusWarning: () => false,
137
+ sendReply: async () => {},
138
+ formatStickerFocusRuleLabel: () => '',
139
+ formatRemainingMinutesLabel: () => 1,
140
+ logger: { warn: () => {}, info: () => {} },
141
+ });
142
+
143
+ const executeRouteSpy = [];
144
+ const dedupe = createSharedCommandDedupe();
145
+ const commandMiddleware = createCommandMiddlewareForTest({ executeRouteSpy, dedupe });
146
+
147
+ const ownerCtx = createContext({
148
+ sessionId: 'session-a',
149
+ key: { id: 'msg-shared' },
150
+ messageInfo: { key: { id: 'msg-shared' }, message: { conversation: '/menu' } },
151
+ });
152
+ const nonOwnerCtx = createContext({
153
+ sessionId: 'session-b',
154
+ key: { id: 'msg-shared' },
155
+ messageInfo: { key: { id: 'msg-shared' }, message: { conversation: '/menu' } },
156
+ });
157
+
158
+ await pre.enforceGroupOwnerMiddleware(ownerCtx);
159
+ await pre.detectCommandIntentMiddleware(ownerCtx);
160
+ await commandMiddleware(ownerCtx);
161
+
162
+ const blockedResult = await pre.enforceGroupOwnerMiddleware(nonOwnerCtx);
163
+ assert.deepEqual(blockedResult, { stop: true });
164
+ await pre.detectCommandIntentMiddleware(nonOwnerCtx);
165
+ if (!nonOwnerCtx.pipelineStopped) {
166
+ await commandMiddleware(nonOwnerCtx);
167
+ }
168
+
169
+ assert.equal(executeRouteSpy.length, 1);
170
+ assert.equal(ownerCtx.analysisPayload.processingResult, 'command_executed');
171
+ assert.equal(nonOwnerCtx.analysisPayload.processingResult, 'blocked_group_owner_enforcement');
172
+ });
173
+
174
+ test('messageProcessingPipeline: dedupe de comando por chat+message impede execução dupla em duas sessões', async () => {
175
+ const executeRouteSpy = [];
176
+ const dedupe = createSharedCommandDedupe();
177
+ const commandMiddleware = createCommandMiddlewareForTest({ executeRouteSpy, dedupe });
178
+
179
+ const firstCtx = createContext({
180
+ sessionId: 'session-a',
181
+ isCommandMessage: true,
182
+ hasCommandPrefix: true,
183
+ key: { id: 'dup-msg-1' },
184
+ messageInfo: { key: { id: 'dup-msg-1' }, message: { conversation: '/menu' } },
185
+ });
186
+ const secondCtx = createContext({
187
+ sessionId: 'session-b',
188
+ isCommandMessage: true,
189
+ hasCommandPrefix: true,
190
+ key: { id: 'dup-msg-1' },
191
+ messageInfo: { key: { id: 'dup-msg-1' }, message: { conversation: '/menu' } },
192
+ });
193
+
194
+ await commandMiddleware(firstCtx);
195
+ await commandMiddleware(secondCtx);
196
+
197
+ assert.equal(executeRouteSpy.length, 1);
198
+ assert.equal(firstCtx.analysisPayload.processingResult, 'command_executed');
199
+ assert.equal(secondCtx.analysisPayload.processingResult, 'duplicate_command_ignored');
200
+ });
@@ -7,7 +7,7 @@ Este arquivo e destinado a agentes de IA para gerar respostas no contexto dos co
7
7
  - arquivo_base: `app/modules/adminModule/commandConfig.json`
8
8
  - schema_version: `2.0.0`
9
9
  - module_enabled: `true`
10
- - generated_at: `2026-03-11T02:35:17.177Z`
10
+ - generated_at: `2026-03-17T04:04:14.195Z`
11
11
 
12
12
  ## Escopo do Modulo
13
13