11 min readOct 16, 2026by jakub

Changelog

Current version: 1.0.0

All notable changes to Helpdesk are listed here, newest first, per package. The packages follow Semantic Versioning.

1.0.0 — 2026-10-10

Helpdesk (qoliber/helpdesk)

First release.

Added

Customer pages (My Account → Support Tickets, Luma; Hyvä with qoliber/helpdesk-hyva)

  • Ticket list with the tickets waiting for the customer, the ticket page with the conversation (20 messages per page) and replies, and the new-ticket form. On the form customers pick a topic from the store view's list (the topic becomes the subject) or "Other" with their own subject, and optionally a department, a product they ordered and one of their orders. A customer reply reopens a ticket that waits for the customer or is resolved.
  • Tickets about an order: "Get help with this order" on the order page opens the form with the order chosen; an open ticket about the same order is offered first ("You already contacted us about this order", "Continue ticket …"). Only the customer's own orders in the website can be linked.
  • A reply, checklist answer or note that the shop refuses (a file too many, the hourly limit) comes back in the form with what the customer typed. The forms check the number and size of the chosen files before sending, within the store's settings and what PHP accepts (upload_max_filesize, post_max_size, max_file_uploads), and show the limits under every file field.
  • Support Preferences: customers switch off reply, status and order update emails and say whether and when the team may call them; agents see this on the ticket page. Guest tickets always get every email.
  • "Download My Support Data" on the ticket list (the customer's tickets and messages as JSON, without internal notes).
  • "Show a Support Link in the Footer" (per store view, default Yes) with its own "Link Text": every page links to /helpdesk, which opens the guest form for visitors and the support tickets for signed-in customers.

Guest tickets (optional, "Allow Tickets Without an Account")

  • /helpdesk form with name, email, topic, message, an optional order number and the department choice. The ticket is saved with the guest's email carrying a personal link; the guest confirms the address with a button (a POST, which mail scanners do not send), and only then is the team emailed and can the guest reply.
  • Personal links: 32 random bytes, stored only as SHA-256, valid "Ticket Links Work For (Days)", created fresh for every email at send time. "Find your support ticket" emails new links and answers the same whether or not the address has tickets.
  • An order number is linked only to an order placed with the same email address in the website; the guest sees the order summary after confirming the address.
  • Spam protection: requests per IP address (stored as a keyed hash for a day), tickets and messages per address, an invisible field bots fill in, one links email per address every ten minutes. Unconfirmed, unanswered guest tickets are deleted after "Delete Unconfirmed Guest Tickets After (Days)".
  • Customers add their guest tickets to My Account after confirming through a link emailed to the account address, opened while signed in. Tickets whose address was confirmed and tickets the team opened in the admin move; the guest links stop working. Each link moves tickets once.
  • Extension containers in the guest forms, above the submit button (qoliber.helpdesk.guest.form.additional, qoliber.helpdesk.guest.links.additional), and Model\Guest\GuestFormValues to keep what a guest entered when a check refuses the form. qoliber/helpdesk-captcha uses them for Magento CAPTCHA and Google reCAPTCHA.

Admin (Helpdesk menu)

  • Tickets grid with customer, email, agent, status, priority, department, store view, customer feedback and follow-up columns and filters; CSV and XML export (cells a spreadsheet would run as a formula are neutralised).
  • Mass actions "Change Status" and "Assign To" (their emails are sent by the retry job, the result reports how many tickets changed) and "Delete", which needs the "Delete Tickets" permission and is offered only with it.
  • Ticket page: the full thread (50 messages per page) with replies, internal notes (never shown or sent to the customer), "then set status", status, priority, agent and department, the guest's address confirmation, the customer's support preferences, invited people, follow-ups, attachments and the ticket's emails with their state and "Send Again". "New Ticket": agents open a ticket for a customer (channel admin).
  • Departments: queues with their own notification address, limited to store views if needed.
  • Statuses: the shop's own statuses (label, colour, sort order, label per store view), each in one of four fixed states (open, waiting for the customer, resolved, closed) that carry the reopen and close rules. Every state has one default status; a status that tickets have cannot be deleted or moved to another state.
  • Saved replies: texts with placeholders ({{customer_first_name}}, {{reference}}, …), optionally per department, inserted with "Insert a saved reply…".
  • Agents are active admin users whose role allows Qoliber_HelpDesk::tickets: they are offered for assignment and follow-ups and emailed about their tickets. A ticket keeps an assignee who loses the permission.
  • Settings per store view (Stores → Configuration → Qoliber → Helpdesk); the ticket reference prefix (HD-000123, up to 21 letters and digits) is global.

Emails

  • New ticket and customer reply to the team (Reply-To the customer, a direct link to the ticket in the admin, guests marked, the team's own footer), replies and status changes to the customer with a link to the ticket, assignment to the agent, follow-up reminders, invitations, guest confirmation and links, and the account move. Store-view templates and sender; texts in the store view's language.
  • Outbox: every email is stored in the transaction of the ticket change and sent right after the commit, so a rolled-back change never sends one. Failed emails are retried by the job qoliber_helpdesk_email_retry (every 5 minutes, batches for up to a minute) after 5 minutes, 15 minutes, 1 hour and 4 hours, and marked failed after 5 attempts. An email being sent is claimed, so "Send Again" never sends it twice. Delivery is at least once. Logs name emails by ID and template, never by the recipient's address. Sent emails are removed after 30 days.

Attachments

  • On new tickets, replies and internal notes: customers, guests in replies once confirmed, invited people and agents. Files are stored under var/qoliber_helpdesk with random names (never under pub/); the content must match an allowed extension (detected with finfo; Office files checked as real OOXML/ODF); file count, size (up to 25 MB) and types per store view. Files are stored only after the ticket's checks passed and deleted after the ticket or message delete commits; orphaned files are cleaned up daily.
  • Private downloads through the ticket's access checks, always as a download, with a sandboxing Content-Security-Policy, nosniff, Cross-Origin-Resource-Policy: same-origin and private, no-store.
  • Previews: photos (JPEG, PNG, GIF, WebP) show as a newly encoded JPEG (at most 320 px, upright, no EXIF or GPS data) in the conversation on Luma, Hyvä and in the admin; other files an icon of their kind. A preview is made once, after the message is saved (up to 16 megapixels) or by the job qoliber_helpdesk_attachment_previews in its own cron group (larger images, 20 seconds each); showing it never decodes an image. Images beyond 12,000 px or 25 megapixels, JPEGs with more than 32 scans, PNGs with compressed chunk floods or more image data than their rows need, damaged files and decompression bombs get the icon. bin/magento qoliber:helpdesk:attachments:previews [--all] [--retry-failed].

Working on tickets

  • Requests for information: agents tick checklist items with a reply (store-view presets or their own: photo, file, text, number, required or optional); customers and confirmed guests answer them in one form on the ticket page; the agent sees each answer next to its item. The reply email lists what to send.
  • Resolution confirmation: a resolved ticket asks "Has this solved your problem?"; "Solved, thank you" closes it, "I still need help" reopens it with what is missing. The answer and a reopen count are kept on the ticket; a reminder goes out before the automatic close.
  • Follow-ups and promised updates: who the team is waiting for (customer, warehouse, carrier, supplier, payment provider), a follow-up owner and time, and "Update Promised By", also set with a reply. Customers see "We will update you by …" and, per store view, who the team is waiting for. The team is reminded before a promise is due and when a follow-up time comes.
  • Ticket invitations: customers and agents invite someone by name and email; the invited person reads the public conversation and replies through personal links, without an account, gets the update emails and can leave. Internal notes, order details, order updates, the resolution question and checklists stay hidden. Removing an invitation ends the access at once. Limits per ticket, address and account, and a resend cooldown.
  • Order updates: new tracking numbers, refunds (also when the payment provider confirms them later) and cancellations are posted to the open tickets about the order whose customer owns it, in the store view's language, and emailed. An order edited in the admin moves its tickets to the new order. The team is alerted once when an open ticket's order has not shipped after a number of days.
  • Automation: resolved tickets without activity close after a number of days (default 7) with the status email; agents are emailed when someone else assigns them a ticket.
  • Limits per store view: new tickets and messages per customer and hour, and no identical message twice within a minute. One customer's, guest's or ticket's invited people's posts are checked and saved one at a time.

Privacy requests (GDPR)

  • Helpdesk → Privacy Requests finds everything stored for an email address (tickets of its customer accounts on all websites, its guest tickets, tickets it was invited to, preferences, email log), downloads it as JSON and erases it after the address is typed again: tickets are anonymised and closed, the person's own messages on other people's tickets erased, preferences, links and logged emails deleted. "Erase Support Data When a Customer Account Is Deleted" erases with the account (the account is not deleted when its data cannot be erased or its invitations cannot be ended). CLI qoliber:helpdesk:privacy:export <email> [--output=<file>] (the file is readable by its owner only) and qoliber:helpdesk:privacy:erase <email> [--yes].

Integration

  • REST API for the support team (tickets, replies, statuses, saved replies, follow-ups, delete) and for customers' own tickets and preferences (/V1/helpdesk/mine/…). The customer API never returns admin user IDs, the follow-up owner or internal notes; tickets created through the team API get the customer's store view, or the default store view of the customer's website.
  • Events after the database commit: qoliber_helpdesk_ticket_created, qoliber_helpdesk_ticket_replied and qoliber_helpdesk_ticket_status_changed (with the old and new states); an exception in an observer is logged and never reported as a failed action.
  • Api\TicketAccessPolicyInterface decides which products a customer may open tickets about; Model\Mail\MailSender and Model\Mail\TicketMailData for add-ons' own emails; Model\Privacy\DataSubjects, PersonalDataExport and Eraser for a shop-wide privacy tool.
  • Deleting a store view (or its store or website) moves its tickets, waiting emails and links to the website's default store view (else the shop's); a department limited to it stays hidden.

Requirements

  • Magento Open Source 2.4.6 or later (Magento Framework 103.0.6) or Mage-OS, PHP 8.1 to 8.5, with Magento_Csp enabled, ext-fileinfo and ext-zlib; ext-zip for docx, xlsx and odt attachments.
  • Magento cron (the default group and the qoliber_helpdesk_previews group). var/qoliber_helpdesk must be shared across releases and web nodes.

Helpdesk Hyvä (qoliber/helpdesk-hyva)

First release.

Added

  • Hyvä templates for the support tickets of qoliber/helpdesk: the ticket list, the ticket page with the conversation and replies, and the new-ticket form with its topic list ("Other" for an own subject), department, product and order choice.
  • Order choice with the "You already contacted us about this order" notice, and "Get help with this order" / "Continue ticket …" on the customer's order page.
  • On the ticket page: "We will update you by …" and who the team is waiting for; "Has this solved your problem?" on resolved tickets; the "We need a few things from you" checklist; "People in this conversation" with "Invite someone to this conversation" and "Remove"; the linked order's summary.
  • Attachments field on the new-ticket, reply and checklist forms; files listed under each message, photos as previews and other files with an icon of their kind. The forms check the number and size of the chosen files before sending, within what the shop and PHP accept.
  • A reply, checklist answer or note that the shop refuses comes back in the form with what was typed.
  • Support Preferences page and "Download My Support Data" on the ticket list.
  • Guest pages: the new-ticket form without an account, "check your email", "Find your support ticket", and the guest ticket page with "Confirm My Email Address"; "Add them to my account" for tickets sent as a guest; the invited person's ticket page.
  • "Customer Support" column in the footer ("Show a Support Link in the Footer"): "Contact Support" and "Find Your Support Ticket" where guest tickets are on, "My Support Tickets" where My Account tickets are on, in the theme's own footer column classes.
  • Extension containers in the guest forms, above the submit button: qoliber.helpdesk.hyva.guest.form.additional and qoliber.helpdesk.hyva.guest.links.additional (qoliber/helpdesk-captcha shows Magento CAPTCHA and Google reCAPTCHA there).
  • Interactivity as CSP-safe Alpine components in static scripts, without inline code.
  • Supports Hyvä 1.3 (Tailwind 3), 1.4 and 1.5 (Tailwind 4), default and CSP themes. After installing or updating, run bin/magento hyva:config:generate and rebuild the theme's Tailwind CSS.

Requirements

  • qoliber/helpdesk 1.0, Magento 2.4.6 or later (Magento Framework 103.0.6) and a Hyvä theme module supported by the installed Magento patch level (current CSP theme modules need Magento's CSP nonce helper).

Helpdesk CAPTCHA (qoliber/helpdesk-captcha)

First release.

Added

  • Magento CAPTCHA on the guest new-ticket form and on "Find Your Support Ticket": "Helpdesk: New guest ticket" and "Helpdesk: Find your support ticket" in Customers → Customer Configuration → CAPTCHA → Forms, shown every time once chosen. Luma uses Magento's CAPTCHA block; Hyvä a template with "Reload captcha" as a static script.
  • Google reCAPTCHA (v2 "I'm not a robot", v2 invisible, v3 invisible) on the same forms: "Enable for Helpdesk: New Guest Ticket" and "Enable for Helpdesk: Find Your Support Ticket" in Security → Google reCAPTCHA Storefront. Luma uses Magento's reCAPTCHA UI component; Hyvä its own reCAPTCHA blocks (inline script registered with Hyvä's CSP helper on Hyvä 1.3.11+).
  • A refused submit goes back to the form with the message and, on the new-ticket form, with everything the visitor entered; the helpdesk's controller never runs, so no ticket or email comes from it.
  • Hyvä: ticking "I'm not a robot" after an early submit unlocks the submit button again, so the typed ticket is kept.

Requirements

  • qoliber/helpdesk 1.0 and, on Hyvä, qoliber/helpdesk-hyva 1.0; Magento 2.4.6 or later (Magento Framework 103.0.6).
Changelog — Helpdesk — Customer Service — Extensions | qoliber Docs