Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

247 changes: 247 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,250 @@
# 2.4.0 (2026-05-06)

### ⚠️ BREAKING CHANGE — License activation is now required

Starting with v2.4.0, every Evolution API instance must be activated against the
Evolution Foundation licensing server before serving API traffic. Until activation,
all business endpoints return:

```
HTTP 503 Service Unavailable
{
"error": "service not activated",
"code": "LICENSE_REQUIRED",
"register_url": "https://<your-host>/manager/login",
"instance_id": "<uuid>",
"docs_url": "https://docs.evolutionfoundation.com.br/licensing",
"message": "..."
}
```

The following routes always remain public so the operator can recover:
`/license/status`, `/license/register`, `/license/activate`, `/manager/**`,
`/health`, `/server/ok`, `/ws`, static assets.

### Migration guide

1. Pull the new version and install dependencies:
```bash
git pull
npm install
```

2. Apply the new migration (creates the `RuntimeConfig` table). Required:
```bash
npm run db:deploy
```
If you skip this step, the server now fails fast with a clear error
asking you to run `db:deploy`.

3. Start the service. There are three activation paths:

- **Already have a valid licensing key?** Set it as `AUTHENTICATION_API_KEY`
in your `.env` and restart. The bootstrap step will validate the key with
the licensing server, persist it, and activate the instance automatically.

- **First-time activation via the manager UI?** Open
`https://<your-host>/manager/login`. The manager detects that the
instance is unlicensed and redirects you to the registration page on
the licensing server. After you complete the form, you are sent back
to `/manager/license/callback?code=...`, the manager exchanges the code,
and the dashboard becomes accessible.

- **Calling the API from code (n8n, Make, custom scripts) without a valid
license?** Every request will receive `503 LICENSE_REQUIRED` with the
`register_url` field pointing to the manager. Open it in a browser to
activate.

### Added

#### Manager v2 — completely redesigned dashboard

The embedded manager (served at `/manager`) was rebuilt from the ground up
on **Tailwind v4** + the new **`@evoapi/design-system`**, using the same
visual language as the rest of the Evolution Foundation product line.
Every screen was refactored — no surface remains untouched.

Highlights:

- **Modern dashboard** with skeleton loading, illustrated empty state,
and a typed-name confirmation modal for instance deletion (no more
accidental clicks).
- **Dual-provider support**: the manager now talks to either
`evolution-api` or `evolution-go` (selected at login, persisted in
localStorage). When connected to a GO backend, the sidebar/router
automatically hide the modules GO does not implement.
- **Sessions panels** for the seven chatbot integrations (OpenAI, Dify,
N8N, EvoAI, EvolutionBot, Flowise, Typebot) gained advanced filters
(name / number / status / time presets + custom),
bulk-status-change actions, client-side pagination, and a real
send-message modal calling `/message/sendText`.
- **License-aware login** — see the *Licensing* section below for the
details.
- **🧪 Test Interactive** modal on each instance card — a 5-tab
payload editor (Reply / CTA / PIX / List / Carousel) for
smoke-testing the new interactive-message endpoints from the
dashboard. Replaces the legacy stand-alone `test-interactive.js`
vanilla script that used to be injected into `index.html`.
- **Full i18n coverage** in **pt-BR / en-US / es-ES / fr-FR** — every
screen, every toast, every modal.
- **Branding refresh** — sidebar/footer/login point to
`docs.evolutionfoundation.com.br`, GitHub links to
`evolution-foundation/evolution-manager-v2`, contact to
`suporte@evofoundation.com.br`.

The new bundle is shipped pre-built under `manager/dist/`. The manager
source repository moved to `evolution-foundation/evolution-manager-v2`
(private) — the previous in-repo submodule was dropped.

#### Licensing
- **Licensing module** under `src/licensing/` — RuntimeContext, gate middleware,
signed/unsigned HTTP transport, hardware-based instance ID, fire-and-forget
heartbeat (every 30 min), graceful shutdown deactivation. Mirrors the
evolution-go `pkg/core/` reference implementation.
- **Public license endpoints**:
- `GET /license/status` — current activation state and (masked) api_key
- `GET /license/register?redirect_uri=` — initiates registration on the
licensing server, returns `register_url`
- `GET /license/activate?code=` — exchanges the authorization code received
on the callback for a real api_key, persists it, marks the runtime active.
- **New Prisma model** `RuntimeConfig` (key/value rows in `RuntimeConfig` table)
for both PostgreSQL and MySQL schemas.
- **Auto-detect missing migration**: if the `RuntimeConfig` table is absent,
the server prints a clear banner explaining `npm run db:deploy` and exits 1
instead of throwing a stack trace from the Prisma client.
- **Manager v2** ships with the new license-aware login flow that recognises
HTTP 503 / `LICENSE_REQUIRED`, calls `/license/register`, and redirects to
the registration server. After the callback, it lands on
`/manager/license/callback?code=...` and finalises activation. The new
manager bundle is included under `manager/dist/`.

#### Interactive Messages (Buttons / List / CTA / PIX / Carousel)
- **New endpoint `POST /message/sendCarousel/{instance}`** — multi-card
product carousel built on top of `interactiveMessage` + `carouselMessage`.
Single-card-without-image falls back to `nativeFlowMessage` for iOS
compatibility. New DTO `SendCarouselDto`, schema `carouselMessageSchema`.
- **Button rendering fixed on WhatsApp Web/Desktop/iOS/Android** — removed the
`viewOnceMessage` wrapper that prevented buttons from rendering and started
injecting the required `<biz><interactive type=native_flow v=1>
<native_flow v=9 name=mixed/></interactive></biz>` node into the
`relayMessage` stanza via Baileys' official `additionalNodes` option.
- **List messages fixed on WhatsApp Web/Desktop** — switched to legacy
`listMessage` with `SINGLE_SELECT` listType (the modern
`interactiveMessage + single_select` format does not render on Web/Desktop)
and added `<biz><list type=product_list v=2/></biz>`.
- **Interactive buttons via `deviceSentMessage`** + corrected CTA limits
(max 2 CTA buttons, no mixing with reply or PIX), aligning with the
WhatsApp Business message contract.
- **PIX support** for interactive button messages (`payment_info` button
type — exactly 1 button, isolated).
- **Quoted product / Catalog `orderMessage`** support — handles
`quotedMessage.productMessage` and the catalog `orderMessage` shape,
including `getTypeMessage` enrichment, deduplication cache for
processed order IDs, and propagation through Chatwoot integration.
- Manager UI: a `🧪 Test Interactive` button on each instance card opens
a modal with five tabs (Reply / CTA / PIX / List / Carousel) and an
editable JSON payload — useful for smoke-testing every kind of
interactive message without leaving the dashboard.

#### History Sync
- **New event `messaging-history.set`** emitted on sync completion, with
cumulative counts (chats, contacts, messages, isLatest, progress).
Allows downstream consumers to know exactly when a history sync has
finished and how much was imported.
- Cumulative counters reset on a new sync start to avoid carry-over
between consecutive syncs.

#### Other
- **New endpoint `POST /chat/markMessageAsPlayed/{instance}`** — emits the
audio "played" receipt (PTT/VOICE), completing the read/delivered/played
triplet for voice messages.
- **SQS integration** now accepts a custom `base_url` (useful for
LocalStack and corporate VPC endpoints).
- **LID → phone-number mapping and caching** — translates the new
`@lid` identifiers WhatsApp uses for hidden-phone profiles into the
real `@s.whatsapp.net` JID for downstream processing, with a cache
to avoid redundant lookups.

#### Branding / Documentation
- README, LICENSE, NOTICE, TRADEMARKS standardised under the
**Evolution Foundation 2026** identity.
- All GitHub URLs migrated from `EvolutionAPI` to `evolution-foundation`.
- New README section "License Activation" linking to
<https://docs.evolutionfoundation.com.br/licensing>.

### Fixed

- **`mentionsEveryOne` honours `false`** — earlier the flag was always
applied regardless of value (#2470).
- **`getLastMessage`**: corrected the Prisma JSON path filter so the
query returns the actual last message (#2495 / #2515).
- **`markMessageAsRead`**: corrected JID filter to cover all user types
(regular, business, broadcast, group).
- **List messages**: removed destructive JSON cloning that triggered
`this.isZero` when the message contained `Long`-typed fields (#2461).
- **History sync race condition**: completion event is now emitted
*before* the contact upsert, so consumers don't observe the sync as
finished while contacts are still being written (#2510).
- **Business API (Cloud)**: race condition in sender identification
resolved (#2493); execution order normalised; `chatwootIds`
correctly propagated.
- **`/instance/logout/{instance}`** — idempotent: returns SUCCESS instead
of 400 when the instance is already closed, so the manager UI delete
flow (logout-then-delete) does not surface a misleading error.
- **`remove.instance` event** — emitted even when logout itself fails,
preventing zombie instances after a partially failed delete (#2520).
- **Chatbot session**: a closed session no longer blocks bot
re-activation.
- **Docker compose**: fresh-install startup failures resolved.
- **WhatsApp chats**: `accountLid` handling, `remoteJid` normalisation
and `chatsRaw` mapping cleaned up to avoid mismatched contact data
on first connection.
- **Facebook ads**: `externalAdReply` context readability and fallback
path for missing fields.
- **Networking**: added the `--network-family-autoselection-attempt-timeout`
flag in `start:prod` so IPv4/IPv6 races no longer hang the boot on
hosts with broken IPv6.
- **Trailing slashes** on configuration URLs are now tolerated in all
HTTP clients.
- Verbose-log fix: undefined `maxRetries` reference inside the
`messages.update` handler.

### Notes

- `AUTHENTICATION_API_KEY` keeps its original meaning (global API key for
business endpoints) **and** gains a second use as the bootstrap license
key. If the value you have is a real licensing key, activation is silent.
If it is not, the service starts unlicensed and waits for activation via
the manager.
- Activation is a one-time operation. The `api_key` is stored in the database
and reused across restarts. The licensing server is only consulted again
for periodic heartbeats (telemetry — non-blocking) and on graceful shutdown
(`/v1/deactivate`).
- If the licensing server is unreachable but the instance has been activated
before, the service continues to serve traffic normally — local DB is the
source of truth for activation state after the first successful call.
- Release builds bake the licensing endpoint into the bundle as an XOR-encoded
string via tsup `define`, so the URL never appears as a plain literal in
`dist/main.js`. Generate the pair with `node tools/encode-url.js <url>` and
pass `LICENSE_ENDPOINT_ENCODED` / `LICENSE_ENDPOINT_XOR_KEY` as Docker
build-args (NOT runtime env vars). Local dev builds use a parts-array
fallback that still avoids a single string literal but is not obfuscated.

### Troubleshooting

- **`HTTP 503 LICENSE_REQUIRED`** — expected before activation. Follow the
migration guide.
- **`The table evolution_api.RuntimeConfig does not exist`** (legacy stack
trace if you somehow bypass the new auto-detect) — run `npm run db:deploy`.
- **`Global API key not accepted by licensing server: invalid signature`** —
your existing `AUTHENTICATION_API_KEY` is not a valid licensing key. Use
the manager UI flow to obtain a new one.
- **Buttons/list not rendering on WhatsApp Web** — make sure you are on
v2.4.0+; the `<biz>` stanza node and the legacy `listMessage` payload
shipped with this release are required for cross-client rendering.

---

# 2.3.7 (2025-12-05)

### Features
Expand Down
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ RUN chmod +x ./Docker/scripts/* && dos2unix ./Docker/scripts/*

RUN ./Docker/scripts/generate_database.sh

# Licensing endpoint is XOR-encoded into the bundle by tsup `define`. Pass the
# pair via build-args (NEVER as runtime env vars) to keep the URL out of the
# compiled JavaScript as a plain literal. Generate them with
# `node tools/encode-url.js <url>`. Leaving them empty is OK for non-release
# builds — the dev fallback in src/licensing/endpoint.ts kicks in.
ARG LICENSE_ENDPOINT_ENCODED
ARG LICENSE_ENDPOINT_XOR_KEY
ENV LICENSE_ENDPOINT_ENCODED=${LICENSE_ENDPOINT_ENCODED}
ENV LICENSE_ENDPOINT_XOR_KEY=${LICENSE_ENDPOINT_XOR_KEY}

RUN NODE_OPTIONS="--max-old-space-size=2048" npm run build

FROM node:24-alpine AS final
Expand Down
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,33 @@ docker run -p 8080:8080 --env-file .env evoapicloud/evolution-api:latest

---

## License Activation

Starting from **v2.4.0**, every Evolution API instance must be activated
against the Evolution Foundation licensing server before serving API
traffic. While unactivated, business endpoints return
`HTTP 503 LICENSE_REQUIRED` with a `register_url` pointing to the manager
UI.

There are two ways to activate:

1. **Set a known licensing key** as `AUTHENTICATION_API_KEY` in your
`.env`. The server validates it on boot, persists it locally and
activates the instance silently.
2. **Activate via the manager UI** at `https://<your-host>/manager/login`.
On first login the manager detects an unlicensed backend and redirects
you to the registration server; once you complete the form you are
redirected back and the dashboard becomes accessible.

Activation is a one-time operation — the key is persisted in the
`RuntimeConfig` table and reused across restarts. The licensing server is
only consulted again for fire-and-forget heartbeats (telemetry) and a
best-effort `/v1/deactivate` notice on graceful shutdown.

Full activation guide: <https://docs.evolutionfoundation.com.br/licensing>

---

## Architecture

Evolution API is built with a multi-provider, event-driven architecture:
Expand Down
1 change: 0 additions & 1 deletion evolution-manager-v2
Submodule evolution-manager-v2 deleted from 3137df
1 change: 1 addition & 0 deletions manager/dist/assets/index-C-JyjMiq.css

Large diffs are not rendered by default.

Loading
Loading