Organization deletes and member removals
Support cleans up after the organization plugin’s own endpoints, with no wiring. After /organization/delete, it deletes that organization’s tickets. After /organization/remove-member and /organization/leave, it unassigns the member’s tickets if they left the staff organization. In a customer organization nothing changes: teammate access is checked live, and requesters keep their own tickets. A hook acts only when the endpoint succeeded, takes ids only from the response, and logs errors without failing the request.
organizationCleanup: false turns the row cleanup off, for apps that keep history. On memory and MongoDB that keeps the organization’s tickets. On SQL the organizationId foreign key still cascades the ticket rows away. The blobs under support/<orgId>/ are always removed when an organization is deleted, because cascaded tickets leave no row that points at them.
Deletes made any other way
For deletes made any other way (a script, an admin tool, a direct database write), call the functions yourself. They run inside a better-auth transaction (runWithTransaction) when called in one, and they are safe to run again:
import {
deleteMemberData,
deleteOrganizationData,
deleteSupportRequesterData,
linkSupportRequester,
} from "@byo-oss/support";
await deleteOrganizationData(auth, organizationId); // → { tickets }, and deletes the support/<orgId>/ blobs
await deleteMemberData(auth, { userId, organizationId }); // → { unassigned }
await deleteSupportRequesterData(auth, { email }); // → { tickets, messages }
await linkSupportRequester(auth, userId); // → { tickets, messages }The cases
-
A user is deleted. Foreign keys null
userId(requester, author, uploader) andassigneeIdon SQL. Auser.deletehook does the same on adapters without them (memory, MongoDB), and clears any stored copy of their email. A user deleted outside better-auth keeps those email copies untildeleteSupportRequesterDataruns for the address. On every adapter, the hook also removes their id from messagementionsand sets it to null inassigneeevent rows (fromandto), which no foreign key reaches. It pages through every agent-authored message to do so, so a user delete costs time in proportion to that table. A user deleted outside better-auth keeps their id in mentions and assignee events, and no exported function removes it. -
An account-less person (someone who only emailed) asks to be erased.
deleteSupportRequesterDatadeletes their tickets with all their messages, tags and attachments, and anonymizes their messages on other tickets. -
An organization is removed outside the organization plugin. It leaves its blobs behind until
deleteOrganizationDataruns. -
With
@byo-oss/core, the fan-out reaches support through itsbyohooks, so one call cleans every BYO plugin:lib/auth.tsimport { deleteMemberData, deleteOrganizationData } from "@byo-oss/core"; organization({ organizationHooks: { afterDeleteOrganization: async ({ organization }) => { await deleteOrganizationData(auth, organization.id); }, afterRemoveMember: async ({ member }) => { await deleteMemberData(auth, { userId: member.userId, organizationId: member.organizationId }); }, }, });Running this next to support’s automatic hooks is safe. Add it for the other plugins’ sake, and for deletes the endpoint hooks don’t see.
Uninstalling
To remove support, see Uninstall.