@omnizap-system/omnizap 2.5.12

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 (425) hide show
  1. package/.clusterfuzzlite/Dockerfile +10 -0
  2. package/.env.example +907 -0
  3. package/.github/codeql/codeql-config.yml +10 -0
  4. package/.github/dependabot.yml +35 -0
  5. package/.github/workflows/ci.yml +73 -0
  6. package/.github/workflows/codeql.yml +106 -0
  7. package/.github/workflows/db-migration-check.yml +98 -0
  8. package/.github/workflows/dependency-review.yml +22 -0
  9. package/.github/workflows/deploy.yml +95 -0
  10. package/.github/workflows/release.yml +106 -0
  11. package/.github/workflows/security-attest-provenance.yml +51 -0
  12. package/.github/workflows/security-gitleaks.yml +34 -0
  13. package/.github/workflows/security-runner-hardening.yml +31 -0
  14. package/.github/workflows/security-scorecard.yml +44 -0
  15. package/.github/workflows/security-zap-baseline.yml +44 -0
  16. package/.github/workflows/security-zap-full-scan.yml +43 -0
  17. package/.github/workflows/security-zizmor.yml +36 -0
  18. package/.github/workflows/wiki-sync.yml +44 -0
  19. package/.gitleaks.toml +15 -0
  20. package/.prettierrc +34 -0
  21. package/CODE_OF_CONDUCT.md +114 -0
  22. package/LICENSE +56 -0
  23. package/README.md +110 -0
  24. package/SECURITY.md +110 -0
  25. package/app/config/index.js +4 -0
  26. package/app/configParts/adminIdentity.js +92 -0
  27. package/app/configParts/baileysConfig.js +1818 -0
  28. package/app/configParts/groupUtils.js +692 -0
  29. package/app/configParts/loggerConfig.js +394 -0
  30. package/app/configParts/messagePersistenceService.js +305 -0
  31. package/app/connection/baileysCompatibility.test.js +40 -0
  32. package/app/connection/baileysDbAuthState.js +344 -0
  33. package/app/connection/socketController.js +2243 -0
  34. package/app/controllers/messageController.js +7 -0
  35. package/app/controllers/messagePipeline/commandMiddleware.js +146 -0
  36. package/app/controllers/messagePipeline/conversationMiddleware.js +183 -0
  37. package/app/controllers/messagePipeline/messagePipelineMiddlewares.test.js +522 -0
  38. package/app/controllers/messagePipeline/postProcessingMiddleware.js +41 -0
  39. package/app/controllers/messagePipeline/preProcessingMiddlewares.js +166 -0
  40. package/app/controllers/messageProcessingPipeline.js +699 -0
  41. package/app/modules/adminModule/AGENT.md +4056 -0
  42. package/app/modules/adminModule/adminAiHelpService.js +56 -0
  43. package/app/modules/adminModule/adminConfigRuntime.js +177 -0
  44. package/app/modules/adminModule/commandConfig.json +7122 -0
  45. package/app/modules/adminModule/groupCommandHandlers.js +1823 -0
  46. package/app/modules/adminModule/groupCommandHandlers.test.js +350 -0
  47. package/app/modules/adminModule/groupEventHandlers.js +399 -0
  48. package/app/modules/aiModule/AGENT.md +547 -0
  49. package/app/modules/aiModule/aiAiHelpService.js +14 -0
  50. package/app/modules/aiModule/aiConfigRuntime.js +135 -0
  51. package/app/modules/aiModule/catCommand.js +967 -0
  52. package/app/modules/aiModule/commandConfig.json +981 -0
  53. package/app/modules/analyticsModule/messageAnalysisEventRepository.js +83 -0
  54. package/app/modules/gameModule/AGENT.md +196 -0
  55. package/app/modules/gameModule/commandConfig.json +366 -0
  56. package/app/modules/gameModule/diceCommand.js +42 -0
  57. package/app/modules/gameModule/gameAiHelpService.js +14 -0
  58. package/app/modules/gameModule/gameConfigRuntime.js +68 -0
  59. package/app/modules/menuModule/AGENT.md +205 -0
  60. package/app/modules/menuModule/commandConfig.json +366 -0
  61. package/app/modules/menuModule/common.js +316 -0
  62. package/app/modules/menuModule/menuAiHelpService.js +14 -0
  63. package/app/modules/menuModule/menuConfigRuntime.js +68 -0
  64. package/app/modules/menuModule/menus.js +66 -0
  65. package/app/modules/playModule/AGENT.md +321 -0
  66. package/app/modules/playModule/commandConfig.json +584 -0
  67. package/app/modules/playModule/playAiHelpService.js +14 -0
  68. package/app/modules/playModule/playCommand.js +1417 -0
  69. package/app/modules/playModule/playConfigRuntime.js +68 -0
  70. package/app/modules/quoteModule/AGENT.md +199 -0
  71. package/app/modules/quoteModule/commandConfig.json +366 -0
  72. package/app/modules/quoteModule/quoteAiHelpService.js +14 -0
  73. package/app/modules/quoteModule/quoteCommand.js +842 -0
  74. package/app/modules/quoteModule/quoteConfigRuntime.js +68 -0
  75. package/app/modules/rpgPokemonModule/AGENT.md +229 -0
  76. package/app/modules/rpgPokemonModule/commandConfig.json +386 -0
  77. package/app/modules/rpgPokemonModule/rpgBattleCanvasRenderer.js +795 -0
  78. package/app/modules/rpgPokemonModule/rpgBattleService.js +2110 -0
  79. package/app/modules/rpgPokemonModule/rpgBattleService.test.js +770 -0
  80. package/app/modules/rpgPokemonModule/rpgEvolutionUtils.js +22 -0
  81. package/app/modules/rpgPokemonModule/rpgPokemonAiHelpService.js +14 -0
  82. package/app/modules/rpgPokemonModule/rpgPokemonCommand.js +174 -0
  83. package/app/modules/rpgPokemonModule/rpgPokemonConfigRuntime.js +68 -0
  84. package/app/modules/rpgPokemonModule/rpgPokemonDomain.js +192 -0
  85. package/app/modules/rpgPokemonModule/rpgPokemonDomain.test.js +93 -0
  86. package/app/modules/rpgPokemonModule/rpgPokemonEvolution.test.js +46 -0
  87. package/app/modules/rpgPokemonModule/rpgPokemonMessages.js +746 -0
  88. package/app/modules/rpgPokemonModule/rpgPokemonRepository.js +1847 -0
  89. package/app/modules/rpgPokemonModule/rpgPokemonService.js +6839 -0
  90. package/app/modules/rpgPokemonModule/rpgProfileCanvasRenderer.js +354 -0
  91. package/app/modules/statsModule/AGENT.md +320 -0
  92. package/app/modules/statsModule/commandConfig.json +540 -0
  93. package/app/modules/statsModule/globalRankingCommand.js +64 -0
  94. package/app/modules/statsModule/rankingCommand.js +41 -0
  95. package/app/modules/statsModule/rankingCommon.js +1305 -0
  96. package/app/modules/statsModule/statsAiHelpService.js +14 -0
  97. package/app/modules/statsModule/statsConfigRuntime.js +68 -0
  98. package/app/modules/stickerModule/AGENT.md +692 -0
  99. package/app/modules/stickerModule/addStickerMetadata.js +239 -0
  100. package/app/modules/stickerModule/commandConfig.json +1216 -0
  101. package/app/modules/stickerModule/convertToWebp.js +367 -0
  102. package/app/modules/stickerModule/stickerAiHelpService.js +14 -0
  103. package/app/modules/stickerModule/stickerCommand.js +446 -0
  104. package/app/modules/stickerModule/stickerConfigRuntime.js +68 -0
  105. package/app/modules/stickerModule/stickerConvertCommand.js +159 -0
  106. package/app/modules/stickerModule/stickerTextCommand.js +653 -0
  107. package/app/modules/stickerPackModule/AGENT.md +215 -0
  108. package/app/modules/stickerPackModule/autoPackCollectorRuntime.js +20 -0
  109. package/app/modules/stickerPackModule/autoPackCollectorService.js +357 -0
  110. package/app/modules/stickerPackModule/commandConfig.json +387 -0
  111. package/app/modules/stickerPackModule/domainEventOutboxRepository.js +227 -0
  112. package/app/modules/stickerPackModule/domainEvents.js +52 -0
  113. package/app/modules/stickerPackModule/semanticReclassificationEngine.js +429 -0
  114. package/app/modules/stickerPackModule/semanticReclassificationEngine.test.js +75 -0
  115. package/app/modules/stickerPackModule/semanticThemeClusterService.js +544 -0
  116. package/app/modules/stickerPackModule/stickerAssetClassificationRepository.js +400 -0
  117. package/app/modules/stickerPackModule/stickerAssetRepository.js +400 -0
  118. package/app/modules/stickerPackModule/stickerAssetReprocessQueueRepository.js +175 -0
  119. package/app/modules/stickerPackModule/stickerAutoPackByTagsRuntime.js +3702 -0
  120. package/app/modules/stickerPackModule/stickerClassificationBackgroundRuntime.js +559 -0
  121. package/app/modules/stickerPackModule/stickerClassificationService.js +557 -0
  122. package/app/modules/stickerPackModule/stickerDedicatedTaskWorkerRuntime.js +249 -0
  123. package/app/modules/stickerPackModule/stickerDomainEventBus.js +65 -0
  124. package/app/modules/stickerPackModule/stickerDomainEventConsumerRuntime.js +208 -0
  125. package/app/modules/stickerPackModule/stickerMarketplaceDriftService.js +99 -0
  126. package/app/modules/stickerPackModule/stickerObjectStorageService.js +285 -0
  127. package/app/modules/stickerPackModule/stickerPackAiHelpService.js +14 -0
  128. package/app/modules/stickerPackModule/stickerPackCommandHandlers.js +1148 -0
  129. package/app/modules/stickerPackModule/stickerPackConfigRuntime.js +68 -0
  130. package/app/modules/stickerPackModule/stickerPackEngagementRepository.js +152 -0
  131. package/app/modules/stickerPackModule/stickerPackErrors.js +30 -0
  132. package/app/modules/stickerPackModule/stickerPackInteractionEventRepository.js +101 -0
  133. package/app/modules/stickerPackModule/stickerPackItemRepository.js +432 -0
  134. package/app/modules/stickerPackModule/stickerPackMarketplaceService.js +313 -0
  135. package/app/modules/stickerPackModule/stickerPackMessageService.js +268 -0
  136. package/app/modules/stickerPackModule/stickerPackRepository.js +450 -0
  137. package/app/modules/stickerPackModule/stickerPackScoreSnapshotRepository.js +179 -0
  138. package/app/modules/stickerPackModule/stickerPackScoreSnapshotRuntime.js +271 -0
  139. package/app/modules/stickerPackModule/stickerPackService.js +733 -0
  140. package/app/modules/stickerPackModule/stickerPackServiceRuntime.js +32 -0
  141. package/app/modules/stickerPackModule/stickerPackUtils.js +107 -0
  142. package/app/modules/stickerPackModule/stickerStorageService.js +559 -0
  143. package/app/modules/stickerPackModule/stickerWorkerPipelineRuntime.js +242 -0
  144. package/app/modules/stickerPackModule/stickerWorkerTaskQueueRepository.js +242 -0
  145. package/app/modules/systemMetricsModule/AGENT.md +193 -0
  146. package/app/modules/systemMetricsModule/commandConfig.json +344 -0
  147. package/app/modules/systemMetricsModule/pingCommand.js +399 -0
  148. package/app/modules/systemMetricsModule/systemMetricsAiHelpService.js +14 -0
  149. package/app/modules/systemMetricsModule/systemMetricsConfigRuntime.js +68 -0
  150. package/app/modules/tiktokModule/AGENT.md +196 -0
  151. package/app/modules/tiktokModule/commandConfig.json +366 -0
  152. package/app/modules/tiktokModule/tiktokAiHelpService.js +14 -0
  153. package/app/modules/tiktokModule/tiktokCommand.js +716 -0
  154. package/app/modules/tiktokModule/tiktokConfigRuntime.js +68 -0
  155. package/app/modules/userModule/AGENT.md +200 -0
  156. package/app/modules/userModule/commandConfig.json +386 -0
  157. package/app/modules/userModule/userAiHelpService.js +14 -0
  158. package/app/modules/userModule/userCommand.js +1155 -0
  159. package/app/modules/userModule/userConfigRuntime.js +68 -0
  160. package/app/modules/waifuPicsModule/AGENT.md +431 -0
  161. package/app/modules/waifuPicsModule/commandConfig.json +780 -0
  162. package/app/modules/waifuPicsModule/waifuPicsAiHelpService.js +14 -0
  163. package/app/modules/waifuPicsModule/waifuPicsCommand.js +586 -0
  164. package/app/modules/waifuPicsModule/waifuPicsConfigRuntime.js +68 -0
  165. package/app/observability/metrics.js +766 -0
  166. package/app/services/ai/aiHelpResponseCacheRepository.js +280 -0
  167. package/app/services/ai/aiLearningRepository.js +400 -0
  168. package/app/services/ai/commandConfigEnrichmentRepository.js +769 -0
  169. package/app/services/ai/commandConfigEnrichmentService.js +452 -0
  170. package/app/services/ai/commandConfigValidationService.js +443 -0
  171. package/app/services/ai/commandToolBuilderService.js +192 -0
  172. package/app/services/ai/conversationRouterService.js +516 -0
  173. package/app/services/ai/geminiService.js +115 -0
  174. package/app/services/ai/geminiService.test.js +87 -0
  175. package/app/services/ai/globalModuleAiHelpService.js +1412 -0
  176. package/app/services/ai/globalToolCallingService.js +203 -0
  177. package/app/services/ai/messageCommandExecutionService.js +391 -0
  178. package/app/services/ai/moduleAiHelpCoreService.js +1099 -0
  179. package/app/services/ai/moduleAiHelpWrapperFactory.js +65 -0
  180. package/app/services/ai/moduleCommandConfigRuntimeService.js +113 -0
  181. package/app/services/ai/moduleToolExecutorService.js +464 -0
  182. package/app/services/ai/moduleToolRegistryService.js +178 -0
  183. package/app/services/ai/toolCandidateSelectorService.js +781 -0
  184. package/app/services/auth/googleWebLinkService.js +80 -0
  185. package/app/services/auth/whatsappLoginLinkService.js +230 -0
  186. package/app/services/external/pokeApiService.js +398 -0
  187. package/app/services/group/groupMetadataService.js +311 -0
  188. package/app/services/infra/dbWriteQueue.js +874 -0
  189. package/app/services/infra/featureFlagService.js +131 -0
  190. package/app/services/infra/queueUtils.js +55 -0
  191. package/app/services/messaging/captchaService.js +491 -0
  192. package/app/services/messaging/messagePersistenceService.js +1 -0
  193. package/app/services/messaging/newsBroadcastService.js +347 -0
  194. package/app/services/sticker/stickerFocusService.js +347 -0
  195. package/app/services/sticker/stickerFocusService.test.js +43 -0
  196. package/app/store/aiPromptStore.js +38 -0
  197. package/app/store/conversationSessionStore.js +131 -0
  198. package/app/store/groupConfigStore.js +58 -0
  199. package/app/store/premiumUserStore.js +54 -0
  200. package/app/utils/antiLink/antiLinkModule.js +700 -0
  201. package/app/utils/http/getImageBufferModule.js +18 -0
  202. package/app/utils/json/jsonSanitizer.js +113 -0
  203. package/app/utils/json/jsonSanitizer.test.js +40 -0
  204. package/app/utils/systemMetrics/systemMetricsModule.js +88 -0
  205. package/app/workers/aiLearningWorker.js +605 -0
  206. package/app/workers/commandConfigEnrichmentWorker.js +242 -0
  207. package/database/index.js +2075 -0
  208. package/database/init.js +151 -0
  209. package/database/migrations/.gitkeep +0 -0
  210. package/database/migrations/20260307_d0_hardening_down.sql +64 -0
  211. package/database/migrations/20260307_d0_hardening_up.sql +79 -0
  212. package/database/migrations/20260307_d1_terms_acceptance_down.sql +11 -0
  213. package/database/migrations/20260307_d1_terms_acceptance_up.sql +37 -0
  214. package/database/migrations/20260307_d2_auth_hardening_down.sql +75 -0
  215. package/database/migrations/20260307_d2_auth_hardening_up.sql +100 -0
  216. package/database/migrations/20260314_d7_canonical_sender_down.sql +53 -0
  217. package/database/migrations/20260314_d7_canonical_sender_up.sql +114 -0
  218. package/database/migrations/20260406_d30_security_analytics_down.sql +95 -0
  219. package/database/migrations/20260406_d30_security_analytics_up.sql +292 -0
  220. package/database/migrations/20260407_d31_web_google_session_token_hardening_down.sql +2 -0
  221. package/database/migrations/20260407_d31_web_google_session_token_hardening_up.sql +17 -0
  222. package/database/migrations/20260408_d32_ai_help_response_cache_down.sql +1 -0
  223. package/database/migrations/20260408_d32_ai_help_response_cache_up.sql +22 -0
  224. package/database/migrations/20260409_d33_ai_learning_tables_down.sql +4 -0
  225. package/database/migrations/20260409_d33_ai_learning_tables_up.sql +52 -0
  226. package/database/migrations/20260410_d34_command_config_enrichment_down.sql +3 -0
  227. package/database/migrations/20260410_d34_command_config_enrichment_up.sql +48 -0
  228. package/database/schema.sql +1186 -0
  229. package/docker-compose.yml +104 -0
  230. package/docs/audits/stickerCatalogController-out-of-scope.md +103 -0
  231. package/docs/audits/stickerCatalogController-symbols.md +58 -0
  232. package/docs/compliance/acceptable-use-policy-2026-03-07.md +35 -0
  233. package/docs/compliance/dpa-b2b-standard-2026-03-07.md +80 -0
  234. package/docs/compliance/monthly-compliance-checklist-2026-03-07.md +88 -0
  235. package/docs/compliance/notice-and-takedown-policy-2026-03-07.md +34 -0
  236. package/docs/compliance/privacy-policy-2026-03-07.md +75 -0
  237. package/docs/compliance/subprocessors-inventory-2026-03-07.md +16 -0
  238. package/docs/database/production-db-evolution-runbook-2026q1.md +365 -0
  239. package/docs/security/dsar-lgpd-runbook-2026-03-07.md +86 -0
  240. package/docs/security/incident-response-lgpd-anpd-runbook-2026-03-07.md +77 -0
  241. package/docs/security/network-hardening-runbook-2026-03-07.md +137 -0
  242. package/docs/seo/omnizap-seo-playbook-br-2026-02-28.md +238 -0
  243. package/docs/seo/satellite-page-template.md +116 -0
  244. package/docs/seo/satellite-pages-phase1.json +364 -0
  245. package/docs/wiki/Home.md +120 -0
  246. package/docs/wiki/pair-extraordinaire-2026-03-08.md +3 -0
  247. package/docs/wiki/recent-changes-2026-03-08.md +47 -0
  248. package/ecosystem.prod.config.cjs +135 -0
  249. package/eslint.config.js +89 -0
  250. package/index.js +488 -0
  251. package/ml/clip_classifier/Dockerfile +18 -0
  252. package/ml/clip_classifier/README.md +118 -0
  253. package/ml/clip_classifier/adaptive_scoring.py +40 -0
  254. package/ml/clip_classifier/classifier.py +654 -0
  255. package/ml/clip_classifier/embedding_store.py +481 -0
  256. package/ml/clip_classifier/env_loader.py +15 -0
  257. package/ml/clip_classifier/llm_label_expander.py +144 -0
  258. package/ml/clip_classifier/main.py +213 -0
  259. package/ml/clip_classifier/requirements.txt +10 -0
  260. package/ml/clip_classifier/similarity_engine.py +74 -0
  261. package/new-logo.png +0 -0
  262. package/observability/alert-rules.yml +60 -0
  263. package/observability/grafana/dashboards/omnizap-mysql.json +136 -0
  264. package/observability/grafana/dashboards/omnizap-overview.json +170 -0
  265. package/observability/grafana/provisioning/dashboards/dashboards.yml +11 -0
  266. package/observability/grafana/provisioning/datasources/datasources.yml +15 -0
  267. package/observability/loki-config.yml +38 -0
  268. package/observability/mysql-setup.sql +46 -0
  269. package/observability/prometheus.yml +35 -0
  270. package/observability/promtail-config.yml +84 -0
  271. package/observability/sticker-catalog-slo.md +83 -0
  272. package/observability/sticker-scale-hardening-rollout.md +128 -0
  273. package/package.json +144 -0
  274. package/public/apple-touch-icon.png +0 -0
  275. package/public/assets/css/commands-react.input.css +71 -0
  276. package/public/assets/css/create-pack-react.input.css +31 -0
  277. package/public/assets/css/home-react.input.css +106 -0
  278. package/public/assets/css/login-react.input.css +58 -0
  279. package/public/assets/css/stickers-react.input.css +18 -0
  280. package/public/assets/css/terms-react.input.css +115 -0
  281. package/public/assets/css/user-react.input.css +57 -0
  282. package/public/assets/images/brand-icon-192.png +0 -0
  283. package/public/assets/images/brand-logo-128.webp +0 -0
  284. package/public/assets/images/hero-banner-1280.jpg +0 -0
  285. package/public/comandos/commands-catalog.json +4517 -0
  286. package/public/css/api-docs.css +161 -0
  287. package/public/css/stickers-admin.css +1288 -0
  288. package/public/css/styles.css +679 -0
  289. package/public/css/systemadm/admin.css +474 -0
  290. package/public/css/systemadm/base.css +73 -0
  291. package/public/css/systemadm/components.css +662 -0
  292. package/public/css/systemadm/layout.css +229 -0
  293. package/public/css/systemadm/tokens.css +56 -0
  294. package/public/favicon-16x16.png +0 -0
  295. package/public/favicon-32x32.png +0 -0
  296. package/public/favicon.ico +0 -0
  297. package/public/js/apps/apiDocsApp.js +235 -0
  298. package/public/js/apps/commandsReactApp.js +528 -0
  299. package/public/js/apps/createPackApp.js +1646 -0
  300. package/public/js/apps/homeReactApp.js +942 -0
  301. package/public/js/apps/loginReactApp.js +496 -0
  302. package/public/js/apps/stickersAdminApp.js +1753 -0
  303. package/public/js/apps/stickersApp.js +3797 -0
  304. package/public/js/apps/termsReactApp.js +528 -0
  305. package/public/js/apps/userApp.js +2540 -0
  306. package/public/js/apps/userProfile/actions.js +66 -0
  307. package/public/js/apps/userReactApp.js +547 -0
  308. package/public/js/catalog.js +950 -0
  309. package/public/pages/api-docs.html +40 -0
  310. package/public/pages/aup.html +158 -0
  311. package/public/pages/comandos.html +41 -0
  312. package/public/pages/dpa.html +227 -0
  313. package/public/pages/home.html +45 -0
  314. package/public/pages/licenca.html +182 -0
  315. package/public/pages/login.html +40 -0
  316. package/public/pages/notice-and-takedown.html +234 -0
  317. package/public/pages/politica-de-privacidade.html +251 -0
  318. package/public/pages/seo-bot-whatsapp-para-grupo.html +350 -0
  319. package/public/pages/seo-bot-whatsapp-sem-programar.html +350 -0
  320. package/public/pages/seo-como-automatizar-avisos-no-whatsapp.html +350 -0
  321. package/public/pages/seo-como-criar-comandos-whatsapp.html +350 -0
  322. package/public/pages/seo-como-evitar-spam-no-whatsapp.html +350 -0
  323. package/public/pages/seo-como-moderar-grupo-whatsapp.html +350 -0
  324. package/public/pages/seo-como-organizar-comunidade-whatsapp.html +350 -0
  325. package/public/pages/seo-melhor-bot-whatsapp-para-grupos.html +350 -0
  326. package/public/pages/stickers-admin.html +31 -0
  327. package/public/pages/stickers-create.html +41 -0
  328. package/public/pages/stickers.html +45 -0
  329. package/public/pages/suboperadores.html +237 -0
  330. package/public/pages/termos-de-uso-texto-integral.html +241 -0
  331. package/public/pages/termos-de-uso.html +41 -0
  332. package/public/pages/user-password-reset.html +32 -0
  333. package/public/pages/user-systemadm.html +508 -0
  334. package/public/pages/user.html +39 -0
  335. package/public/robots.txt +9 -0
  336. package/public/site.webmanifest +24 -0
  337. package/public/sitemap.xml +98 -0
  338. package/schemas/command-config.schema.json +582 -0
  339. package/scripts/baileys-compat-smoke.mjs +12 -0
  340. package/scripts/cache-bust.mjs +142 -0
  341. package/scripts/deploy.sh +916 -0
  342. package/scripts/email-broadcast-terms-update.mjs +170 -0
  343. package/scripts/enrich-command-discovery-fields.mjs +286 -0
  344. package/scripts/generate-command-config-schema.mjs +273 -0
  345. package/scripts/generate-commands-catalog.mjs +308 -0
  346. package/scripts/generate-module-agents.mjs +631 -0
  347. package/scripts/generate-seo-satellite-pages.mjs +400 -0
  348. package/scripts/github-deploy-notify.mjs +174 -0
  349. package/scripts/github-release-notify.mjs +219 -0
  350. package/scripts/release.sh +599 -0
  351. package/scripts/run-codeql-local.sh +116 -0
  352. package/scripts/run-prettier-all.mjs +25 -0
  353. package/scripts/security-smoketest.mjs +581 -0
  354. package/scripts/sticker-catalog-loadtest.mjs +210 -0
  355. package/scripts/sticker-worker-task.mjs +119 -0
  356. package/scripts/sync-readme-snapshot.mjs +133 -0
  357. package/scripts/validate-command-config-schema.mjs +130 -0
  358. package/scripts/validate-command-configs.mjs +15 -0
  359. package/scripts/wiki-sync.sh +191 -0
  360. package/server/auth/googleWebAuth/googleWebAuthRuntime.js +62 -0
  361. package/server/auth/googleWebAuth/googleWebAuthService.js +807 -0
  362. package/server/auth/jwt/webJwtService.js +147 -0
  363. package/server/auth/stickerCatalogAuthContext.js +165 -0
  364. package/server/auth/termsAcceptance/termsAcceptanceHandler.js +189 -0
  365. package/server/auth/userPassword/index.js +14 -0
  366. package/server/auth/userPassword/userPasswordAuthService.js +422 -0
  367. package/server/auth/userPassword/userPasswordCrypto.js +199 -0
  368. package/server/auth/userPassword/userPasswordCrypto.test.js +76 -0
  369. package/server/auth/userPassword/userPasswordRecoveryService.js +728 -0
  370. package/server/auth/validation/authSchemas.js +236 -0
  371. package/server/auth/webAccount/webAccountHandlers.js +1434 -0
  372. package/server/controllers/admin/adminBanService.js +138 -0
  373. package/server/controllers/admin/adminPanelHandlers.js +2083 -0
  374. package/server/controllers/admin/stickerCatalogAdminContext.js +17 -0
  375. package/server/controllers/admin/systemAdminController.js +201 -0
  376. package/server/controllers/email/emailAutomationController.js +239 -0
  377. package/server/controllers/metricsController.js +21 -0
  378. package/server/controllers/seo/stickerCatalogSeoContext.js +514 -0
  379. package/server/controllers/sticker/nonCatalogHandlers.js +303 -0
  380. package/server/controllers/sticker/stickerCatalogController.js +4700 -0
  381. package/server/controllers/system/contactController.js +115 -0
  382. package/server/controllers/system/githubController.js +137 -0
  383. package/server/controllers/system/stickerCatalogSystemContext.js +758 -0
  384. package/server/controllers/system/storageController.js +154 -0
  385. package/server/controllers/system/systemController.js +135 -0
  386. package/server/controllers/system/systemMetricsController.js +156 -0
  387. package/server/controllers/system/visitController.js +90 -0
  388. package/server/controllers/userController.js +145 -0
  389. package/server/email/emailAutomationRuntime.js +225 -0
  390. package/server/email/emailAutomationService.js +125 -0
  391. package/server/email/emailOutboxRepository.js +282 -0
  392. package/server/email/emailTemplateService.js +480 -0
  393. package/server/email/emailTransportService.js +156 -0
  394. package/server/http/clientIp.js +95 -0
  395. package/server/http/httpRequestUtils.js +262 -0
  396. package/server/http/httpRequestUtils.test.js +80 -0
  397. package/server/http/httpServer.js +180 -0
  398. package/server/http/requestContext.js +20 -0
  399. package/server/http/siteRoutingUtils.js +87 -0
  400. package/server/index.js +1 -0
  401. package/server/middleware/cachePolicy.js +26 -0
  402. package/server/middleware/cachePolicyHelpers.js +1 -0
  403. package/server/middleware/endpointRateLimit.js +181 -0
  404. package/server/middleware/rateLimit.js +70 -0
  405. package/server/middleware/requireAdminAuth.js +48 -0
  406. package/server/middleware/securityHeaders.js +97 -0
  407. package/server/routes/admin/systemAdminRouter.js +64 -0
  408. package/server/routes/email/emailAutomationRouter.js +46 -0
  409. package/server/routes/health/healthRouter.js +41 -0
  410. package/server/routes/indexRouter.js +234 -0
  411. package/server/routes/metrics/metricsRouter.js +58 -0
  412. package/server/routes/static/staticPageRouter.js +134 -0
  413. package/server/routes/sticker/catalogHandlers/catalogAdminHttp.js +105 -0
  414. package/server/routes/sticker/catalogHandlers/catalogAuthHttp.js +77 -0
  415. package/server/routes/sticker/catalogHandlers/catalogPublicHttp.js +120 -0
  416. package/server/routes/sticker/catalogHandlers/catalogUploadHttp.js +83 -0
  417. package/server/routes/sticker/catalogRouter.js +77 -0
  418. package/server/routes/sticker/stickerApiRouter.js +84 -0
  419. package/server/routes/sticker/stickerDataRouter.js +145 -0
  420. package/server/routes/sticker/stickerSiteRouter.js +43 -0
  421. package/server/routes/user/userApiPaths.js +66 -0
  422. package/server/routes/user/userRouter.js +65 -0
  423. package/server/utils/safePath.js +26 -0
  424. package/utils/logger/loggerModule.js +35 -0
  425. package/vite.config.mjs +38 -0
@@ -0,0 +1,631 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ const repoRoot = path.resolve(__dirname, '..');
10
+ const modulesRoot = path.join(repoRoot, 'app', 'modules');
11
+ const nowIso = new Date().toISOString();
12
+
13
+ const normalizeBoolLabel = (value) => (value ? 'sim' : 'nao');
14
+
15
+ const ensureArray = (value) => (Array.isArray(value) ? value.filter((item) => item !== undefined && item !== null && item !== '') : []);
16
+ const ensureObject = (value) => (value && typeof value === 'object' && !Array.isArray(value) ? value : {});
17
+ const hasOwn = (target, key) => Object.prototype.hasOwnProperty.call(target || {}, key);
18
+ const hasEntries = (value) => Object.keys(ensureObject(value)).length > 0;
19
+
20
+ const normalizeText = (value, fallback = '(nao informado)') => {
21
+ const raw = String(value || '').trim();
22
+ return raw || fallback;
23
+ };
24
+
25
+ const normalizeToken = (value) =>
26
+ String(value || '')
27
+ .trim()
28
+ .toLowerCase();
29
+
30
+ const getArgValue = (flag) => {
31
+ const index = process.argv.indexOf(flag);
32
+ if (index < 0) return null;
33
+ const next = process.argv[index + 1];
34
+ if (!next || next.startsWith('--')) return null;
35
+ return next;
36
+ };
37
+
38
+ const deepMerge = (left, right) => {
39
+ const base = ensureObject(left);
40
+ const override = ensureObject(right);
41
+ const output = { ...base };
42
+ for (const key of Object.keys(override)) {
43
+ const leftValue = base[key];
44
+ const rightValue = override[key];
45
+ if (Array.isArray(rightValue)) {
46
+ output[key] = rightValue.slice();
47
+ continue;
48
+ }
49
+ if (rightValue && typeof rightValue === 'object') {
50
+ output[key] = deepMerge(leftValue, rightValue);
51
+ continue;
52
+ }
53
+ output[key] = rightValue;
54
+ }
55
+ return output;
56
+ };
57
+
58
+ const pickFirst = (...values) => {
59
+ for (const value of values) {
60
+ if (value !== undefined && value !== null && value !== '') return value;
61
+ }
62
+ return undefined;
63
+ };
64
+
65
+ const pickFirstBoolean = (...values) => {
66
+ for (const value of values) {
67
+ if (typeof value === 'boolean') return value;
68
+ }
69
+ return false;
70
+ };
71
+
72
+ const unique = (items = []) => {
73
+ const out = [];
74
+ for (const item of ensureArray(items)) {
75
+ const raw = String(item).trim();
76
+ if (!raw || out.includes(raw)) continue;
77
+ out.push(raw);
78
+ }
79
+ return out;
80
+ };
81
+
82
+ const printList = (items, emptyText = '(nenhum)') => {
83
+ const safeItems = ensureArray(items);
84
+ if (!safeItems.length) return [`- ${emptyText}`];
85
+ return safeItems.map((item) => `- ${String(item)}`);
86
+ };
87
+
88
+ const printObjectPairs = (obj, fallback = '(nao informado)') => {
89
+ if (!obj || typeof obj !== 'object' || Array.isArray(obj)) return [`- ${fallback}`];
90
+ const entries = Object.entries(obj);
91
+ if (!entries.length) return [`- ${fallback}`];
92
+ return entries.map(([key, value]) => `- ${key}: ${String(value)}`);
93
+ };
94
+
95
+ const printObjectPairsDeep = (obj, prefix = '') => {
96
+ if (!obj || typeof obj !== 'object') return [];
97
+ const entries = Object.entries(obj);
98
+ if (!entries.length) return [];
99
+
100
+ const lines = [];
101
+ for (const [key, value] of entries) {
102
+ const nextKey = prefix ? `${prefix}.${key}` : key;
103
+ if (Array.isArray(value)) {
104
+ if (!value.length) {
105
+ lines.push(`- ${nextKey}: (nenhum)`);
106
+ } else {
107
+ const serialized = value.map((item) => (typeof item === 'object' ? JSON.stringify(item) : String(item))).join(', ');
108
+ lines.push(`- ${nextKey}: ${serialized}`);
109
+ }
110
+ continue;
111
+ }
112
+ if (value && typeof value === 'object') {
113
+ lines.push(...printObjectPairsDeep(value, nextKey));
114
+ continue;
115
+ }
116
+ lines.push(`- ${nextKey}: ${String(value)}`);
117
+ }
118
+ return lines;
119
+ };
120
+
121
+ const normalizeLegacyRequirements = (requirements = {}) => ({
122
+ requer_grupo: pickFirstBoolean(requirements.require_group, requirements.requer_grupo),
123
+ requer_admin: pickFirstBoolean(requirements.require_group_admin, requirements.requer_admin),
124
+ requer_admin_principal: pickFirstBoolean(requirements.require_bot_owner, requirements.requer_admin_principal),
125
+ requer_google_login: pickFirstBoolean(requirements.require_google_login, requirements.requer_google_login),
126
+ requer_nsfw: pickFirstBoolean(requirements.require_nsfw_enabled, requirements.requer_nsfw),
127
+ requer_midia: pickFirstBoolean(requirements.require_media, requirements.requer_midia),
128
+ requer_mensagem_respondida: pickFirstBoolean(requirements.require_reply_message, requirements.requer_mensagem_respondida),
129
+ });
130
+
131
+ const normalizeRateLimit = (rateLimit = {}) => ({
132
+ max: pickFirst(rateLimit.max, null),
133
+ janela_ms: pickFirst(rateLimit.janela_ms, rateLimit.window_ms, null),
134
+ escopo: normalizeText(pickFirst(rateLimit.escopo, rateLimit.scope), '(nao informado)'),
135
+ });
136
+
137
+ const normalizePlanEntry = (entry = {}) => ({
138
+ max: pickFirst(entry.max, null),
139
+ janela_ms: pickFirst(entry.janela_ms, entry.window_ms, null),
140
+ escopo: normalizeText(pickFirst(entry.escopo, entry.scope), '(nao informado)'),
141
+ });
142
+
143
+ const normalizeArgument = (arg = {}) => {
144
+ const safeArg = ensureObject(arg);
145
+ const name = normalizeText(pickFirst(safeArg.name, safeArg.nome), '');
146
+ if (!name) return null;
147
+ return {
148
+ name,
149
+ type: normalizeText(pickFirst(safeArg.type, safeArg.tipo, 'any'), 'any'),
150
+ required: pickFirstBoolean(safeArg.required, safeArg.obrigatorio),
151
+ validation: normalizeText(pickFirst(safeArg.validation, safeArg.validacao), 'livre'),
152
+ defaultValue: hasOwn(safeArg, 'default') ? safeArg.default : null,
153
+ description: normalizeText(pickFirst(safeArg.description, safeArg.descricao), '(nao informado)'),
154
+ enumValues: ensureArray(safeArg.enum),
155
+ position: pickFirst(safeArg.position, null),
156
+ };
157
+ };
158
+
159
+ const renderArgumentLine = (argument) => {
160
+ const normalized = normalizeArgument(argument);
161
+ if (!normalized) return '- (argumento invalido)';
162
+ const obrigatorio = normalized.required ? 'obrigatorio' : 'opcional';
163
+ const defaultValue = normalized.defaultValue === undefined ? 'null' : JSON.stringify(normalized.defaultValue);
164
+ const enumLabel = normalized.enumValues.length ? ` | enum: ${normalized.enumValues.join(', ')}` : '';
165
+ const positionLabel = normalized.position === null ? '' : ` | posicao: ${normalized.position}`;
166
+ return `- ${normalized.name} | tipo: ${normalized.type} | ${obrigatorio} | validacao: ${normalized.validation} | default: ${defaultValue}${enumLabel}${positionLabel}`;
167
+ };
168
+
169
+ const resolveGuideTitle = (moduleName) => {
170
+ const raw = String(moduleName || 'module').trim() || 'module';
171
+ return `${raw.charAt(0).toUpperCase()}${raw.slice(1)} Agent Guide`;
172
+ };
173
+
174
+ const normalizeCommand = (command = {}, moduleDefaults = {}) => {
175
+ const mergedCommand = deepMerge(moduleDefaults.command, ensureObject(command));
176
+
177
+ const docs = deepMerge(moduleDefaults.docs, deepMerge(mergedCommand.docs, mergedCommand.documentacao));
178
+ const behavior = deepMerge(moduleDefaults.behavior, mergedCommand.behavior);
179
+ const limits = deepMerge(moduleDefaults.limits, mergedCommand.limits);
180
+ const discovery = deepMerge(moduleDefaults.discovery, mergedCommand.discovery);
181
+
182
+ const rawRequirements = deepMerge(moduleDefaults.requirements || moduleDefaults.pre_condicoes, mergedCommand.requirements || mergedCommand.pre_condicoes);
183
+ const requirementsLegacy = deepMerge(rawRequirements.legacy, deepMerge(moduleDefaults.pre_condicoes, mergedCommand.pre_condicoes));
184
+ const normalizedRequirements = {
185
+ require_group: pickFirstBoolean(rawRequirements.require_group, rawRequirements.requer_grupo, requirementsLegacy.require_group, requirementsLegacy.requer_grupo),
186
+ require_group_admin: pickFirstBoolean(rawRequirements.require_group_admin, rawRequirements.requer_admin, requirementsLegacy.require_group_admin, requirementsLegacy.requer_admin),
187
+ require_bot_owner: pickFirstBoolean(rawRequirements.require_bot_owner, rawRequirements.requer_admin_principal, requirementsLegacy.require_bot_owner, requirementsLegacy.requer_admin_principal),
188
+ require_google_login: pickFirstBoolean(rawRequirements.require_google_login, rawRequirements.requer_google_login, requirementsLegacy.require_google_login, requirementsLegacy.requer_google_login),
189
+ require_nsfw_enabled: pickFirstBoolean(rawRequirements.require_nsfw_enabled, rawRequirements.requer_nsfw, requirementsLegacy.require_nsfw_enabled, requirementsLegacy.requer_nsfw),
190
+ require_media: pickFirstBoolean(rawRequirements.require_media, rawRequirements.requer_midia, requirementsLegacy.require_media, requirementsLegacy.requer_midia),
191
+ require_reply_message: pickFirstBoolean(rawRequirements.require_reply_message, rawRequirements.requer_mensagem_respondida, requirementsLegacy.require_reply_message, requirementsLegacy.requer_mensagem_respondida),
192
+ };
193
+
194
+ const rawRateLimit = deepMerge(moduleDefaults.rate_limit, deepMerge(limits.rate_limit, mergedCommand.rate_limit));
195
+ const rateLimit = normalizeRateLimit(rawRateLimit);
196
+
197
+ const rawAccess = deepMerge(moduleDefaults.access || moduleDefaults.acesso, mergedCommand.access || mergedCommand.acesso);
198
+ const access = {
199
+ premium_only: pickFirstBoolean(rawAccess.premium_only, rawAccess.somente_premium),
200
+ allowed_plans: unique(ensureArray(pickFirst(rawAccess.allowed_plans, rawAccess.planos_permitidos))),
201
+ };
202
+
203
+ const rawPlanLimits = deepMerge(moduleDefaults.plan_limits || moduleDefaults.limite_uso_por_plano, mergedCommand.plan_limits || mergedCommand.limite_uso_por_plano);
204
+ const planLimits = {
205
+ comum: normalizePlanEntry(rawPlanLimits.comum),
206
+ premium: normalizePlanEntry(rawPlanLimits.premium),
207
+ };
208
+
209
+ const rawResponses = deepMerge(moduleDefaults.responses || moduleDefaults.respostas_padrao, mergedCommand.responses || mergedCommand.respostas_padrao);
210
+
211
+ const rawObservability = deepMerge(moduleDefaults.observability || moduleDefaults.observabilidade, mergedCommand.observability || mergedCommand.observabilidade);
212
+ const observability = {
213
+ event_name: pickFirst(rawObservability.event_name, rawObservability.evento_analytics, null),
214
+ analytics_event: pickFirst(rawObservability.analytics_event, rawObservability.evento_analytics, null),
215
+ tags: unique([...ensureArray(rawObservability.tags), ...ensureArray(rawObservability.tags_log)]),
216
+ level: normalizeText(pickFirst(rawObservability.log_level, rawObservability.nivel_log), '(nao informado)'),
217
+ };
218
+
219
+ const rawPrivacy = deepMerge(moduleDefaults.privacy || moduleDefaults.privacidade, mergedCommand.privacy || mergedCommand.privacidade);
220
+ const privacy = {
221
+ data_categories: unique([...ensureArray(rawPrivacy.data_categories), ...ensureArray(rawPrivacy.dados_sensiveis)]),
222
+ retention: normalizeText(pickFirst(rawPrivacy.retention_policy, rawPrivacy.retencao), '(nao informado)'),
223
+ legal_basis: normalizeText(pickFirst(rawPrivacy.legal_basis, rawPrivacy.base_legal), '(nao informado)'),
224
+ };
225
+
226
+ const argsRaw = ensureArray(mergedCommand.arguments).length ? mergedCommand.arguments : mergedCommand.argumentos;
227
+ const normalizedArguments = ensureArray(argsRaw)
228
+ .map((entry) => normalizeArgument(entry))
229
+ .filter(Boolean);
230
+
231
+ const usage = unique(ensureArray(pickFirst(mergedCommand.usage, mergedCommand.metodos_de_uso, docs.usage_examples)));
232
+ const usageVariants = deepMerge(docs.usage_variants, mergedCommand.mensagens_uso);
233
+
234
+ const systemMessages = deepMerge(moduleDefaults.mensagens_sistema, mergedCommand.mensagens_sistema);
235
+ const operationalLimits = deepMerge(moduleDefaults.limites_operacionais, mergedCommand.limites_operacionais);
236
+ const options = deepMerge(moduleDefaults.opcoes || moduleDefaults.behavior_templates, mergedCommand.opcoes);
237
+
238
+ return {
239
+ name: normalizeText(mergedCommand.name, 'comando'),
240
+ id: normalizeText(mergedCommand.id, '(nao informado)'),
241
+ aliases: unique(ensureArray(mergedCommand.aliases)),
242
+ enabled: mergedCommand.enabled !== false,
243
+ category: normalizeText(pickFirst(mergedCommand.category, mergedCommand.categoria), '(nao informado)'),
244
+ description: normalizeText(pickFirst(mergedCommand.description, mergedCommand.descricao), 'Sem descricao cadastrada.'),
245
+ permission: normalizeText(pickFirst(mergedCommand.permission, mergedCommand.permissao_necessaria), '(nao informado)'),
246
+ version: normalizeText(mergedCommand.version, '(nao informado)'),
247
+ stability: normalizeText(mergedCommand.stability, '(nao informado)'),
248
+ deprecated: pickFirstBoolean(mergedCommand.deprecated),
249
+ replaced_by: normalizeText(mergedCommand.replaced_by, ''),
250
+ risk_level: normalizeText(mergedCommand.risk_level, '(nao informado)'),
251
+ contexts: unique(ensureArray(pickFirst(mergedCommand.contexts, mergedCommand.local_de_uso))),
252
+ subcommands: unique(ensureArray(mergedCommand.subcomandos)),
253
+ usage,
254
+ usageVariants: ensureObject(usageVariants),
255
+ arguments: normalizedArguments,
256
+ requirementsLegacy: normalizeLegacyRequirements(normalizedRequirements),
257
+ rateLimit,
258
+ access,
259
+ planLimits,
260
+ collectedData: unique(ensureArray(pickFirst(mergedCommand.collected_data, mergedCommand.informacoes_coletadas))),
261
+ dependencies: unique(ensureArray(pickFirst(mergedCommand.dependencies, mergedCommand.dependencias_externas))),
262
+ sideEffects: unique(ensureArray(pickFirst(mergedCommand.side_effects, mergedCommand.efeitos_colaterais))),
263
+ responses: ensureObject(rawResponses),
264
+ systemMessages: ensureObject(systemMessages),
265
+ operationalLimits: ensureObject(operationalLimits),
266
+ options: ensureObject(options),
267
+ observability,
268
+ privacy,
269
+ docs: ensureObject(docs),
270
+ behavior: ensureObject(behavior),
271
+ limits: ensureObject(limits),
272
+ discovery: ensureObject(discovery),
273
+ handler: ensureObject(mergedCommand.handler),
274
+ };
275
+ };
276
+
277
+ const buildCommandSection = (command = {}) => {
278
+ const commandName = normalizeText(command.name, 'comando');
279
+ const lines = [];
280
+ lines.push(`### ${commandName}`);
281
+ const aliases = unique(ensureArray(command.aliases));
282
+ lines.push(`- id: ${normalizeText(command.id)}`);
283
+ lines.push(`- aliases: ${aliases.length ? aliases.join(', ') : '(nenhum)'}`);
284
+ lines.push(`- enabled: ${command.enabled !== false}`);
285
+ lines.push(`- categoria: ${normalizeText(command.category)}`);
286
+ lines.push(`- descricao: ${normalizeText(command.description, 'Sem descricao cadastrada.')}`);
287
+ lines.push(`- permissao_necessaria: ${normalizeText(command.permission)}`);
288
+ lines.push(`- version: ${normalizeText(command.version)}`);
289
+ lines.push(`- stability: ${normalizeText(command.stability)}`);
290
+ lines.push(`- deprecated: ${normalizeBoolLabel(Boolean(command.deprecated))}`);
291
+ if (command.replaced_by) {
292
+ lines.push(`- replaced_by: ${command.replaced_by}`);
293
+ }
294
+ lines.push(`- risk_level: ${normalizeText(command.risk_level)}`);
295
+
296
+ lines.push('- local_de_uso:');
297
+ lines.push(...printList(command.contexts));
298
+
299
+ lines.push('- metodos_de_uso:');
300
+ lines.push(...printList(command.usage));
301
+
302
+ if (command.usageVariants && typeof command.usageVariants === 'object') {
303
+ lines.push('- mensagens_uso (variantes):');
304
+ const usageVariants = Object.entries(command.usageVariants);
305
+ if (!usageVariants.length) {
306
+ lines.push('- (nenhum)');
307
+ } else {
308
+ for (const [variant, usageList] of usageVariants) {
309
+ lines.push(`- ${variant}:`);
310
+ lines.push(...printList(usageList));
311
+ }
312
+ }
313
+ }
314
+
315
+ lines.push('- subcomandos:');
316
+ lines.push(...printList(command.subcommands));
317
+
318
+ lines.push('- argumentos:');
319
+ const argumentos = ensureArray(command.arguments);
320
+ if (!argumentos.length) {
321
+ lines.push('- (nenhum)');
322
+ } else {
323
+ lines.push(...argumentos.map((arg) => renderArgumentLine(arg)));
324
+ }
325
+
326
+ lines.push('- pre_condicoes:');
327
+ const pre = ensureObject(command.requirementsLegacy);
328
+ lines.push(`- requer_grupo: ${normalizeBoolLabel(Boolean(pre.requer_grupo))}`);
329
+ lines.push(`- requer_admin: ${normalizeBoolLabel(Boolean(pre.requer_admin))}`);
330
+ lines.push(`- requer_admin_principal: ${normalizeBoolLabel(Boolean(pre.requer_admin_principal))}`);
331
+ lines.push(`- requer_google_login: ${normalizeBoolLabel(Boolean(pre.requer_google_login))}`);
332
+ lines.push(`- requer_nsfw: ${normalizeBoolLabel(Boolean(pre.requer_nsfw))}`);
333
+ lines.push(`- requer_midia: ${normalizeBoolLabel(Boolean(pre.requer_midia))}`);
334
+ lines.push(`- requer_mensagem_respondida: ${normalizeBoolLabel(Boolean(pre.requer_mensagem_respondida))}`);
335
+
336
+ const rateLimit = ensureObject(command.rateLimit);
337
+ lines.push('- rate_limit:');
338
+ lines.push(`- max: ${rateLimit.max ?? 'null'}`);
339
+ lines.push(`- janela_ms: ${rateLimit.janela_ms ?? 'null'}`);
340
+ lines.push(`- escopo: ${rateLimit.escopo ?? '(nao informado)'}`);
341
+
342
+ lines.push('- acesso:');
343
+ if (command.access && typeof command.access === 'object') {
344
+ lines.push(`- somente_premium: ${normalizeBoolLabel(Boolean(command.access.premium_only))}`);
345
+ lines.push(`- planos_permitidos: ${command.access.allowed_plans.length ? command.access.allowed_plans.join(', ') : '(nao informado)'}`);
346
+ } else {
347
+ lines.push('- (nao informado)');
348
+ }
349
+
350
+ lines.push('- limite_uso_por_plano:');
351
+ if (command.planLimits && typeof command.planLimits === 'object') {
352
+ const planos = command.planLimits;
353
+ const comum = planos.comum && typeof planos.comum === 'object' ? planos.comum : null;
354
+ const premium = planos.premium && typeof planos.premium === 'object' ? planos.premium : null;
355
+ if (!comum && !premium) {
356
+ lines.push('- (nao informado)');
357
+ } else {
358
+ if (comum) {
359
+ lines.push(`- comum: max=${comum.max ?? 'null'}, janela_ms=${comum.janela_ms ?? 'null'}, escopo=${comum.escopo ?? '(nao informado)'}`);
360
+ }
361
+ if (premium) {
362
+ lines.push(`- premium: max=${premium.max ?? 'null'}, janela_ms=${premium.janela_ms ?? 'null'}, escopo=${premium.escopo ?? '(nao informado)'}`);
363
+ }
364
+ }
365
+ } else {
366
+ lines.push('- (nao informado)');
367
+ }
368
+
369
+ lines.push('- informacoes_coletadas:');
370
+ lines.push(...printList(command.collectedData));
371
+
372
+ lines.push('- dependencias_externas:');
373
+ lines.push(...printList(command.dependencies));
374
+
375
+ lines.push('- efeitos_colaterais:');
376
+ lines.push(...printList(command.sideEffects));
377
+
378
+ lines.push('- respostas_padrao:');
379
+ lines.push(...printObjectPairs(command.responses));
380
+
381
+ lines.push('- mensagens_sistema:');
382
+ const mensagensSistema = hasEntries(command.systemMessages) ? command.systemMessages : null;
383
+ if (!mensagensSistema) {
384
+ lines.push('- (nao informado)');
385
+ } else {
386
+ const deepPairs = printObjectPairsDeep(mensagensSistema);
387
+ lines.push(...(deepPairs.length ? deepPairs : ['- (nao informado)']));
388
+ }
389
+
390
+ lines.push('- limites_operacionais:');
391
+ const limitesOperacionais = hasEntries(command.operationalLimits) ? command.operationalLimits : null;
392
+ if (!limitesOperacionais) {
393
+ lines.push('- (nao informado)');
394
+ } else {
395
+ const deepPairs = printObjectPairsDeep(limitesOperacionais);
396
+ lines.push(...(deepPairs.length ? deepPairs : ['- (nao informado)']));
397
+ }
398
+
399
+ lines.push('- opcoes:');
400
+ const opcoes = hasEntries(command.options) ? command.options : null;
401
+ if (!opcoes) {
402
+ lines.push('- (nao informado)');
403
+ } else {
404
+ const deepPairs = printObjectPairsDeep(opcoes);
405
+ lines.push(...(deepPairs.length ? deepPairs : ['- (nao informado)']));
406
+ }
407
+
408
+ lines.push('- observabilidade:');
409
+ if (command.observability && typeof command.observability === 'object') {
410
+ lines.push(`- event_name: ${command.observability.event_name ?? '(nao informado)'}`);
411
+ lines.push(`- analytics_event: ${command.observability.analytics_event ?? '(nao informado)'}`);
412
+ lines.push(`- tags_log: ${command.observability.tags.length ? command.observability.tags.join(', ') : '(nenhum)'}`);
413
+ lines.push(`- nivel_log: ${command.observability.level ?? '(nao informado)'}`);
414
+ } else {
415
+ lines.push('- (nao informado)');
416
+ }
417
+
418
+ lines.push('- privacidade:');
419
+ if (command.privacy && typeof command.privacy === 'object') {
420
+ const privacy = command.privacy;
421
+ lines.push('- dados_sensiveis:');
422
+ lines.push(...printList(privacy.data_categories));
423
+ lines.push(`- retencao: ${privacy.retention ?? '(nao informado)'}`);
424
+ lines.push(`- base_legal: ${privacy.legal_basis ?? '(nao informado)'}`);
425
+ } else {
426
+ lines.push('- (nao informado)');
427
+ }
428
+
429
+ lines.push('- docs:');
430
+ if (hasEntries(command.docs)) {
431
+ const deepPairs = printObjectPairsDeep(command.docs);
432
+ lines.push(...(deepPairs.length ? deepPairs : ['- (nao informado)']));
433
+ } else {
434
+ lines.push('- (nao informado)');
435
+ }
436
+
437
+ lines.push('- behavior:');
438
+ if (hasEntries(command.behavior)) {
439
+ const deepPairs = printObjectPairsDeep(command.behavior);
440
+ lines.push(...(deepPairs.length ? deepPairs : ['- (nao informado)']));
441
+ } else {
442
+ lines.push('- (nao informado)');
443
+ }
444
+
445
+ lines.push('- limits:');
446
+ if (hasEntries(command.limits)) {
447
+ const deepPairs = printObjectPairsDeep(command.limits);
448
+ lines.push(...(deepPairs.length ? deepPairs : ['- (nao informado)']));
449
+ } else {
450
+ lines.push('- (nao informado)');
451
+ }
452
+
453
+ lines.push('- discovery:');
454
+ if (hasEntries(command.discovery)) {
455
+ const deepPairs = printObjectPairsDeep(command.discovery);
456
+ lines.push(...(deepPairs.length ? deepPairs : ['- (nao informado)']));
457
+ } else {
458
+ lines.push('- (nao informado)');
459
+ }
460
+
461
+ lines.push('- handler:');
462
+ if (hasEntries(command.handler)) {
463
+ lines.push(...printObjectPairs(command.handler));
464
+ } else {
465
+ lines.push('- (nao informado)');
466
+ }
467
+
468
+ return lines;
469
+ };
470
+
471
+ const buildAgentMarkdown = ({ moduleDirName, config }) => {
472
+ const safeConfig = ensureObject(config);
473
+ const moduleName = normalizeText(safeConfig.module || moduleDirName || 'module', 'module');
474
+ const schemaVersion = normalizeText(safeConfig.schema_version, '1.0.0');
475
+ const moduleEnabled = config?.enabled !== false;
476
+ const sourceFiles = ensureArray(safeConfig.source_files);
477
+ const moduleDefaults = ensureObject(safeConfig.defaults);
478
+ const commands = ensureArray(safeConfig.commands).map((entry) => normalizeCommand(entry, moduleDefaults));
479
+ const enabledCommands = commands.filter((entry) => entry && entry.enabled !== false);
480
+
481
+ const lines = [];
482
+ lines.push(`# ${resolveGuideTitle(moduleName)}`);
483
+ lines.push('');
484
+ lines.push('Este arquivo e destinado a agentes de IA para gerar respostas no contexto dos comandos deste modulo.');
485
+ lines.push('');
486
+ lines.push('## Fonte de Verdade');
487
+ lines.push(`- arquivo_base: \`app/modules/${moduleDirName}/commandConfig.json\``);
488
+ lines.push(`- schema_version: \`${schemaVersion}\``);
489
+ lines.push(`- module_enabled: \`${moduleEnabled}\``);
490
+ lines.push(`- generated_at: \`${nowIso}\``);
491
+ lines.push('');
492
+ lines.push('## Escopo do Modulo');
493
+ lines.push(`- module: \`${moduleName}\``);
494
+ lines.push('- source_files:');
495
+ lines.push(...printList(sourceFiles));
496
+ lines.push(`- total_commands: \`${commands.length}\``);
497
+ lines.push(`- total_enabled_commands: \`${enabledCommands.length}\``);
498
+
499
+ if (hasEntries(moduleDefaults)) {
500
+ lines.push('');
501
+ lines.push('## Defaults Schema v2');
502
+ lines.push(`- inheritance_mode: ${normalizeText(moduleDefaults.inheritance_mode, '(nao informado)')}`);
503
+ lines.push(`- compatibility_mode: ${normalizeText(moduleDefaults.compatibility_mode, '(nao informado)')}`);
504
+ lines.push('- legacy_field_aliases:');
505
+ lines.push(...printObjectPairs(moduleDefaults.legacy_field_aliases));
506
+
507
+ lines.push('- defaults.command:');
508
+ const commandDefaultsPairs = printObjectPairsDeep(moduleDefaults.command);
509
+ lines.push(...(commandDefaultsPairs.length ? commandDefaultsPairs : ['- (nao informado)']));
510
+
511
+ lines.push('- defaults.requirements (legacy view):');
512
+ const reqLegacy = normalizeLegacyRequirements(ensureObject(moduleDefaults.requirements));
513
+ lines.push(`- requer_grupo: ${normalizeBoolLabel(Boolean(reqLegacy.requer_grupo))}`);
514
+ lines.push(`- requer_admin: ${normalizeBoolLabel(Boolean(reqLegacy.requer_admin))}`);
515
+ lines.push(`- requer_admin_principal: ${normalizeBoolLabel(Boolean(reqLegacy.requer_admin_principal))}`);
516
+ lines.push(`- requer_google_login: ${normalizeBoolLabel(Boolean(reqLegacy.requer_google_login))}`);
517
+ lines.push(`- requer_nsfw: ${normalizeBoolLabel(Boolean(reqLegacy.requer_nsfw))}`);
518
+ lines.push(`- requer_midia: ${normalizeBoolLabel(Boolean(reqLegacy.requer_midia))}`);
519
+ lines.push(`- requer_mensagem_respondida: ${normalizeBoolLabel(Boolean(reqLegacy.requer_mensagem_respondida))}`);
520
+ }
521
+
522
+ if (config?.ai_help && typeof config.ai_help === 'object') {
523
+ const aiHelp = config.ai_help;
524
+ lines.push('');
525
+ lines.push('## Configuracao AI Help');
526
+ lines.push(`- enabled: ${aiHelp.enabled !== false}`);
527
+ lines.push(`- mode: ${String(aiHelp.mode || '(nao informado)')}`);
528
+ lines.push('- rag_sources:');
529
+ lines.push(...printList(aiHelp.rag_sources));
530
+ const faq = aiHelp.faq && typeof aiHelp.faq === 'object' ? aiHelp.faq : {};
531
+ const llm = aiHelp.llm && typeof aiHelp.llm === 'object' ? aiHelp.llm : {};
532
+ lines.push(`- faq.cache_file: ${faq.cache_file ?? '(nao informado)'}`);
533
+ lines.push(`- faq.interval_ms: ${faq.interval_ms ?? '(nao informado)'}`);
534
+ lines.push(`- faq.auto_generate_on_start: ${faq.auto_generate_on_start ?? '(nao informado)'}`);
535
+ lines.push(`- llm.enabled: ${llm.enabled ?? '(nao informado)'}`);
536
+ lines.push(`- llm.model: ${llm.model ?? '(nao informado)'}`);
537
+ lines.push(`- llm.max_agent_context_chars: ${llm.max_agent_context_chars ?? '(nao informado)'}`);
538
+ lines.push(`- llm.max_response_chars: ${llm.max_response_chars ?? '(nao informado)'}`);
539
+ lines.push(`- llm.timeout_ms: ${llm.timeout_ms ?? '(nao informado)'}`);
540
+ }
541
+
542
+ lines.push('');
543
+ lines.push('## Protocolo de Resposta para IA');
544
+ lines.push('- Passo 1: identificar comando pelo token apos o prefixo.');
545
+ lines.push('- Passo 2: resolver alias para nome canonico usando campo `aliases`.');
546
+ lines.push('- Passo 3: validar `enabled`, `pre_condicoes`, permissao e local de uso.');
547
+ lines.push('- Passo 4: se houver erro de uso, responder com `mensagens_uso` (quando existir) ou `metodos_de_uso`.');
548
+ lines.push('- Passo 5: seguir `respostas_padrao` como fallback de texto.');
549
+ lines.push('- Passo 6: considerar `informacoes_coletadas`, `privacidade` e `observabilidade` ao elaborar resposta.');
550
+
551
+ lines.push('');
552
+ lines.push('## Regras de Seguranca para IA');
553
+ lines.push('- A IA orienta, mas nao executa acao administrativa automaticamente.');
554
+ lines.push('- Nao inventar comandos, subcomandos ou permissao fora do JSON.');
555
+ lines.push('- Sempre informar onde pode usar (grupo/privado) e quem pode usar.');
556
+ lines.push('- Em duvida de permissao, responder com orientacao conservadora.');
557
+
558
+ lines.push('');
559
+ lines.push('## Catalogo de Comandos');
560
+ if (!commands.length) {
561
+ lines.push('- (nenhum comando configurado)');
562
+ } else {
563
+ for (const command of commands) {
564
+ lines.push(...buildCommandSection(command));
565
+ lines.push('');
566
+ }
567
+ while (lines.length && lines[lines.length - 1] === '') {
568
+ lines.pop();
569
+ }
570
+ }
571
+
572
+ lines.push('');
573
+ return lines.join('\n');
574
+ };
575
+
576
+ const listModuleDirs = async () => {
577
+ const entries = await fs.readdir(modulesRoot, { withFileTypes: true });
578
+ return entries
579
+ .filter((entry) => entry.isDirectory())
580
+ .map((entry) => entry.name)
581
+ .sort();
582
+ };
583
+
584
+ const shouldSkipModule = (moduleDirName, includeAdmin) => {
585
+ if (moduleDirName === 'adminModule' && !includeAdmin) return true;
586
+ return false;
587
+ };
588
+
589
+ const main = async () => {
590
+ const includeAdmin = process.argv.includes('--include-admin');
591
+ const dryRun = process.argv.includes('--dry-run');
592
+ const onlyModule = normalizeToken(getArgValue('--module'));
593
+ const moduleDirs = await listModuleDirs();
594
+ const generated = [];
595
+
596
+ for (const moduleDirName of moduleDirs) {
597
+ if (shouldSkipModule(moduleDirName, includeAdmin)) continue;
598
+ if (onlyModule && normalizeToken(moduleDirName) !== onlyModule) continue;
599
+
600
+ const configPath = path.join(modulesRoot, moduleDirName, 'commandConfig.json');
601
+ let raw = '';
602
+ try {
603
+ raw = await fs.readFile(configPath, 'utf8');
604
+ } catch (error) {
605
+ if (error?.code === 'ENOENT' || error?.code === 'ENOTDIR') {
606
+ continue;
607
+ }
608
+ throw error;
609
+ }
610
+ if (!raw) {
611
+ continue;
612
+ }
613
+ const config = JSON.parse(raw);
614
+ const markdown = buildAgentMarkdown({ moduleDirName, config });
615
+ const targetPath = path.join(modulesRoot, moduleDirName, 'AGENT.md');
616
+ if (!dryRun) {
617
+ await fs.writeFile(targetPath, markdown, 'utf8');
618
+ }
619
+ generated.push(path.relative(repoRoot, targetPath));
620
+ }
621
+
622
+ for (const item of generated) {
623
+ console.log(`${dryRun ? 'planned' : 'generated'}: ${item}`);
624
+ }
625
+ console.log(`total_${dryRun ? 'planned' : 'generated'}: ${generated.length}`);
626
+ };
627
+
628
+ main().catch((error) => {
629
+ console.error(error);
630
+ process.exit(1);
631
+ });