# Account Deletion Policies

> Customize account deletion authorization rules.

*Canonical: https://makerkit.dev/docs/nextjs-drizzle/personal-accounts/authorization-policies*

---

Account deletion policies control when users can delete their accounts. The system ships with default policies that can be extended or replaced.

## Default Policies

The `@kit/account-hooks` package includes two default policies:

| Policy | ID | Behavior |
|--------|-----|----------|
| `checkSubscriptionsPolicy` | `account-deletion.check-subscriptions` | Blocks if user has active subscriptions |
| `checkOrganizationsPolicy` | `account-deletion.check-organizations` | Blocks if sole owner of orgs with other members |

## Adding Custom Policies

### 1. Create Your Policy

```typescript
// In your app or a custom package
import { definePolicy, allow, deny } from '@kit/policies';
import type { AccountDeleteContext } from '@kit/account-hooks';

export const gracePeriodPolicy = definePolicy<AccountDeleteContext>({
  id: 'account-deletion.grace-period',
  evaluate: async (context) => {
    const user = await getUser(context.userId);
    const daysSinceCreation = daysBetween(user.createdAt, new Date());

    if (daysSinceCreation < 7) {
      return deny({
        code: 'ACCOUNT_TOO_NEW',
        message: 'Accounts must be at least 7 days old before deletion',
        remediation: `Please wait ${7 - daysSinceCreation} more days`,
      });
    }

    return allow();
  },
});
```

### 2. Register Your Policy

Extend the default registry:

```typescript
import { accountDeletionRegistry } from '@kit/account-hooks';
import { gracePeriodPolicy } from './my-policies';

// Add to existing defaults
accountDeletionRegistry.registerPolicy(gracePeriodPolicy);
```

## Context Type

```typescript
interface AccountDeleteContext {
  userId: string;      // User attempting to delete account
  timestamp: string;   // ISO timestamp
}
```

## Customization Patterns

### Use Defaults As-Is

```typescript
import { accountDeletion } from '@kit/account-hooks';

const result = await accountDeletion.run({
  userId: user.id,
  timestamp: new Date().toISOString(),
});
```

### Extend Defaults

```typescript
import { accountDeletionRegistry } from '@kit/account-hooks';
import { myCustomPolicy } from './policies';

accountDeletionRegistry.registerPolicy(myCustomPolicy);
```

### Cherry-Pick Policies

```typescript
import { createPolicyRegistry, createPolicyRuntime } from '@kit/policies';
import { checkOrganizationsPolicy } from '@kit/account-hooks';

const registry = createPolicyRegistry();
// Only check organizations, skip subscriptions
registry.registerPolicy(checkOrganizationsPolicy);

const runtime = createPolicyRuntime(registry);
```

### Replace a Policy

```typescript
import { createPolicyRegistry, createPolicyRuntime } from '@kit/policies';
import { checkOrganizationsPolicy } from '@kit/account-hooks';
import { mySubscriptionPolicy } from './policies';

const registry = createPolicyRegistry();
registry.registerPolicy(checkOrganizationsPolicy);
registry.registerPolicy(mySubscriptionPolicy); // Your replacement

const runtime = createPolicyRuntime(registry);
```

## Example: Auto-Cancel Subscriptions

Instead of blocking deletion, auto-cancel subscriptions:

```typescript
import { definePolicy, allow } from '@kit/policies';

export const autoCancelPolicy = definePolicy<AccountDeleteContext>({
  id: 'account-deletion.auto-cancel-subscriptions',
  evaluate: async (context) => {
    const subscriptions = await getActiveSubscriptions(context.userId);

    for (const sub of subscriptions) {
      await cancelSubscription(sub.id);
    }

    return allow({
      cancelledSubscriptions: subscriptions.length,
    });
  },
});
```

## Example: Require Data Export

```typescript
export const dataExportPolicy = definePolicy<AccountDeleteContext>({
  id: 'account-deletion.require-export',
  evaluate: async (context) => {
    const hasExported = await checkDataExportStatus(context.userId);

    if (!hasExported) {
      return deny({
        code: 'DATA_NOT_EXPORTED',
        message: 'Please export your data before deleting your account',
        remediation: 'Go to Settings > Privacy > Export Data',
      });
    }

    return allow();
  },
});
```

## Integration

The policies are evaluated in the Better Auth `beforeDeleteUser` hook:

```typescript
// packages/account/hooks/src/before-delete.ts
import { accountDeletion } from './policies/registry';

export async function beforeAccountDelete(userId: string) {
  const result = await accountDeletion.run({
    userId,
    timestamp: new Date().toISOString(),
  });

  if (!result.allowed) {
    throw new Error('Account deletion blocked');
  }
}
```

---

**Next:** [Preferences →](./preferences)
