Repository navigation
feat(retention): delete an organization from Settings - #473
Merged
Merged
Conversation
Admins can delete the organization from the Company page of Settings after typing its name. The server checks the role and the name again. A new runtime extension point, requestOrganizationDeletion, decides what the action does; without one the organization is purged at once. The capability is on for self-host and off in the hosted distribution until it opts in. Better Auth's own delete stays closed, so every deletion goes through the purge. Also proves PDFs, public links and exports keep working while the organization is read-only. Refs QUI-252
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
The card shows its own error, so the shared banner must not report it again. Refs QUI-252
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Nothing in the app can delete an organization. Better Auth's delete is switched off because it would remove only some rows, and the purge from #471 and #472 is not reachable from the UI. Customers need a way to have their data deleted, and a distribution needs to decide what that means for it, for example a waiting period before the purge.
Change
organizationDeletion.enabledis on. The copy says the deletion is permanent, reminds the user to keep invoices and credit notes for 5 years, and links to the existing export (Activity → Accounting). A dialog asks the user to type the organization's name.settings.deleteOrganizationmutation. It checks again, on the server, that the caller is a signed-in admin (agent keys are refused) and that the typed name matches. Then it callsrequestOrganizationDeletion. When the organization is gone, it returns the user's next organization. The client switches to that organization, or signs the user out if there is none (a sole member's account goes with the organization).RuntimeExtension.requestOrganizationDeletion(request), a new extension point. The first extension that sets it decides what the action does and returns{ status: "deleted" }or{ status: "scheduled", deleteAfter }. Without one (self-host), the organization is purged at once throughpurgeOrganization. A scheduled deletion must still end inpurgeOrganization. A hosted distribution can use this to schedule a cancellable deletion after a waiting period.organizationDeletion: { enabled }in@quits/contracts/runtime. It defaults to on for self-host and off whenQUITS_DISTRIBUTION=cloud, so a hosted upgrade does not show an instant purge before the hosted side opts in throughresolveCapabilities. Consumers of older releases read it as off.disableOrganizationDeletion: trueremains, and its comment now says why: every deletion goes throughrequestOrganizationDeletionand ends in the purge, so Better Auth's partial delete can't be used to get around it.Read-only state. OSS already has the
read_onlyorganization access state (OrganizationAccessinlib/billing/types.ts); only document creation checks it. A new test puts an organization inread_onlyand shows that a private PDF download, a public PDF link, the public payment page and the accounting CSV export all still work.Linear
Refs QUI-252
Verification
settings-delete-organization.integration.test.ts(new): members and accountants get FORBIDDEN; a mistyped name gets BAD_REQUEST; a distribution turning off the capability gets FORBIDDEN; with no extension, the organization is purged and the admin is sent to their other organization; an extension's scheduled outcome replaces the purge.pdf-access.integration.test.ts(extended): the read-only case above.organization-purge.integration.test.ts: unchanged, still passing.vp lint --deny-warningson the changed files;bun run typecheck:app; contracts typecheck.Risk
On self-host, a deletion is permanent at once and can't be undone. That is intended, and it sits behind typed confirmation and the admin role.