Administrators and Account Ownership
- Owners and administrators can now grant and revoke the Admin role from the role dialog on Account Users, which previously locked every system role. The Basic role stays fixed, because every member holds it automatically.
- An account always keeps an administrator: removing the Admin role from the last remaining administrator is refused. You may give up your own while another administrator remains, and you are warned first that you will not be able to restore it yourself.
- The account owner can transfer ownership to another member from Account Users, confirming their identity first. The new owner also receives the Admin role, and only they can transfer it back.
- An account can no longer be left without an owner. A user who owns one cannot be deleted or unlinked from it until ownership has been transferred to somebody else.
- Removing someone’s role now narrows every API and MCP token they created straight away, because token permissions are checked against what the holder currently holds rather than what they held when the token was made.
- When an account owner deletes their account and no other members remain, the account is now deactivated and any outstanding invitations are withdrawn, rather than being left active and empty.
Help Desk
- Creating a ticket from an email now carries the email’s formatting across. Headings, lists, bold text, links, and images previously arrived as flat text.
- Creating an issue from a ticket keeps the ticket description’s formatting in the same way.
- Both description fields are now full rich text editors, with the toolbar, tables, the media library, image upload by drag and drop or paste, and AI assist. Both dialogs are wider so the toolbar fits comfortably.
- Nothing changes for existing tickets or issues, and no action is needed from anyone.
Ticket Conversations and Board Visibility
- Email replies from requesters now appear directly in the ticket conversation. A new Add Email to Conversation workflow action appends an inbound reply to the thread of the ticket it belongs to, so you read what was said in order alongside your own replies instead of opening a linked email to find it. Add the action to an email workflow after Extract Ticket References; it needs no configuration of its own.
- Each entry is attributed to the person who sent it, so the thread shows their name rather than System, and a contact is created automatically the first time an unknown address writes in. Processing the same email twice never duplicates an entry.
- An inbound reply does not satisfy the first response target on your SLA, because a requester writing in is not an agent responding, and it does not change the ticket’s status. Reply handling stays yours to define through workflows.
- Tickets waiting on your team now stand out on the Kanban board. When a requester replies, the card is marked with an accent and a Requester replied badge showing how long the reply has been waiting, so a two hour wait looks different from a two day one.
- Those cards float to the top of their lane, which makes a pending response hard to miss when scanning the board. Your chosen sort still applies within each group, so floating never overrides how you have ordered a lane.
- A new Awaiting Reply filter narrows the board to what is waiting on your team or on the requester, and a Last Reply sort orders tickets by most recent conversation activity. Both are available on the ticket list and its exports too.
- Internal notes do not count as answering the requester, so adding a note leaves a ticket marked as still awaiting a reply. Replies sent by automation, such as a canned response from a workflow, do count. Existing tickets were included, so the board reflects real conversation state straight away.
- Fixed tickets disappearing from the Kanban board. The board was only ever loading the ten most recent tickets and spreading them across all six lanes, so cards seemed to vanish at random whenever a ticket was created or the sort changed. The board now loads its full set, and the page size selector on the ticket list works instead of always returning ten rows. Tickets show thirty per page by default.
AI Writing Assistant
- A new Reformat action in the Refine tab tidies how your content is laid out without changing a single word of it. It splits a wall of text into paragraphs, turns a run of items into a proper list, promotes lines that read as section titles into headings, and cleans up stray formatting.
- Every other refine action changes your words, whether shortening, expanding, or adjusting the tone, so Reformat is the one to reach for after pasting content in from somewhere else.
- Existing refine actions are unchanged, and Reformat is available wherever the AI Assist panel appears, in English, Spanish, and German.
Data Retention (new)
- A Data Retention and Disposal Policy is now available in Compliance, setting a seven year baseline for business records, with shorter periods where a shorter period is justified.
Notes, Tasks and Contacts
- Notes, tasks, and contacts now record who created them. The notes and contacts lists show a Created By column, and the CSV export for all three includes it.
- A new Created by filter on those three lists narrows them to one person’s records, with a System option for anything created by a workflow, the scheduler, or from an inbound email rather than by a member of your team.
- Notes now have bulk delete. Selecting several and removing them is a single action, where before each note was deleted one at a time.
- Records created before this release show System as their creator, because the creator was not recorded at the time. Nothing about those records is changed, and no action is needed from anyone.
Improvements
- Bulk actions now tell you how far they got. Where an action has to be applied to each record in turn, it no longer stops at the first problem and reports one generic failure. It continues through the rest of the selection and tells you how many records were processed, and if it stopped because a limit was reached it says how many are left so you can run it again for the remainder.
- Bulk delete on features and user stories is now a single request rather than one per record, which makes it noticeably quicker on a large selection.
- You can now get yourself out of the unverified email block. If the verification email never arrived, or its link expired, signing in with your email and password takes you to a page offering to send a new one, with your address already filled in, instead of leaving you on the login screen with nothing to act on. A new link can be requested once a minute and up to three times an hour. Note that resetting your password does not lift the block, so use the resend rather than Forgot password?. Reported through our vulnerability disclosure program.
- Fixed notes dropping out of search after an automation updated them. A workflow that changed a note’s content did not refresh the text used for searching and for CSV and PDF exports, so a note could stop matching a search for words it plainly contained, and an export could show text from an earlier revision. Affected notes are corrected on upgrade.
- Clearer limits on the sign-up form. The Full Name and Company Name fields now stop at 255 characters and tell you when you have reached the limit, instead of accepting a long value and then failing with a generic error on submit. The same limit now applies when you sign up from the mobile app. No stored names are affected and no action is needed from existing users.
- The Add User dialog now tells you where you stand before you fill it in. It shows how much of your account’s user allowance is in use, and when the allowance is reached it says so and explains what to do about it, rather than accepting the form and refusing it on submit.
- Fixed being signed out when setting your first password after signing up with Google. An account created through Google has no password, and setting one asks you to confirm your Google account first. Returning from Google ended the session that had just been created and left you back at the sign-in screen. Signing in again and repeating the steps worked, which is what made it look intermittent. Accounts created by signing up with Google now receive exactly the same session as any other sign-in.
- Fixed linking a Google account from Security Settings, which signed you in again instead of linking anything. Choosing Link Google account now takes you to Google, asks which account you want to attach rather than assuming the one you are already signed in to, and reports the outcome when you return. If a Google account is already attached to your profile you are told so before the trip to Google rather than after it.
Security
- Fixed a privilege escalation in account and role management. Permissions on account level requests were checked against the account you had marked as active rather than the account the request actually addressed, so someone who belonged to more than one organization could use one of them to gain administrative access to another, including granting themselves its Admin role. Permissions are now always evaluated against the account named in the request, and you must be a member of that account. Reported to us externally with a clear, reproducible proof of concept.
- Nobody can hand out more authority than they hold themselves. Assigning a role, creating a role, or adding permissions to an existing role is now refused when it would grant a permission you do not have in that account. Renaming or trimming a role that is broader than your own access still works.
- Requests aimed at a disabled account are now rejected even when your own active account is healthy.
- Fixed dashboard figures being readable without the permission for the module they came from. Which panels appeared on the dashboard was decided in the browser alone, so the figures behind a panel could still be read by a member with no access to that part of the product. Every panel is now checked on the server against the same permission that governs the module itself. Nothing changes for anyone whose role already covered the modules on their dashboard. Reported to us externally with a clear, reproducible proof of concept.
- A member who can reach some modules but not others still gets a working dashboard, showing the parts they are entitled to rather than being refused the page outright. Panels belonging to a module that has been switched off no longer return anything either.
- Account invitations are now rate limited, per administrator and per account, covering both sending a new invitation and resending an existing one. This closes off a way the invitation system could have been used to send large volumes of unwanted email. Inviting people at a normal pace is unaffected. Reported through our vulnerability disclosure program.
- There is now a ceiling on how many users an account can hold, counting invitations that have been sent but not yet answered. Accounts with an active subscription are held to a high limit that no real team reaches, because every user added is already billed for. Accounts without one are held to a much lower limit, and subscribing lifts it straight away with nothing to ask for. Rate limiting alone bounded how fast users could be added but not how many, so an account could still accumulate them indefinitely. Reported through our vulnerability disclosure program.
- Nothing existing is affected by that ceiling. An account already above its limit keeps every member and all of its data, and is only prevented from adding more. If you reach the limit while adding your team, the message tells you whether to subscribe or to contact us.
- The number of organizations one person can create is now limited, and creating them is rate limited too. Without this the user ceiling above could have been sidestepped by starting another organization rather than filling the current one.
- The number of active API tokens an account can hold is now limited, and MCP request limits now apply per account as well as per token. Previously each token carried its own separate allowance, so holding more tokens raised the total an account could send. Revoke a token you no longer use to make room for a new one.
- Working in an organization now requires an active subscription. When a free trial runs out, or a cancelled subscription reaches the end of its paid period, requests for that organization’s records are refused until it is subscribed again. Until now an expired trial kept full access indefinitely, so the caps above bounded how large an unbilled account could become but nothing brought it to a close.
- Nothing is deleted when that happens. Your issues, tests, documents, and history stay exactly as they were and are all there again the moment you subscribe.
- What you need in order to resolve it, or to leave, stays open: signing in, the billing pages and your invoice history, switching to another organization you belong to, viewing and accepting invitations, your own profile and security settings, a full data export, and deleting the account. So nobody is ever locked out of the one page that brings the organization back, and no organization is held hostage to get its data out. Other organizations you belong to are untouched, because the block applies to an organization and never to your user.
- A failed payment that Stripe is still retrying does not lock anybody out. Your organization keeps working normally throughout the grace period, which is the window to update the card, and only an exhausted retry sequence ends access.
- API tokens and MCP clients follow the same rule with one refinement: they can still list the tools available to them and read records, but anything that would create, update, or delete is refused with a payment required response. An integration therefore reports the reason plainly rather than appearing to break, and starts writing again as soon as the subscription is active, with no change needed on its side.
- Every part of the API now sits behind an overall limit on requests per minute, applied per signed-in user rather than per location, so nobody’s activity can crowd out a colleague’s. The limit is set far above normal use and the admin console and mobile app never approach it. If you build your own integration and exceed it, the response says so and tells you how long to wait. Inbound webhooks from Stripe, Google Calendar, and your own chat and workflow integrations are unaffected, and the MCP server keeps its existing per-token limit.
- Requests that create, edit, or delete now carry their own limits, per user and per account, on top of that overall limit. The overall limit was sized for the volume of reading the admin console does, which made it far too generous as the only bound on writing, so a script could keep adding records for as long as it liked without ever reaching it. Reading is unaffected, and the new limits sit well above anything the console or the mobile app does, including deleting a full page of records at once. Recording who created a note, task, or contact, and the new bulk delete for notes, are part of the same work: together they make a large batch of unwanted records straightforward to find and clear rather than something to remove one record at a time. Reported through our vulnerability disclosure program.
- There is now a ceiling on the number of personal calendars you can hold in an organization, and a limit on how quickly calendars and events can be created. Creating calendars at a normal pace is never affected, and your account calendar and any calendars you connect from Google do not count towards the ceiling. Previously nothing bounded this, so a single account could accumulate enough calendars to make its own calendar sidebar slow to load. Reported through our vulnerability disclosure program.
- Hardened how uploaded files are served back to the browser, following a report through our vulnerability disclosure program. Only images and PDFs are now displayed inline. Every other file type is delivered as a download, and file types a browser can execute as a page or a script, such as HTML and JavaScript, are no longer accepted as attachments. This closes a stored cross-site scripting risk where a crafted attachment could run code in the browser, and it also prevents attacker controlled pages being hosted on an ISO Mate address for phishing. Previewing images and PDFs, and downloading any attachment, work exactly as before. If you need to share a web page or a script, add it inside a zip archive.
- The same file protection applies everywhere ISO Mate serves an uploaded file, including issue attachments, chat attachments, compliance evidence, media library images, email attachments, help desk ticket attachments, and test execution attachments. Files uploaded before this change are covered too, because the restriction is applied at the moment a file is served.
- File and image links no longer carry your access token. Previously, opening an attachment preview or displaying your account logo placed a credential in the address, where it could be kept in browser history and server logs. The admin console and the mobile app now request the file over an authenticated connection instead, and the ability to sign in through a link has been removed from the API altogether. Attachment previews, image display, and your account logo all work as before.
- System role definitions are read only through the API. The Admin and Basic roles can no longer be renamed or have their permissions changed through the API, matching the restriction that already applied in the console. Assigning those roles to a user is a separate action and is now allowed.
- Billing management can no longer be attached to an API or MCP token. It was already hidden from the scope picker, and it is now also refused when a token is created.
- Fixed an email verification bypass when signing in with Google. Signing in with Google granted full access to an account whose email address had never been confirmed, even though signing in with a password correctly refused it. Because Google confirms the address before passing it to us, a matching address now counts as proof that the address is yours and the account is recorded as verified, so signing in with a password works from then on too. Reported through our vulnerability disclosure program.
- A password that was set on an account whose address had never been confirmed is now discarded once Google confirms that address. Anyone can type somebody else’s email address when registering, so a password set before the address was confirmed cannot be attributed to the person who owns it. If this applies to you, you stay signed in through Google and are asked to set a new password in Security Settings. Very few people are affected, because it only arises where an account was registered with a password, never confirmed, and later signed in to with Google.
- Accounts created by signing up with Google were being recorded as unverified, because the verification stamp was dropped as the account was created. Existing accounts have been corrected and new ones are recorded properly, so the verification state shown for an account now matches reality.
- An account that has not confirmed its email address can no longer reach any part of the API. Verification was previously enforced only at the moment of signing in, so this adds a second, independent check on every request. Signing out and checking your own sign-in status still work, so an unconfirmed account is never left stranded.
- Signing in with Google is now tied to the specific Google account linked to your profile. If a different Google account is used, sign-in is refused, even when its address matches the address on your ISO Mate account. Previously the profile could be opened by either one, so two separate Google identities could reach the same account while only one of them was recorded as linked. Reported through our vulnerability disclosure program.
- Changing your email address now unlinks a Google account that was linked to the address you are leaving behind, and signs you out of your other sessions. That link used to survive the change, so the old Google account kept working indefinitely. It matters most when a work address is reassigned to somebody else after you leave an organization, because the new holder of that address could otherwise still sign in to your ISO Mate account. You keep access with your password, and can link Google again from Security Settings at any time. A Google account you deliberately linked under some other address is left alone.
- Replacing the Google account linked to your profile now requires unlinking the current one first, which asks for either your password or a confirmation sent to your email address. Previously the link could be pointed at a different Google account without either of those.
- Attaching a Google account to your profile now happens only inside your own signed-in session. The step that completed a link could be reached without signing in, and it trusted the identity named in the request rather than confirming who was asking, which would have let somebody attach their own Google account to another person’s profile and then sign in as them. It was never reachable in practice, because a separate broken check meant no such request could be started, but that was an accident rather than a deliberate refusal. The unauthenticated path has been removed outright, and linking now runs on a route that confirms the request belongs to you.
- Signing out now revokes your session even when a client sends nothing but its short-lived access token. Sign-out already worked correctly from the admin console and the mobile app, because both present the credential that identifies the session, but a client that sent only the access token was told the sign-out had succeeded while the session actually stayed live for the remainder of that token’s fifteen minute life. That path now revokes every token in the session and records the sign-out in your account’s audit trail. Reported through our vulnerability disclosure program.
- Hardened the sign-in window against whatever opened it. A browser instruction that isolates the admin console from any page that opened it was already served by our content network, and the console now also checks for itself, on the sign-in and registration pages, refusing to start the Google sign-in flow when it has been opened by a page from another site. The API sends the same isolation instruction as the console. The protection therefore no longer rests on a single piece of infrastructure, so it holds on any surface that does not sit behind the content network. Prompted by a report through our vulnerability disclosure program describing an account takeover that does not reproduce against ISO Mate, because that instruction is already in place.
- Links that open in a new tab are now hardened everywhere, not only inside formatted content. Every link the admin console opens to an outside destination, such as the billing portal, an invoice, or a Google Meet, is now opened in a way that leaves the new tab with no reference back to the ISO Mate tab that opened it. Current browsers already do this for ordinary links, but not for windows an application opens itself, which is the gap this closes. Nothing changes about how those links behave for you. Reported through our vulnerability disclosure program.
- Our website now sends the browser instruction that isolates a page from any other page that opened it, or that it opens. The admin console and the API already sent it, so all three now agree. Links on the website that open in a new tab also carry the protective attributes again, which WordPress stopped adding automatically in a recent version.
- Responses from the API are no longer written to the browser’s own cache. They were already kept out of shared and proxy caches, but a browser could still keep a copy on disk, so records carrying personal details could persist on a device after the session ended and be recovered by anyone with access to that device. Every API response now says not to store it, while deliberate caching of downloads, exports, and the public requester portal is left alone. The admin console also re-checks that you are still signed in when the browser restores a page from its back-forward cache. Prompted by a report through our vulnerability disclosure program about seeing cached pages after signing out. That path was already closed, because the console’s entry point is never cached, no credential or personal detail is kept in browser storage once you sign out, and every protected page is revalidated against the server before it loads.
- Inbound email to isomate.io now declares that encryption is required. A published MTA-STS policy tells a sending server which mail hosts are legitimate and that the connection must be encrypted, so a sender cannot be tricked into delivering a message unencrypted or to a substituted host. TLS reporting is published alongside it, so any failure is visible to us. The policy starts in testing mode, which reports problems without affecting delivery, and moves to enforcement once the reports confirm it is correct. Protections for mail we send, SPF, DKIM, and DMARC, were already in place; this is the inbound counterpart. Reported through our vulnerability disclosure program.
- Third-party components across the API and the admin console have been brought up to their current patched releases, clearing every advisory raised by our automated dependency scans. Reviewing them against how ISO Mate is actually built found almost none to be reachable, because they rely on features and rendering modes we do not use. One was worth acting on for its own sake rather than for the scan: the library that filters formatted text in the browser was several patches behind, and that code does handle untrusted content, so it now runs a current release.
- The console’s runtime packages had been fixed to exact versions, which is why they could not pick up security patches on their own and the same findings kept returning on every scan. They now track patch releases, and unused server-side rendering packages have been removed rather than carried along and rescanned each month.