SaaS Starter
Platform admin

Managing organizations

Cross-tenant org lifecycle — suspend, reactivate, soft-delete, transfer ownership.

/admin/organizations lists every org. Click an org name to open the detail page (members, invitations, API keys, subscription summary, danger zone).

Actions

ActionRouteAuditNotes
SuspendPOST /api/v1/platform/organizations/{id}/suspendplatform.org.suspendedSets isActive=false. Members hit rejectIfOrgSuspended on org-scoped routes.
ReactivatePOST /api/v1/platform/organizations/{id}/reactivateplatform.org.reactivatedRefuses on soft-deleted orgs.
Soft-deleteDELETE /api/v1/platform/organizations/{id}platform.org.soft_deletedSets deletedAt. Idempotent.
Transfer ownershipPOST /api/v1/platform/organizations/{id}/transfer-ownershipplatform.org.ownership_transferredReassigns the system "owner" role on OrganizationMember.

How transfer ownership works

The boilerplate uses role-based ownership — there is no Organization.ownerUserId column. The "owner" is whichever member's roleId matches the org's system Role(name='owner', isSystem=true). Transfer:

  1. Resolves the current owner automatically (the platform admin doesn't have to know who they are).
  2. Validates the target user exists, is active, not soft-deleted, and is a current member of the org.
  3. Atomically re-assigns the owner role to the target and demotes the previous owner to 'admin' (or whatever demotedRoleName is passed).
  4. Audits platform.org.ownership_transferred with { previousOwnerId, newOwnerId }.

If the boilerplate ever migrates to an Organization.ownerUserId column, only apps/server/src/modules/tenancy/application/use-cases/admin/transfer-organization-ownership.ts and the underlying TransferOwnershipUseCase need to change.

What soft-delete does NOT do

  • Cancel subscriptions. The boilerplate's Subscription.customerInternalId is the user id, not the org id (a user can own multiple orgs). Cancelling on soft-delete would clobber the wrong tenant. Cancel separately via the Billing admin page.
  • Hard-delete data. All FKs use onDelete: Cascade for hard deletes only. Soft-delete just flips deletedAt; members, invitations, API keys, and subscriptions stay queryable for incident investigation.
  • Sign members out. A soft-deleted org's members keep their existing sessions but immediately hit rejectIfOrgSuspended if they try to act on the org's resources. They can still access other orgs they belong to.

On this page