Identity deletion
Soft account and organization deletion with host policy in the same transaction.
SqlOSIdentityDeletionService is the shared service behind operator deletion and host product flows. Call DeleteUserAsync(userId, actorId, confirm) or DeleteOrganizationAsync(organizationId, actorId, confirm) only after authorizing the authenticated caller. The operator dashboard and POST /sqlos/admin/auth/api/users/{id}/delete / organizations/{id}/delete require operator authorization and explicit confirmation. Membership offboarding uses RemoveMembershipAsync. Its optional prepare callback performs host ownership handoff after the organization lock is acquired and before membership deactivation, in the same transaction. A refused preparation rolls back; inactive-membership retries skip it. Acquire host role locks inside this callback so identity operations and handoff use the same lock order.
Deletion is soft: the identity receives DeletedAt and becomes inactive. Names, addresses, credentials, linked identities, organization domains and membership records remain stored. Memberships become inactive, sessions and refresh tokens are revoked, pending organization invitations are revoked, SSO/SCIM is disabled and organization-owned machine clients stop admitting tokens. Historical attribution and security audit remain. Deletion neither purges host content nor erases principal data.
Hosts register ISqlOSIdentityDeletionParticipant for ownership safeguards, billing checks and application policy. Participants run before identity changes in the same transaction and may veto by throwing. Use the same scoped EF context; never perform external I/O from participants. Hosts choosing soft deletion must retain their application data too. A host may hold an enclosing transaction. Idempotent retries return AlreadyDeleted without repeating participants.
Code-first seeding of a deletion is not applicable: deletion is an explicit runtime lifecycle action. Services, operator APIs and dashboard share the same participant pipeline. Setting IsActive alone cannot restore a deleted identity. No restoration endpoint is supplied. A deleted organization cannot receive new memberships or be reactivated through UpdateOrganizationAsync.