Releases: QuackbackIO/quackback
v0.13.1
This release fixes dark-mode theme flashing and its cache keying, repairs slug generation for non-Latin and symbol-only board and help-center names, makes inbound chat email replies deliver reliably, restores images in API/MCP/webhook content, and splits the CSAT webhook so integrations stop double-counting ratings. It also adds a presentation-only published-date override for changelog entries.
Features
- Changelog published-date override. Set or clear a presentation-only published date on a live changelog entry, separate from when it actually went live. The portal list, detail, feed, and sitemap all use the chosen date, and it never sends notifications. (#288)
Bug fixes
- No more white flash in dark mode. The server now commits the resolved theme straight onto the rendered page, so dark-mode visitors no longer see a white flash on load. The
systemsetting is resolved server-side too on browsers that report the OS preference, and the response is cache-keyed correctly so a shared cache can't serve a mismatched theme. (#297, #298) - Images preserved in API, MCP, and webhook content. Rich-text posts, changelog entries, and help-center articles dropped embedded images from the markdown returned by the REST API and MCP and emitted in webhook and notification payloads. Markdown is now rendered from the source rich text so images survive as
, and existing entries self-heal without a backfill. (#317, fixes #292) - Valid slugs for non-Latin and symbol-only names. Board and help-center names in scripts like Chinese, Japanese, or Korean (or emoji- and punctuation-only names) no longer produce an empty slug that broke board selection and help-center routing. Names are transliterated to a readable slug, with a safe fallback when nothing remains, and existing broken slugs are healed. (#295, closes #285)
- Inbound chat email replies deliver again. Agent reply-to addresses exceeded the 64-character local-part limit some providers enforce, so inbound replies were rejected and never reached the visitor. The address now stays within the limit. (#294, fixes #293)
- CSAT webhook no longer double-counts. A satisfaction survey now emits
conversation.csat_submittedexactly once when the rating is banked, and an optional follow-up comment rides its ownconversation.csat_comment_addedevent, so integrations stop double-counting a rating when a visitor adds a comment. (#299) - Reliable changelog publish notifications. Publish notifications now fire exactly once per entry and recover automatically if the delivery job is dropped, so subscribers are never missed or notified twice.
Full Changelog: v0.13.0...v0.13.1
v0.13.0
This release unifies sign-in into a single dialog for both portal users and team admins, and reworks SSO into a multi-provider model: you can register any number of OIDC identity providers, each with its own verified domains, email routing, and per-domain enforcement. It also ships a redesigned provider editor, a settings-permission fix, and a security update.
Upgrade notes for self-hosters
- Auth and feature flags are now managed in the admin UI only. The config file no longer applies
authorfeaturesblocks. If yours still contains them they are ignored (and surfaced as a warning in status), not a hard error. Configure sign-in methods, OIDC providers, and feature flags under Settings. - Magic link is opt-in. Magic-link sign-in is now off by default for every role unless enabled. Upgrading workspaces keep whatever sign-in methods they already had working.
- Old auth routes redirect.
/admin/login,/auth/login,/auth/signup,/sso, and the standalone two-factor pages now redirect into the unified sign-in dialog.
Features
- One sign-in surface for everyone. Portal users and team admins now sign in through the same dialog, with a recovery-code break-glass path for SSO-only workspaces. (#284)
- Multiple OIDC identity providers. Register any number of OIDC providers (Okta, Microsoft Entra, Google Workspace, Auth0, Keycloak, or any OIDC issuer). Each provider carries its own verified domains: emails at a verified domain are routed to that provider, and a domain can be enforced so its users sign in with SSO only. Roles map from the provider's group or role claims, and a claim-attested role provisions regardless of email domain. (#284)
- Redesigned SSO provider editor. One default-role control, progressive group/claim mapping with autocomplete, full ID-token inspection in the connection test, manual-endpoint support for IdPs without a discovery document, and a per-provider toggle to show or hide the sign-in button. (#287)
- Inline two-factor. Two-factor enrollment and challenge now happen inside the sign-in dialog instead of separate pages. (#284)
Bug fixes
- Settings are admin-only. The settings cog is hidden from non-admin team members, and a non-admin who reaches an admin-only page sees a calm permission notice instead of a raw error. (71b6c8f6)
Security
- nodemailer 9.0.1 (GHSA-p6gq-j5cr-w38f). Patches a message-level option that could bypass file and URL access controls. Quackback never used the affected option, but the dependency itself was flagged. (74d3dab4)
Full Changelog: v0.12.4...v0.13.0
v0.12.4
This patch lets portal users at a verified domain sign in with SSO, and quiets health-check noise in self-hosted logs.
Features
- Portal SSO sign-in. Portal users at a verified domain can now sign in with SSO instead of being offered it and then rejected at the callback. (#264)
Internal
- Quieter health-check logs. Successful health-check requests are no longer written to the access log, cutting recurring probe noise; failed probes and errors are still recorded. (#257)
- Workspace state cleanup. Removed unused internal workspace state-handling code. (#267)
Full Changelog: v0.12.3...v0.12.4
v0.12.3
This release adds Simplified and Traditional Chinese, an ntfy integration, and structured logging for self-hosters, plus fixes to private-portal sign-in and outbound automation delivery.
Features
- Simplified and Traditional Chinese. The portal and widget are now available in zh-CN and zh-TW, served automatically based on browser language. (#244)
- ntfy notifications. Send notifications to your own devices through the new ntfy integration. (#242)
- Language-aware page rendering. Pages now declare their language and text direction during server rendering, so right-to-left locales display correctly from the first paint. (#246)
- Structured server logs. Self-hosted deployments now emit structured JSON logs for easier searching and monitoring. (#245)
Bug fixes
- Private portal sign-in. Signing in to a private portal now lands you in cleanly: no flash of the logged-out buttons, no crash on the sign-in screen, and no getting stranded on the access wall after authenticating. (#249, #250, #252)
- Automation delivery. Events now reach n8n, Make, Zapier, and Monday; a channel-resolution mismatch had been silently dropping every event. (#241)
Internal
- Widget locale parity. The widget and app now share a single supported-locale list, so they can't drift apart. (#248)
- Route tree cleanup. Colocated route-helper modules are excluded from the generated route tree, silencing dev-server warnings. (#251)
Full Changelog: v0.12.2...v0.12.3
v0.12.2
A small follow-up to v0.12.1 with one fix that landed just after it was tagged.
Bug fixes
- Custom OIDC setup shows the correct callback URL. The "Configure Custom OIDC" modal listed
/api/auth/callback/<id>, but better-auth's genericOAuth callback is/api/auth/oauth2/callback/<id>, so registering the shown value at the IdP failed with a callback mismatch. The modal now shows the correct path; built-in social providers (Google, GitHub) are unchanged. (#238, closes #233)
Full Changelog: v0.12.1...v0.12.2
v0.12.1
This patch fixes sign-in on 0.12.0 (the admin dashboard was unreachable behind a React Intl error), restores OAuth-only portal sign-in, and hardens auth, SSO, and file uploads.
Bug fixes
- Admin sign-in works again on 0.12.0. Signing in at
/admin/logindead-ended on a blank "[React Intl] Could not find requiredintlobject" page, leaving the dashboard unreachable; the form now renders. (#234) - Portal sign-in with only OAuth/OIDC enabled. With password and magic-link off and just an OAuth provider (a custom OIDC provider or Discord), the portal showed a dead-end email field; it now shows only the provider button. (#235, closes #231, #186)
- Settings toggles persist after saving. Some toggles reverted on the next view because the query cache wasn't invalidated after a save. (#230)
- Admin avatar loads with the page. The sidebar avatar now server-renders and is fetched during the initial load instead of after hydration. (#236)
- Invitation links are revocable and last 30 days. (#228)
Security
- better-auth upgraded to 1.6.16. Fixes a refresh-token rotation issue that could force a re-login about once a day, plus a grace window that heals benignly-stale tokens. (#217)
- PKCE on SSO sign-in. The SSO authorization-code flow now sends PKCE (S256). (#214)
- Stricter file uploads. Uploaded bytes are verified against the declared image type, proxied reads send
nosniff, and trusted-attachment URL matching is tightened to a path-segment boundary. (#219, #218)
Preview, behind Labs (off by default)
This release also lands an early preview of the Support Inbox (agent conversations, a portal Support tab, widget live chat) and inline link previews. They're off by default; enable them under Settings → Labs to try them.
Full Changelog: v0.12.0...v0.12.1
v0.12.0
This release makes AI configuration explicit (a breaking change if you use AI), promotes Analytics out of Labs, and fixes Shortcut status sync.
Breaking change: AI now requires explicit configuration
AI features are off until fully configured. Previously, Quackback assumed OpenAI's endpoint while hardcoding gateway-style model names, so a self-hoster with just an API key got an error on every AI call (#180).
To enable AI, set all four variables:
OPENAI_API_KEY=sk-...
# Any OpenAI-compatible endpoint, declared explicitly. Examples:
# Direct OpenAI: https://api.openai.com/v1
# OpenRouter: https://openrouter.ai/api/v1
# Cloudflare AI Gateway: https://gateway.ai.cloudflare.com/v1/<account>/<gateway>/openai
OPENAI_BASE_URL=https://api.openai.com/v1
# Model ids your endpoint accepts (direct OpenAI examples shown)
AI_CHAT_MODEL=gpt-4o-mini # summaries, sentiment, triage, duplicate checks
AI_EMBEDDING_MODEL=text-embedding-3-small # duplicate detection, semantic searchUpgrading from v0.11.0 or earlier: if you had OPENAI_API_KEY set, add OPENAI_BASE_URL and the two model variables to keep AI working. Until you do, AI features stay off and a warning is logged at startup.
Each feature can also use its own model via AI_SUMMARY_MODEL, AI_SENTIMENT_MODEL, AI_EXTRACTION_MODEL, AI_QUALITY_GATE_MODEL, AI_INTERPRETATION_MODEL, and AI_MERGE_MODEL. Set one to off to disable just that feature. See .env.example for the full reference.
Features
- Analytics is now generally available. The dashboard is out of Labs and on for every workspace, with period-over-period trends on each metric, a clearer activity chart, and full mobile and tablet support. (#198)
- Integration credentials from the environment. OAuth app credentials for integrations can be supplied via
INTEGRATION_<PROVIDER>_*environment variables by settingPLATFORM_CREDENTIALS_SOURCE=env. The default (database, managed in the admin UI) is unchanged. (#209)
Bug fixes
- Shortcut status sync now works. Moving a linked story to a new workflow state updates the feedback post's status; previously the webhook arrived but the status never changed. (#204)
- Webhook signing secret shown in settings. Shortcut and Azure DevOps now display the signing secret needed to finish manual webhook setup, next to the webhook URL. (#204)
- Complete translations. Portal sign-in screens are now translated, and every locale was backfilled to full parity with English. (#202, #203)
Full Changelog: v0.11.0...v0.12.0
v0.11.0
This release adds a major new opt-in feature, Conversations, alongside a wave of improvements to access, moderation, and the everyday admin experience.
Conversations (new, experimental). You can now switch on real-time chat and a shared support inbox. Visitors message your team right from the widget and see when you're typing and when you've read their message, while your team handles every thread in one place, with assignment, priorities, labels, internal notes, and search. You can reply by email and keep it in the same thread, turn a conversation into a feedback post, and ask visitors how the chat went. It's off by default, so nothing changes until you turn it on.
Granular board access. Every board now controls who can view, vote, comment, and submit, independently. Open each to anyone, to signed-in users, to specific customer segments, or to your team only. So you can let everyone read a board but require sign-in to vote, or reserve submissions for a beta group. New Public and Private presets make setup quick, and your existing boards carry over exactly as they were.
Private portals. Make your feedback portal private with a single switch, then choose who gets in: your team, people on a trusted email domain, anyone you invite, a customer segment, or visitors who signed in through your widget. Private portals show a clean sign-in wall and stay out of search engines. Public portals are unaffected.
Moderation. Optionally hold posts and comments for review before they go public, with a queue to approve or reject. Set it per board or across your whole workspace. Off by default.
Nicer to use, everywhere. Brazilian Portuguese for the portal and widget, new ways to group customers into segments, a friendlier widget home screen with a peek at your latest changelog, a polish pass across the whole admin panel, and reactions that now show who reacted.
For self-hosters. A proper production Docker setup, an image that runs natively on both Intel and ARM machines, smoother running across multiple instances, and a batch of reliability and security fixes.
Features
- Conversations (new, experimental, off by default). A real-time chat channel in the widget plus a shared agent inbox. Visitors message your team and see typing indicators and read receipts; agents triage from one place with assignment, priority, status, labels, internal notes with @-mentions, message reactions, saved-for-later, and search. Turn it on from the Labs settings.
- Email replies for conversations. Agents can reply by email and the visitor's response threads back into the same conversation. Requires configuring an inbound email address.
- Convert a conversation into feedback. Turn a support chat into a feedback post, or upvote a similar existing post on the visitor's behalf, in one step.
- Customer satisfaction (CSAT). Visitors can rate a closed chat, rolled up in a new Support section of Analytics.
- Granular board access. A per-board permission matrix controlling view, vote, comment, and submit independently, each open to anyone, signed-in users, specific segments, or team only, with Public and Private presets. (#191)
- Private portals. Require sign-in to view the portal, with access granted by team membership, trusted email domains, email invites, customer segments, or widget sign-in. Private portals are excluded from search engines and feeds.
- Post and comment moderation. Optionally hold submissions for review before they publish, configurable per board or workspace-wide and separately for anonymous and signed-in authors, with an approve and reject queue.
- Brazilian Portuguese. The portal and widget are now available in pt-BR, served automatically based on browser language. Contributed by @arthurbarret0. (#194)
- More customer segments. Group people by country, language, last-active recency, and signup source.
- Widget home screen. A new landing tab that greets visitors, points them to the right section, and previews your latest changelog entry, with help articles and messaging combined under one Help surface.
- Reactions show who reacted. Hover a reaction on a comment or chat message to see who is behind it.
- Reworked authentication settings. Sign-in providers are managed from one place with a single toggle each, custom identity providers offer a preset picker with issuer auto-detection, and guardrails stop you from locking yourself out.
- Richer audit log. Each event now records the request ID, actor type, and sign-in method, all included in the CSV export.
- Multi-architecture Docker image. Official images now run natively on both Intel and ARM. (#195)
Bug fixes
- Widget hydration error behind font-proxying CDNs. Self-hosting the Inter font stops CDNs that rewrite font links from breaking the widget. (#133)
- Clearer sign-in rate-limit message. Hitting the sign-in limit now returns a proper "too many attempts" message with a retry hint instead of a misleading "invalid email or password" error.
Performance
- Faster public changelog. Visibility checks are pushed into the database query instead of loading every linked post and filtering in memory.
Security
- SSRF hardening for image rehosting. External image fetches now connect to the already-validated address instead of re-resolving DNS, closing a rebinding window reachable across posts, changelog, and help-center content.
- Integration webhook allowlist. Outbound integration webhooks route through the safe-fetch guard and enforce host allowlists. Thanks to @endscene665.
- Signed email reply addresses. Conversation reply addresses are cryptographically tied to their conversation, so an agent email cannot be used to inject a reply into someone else's thread.
- Verified-email guards on portal access. Email-based access grants require a verified email, so a segment rule cannot be used to walk into a private portal unverified.
- Email masking in logs. Email addresses are obfuscated in unstructured server log output.
Internal
- Multi-replica-safe background jobs. Background sweepers (audit-log prune, invite expiry, stuck-item recovery, AI summaries, duplicate detection) now run under a cross-instance lock so only one replica runs each tick.
- Duplicate-detection circuit breaker. The merge-suggestion sweep aborts after repeated failures instead of retrying in place.
- Hardened production Docker stack. A new
docker-compose.prod.ymlships the app and datastores with no exposed database ports, required-secret checks, healthcheck-gated startup, and a private upload bucket; the rootdocker-compose.ymlis now development-only. (#195)
Tests
- Extensive new coverage across live chat and the support inbox, board and portal access policy, moderation, and email-channel signature verification.
Upgrade notes
- Run database migrations on upgrade (0066 through 0104). All are additive or migrate existing data automatically; no manual data changes are required.
- Conversations is experimental and off by default. Enable it from the Labs settings. Inbound email replies additionally require the
EMAIL_INBOUND_DOMAINandEMAIL_INBOUND_SIGNING_SECRETenvironment variables. - Some admin settings pages moved: API is now Developers, User Attributes and Segments are now People, and Portal auth now lives under Security. Update any bookmarks.
- The legacy board "audience" field was replaced by the new access model. Existing boards are migrated automatically; the REST API still exposes a read-only
audiencefield, and vote endpoints now enforce each board's vote permission (a board that requires sign-in to vote will reject anonymous API votes). - Self-hosters: use
docker-compose.prod.ymlfor production (the root compose is now development-only), and note that values in.envfiles must be unquoted for Docker--env-file.
Contributors
Thank you to the community contributors in this release:
- @arthurbarret0 added the Brazilian Portuguese (pt-BR) translation. (#194)
- @endscene665 hardened outbound integration webhooks against SSRF.
Full changelog: v0.10.5...v0.11.0
v0.10.5
Fixes
- Emoji rendering in comments. Emojis inserted via the picker now render correctly in saved comments instead of disappearing.
- Enter selects from the emoji picker. Pressing Enter while the emoji picker is open picks the highlighted item instead of inserting a newline.
Improvements
- Workspace-unavailable UX. Suspended or otherwise unavailable workspaces now show a consistent, friendly message at sign-in and on the workspace page itself.
Full changelog: v0.10.4...v0.10.5
v0.10.4
Features
- Faster managed-cloud onboarding. New
workspace.onboardingCompleteflag in the config-file schema lets the control plane mark the workspace as set-up at provision time, so CP-provisioned tenants skip the OSS/onboardingwizard and land straight at/admin. - Magic-link auto-redirect.
/verify-magic-linknow auto-triggers the verify endpoint on mount with a short delay (preserves the email-prefetch defense), and hides the manual Continue button for the first 5 seconds so the happy path lands without a competing CTA.
Fixes
- SSR window crash on magic-link verify. The verify URL is now constructed inside
useEffect, so SSR doesn't crash on a missingwindow. - Comment content in portal view.
contentJsonis now passed through when mapping comments for portal rendering, so rich-text comments render correctly on the public side.
Reliability
- Stale-summary sweep hardening. Added a circuit breaker and per-board deduplication so a single failing summary refresh can't cascade across the queue.
Full changelog: v0.10.3...v0.10.4