@omnizap-system/omnizap 2.6.1 → 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 (156) hide show
  1. package/.env.example +54 -9
  2. package/.github/workflows/ci.yml +3 -3
  3. package/.github/workflows/security-runner-hardening.yml +1 -1
  4. package/.github/workflows/security-zap-full-scan.yml +1 -0
  5. package/app/config/index.js +2 -0
  6. package/app/configParts/adminIdentity.js +5 -5
  7. package/app/configParts/baileysConfig.js +226 -55
  8. package/app/configParts/groupUtils.js +5 -0
  9. package/app/configParts/messagePersistenceService.js +143 -3
  10. package/app/configParts/sessionConfig.js +157 -0
  11. package/app/connection/baileysCompatibility.test.js +1 -1
  12. package/app/connection/groupOwnerWriteStateResolver.js +109 -0
  13. package/app/connection/socketController.js +625 -124
  14. package/app/connection/socketController.multiSession.test.js +108 -0
  15. package/app/controllers/messageController.js +1 -1
  16. package/app/controllers/messagePipeline/commandMiddleware.js +12 -10
  17. package/app/controllers/messagePipeline/conversationMiddleware.js +2 -1
  18. package/app/controllers/messagePipeline/messagePipelineMiddlewares.test.js +104 -0
  19. package/app/controllers/messagePipeline/preProcessingMiddlewares.js +80 -2
  20. package/app/controllers/messageProcessingPipeline.js +88 -9
  21. package/app/controllers/messageProcessingPipeline.test.js +200 -0
  22. package/app/modules/adminModule/AGENT.md +1 -1
  23. package/app/modules/adminModule/commandConfig.json +3318 -1347
  24. package/app/modules/adminModule/groupCommandHandlers.js +856 -14
  25. package/app/modules/adminModule/groupCommandHandlers.test.js +375 -9
  26. package/app/modules/adminModule/groupWarningRepository.js +152 -0
  27. package/app/modules/aiModule/AGENT.md +47 -30
  28. package/app/modules/aiModule/aiConfigRuntime.js +1 -0
  29. package/app/modules/aiModule/catCommand.js +132 -25
  30. package/app/modules/aiModule/commandConfig.json +114 -28
  31. package/app/modules/analyticsModule/messageAnalysisEventRepository.js +54 -6
  32. package/app/modules/gameModule/AGENT.md +1 -1
  33. package/app/modules/gameModule/commandConfig.json +29 -0
  34. package/app/modules/menuModule/AGENT.md +1 -1
  35. package/app/modules/menuModule/commandConfig.json +45 -10
  36. package/app/modules/menuModule/menuCatalogService.js +190 -0
  37. package/app/modules/menuModule/menuCommandUsageRepository.js +109 -0
  38. package/app/modules/menuModule/menuDynamicService.js +511 -0
  39. package/app/modules/menuModule/menuDynamicService.test.js +141 -0
  40. package/app/modules/menuModule/menus.js +36 -5
  41. package/app/modules/playModule/AGENT.md +10 -5
  42. package/app/modules/playModule/commandConfig.json +74 -16
  43. package/app/modules/playModule/playCommandConstants.js +13 -7
  44. package/app/modules/playModule/playCommandCore.js +4 -6
  45. package/app/modules/playModule/{playCommandYtDlpClient.js → playCommandMediaClient.js} +684 -332
  46. package/app/modules/playModule/playConfigRuntime.js +5 -6
  47. package/app/modules/playModule/playModuleCriticalFlows.test.js +44 -59
  48. package/app/modules/quoteModule/AGENT.md +1 -1
  49. package/app/modules/quoteModule/commandConfig.json +29 -0
  50. package/app/modules/rpgPokemonModule/AGENT.md +1 -1
  51. package/app/modules/rpgPokemonModule/commandConfig.json +29 -0
  52. package/app/modules/statsModule/AGENT.md +1 -1
  53. package/app/modules/statsModule/commandConfig.json +58 -0
  54. package/app/modules/stickerModule/AGENT.md +1 -1
  55. package/app/modules/stickerModule/commandConfig.json +145 -0
  56. package/app/modules/stickerPackModule/AGENT.md +1 -1
  57. package/app/modules/stickerPackModule/autoPackCollectorService.js +5 -1
  58. package/app/modules/stickerPackModule/commandConfig.json +29 -0
  59. package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +1 -1
  60. package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +78 -57
  61. package/app/modules/stickerPackModule/stickerPackService.js +13 -6
  62. package/app/modules/systemMetricsModule/AGENT.md +1 -1
  63. package/app/modules/systemMetricsModule/commandConfig.json +29 -0
  64. package/app/modules/tiktokModule/AGENT.md +1 -1
  65. package/app/modules/tiktokModule/commandConfig.json +29 -0
  66. package/app/modules/userModule/AGENT.md +1 -1
  67. package/app/modules/userModule/commandConfig.json +29 -0
  68. package/app/modules/waifuPicsModule/AGENT.md +57 -27
  69. package/app/modules/waifuPicsModule/commandConfig.json +87 -0
  70. package/app/observability/metrics.js +136 -0
  71. package/app/services/ai/commandConfigEnrichmentService.js +229 -47
  72. package/app/services/ai/geminiService.js +131 -7
  73. package/app/services/ai/geminiService.test.js +59 -2
  74. package/app/services/ai/moduleAiHelpCoreService.js +33 -4
  75. package/app/services/group/groupMetadataService.js +24 -1
  76. package/app/services/infra/dbWriteQueue.js +51 -21
  77. package/app/services/messaging/newsBroadcastService.js +843 -27
  78. package/app/services/multiSession/assignmentBalancerService.js +457 -0
  79. package/app/services/multiSession/groupOwnershipRepository.js +381 -0
  80. package/app/services/multiSession/groupOwnershipService.js +890 -0
  81. package/app/services/multiSession/groupOwnershipService.test.js +309 -0
  82. package/app/services/multiSession/sessionRegistryService.js +293 -0
  83. package/app/store/aiPromptStore.js +36 -19
  84. package/app/store/groupConfigStore.js +41 -5
  85. package/app/store/premiumUserStore.js +21 -7
  86. package/app/utils/antiLink/antiLinkModule.js +352 -16
  87. package/app/workers/aiHelperContinuousLearningWorker.js +512 -0
  88. package/database/index.js +6 -0
  89. package/database/migrations/20260307_d0_hardening_down.sql +1 -1
  90. package/database/migrations/20260314_d7_canonical_sender_down.sql +1 -1
  91. package/database/migrations/20260406_d30_security_analytics_down.sql +1 -1
  92. package/database/migrations/20260411_d35_group_community_metadata_down.sql +59 -0
  93. package/database/migrations/20260411_d35_group_community_metadata_up.sql +62 -0
  94. package/database/migrations/20260412_d36_system_config_tables_down.sql +32 -0
  95. package/database/migrations/20260412_d36_system_config_tables_up.sql +66 -0
  96. package/database/migrations/20260413_d37_group_user_warnings_down.sql +11 -0
  97. package/database/migrations/20260413_d37_group_user_warnings_up.sql +24 -0
  98. package/database/migrations/20260414_d38_multi_session_foundation_down.sql +72 -0
  99. package/database/migrations/20260414_d38_multi_session_foundation_up.sql +125 -0
  100. package/database/migrations/20260414_d39_multi_session_cutover_down.sql +103 -0
  101. package/database/migrations/20260414_d39_multi_session_cutover_up.sql +83 -0
  102. package/database/schema.sql +102 -1
  103. package/docker-compose.yml +4 -1
  104. package/docs/compliance/acceptable-use-policy-2026-03-07.md +1 -1
  105. package/docs/compliance/privacy-policy-2026-03-07.md +2 -2
  106. package/docs/security/dsar-lgpd-runbook-2026-03-07.md +1 -1
  107. package/docs/security/network-hardening-runbook-2026-03-07.md +53 -0
  108. package/docs/security/omnizap-static-security-headers.conf +25 -0
  109. package/ecosystem.prod.config.cjs +31 -11
  110. package/index.js +52 -18
  111. package/observability/alert-rules.yml +20 -0
  112. package/observability/grafana/dashboards/omnizap-system-admin.json +229 -0
  113. package/observability/mysql-setup.sql +4 -4
  114. package/observability/system-admin-observability.md +26 -0
  115. package/package.json +12 -5
  116. package/public/comandos/commands-catalog.json +2253 -78
  117. package/public/js/apps/commandsReactApp.js +267 -87
  118. package/public/js/apps/createPackApp.js +3 -3
  119. package/public/js/apps/stickersApp.js +255 -103
  120. package/public/js/apps/termsReactApp.js +57 -8
  121. package/public/js/apps/userPasswordResetReactApp.js +406 -0
  122. package/public/js/apps/userReactApp.js +96 -47
  123. package/public/js/apps/userSystemAdmReactApp.js +1506 -0
  124. package/public/pages/politica-de-privacidade.html +1 -1
  125. package/public/pages/stickers.html +5 -5
  126. package/public/pages/termos-de-uso-texto-integral.html +1 -1
  127. package/public/pages/termos-de-uso.html +1 -1
  128. package/public/pages/user-password-reset.html +3 -4
  129. package/public/pages/user-systemadm.html +8 -462
  130. package/public/pages/user.html +1 -1
  131. package/scripts/clear-whatsapp-session.sh +123 -0
  132. package/scripts/core-ai-mode.mjs +163 -0
  133. package/scripts/deploy.sh +10 -0
  134. package/scripts/enrich-command-config-ux-openai.mjs +492 -0
  135. package/scripts/generate-commands-catalog.mjs +155 -0
  136. package/scripts/new-whatsapp-session.sh +317 -0
  137. package/scripts/security-web-surface-check.mjs +218 -0
  138. package/server/controllers/admin/adminPanelHandlers.js +253 -3
  139. package/server/controllers/admin/systemAdminController.js +267 -0
  140. package/server/controllers/sticker/stickerCatalogController.js +9 -23
  141. package/server/controllers/system/contactController.js +9 -17
  142. package/server/controllers/system/stickerCatalogSystemContext.js +27 -6
  143. package/server/controllers/system/systemController.js +254 -1
  144. package/server/controllers/userController.js +6 -0
  145. package/server/email/emailTemplateService.js +3 -2
  146. package/server/http/httpServer.js +8 -4
  147. package/server/middleware/securityHeaders.js +20 -1
  148. package/server/routes/admin/systemAdminRouter.js +6 -0
  149. package/server/routes/indexRouter.js +30 -6
  150. package/server/routes/observability/grafanaProxyRouter.js +254 -0
  151. package/server/routes/static/staticPageRouter.js +27 -1
  152. package/server/utils/publicContact.js +31 -0
  153. package/utils/whatsapp/contactEnv.js +39 -0
  154. package/vite.config.mjs +2 -1
  155. package/app/modules/playModule/local/installYtDlp.js +0 -25
  156. package/app/modules/playModule/local/ytDlpInstaller.js +0 -28
@@ -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