npm package: @rivtor/erasure
Description: GDPR Article 17 Right to be Forgotten with legal retention engine and dependency graph resolver
Author: Rivtor
Latest version: 1.1.0

# @rivtor/erasure

**Production-ready GDPR Article 17 Right to be Forgotten with legal retention engine**

## Features

- **Legal Retention Engine**: Pre-configured retention rules for EU/UK/California jurisdictions
- **Dependency Graph Resolver**: Intelligent cascading deletes across related tables
- **Anonymization Strategies**: Hash, tokenize, nullify, randomize, and aggregate options
- **Processor Notification Queue**: Automatic webhook notifications to Stripe, SendGrid, and more
- **Grace Period Management**: 30-day grace period with cancellation support
- **Comprehensive Audit Trail**: Complete logging of all erasure operations

## Installation

```bash
npm install @rivtor/erasure
# or
yarn add @rivtor/erasure
# or
pnpm add @rivtor/erasure
```

## Quick Start

### 1. Execute Immediate Erasure

```typescript
import { executeEraseUser } from '@rivtor/erasure/server';

const result = await executeEraseUser('user-123', {
  retention_overrides: {
    invoices: {
      retain_until: '2035-01-01',
      reason: 'German tax law (10 years)',
      legal_basis: 'legal_obligation',
      jurisdiction: 'DE'
    }
  },
  anonymize_instead_of_delete: {
    analytics: {
      strategy: 'aggregate',
      fields: ['user_id', 'ip_address']
    }
  },
  notify_processors: true
});

console.log(result);
// {
//   success: true,
//   deletedTables: ['users', 'profiles', 'sessions'],
//   anonymizedTables: ['analytics_events'],
//   retainedTables: ['invoices'],
//   notifications: ['stripe', 'sendgrid']
// }
```

### 2. Schedule Deletion with Grace Period

```typescript
import { scheduleDeletion } from '@rivtor/erasure/server';

// Schedule for 30 days from now
const deletionId = await scheduleDeletion('user-123', 'user', 30);

// User can cancel within grace period
await cancelScheduledDeletion(deletionId);
```

### 3. Process Scheduled Deletions

```typescript
import { processScheduledDeletions } from '@rivtor/erasure/server';

// Call from cron job (e.g., every hour)
const processed = await processScheduledDeletions(10);
console.log(`Processed ${processed} deletions`);
```

### 4. Check Deletion Status

```typescript
import { checkDeletionStatus } from '@rivtor/erasure/server';

const { status, tracker } = await checkDeletionStatus('user-123');
console.log(status);
// 'pending' | 'processing' | 'completed' | 'failed' | 'not_found'
```

## API Reference

### Server Functions

```typescript
import {
  executeEraseUser,
  scheduleDeletion,
  cancelScheduledDeletion,
  processScheduledDeletions,
  checkDeletionStatus
} from '@rivtor/erasure/server';

// Execute immediate erasure
await executeEraseUser(
  userId: string,
  options?: {
    retention_overrides?: Record<string, RetentionOverride>;
    anonymize_instead_of_delete?: Record<string, AnonymizationConfig>;
    notify_processors?: boolean;
    external_apis?: ExternalApiConfig[];
  }
): Promise<ErasureResult>;

// Schedule deletion with grace period
await scheduleDeletion(
  userId: string,
  entityType: string,
  gracePeriodDays: number,
  options?: ErasureOptions
): Promise<string>; // Returns deletionId

// Cancel scheduled deletion
await cancelScheduledDeletion(deletionId: string): Promise<boolean>;

// Process scheduled deletions (for cron jobs)
await processScheduledDeletions(limit?: number): Promise<number>; // Returns count

// Check deletion status
await checkDeletionStatus(
  userId: string
): Promise<{
  status: 'pending' | 'processing' | 'completed' | 'failed' | 'not_found';
  tracker?: ErasureTracker;
}>;
```

### Anonymization Strategies

```typescript
type AnonymizationStrategy =
  | 'hash'      // One-way hash of the value
  | 'tokenize'  // Replace with random token
  | 'nullify'   // Set to NULL
  | 'randomize' // Replace with random realistic value
  | 'aggregate'; // Aggregate with other records

// Example usage
await executeEraseUser('user-123', {
  anonymize_instead_of_delete: {
    // Hash email for login records
    auth_logs: {
      strategy: 'hash',
      fields: ['email', 'ip_address']
    },
    // Nullify PII in analytics
    analytics_events: {
      strategy: 'nullify',
      fields: ['user_agent', 'referrer']
    },
    // Aggregate user interactions
    interactions: {
      strategy: 'aggregate',
      fields: ['user_id']
    }
  }
});
```

### Retention Overrides

```typescript
interface RetentionOverride {
  retain_until: string;      // ISO date string
  reason: string;            // Legal reason for retention
  legal_basis: string;       // 'legal_obligation' | 'contract' | 'legitimate_interest'
  jurisdiction: string;      // Country code (DE, UK, CA, etc.)
}

// Pre-configured retention rules for common jurisdictions
await executeEraseUser('user-123', {
  retention_overrides: {
    // German tax law (10 years)
    invoices: {
      retain_until: '2035-01-01',
      reason: 'German tax law (10 years)',
      legal_basis: 'legal_obligation',
      jurisdiction: 'DE'
    },
    // UK financial records (7 years)
    transactions: {
      retain_until: '2032-01-01',
      reason: 'UK financial regulations',
      legal_basis: 'legal_obligation',
      jurisdiction: 'UK'
    }
  }
});
```

### Processor Notifications

```typescript
interface ExternalApiConfig {
  name: string;
  url: string;
  method: 'POST' | 'DELETE';
  headers?: Record<string, string>;
  body_template?: string;
  retry_count?: number;
}

await executeEraseUser('user-123', {
  external_apis: [
    {
      name: 'stripe',
      url: 'https://api.stripe.com/v1/customers/{{user_id}}',
      method: 'DELETE',
      headers: {
        'Authorization': `Bearer ${process.env.STRIPE_API_KEY}`
      },
      retry_count: 3
    },
    {
      name: 'sendgrid',
      url: 'https://api.sendgrid.com/v3/marketing/contacts',
      method: 'DELETE',
      headers: {
        'Authorization': `Bearer ${process.env.SENDGRID_API_KEY}`
      }
    }
  ]
});
```

## Database Schema

```sql
-- Scheduled deletions with grace period
CREATE TABLE scheduled_deletions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL,
    entity_type TEXT NOT NULL,
    scheduled_for TIMESTAMPTZ NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending',
    created_at TIMESTAMPTZ DEFAULT NOW(),
    cancelled_at TIMESTAMPTZ,
    completed_at TIMESTAMPTZ,
    error TEXT,
    options JSONB
);

-- Comprehensive erasure audit logs
CREATE TABLE erasure_audit_logs (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL,
    entity_type TEXT NOT NULL,
    status TEXT NOT NULL,
    started_at TIMESTAMPTZ NOT NULL,
    completed_at TIMESTAMPTZ,
    deleted_tables TEXT[] NOT NULL DEFAULT '{}',
    anonymized_tables TEXT[] NOT NULL DEFAULT '{}',
    retained_tables TEXT[] NOT NULL DEFAULT '{}',
    retention_overrides JSONB,
    external_api_calls JSONB,
    errors JSONB,
    requested_by TEXT,
    ip_address TEXT
);

-- Indexes for efficient queries
CREATE INDEX idx_scheduled_deletions_user ON scheduled_deletions(user_id);
CREATE INDEX idx_scheduled_deletions_status ON scheduled_deletions(status);
CREATE INDEX idx_scheduled_deletions_scheduled_for ON scheduled_deletions(scheduled_for);
CREATE INDEX idx_erasure_audit_logs_user ON erasure_audit_logs(user_id);
CREATE INDEX idx_erasure_audit_logs_status ON erasure_audit_logs(status);
```

## Configuration

```typescript
import { configureErasure } from '@rivtor/erasure/server';

configureErasure({
  // Default grace period in days
  defaultGracePeriodDays: 30,

  // Default retention rules by jurisdiction
  defaultRetention: {
    EU: {
      invoices: { years: 10 },
      tax_records: { years: 10 },
      contracts: { years: 5 }
    },
    UK: {
      financial_records: { years: 7 },
      invoices: { years: 6 }
    },
    US: {
      tax_records: { years: 7 },
      employment_records: { years: 7 }
    }
  },

  // Default anonymization strategy
  defaultAnonymization: {
    strategy: 'hash',
    fields: ['email', 'name', 'phone']
  },

  // External API retry settings
  retryConfig: {
    maxRetries: 3,
    backoffMs: 1000,
    timeoutMs: 30000
  }
});
```

## Best Practices

1. **Always Use Grace Periods**: Give users time to change their mind
2. **Document Retention**: Keep clear records of why data is retained
3. **Test Anonymization**: Verify anonymization strategies before production
4. **Monitor External APIs**: Track processor notification success rates
5. **Regular Audit Reviews**: Review erasure audit logs periodically

## Legal Compliance

This package helps comply with:

- **GDPR Article 17**: Right to erasure (right to be forgotten)
- **CCPA**: Right to delete
- **UK GDPR**: Data deletion requirements
- **Various Tax Laws**: Legal retention obligations

## License

MIT

---

Made with ❤️ by [Rivtor](https://rivtor.com)