github aldinokemal/go-whatsapp-web-multidevice v9.0.0

2 days ago

What's New in v9.0.0

🚀 Major Release: Standalone gowa-ui Dashboard, Pure API Backend & Fiber v3

This release splits the web dashboard out of the binary. gowa is now a pure API server that downloads the latest gowa-ui release at runtime, verifies it, caches it, and serves it at / — same URL, same basic auth. The second breaking change is the move to Fiber v3, which reshapes the Go-level API for anyone embedding gowa as a library while leaving HTTP consumers untouched. This release also adds GET /app/info and cross-origin WebSocket auth so standalone UIs can talk to the server, and fixes sent messages being lost under SQLite write contention plus percent-encoded chat_jid path params never matching.


⚠️ Breaking Changes

Embedded Dashboard Removed (#766)

  • src/views/ (56 Vue components), the go:embed bundle, the HTML template engine, and the basic-auth token echo middleware are gone; the dashboard now lives in its own repo — aldinokemal/gowa-ui (React 19 + Vite + Tailwind 4 + shadcn/ui), released as a single self-contained gowa-ui.html
  • The server fetches that asset at runtime and serves it at /same URL, same basic auth, so a normal browser-based deployment behaves as before after the first download
  • APP_UI_ENABLED=false turns / into a JSON banner for pure-API deployments
  • Air-gapped installs: set APP_UI_AUTO_UPDATE=false and pre-seed storages/ui/, or disable the UI entirely

Fiber v3 Upgrade (#764)

  • Fiber core v2.52.14v3.4.0, GoFiber utilities to v2.1.2, and the WebSocket add-on from github.com/gofiber/websocket/v2 to github.com/gofiber/contrib/v3/websocket v1.2.1
  • Relevant if you embed gowa as a library or build against its handlers: Fiber v3 changes the context, binding, static middleware, configuration, testing, and utilities APIs
  • The whole Fiber-dependent surface was migrated in one pass — REST handlers, middleware, request binding, query parsing, context propagation, trusted-proxy/listen configuration, static delivery, and tests — so no mixed v2/v3 behavior is retained
  • HTTP API consumers are unaffected: routes, payloads, device scoping, and WebSocket behavior are preserved, the plaintext APP_BASIC_AUTH=user:secret contract is kept via a constant-time custom authorizer, and generated QR/media URLs stay correct through the Fiber v3 request scheme API

✨ New Features

Runtime-Downloaded Dashboard (#766)

  • New src/infrastructure/uiasset fetches the latest gowa-ui.html release asset of APP_UI_REPO (default aldinokemal/gowa-ui), compares sha256 digests, uses ETag-conditional requests, and writes an atomic cache at storages/ui/
  • Serves the cached asset with ETag/304, auto-updating every APP_UI_UPDATE_INTERVAL (default 3h, ±10% jitter), and falls back to a graceful offline page when the cache is empty and GitHub is unreachable
  • Config: APP_UI_ENABLED, APP_UI_AUTO_UPDATE, APP_UI_REPO, APP_UI_ASSET_NAME, APP_UI_UPDATE_INTERVAL, APP_UI_GITHUB_TOKEN (optional, raises the GitHub API rate limit)
  • APP_UI_ASSET_SHA256 is an operator-supplied supply-chain pin: when set, the server refuses to download or serve any asset whose sha256 differs — checked against the release digest before download, against the downloaded bytes, and against the cache on boot

Server Metadata Endpoint (#766)

  • Adds GET /app/info returning {version, os, base_path, max_file_size, max_video_size, max_image_size, chatwoot_enabled}, replacing the HTML template injection that standalone UIs can no longer rely on

Cross-Origin WebSocket Auth & CORS (#766)

  • Browsers cannot set headers on a WebSocket handshake, so /ws?authorization=<base64(user:pass)> is now accepted and validated by the same constant-time basic-auth authorizer — TLS is required in production
  • CORS is widened and moved ahead of statics: Authorization and X-Device-Id are allowed with explicit methods, and QR PNGs plus media under /statics now carry CORS headers

🐛 Bug Fixes

Sent Messages Lost Under Write Contention (#766)

  • wrapSendMessage stored sent messages in a detached goroutine with a 2s budget while SQLite's busy_timeout is 30s, so during history-sync contention the deadline could expire between the chat-bump write and the message insert — leaving a bumped chat with a missing message
  • The message row is now written first (a partial failure loses only the invisible timestamp bump), the budget is raised to 15s, and failure logs carry the message ID and recipient

Percent-Encoded chat_jid Never Matched (#766)

  • Fiber does not URL-decode path params, so any client that percent-encodes the JID path segment (gowa-ui and most HTTP libraries) got empty results from /chat/{chat_jid}/* even though the rows existed
  • All four chat handlers now url.PathUnescape the param — a raw @ is unchanged, so existing clients see no behavior change — and malformed escapes return the standard 400 JSON envelope
  • OpenAPI notes added on all four chat_jid params

Contact Display Names in Listings

  • MyListContacts returned only FullName, so contacts saved without one came back with an empty name
  • Contact listings now apply the same saved → push → business name precedence used elsewhere, with unit test coverage for the fallback order

🔧 Technical Improvements

Dependency Updates

  • go.mau.fi/whatsmeow: refreshed to the latest snapshot (v0.0.0-20260718134955-fac667d55293)
  • Fiber and its add-ons moved to v3 — see Breaking Changes above for the full list
  • Dropped github.com/gofiber/template/html/v2 along with the template engine; go.mau.fi/util and assorted indirect dependencies refreshed

Cleanup

  • Removed dead Chatwoot client code and its now-redundant test scaffolding, a stale error constant, and obsolete planning docs
  • Logo moved to gallery/gowa.svg; obsolete dashboard screenshots removed from the gallery

Release Metadata

  • AppVersion is now v9.0.0, so runtime status matches the published release tag

What's Changed

Full Changelog: v8.11.0...v9.0.0

Don't miss a new go-whatsapp-web-multidevice release

NewReleases is sending notifications on new releases.