1#![deny(missing_docs)]
3
4#[cfg(feature = "api-providers")]
5mod api;
6#[cfg(feature = "keycloak")]
7mod keycloak;
8mod store;
9mod worker;
10
11use std::{future::Future, pin::Pin};
12
13#[cfg(feature = "api-providers")]
14pub use api::{ApiDeletionConfig, ClerkAccountDeleter, WorkOsAccountDeleter};
15#[cfg(feature = "keycloak")]
16pub use keycloak::{KeycloakAccountDeleter, KeycloakDeletionConfig};
17pub use store::{
18 ErasureError, ErasureOutcome, ErasurePreflight, ErasureService, ErasureState,
19 IdentityRetention, PostgresErasureStore, ProductErasure, reject_fenced_subject,
20};
21pub use worker::IdentityDeletionHandler;
22
23pub const POSTGRES_MIGRATION_SQL: &str = include_str!("../migrations/0001_erasure.sql");
25pub const POSTGRES_REONBOARDING_MIGRATION_SQL: &str =
27 include_str!("../migrations/0002_erasure_reonboarding.sql");
28pub const IDENTITY_DELETE_JOB_TYPE: &str = "identity.account.delete";
30pub type ErasureFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
32
33#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
35pub enum IdentityDeletionError {
36 #[error("identity deletion temporarily unavailable")]
38 Retryable,
39 #[error("identity deletion rejected permanently")]
41 Permanent,
42}
43
44pub trait IdentityAccountDeleter: Send + Sync + 'static {
46 fn delete_account<'a>(
48 &'a self,
49 subject: &'a str,
50 ) -> ErasureFuture<'a, Result<(), IdentityDeletionError>>;
51}