Develop#2632
Open
GMNAPI wants to merge 131 commits into
Open
Conversation
Introduces a new API endpoint and supporting logic to decrypt WhatsApp poll votes. Adds DecryptPollVoteDto, validation schema, controller method, and service logic to process and aggregate poll vote results based on poll creation message key.
Updated DecryptPollVoteDto to use a nested message.key structure and moved remoteJid to the top level. Adjusted the controller and validation schema to match the new structure for consistency and clarity.
feat(channel): add support for @newsletter in sendMessage and findChannels
…elop Feature: Endpoint para Descriptografar e Visualizar Votos de Enquetes
…es in chat controller
…tejid-wrong-format fix(baileys): normalize remote JIDs for consistent database lookups
… in contact cache
…tejid-normalization-and-cache-race fix: normalize remoteJid in message updates and handle race condition in contact cache
- Introduced a flag to prevent reconnection during instance deletion. - Improved logging for connection updates and errors during logout. - Added a delay before reconnection attempts to avoid rapid loops. - Enhanced webhook headers for better tracking and debugging. - Updated configuration to support manual Baileys version setting.
…QL, and PSQL Bouncer schemas
Creates new migration to ensure lid column exists even in databases where it was previously dropped by the Kafka integration migration. Uses prepared statement to check column existence before adding, ensuring compatibility with both fresh and existing installations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add audio-decode library for audio buffer analysis - Implement getAudioDuration() to extract duration from audio - Implement getAudioWaveform() to generate 64-value waveform array - Normalize waveform values to 0-100 range for WhatsApp compatibility - Change audio bitrate from 128k to 48k per WhatsApp PTT requirements - Add Baileys patch to prevent waveform overwrite - Increase Node.js heap size for build to prevent OOM Fixes evolution-foundation#1086
…preview - Fix linkPreview logic in Baileys to default to true - Add support for 'file' and 'embed' types in Typebot integration - Ensure correct media type detection for PDFs and docs
…ng, Typebot integration, and comprehensive API functionalities for chat, group, and business profiles.
…tions, messages, groups, profiles, and integrating with Chatwoot, OpenAI, and S3.
…ryption, and channel fetching
…-foundation#2470) - Changed truthy check to strict equality (=== true) to properly handle string values like "false" sent by clients (e.g., n8n) - Fixed validation schema property name from 'everyOne' to 'mentionsEveryOne' to match DTO and service code Fixes evolution-foundation#2431 Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
… destructive JSON cloning (evolution-foundation#2461) * fix(whatsapp): resolve this.isZero error in list messages by removing destructive JSON cloning * refactor: extract listType normalization into a helper function
…on (evolution-foundation#2493) The BusinessStartupService shared a mutable this.phoneNumber property across concurrent webhook requests. When two webhooks arrived near- simultaneously for the same phone_number_id, the second request could overwrite phoneNumber before the first finished processing, causing messages to be attributed to the wrong sender (wrong remoteJid). Changes: - Compute senderJid as a local variable before calling eventHandler - Pass senderJid as parameter through eventHandler -> messageHandle - Await eventHandler to prevent concurrent mutation - Replace all this.phoneNumber reads inside messageHandle with the local senderJid parameter Made-with: Cursor
…on-foundation#2519) Adds POST /chat/markMessageAsPlayed/{instance} for marking received audio messages as played (blue microphone in WhatsApp), mirroring the existing markMessageAsRead pattern. Baileys natively supports sock.sendReceipts(keys, 'played') but Evolution only exposed the 'read' type via /chat/markMessageAsRead. CRMs that play back voice notes received from contacts had no way to send the played ack — this endpoint fills the gap with the same DTO/schema shape (key shape: id, fromMe, remoteJid) under a 'playedMessages' array. Mirrors: - DTO: MarkMessageAsPlayedDto extends Key array (mirrors ReadMessageDto) - Schema: markMessageAsPlayedSchema (JSONSchema7, mirrors readMessageSchema) - Service: markMessageAsPlayed -> client.sendReceipts(keys, 'played') - Controller: markMessageAsPlayed -> waMonitor delegation - Router: POST routerPath('markMessageAsPlayed') Use case: agent CRMs (Chatwoot-like) that present audio messages with a play button and need to send the played receipt back to the contact when the agent plays the audio in the dashboard.
…oundation#2510) * fix(history-sync): emit completion before contact upsert * chore(ci): rerun checks on current head * fix(history-sync): include progress in completion event * style(chatwoot): fix lint violations * fix(history-sync): ignore non-primary completions * Revert "fix(history-sync): ignore non-primary completions" This reverts commit c0523d6. * chore: add ghcr publish workflow to branch
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…n-foundation Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
) * feat(group): add updateMemberAddMode endpoint Expose the WhatsApp protocol's group "member add mode" setting (supported by Baileys via groupMemberAddMode) as a new endpoint, so clients can toggle whether non-admin members are allowed to add participants to a group. POST /group/updateMemberAddMode/{instance}?groupJid=<jid> body: { "mode": "admin_add" | "all_member_add" } - admin_add → only admins can add new members - all_member_add → any member can add new members (WhatsApp default) Mirrors the existing pattern of updateSetting: - DTO : GroupUpdateMemberAddModeDto - Schema: updateMemberAddModeSchema (validates mode enum) - Service: WhatsappBaileysService.updateMemberAddMode - Controller: GroupController.updateMemberAddMode - Route: POST /group/updateMemberAddMode No breaking change. No new dependency. * ci: build & publish fork Docker image to GHCR Triggered on every push to feat/group-member-add-mode. Produces: ghcr.io/hassankaid/evolution-api:member-add-mode ghcr.io/hassankaid/evolution-api:sha-<commit> Allows users running self-hosted Evolution to swap their Docker image to this fork while keeping all their state (sessions, DB, Redis) untouched, until the upstream PR evolution-foundation#2525 is merged.
…dation#2530) * feat(licensing): mirror evolution-go license activation system Phase 1 of the licensing rollout — backend only. Brings the same activation lifecycle that already exists in evolution-go (pkg/core) into evolution-api as src/licensing/, plus a public /license/* router and a gate middleware that 503s API traffic until activation. Module layout (mirrors pkg/core/*.go): - src/licensing/model.ts (config keys, type contracts) - src/licensing/store.ts (Prisma RuntimeConfig CRUD + hardware-based instance ID) - src/licensing/endpoint.ts (XOR-decoded URL with parts-array dev fallback) - src/licensing/transport.ts (axios + HMAC-SHA256 signing) - src/licensing/integrity.ts (paridade-only stubs - Baileys does not consume) - src/licensing/runtime.ts (RuntimeContext, initializeRuntime, gateMiddleware, heartbeat, shutdown, completeActivation) Public routes (no auth) - same contract as evolution-go: - GET /license/status -> {status, instance_id, api_key (masked)} - GET /license/register?redirect_uri -> POST /v1/register/init upstream - GET /license/activate?code= -> POST /v1/register/exchange + activate Bootstrap order in src/main.ts: 1. setDB(prisma) 2. initializeRuntime({tier: 'evolution-api', version, globalApiKey}) 3. /license router (always public) 4. gateMiddleware (503 LICENSE_REQUIRED before business routers) 5. business routers 6. startHeartbeat (30 min, fire-and-forget) 7. SIGTERM/SIGINT -> POST /v1/deactivate (best-effort) Behaviour notes: - AUTHENTICATION_API_KEY is reused as bootstrap key (mirrors GLOBAL_API_KEY in Go). If a license already exists in the DB, the service runs locally even if the licensing server is unreachable. - Gate middleware allowlist: /license/*, /manager/**, /assets/**, /store/**, /health, /server/ok, /favicon.ico, /ws, common static extensions. - Heartbeat carries optional telemetry_bundle with messages_sent / messages_recv that callers can feed via trackMessageSent() / trackMessageRecv(). Schema: - New Prisma model RuntimeConfig (key/value) on both postgresql and mysql schemas. Run npm run db:migrate:dev per provider before starting the service. Endpoint URL ofuscation: - Set LICENSE_ENDPOINT_ENCODED + LICENSE_ENDPOINT_XOR_KEY (hex) in release builds to avoid the licensing URL appearing as a plain string in the bundle. - Dev fallback assembles license.evolutionfoundation.com.br from a parts array, same technique as evolution-go. Phase 2 (manager-v2 UI for the activation flow) lands in a separate PR under evolution-foundation/evolution-manager-v2. * feat(licensing): add Prisma migration for RuntimeConfig table Adds the database migration that creates the licensing storage table (postgres + mysql). This was missing from the previous licensing commit. Without this migration, npm run db:deploy is a no-op and the server will fail to find the table at boot. * release: 2.4.0 - license activation required Polishes the licensing rollout for public release: - Better error UX: HTTP 503 now carries instance_id, docs_url and an actionable message instructing the operator to open the manager UI or set AUTHENTICATION_API_KEY in .env. - Better boot banner: lists the activation paths (manager UI, env var) with the docs URL and the instance_id. - Auto-detect missing migration: if the RuntimeConfig table is absent, the server prints a clear banner asking the operator to run npm run db:deploy and exits 1, instead of throwing a Prisma stack trace from inside the bootstrap. - Version bump 2.3.7 -> 2.4.0. - CHANGELOG entry with BREAKING CHANGE notice and migration guide. - README section 'License Activation' linking to docs.evolutionfoundation.com.br/licensing. * build(manager): refresh manager/dist with v2.4.0 bundle - Bumps the embedded manager UI to the version published on evolution-foundation/evolution-manager-v2 main, which now includes the license-aware login flow that mirrors evolution-go-manager. - Removes the legacy manager/dist/assets/test-interactive.js stand-alone script — its functionality is now a proper React component (TestInteractiveModal) inside the bundle, accessed from the instance card on the dashboard. - Updates the manager-v2 submodule pointer to track main. * style(licensing): apply prettier/eslint autofix and hoist DOCS_URL The autofix from the pre-push hook reorders imports, normalizes line breaks and reformats the constructor signature. Also moves DOCS_URL to the top of the module so the auto-detect error path can reference it without hitting the temporal dead zone. * feat(licensing): bake licensing endpoint into bundle at build time Mirrors evolution-go/tools/build-dist/obfuscate.go: the URL of the licensing server is now XOR-encoded into the JS bundle by tsup `define`, so it never appears as a plain literal in dist/main.js. The Dockerfile accepts the pair as build-args (NOT runtime env vars) so an operator cannot point the running service at a different licensing server. - src/licensing/endpoint.ts: read from compile-time `__LICENSE_ENDPOINT_*__` identifiers replaced by tsup; keep parts-array fallback for dev builds. - tsup.config.ts: `define` reads LICENSE_ENDPOINT_ENCODED / _XOR_KEY from build env at the moment npm run build is invoked. - tools/encode-url.js: helper to generate the hex pair for a given URL. Usage: eval "$(node tools/encode-url.js <url>)". - Dockerfile: ARG + ENV plumbing for the build stage only. - CHANGELOG: notes about the build-time obfuscation. * chore: drop evolution-manager-v2 submodule The manager-v2 source repository is now private, so the CI checkout step fails when trying to fetch the submodule (no PAT configured, GITHUB_TOKEN has no cross-repo read scope). Drop the submodule entirely — the runtime artefact already lives under manager/dist/ in this repo, which is what the Express server serves. Source for the manager continues to be maintained at evolution-foundation/evolution-manager-v2 (private). * style(licensing): prettier autofix on endpoint.ts * docs(changelog): expand 2.4.0 entry with all features since 2.3.7 Previous entry only covered the licensing rollout. The release actually includes 50 commits worth of work: - Manager v2 completely redesigned (Tailwind v4 + @evoapi/design-system, dual-provider support, advanced sessions panels, license flow, Test Interactive modal, full i18n). - Carousel message endpoint (POST /message/sendCarousel). - Cross-client fix for buttons and list rendering on WhatsApp Web/Desktop/iOS via the <biz> stanza node and the legacy listMessage payload. - Interactive buttons via deviceSentMessage with corrected CTA limits and PIX payment_info support. - Catalog orderMessage and quoted productMessage support. - New messaging-history.set event with cumulative counts. - markMessageAsPlayed audio receipt endpoint. - SQS custom base_url. - LID -> phone-number mapping with cache. - Multiple bug fixes (mentionsEveryOne, getLastMessage, markMessageAsRead, list-message JSON cloning, Cloud API race conditions, instance logout idempotency, zombie-instance cleanup, network family timeout, etc.).
…n/fix/logout-baileys fix: logout instance
AxiosHeaderValue widened to include number; explicit String() cast keeps runtime behavior and unblocks tsc --noEmit.
When EVOLUTION_OPERATOR_EMAIL is set in .env, initializeRuntime silently calls the licensing server's /v1/register/auto endpoint on startup, persists the returned api_key and activates the instance — skipping the browser registration flow entirely. Falls back to the manual registration flow on any failure (email not yet registered, server unreachable, key suspended, etc.). Non-fatal. Requires one prior manual registration so the email is known server-side.
…volution-foundation#2544) After WhatsApp's LID (Linked Identity) migration, DMs to contacts that resolve to @lid JIDs fail with a BadRequestException because onWhatsApp returns exists:false for LID-based identifiers. Add @lid to the whitelist alongside @broadcast in both sendMessageWithTyping and sendPresence so these contacts are not rejected by the existence check. Co-authored-by: CORREIA Eduardo <eduardo.correia@hexagon.com>
…olution-foundation#2485) (evolution-foundation#2516) The `audioWhatsapp` method was not forwarding `data.quoted` to `sendMessageWithTyping`, so audio messages sent with a `quoted` key were delivered as standalone messages instead of replies. Added `quoted: data?.quoted` to the options object in both `sendMessageWithTyping` call sites inside `audioWhatsapp` (the encoding path and the direct path), matching the pattern used by all other message-sending methods (textMessage, pollMessage, etc.). Co-authored-by: octo-patch <octo-patch@github.com>
…ose' state (evolution-foundation#2420) Evolution is a webhook-based integration that should always be considered 'open' since it passively receives events. Three changes fix the issue: 1. monitor.service.ts: Always call connectToWhatsapp() for Evolution instances on server restart, regardless of stored connection status. 2. instance.controller.ts: Call connectToWhatsapp() for Evolution instances during creation to initialize Chatwoot settings. 3. evolution.channel.service.ts: Restore stateConnection to 'open' and persist it to DB when connectToWhatsapp() is called in init mode. Closes evolution-foundation#2419 https://claude.ai/code/session_013wxk4cj5U2H5fr2cxCgWdH Co-authored-by: Claude <noreply@anthropic.com>
…ion#2546) Prevents instances with trailing/leading whitespace in their names from becoming undeletable via the API or UI. Fixes evolution-foundation#2543.
…foundation#2540) * feat: add gifPlayback support for video messages Allow gifPlayback and gifAttribution options to be passed to Baileys video messages. * feat: add gif options to media DTOs Add gifPlayback and gifAttribution properties to media DTO definitions. * feat: add gif fields to media message schema Add gifPlayback and gifAttribution validation support to media message schema. * fix: validate gifAttribution values before assignment Prevent invalid gifAttribution values from reaching Baileys media payload.
Stabilization release on top of 2.4.0-rc1. No DB or HTTP contract changes — fixes in WhatsApp/Baileys (@lid bypass, audio quoted, instanceName trim) and Evolution Channel (instances stuck in close), native GIF send support, and optional headless licensing auto-activation via EVOLUTION_OPERATOR_EMAIL. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…m:error 515 (evolution-foundation#2509) * fix(baileys): prevent healthy instances from being killed after stream:error 515 When WhatsApp sends stream:error code=515 (Connection Replaced), Baileys handles the reconnect correctly and fires connection.update with state='open'. However, WhatsApp then sends a 401 (loggedOut) to clean up the old session slot, which Evolution API incorrectly treated as a real logout, killing the newly-connected healthy instance. The fix tracks when a stream:error 515 node arrives via the CB:stream:error WebSocket event. If a loggedOut (401) close event fires within 30 seconds of a 515, it is treated as a transient reconnect rather than a real logout. Fixes evolution-foundation#2498 * fix(baileys): name the 515 reconnect grace + tighten stream-error types Addresses sourcery-ai review feedback on the previous commit: - Extract the 30 000ms reconnect grace window into a named class constant STREAM_515_RECONNECT_GRACE_MS so future tuning is self-documenting rather than a literal scattered through the close handler. - Extract the magic '515' string into STREAM_ERROR_CODE_RECONNECT. - Replace the loose 'node: any' on the 'CB:stream:error' handler with a minimal structural type ({ attrs?: { code?: string | number } }) so the payload shape is documented and type-checked. - Compare the code via String(...) so a numeric 515 from the underlying socket library still triggers the grace window — the original literal '515' check would have silently broken on a type change. * fix(baileys): satisfy prettier — collapse 515 reconnect guard onto one line Check Code Quality lint failed on prettier/prettier (the recentStream515 expression fits within the project's 120-col printWidth on a single line, while shouldReconnect still needs to break across two). Co-authored-by: Octopus <liyuan851277048@icloud.com> --------- Co-authored-by: octo-patch <octo-patch@github.com> Co-authored-by: octo-patch <octo-patch@users.noreply.github.com>
…hName in fetchChats (evolution-foundation#2460) * refactor(channel): remove unused pushName field * refactor(channel): simplify pushName assignment logic * fix(channel): remove Message.pushName fallback from MySQL CASE query * fix(channel): remove duplicated pushName alias and prefer Contact.pushName in fetchChats
…olution-foundation#2514) * fix(meta): handle message_echoes and guard missing contact fields * feat(meta): fallback pushName from persisted contact on cloud api * fix(meta): address review feedback on remoteId and status fromMe
…-foundation#2483) * feat(chat): add fetchLid endpoint for PN to LID resolution * fix(pr-feedback): log error when failing to fetch LID for WUID * chore: trigger CI --------- Co-authored-by: shennawy <m.alshenaawy@mu.edu.sa>
…(CVE pending, evolution-foundation#2435) (evolution-foundation#2549) * security: prevent cross-instance auth bypass via query/body override (evolution-foundation#2435) The auth guard in src/api/guards/auth.guard.ts validates instance ownership using req.params.instanceName. The abstract router then merged req.query (and, on /instance/create, req.body) into the instance object via Object.assign — which silently overwrote the already-authenticated instanceName. An attacker with one valid token could send: GET /chat/findMessages/MY_INSTANCE?instanceName=VICTIM_INSTANCE Auth passed for MY_INSTANCE, but dataValidate() then replaced the instance with VICTIM_INSTANCE before execute() ran — giving the caller full access to read/send messages, modify settings, and delete other tenants' instances. CWE-639: Authorization Bypass Through User-Controlled Key Fix: introduce sanitizeUntrustedInput() that strips PROTECTED_INSTANCE_FIELDS (instanceName, instanceId) from any untrusted source before merging into the instance object. Logs a warning on attempts so abuse is auditable. Closes evolution-foundation#2435 Reported by @lighthousekeeper1212 via static analysis. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(lint): remove extra blank line introduced by recent merge Pre-push lint flagged whatsapp.baileys.service.ts:531 (double blank line after the stream:error 515 fix merged via evolution-foundation#2509). Trivial prettier fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-foundation#2577) * fix(gitignore): exclude _evo* files from version control * feat(channel): add EvoHub channel (Phase 1 — link-existing) EvoHub é um canal adicional, espelho transparente do canal Meta (Cloud API) roteado pelo proxy do EvoHub. Não altera o comportamento do canal Meta existente. Data-plane: EvoHubStartupService extends BusinessStartupService, sobrescreve só o transporte (URL {HUB}/meta sem versão + Bearer channel_token). Control-plane: EvoHubClient + rotas /evohub/* (apikey global). Fase 1 entrega o fluxo link-existing (resolve token + phone_number_id server-side via GET /api/v1/channels/:id; o front nunca vê o token). Webhook: EvoHubController reusa o parser Meta + valida HMAC X-Hub-Signature-256 sobre raw body (soft-mode na Fase 1). Edição mínima na base Meta (autorizada): 3 private→protected + helper fetchMediaFromGraph (JS emitido idêntico; bloco S3 inline roteado pelo helper p/ evitar vazamento de mídia inbound EvoHub para a Meta com S3 ligado). tsc --noEmit verde, eslint limpo, tsup build success. * fix(evohub): normalize hub channel list response + correct self endpoints - listChannels: o hub retorna { channels: [...], count } (channel_handler.go GetChannels), não um array nu — causava 'channels.filter is not a function' na rota /evohub/available-channels. Adiciona normalizeChannelList (tolera channels|data|array nu). - getPlan/getMetaAppOptions: corrige paths para /me/plan e /me/meta-app-options (endpoints self-service do hub; /plan é admin-por-id e exige UUID). Fase 2. * fix(evohub): provision request mapping + channel list normalization + filtros whatsapp - evohub.client: listChannels normaliza a resposta do hub { channels: [] } (não array nu) — corrige 'channels.filter is not a function'. - evohub.client.provisionChannel: monta o request correto do hub { name, type, channel_credentials_id?, webhook_url } (antes passava o body cru → 400) e registra o webhook do evolution-api (single-shot, register-with-own-secret). Normaliza a resposta { channel } | plano. - getPlan/getMetaAppOptions: paths corretos /me/plan e /me/meta-app-options. - controlplane.router: /provision mapeia instanceName→name, fixa type=whatsapp, monta webhook_url do SERVER.URL; /available-channels filtra só type=whatsapp (evolution-api é API de WhatsApp; o hub devolve fb/ig também). - env: EVOLUTION_HUB_FRONTEND_URL default corrigido p/ o domínio do hub. * build(manager): rebuild manager-v2 com o canal EvoHub (Fase 1) Atualiza manager/dist com o build do evolution-manager-v2 incluindo a opção de canal EvoHub na criação de instância (vincular-existente + criar-novo).
…5, ESLint 10, Redis 6, TS 6 (evolution-foundation#2575) * chore(deps): bump baileys 7.0.0-rc.9 -> rc13 and drop obsolete waveform patch - baileys atualizado para a ultima versao publicada (rc13) - remove patches/baileys+7.0.0-rc.6.patch: a correcao de waveform PTT (requiresWaveformProcessing) ja foi incorporada upstream no rc13 - API additionalNodes do relayMessage confirmada identica: botoes/lista/carrossel preservados - adiciona ATUALIZACAO-DEPENDENCIAS.md (plano de atualizacao em tiers) tsc --noEmit e build (tsup) passam limpos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(deps): tier 1 - safe minor/patch bumps within same major - runtime: axios 1.17, @sentry/node 10.56, pg 8.21, dayjs, jimp, socket.io(+client) 4.8.3, minio, mediainfo.js, libphonenumber-js, jsonwebtoken, cors, fetch-socks, multer 2.1, @aws-sdk/client-sqs, prisma+@prisma/client 6.19.3, undici 7.27 - dev: prettier 3.8, tsx 4.22, @typescript-eslint/* 8.60, eslint-plugin-prettier, @types/node 24, lint-staged 16 - fix(types): cast response.headers['content-type'] as string (axios 1.17 endureceu AxiosHeaderValue) em whatsapp.baileys.service.ts e chatwoot.service.ts tsc --noEmit e build passam limpos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(deps): tier 2 - low/medium-risk majors - uuid 14, dotenv 17, node-cron 4, i18next 26, @paralleldrive/cuid2 3, class-validator 0.15, pusher 5.3, mime-types 3 (+@types/mime-types 3), amqplib 2 - fix(rabbitmq): coerce url.port para Number (amqplib 2 exige port:number) - mantidos na faixa de peer do baileys rc13 (evita ERESOLVE/quebra interna): audio-decode 2, link-preview-js 3, pino 9, jimp 1.6 - adiados (majors ESM-only que exigiriam mudar moduleResolution): https-proxy-agent 9, socks-proxy-agent 10, undici 8 -> mantidos em 7/8/7 tsc --noEmit e build passam limpos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(deps): tier 3a - migrate to eslint 10 flat config - eslint 8 -> 10 com eslint.config.mjs (flat config), removendo .eslintrc.js e .eslintignore - substitui @typescript-eslint/eslint-plugin+parser pelo meta-pacote typescript-eslint 8 - troca eslint-plugin-import (sem suporte a eslint 10) por eslint-plugin-import-x 4 (regras import-x/first e import-x/no-duplicates) - simple-import-sort 13, @commitlint/* 21, lint-staged 17, globals - desativa regras novas do recommended do eslint 10 (preserve-caught-error, no-useless-assignment) para preservar baseline - scripts lint/lint:check sem --ext (flat config) - reinstalacao limpa da arvore (lock regenerado, peers do baileys respeitados) lint:check, tsc --noEmit e build passam limpos (apos prisma generate). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(deps): tier 3b - migrate to express 5 - express 4 -> 5 (+@types/express 5), movido de volta para dependencies - rotas wildcard adaptadas ao path-to-regexp v8: - index.router.ts: /assets/* -> /assets/*splat (req.params.splat agora e array, juntado com '/') - view.router.ts: '*' -> /{*splat} - cast 'as string' em req.params.<id> nos 7 routers de chatbot (req.params agora e string|string[] no @types/express 5; rotas :param sempre retornam string) tsc --noEmit, lint e build passam limpos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(deps): tier 3c - openai 6 + remove express-async-errors (incompativel com express 5) - openai 4 -> 6: beta.threads.runs.retrieve/submitToolOutputs agora recebem runId e thread_id no objeto de params - remove express-async-errors (peer so suporta express 4; express 5 ja trata erros async de handlers nativamente) e seu import em abstract.router.ts tsc --noEmit, lint e build passam limpos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(deps): tier 3d - redis (node-redis) 4 -> 6 - redis 4 -> 6: cast 'as string' no retorno de get()/hGet() em rediscache.ts (redis 6/RESP3 tipa retorno como string|{}; JSON.parse exige string) - has() ja tratava exists() > 0 (exists retorna numero) tsc --noEmit, lint e build passam limpos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(deps): tier 3e - typescript 5 -> 6 - typescript 5.7 -> 6.0.3 (compativel com typescript-eslint <6.1.0) - adiciona 'ignoreDeprecations: 6.0' no tsconfig: baseUrl e moduleResolution=node10 viraram deprecation-error no TS 6; migracao real (node16/bundler) exigiria extensoes .js em todos os imports — adiado para o TS 7 tsc --noEmit, lint e build passam limpos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: atualiza plano de dependencias com progresso dos tiers 0-3 e notas finais Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(deps): override whatsapp-rust-bridge to 0.5.5 (fix CJS runtime resolution) - baileys rc13 depende de whatsapp-rust-bridge@0.5.4 (ESM-only, exports so com 'import'): app nao sobe via tsx/require (ERR_PACKAGE_PATH_NOT_EXPORTED) - 0.5.5 adiciona condicao 'require' nos exports -> resolve em contexto CommonJS (Node 24 suporta require de ESM) - aplicado via overrides no package.json Validado: require do modulo funciona e dev:server inicializa toda a stack ate a conexao de infra (DB/Redis). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(deps): tier 3f - moduleResolution bundler + proxy agents 9/10 - tsconfig: module CommonJS->preserve, moduleResolution node10->bundler - remove baseUrl e ignoreDeprecations: elimina por completo a divida de deprecacao do TS 6/7 (node10 e baseUrl); paths resolvem relativo ao tsconfig (validado em tsc, tsup e tsx) - https-proxy-agent 7->9 e socks-proxy-agent 8->10 (majors ESM-only, agora resolviveis com bundler) - src nao usa require()/export = (compativel com module preserve) Validado: tsc, lint, build limpos; dev:server carrega TODOS os modulos (aliases + proxy agents ESM-only) ate a fronteira de infra (auth do Postgres). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(deps)!: tier 4 - migrate to Prisma 7 (driver adapters + prisma-client generator) BREAKING: Prisma 6 -> 7 (ESM-only, driver adapters obrigatorios) - @prisma/client+prisma 7.8.0; adiciona @prisma/adapter-pg e @prisma/adapter-mariadb - generator 'prisma-client-js' -> 'prisma-client' com output ./generated/client (TS gerado) nos 3 schemas (postgresql, mysql, psql_bouncer); url removida do datasource (proibida no v7) - prisma.config.ts: connection string (datasource.url via DATABASE_CONNECTION_URI) + selecao dinamica de schema/migrations por DATABASE_PROVIDER (multi-provider) - repository.service.ts: instancia PrismaClient com driver adapter conforme provider (PrismaPg | PrismaMariaDb) - alias @prisma/client -> client gerado: no tsconfig (tsx/tsc) e reforcado no tsup (noExternal + esbuild alias), pois esbuild nao honra paths do tsconfig - tsup: shims:true (shim de import.meta.url p/ client v7 no bundle CJS) e platform:node - start:prod usa dist/main.js (CJS) - ESM puro quebra por imports sem extensao do @figuro/chatwoot-sdk - 3 imports de JsonValue: @prisma/client/runtime/library -> /runtime/client (caminho mudou no v7) - prisma/generated/ no .gitignore (gerado por provider via db:generate) Validado: db:generate (postgres+mysql), tsc, lint, build; boot dev (tsx) e prod (node dist/main.js) inicializam ate a query real (DriverAdapterError: AuthenticationFailed = credenciais/infra, nao codigo). HTTP server sobe na porta 3210. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: registra Tier 3f (moduleResolution+proxies) e Tier 4 (Prisma 7) concluidos Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(audio): delega waveform/duracao ao Baileys rc13 nativo (EVO-1670) Remove o getAudioMetadata() redundante: o Baileys rc13 ja calcula seconds/waveform nativamente (getAudioDuration/getAudioWaveform via audio-decode) quando ausentes no envio de PTT. - removido getAudioMetadata() (~50 linhas) e o import orfao de audio-decode - audioWhatsapp() para de passar seconds/waveform nos 2 caminhos; agora URL tambem ganha waveform - audio-decode mantido no package.json (peerOptional usado internamente pelo Baileys) Validado: tsc/lint/build limpos; PTT real -> resposta com seconds:9 + waveform (Uint8Array) gerados pelo Baileys; confirmado visualmente pelo usuario. Ref: EVO-1670 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Matheus Pastorini <matheus.pastorini@etus.com.br> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Davidson Gomes <davidsongviolao@gmail.com>
Contributor
There was a problem hiding this comment.
Sorry @GMNAPI, your pull request is larger than the review limit of 150000 diff characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📋 Description
🔗 Related Issue
Closes #(issue_number)
🧪 Type of Change
🧪 Testing
📸 Screenshots (if applicable)
✅ Checklist
📝 Additional Notes