Safety

aether-compliance

GDPR data deletion, export, pseudonymization, and retention

The aether-compliance crate handles privacy and legal compliance for Aether, including GDPR account deletion, data export, pseudonymization, retention scheduling, legal hold management, and compliance keystores.

Overview

Data protection regulations require specific capabilities that this crate provides:

  • Deletion pipeline that processes account deletion requests across all data stores in configurable stages.
  • Data export that bundles a user's personal data into a portable format.
  • Pseudonymization that replaces identifiers with hashed tokens for analytics without exposing PII.
  • Retention scheduling that automatically purges data after configurable windows expire.
  • Legal hold that prevents deletion of data subject to legal proceedings.
  • Compliance keystore for managing encryption keys with purpose tagging.

Key Types

DeletionPipeline

Orchestrates the multi-step deletion of a user's data across all backend systems.

use aether_compliance::{DeletionPipeline, DeleteRequest, DeleteScope, DeletionStatus};

let pipeline = DeletionPipeline::new();
let request = DeleteRequest {
    user_id: user_id,
    scope: DeleteScope::Full,
    reason: "User-initiated GDPR request".into(),
};
let status: DeletionStatus = pipeline.execute(request)?;

DeletionStep

Each step in the deletion pipeline targets a specific data store or service.

use aether_compliance::{DeletionStep, StepExecutor, StepResult, NoOpExecutor};

let step = DeletionStep {
    name: "delete_chat_history".into(),
    executor: Box::new(NoOpExecutor), // Replace with real executor
};

DataExporter

Bundles all personal data for a user into an export package.

use aether_compliance::{DataExporter, ExportBundle, ExportSection, ExportStatus};

let exporter = DataExporter::new();
let bundle: ExportBundle = exporter.export(user_id)?;
for section in &bundle.sections {
    // Each section contains data from one service (profile, chat, economy, etc.)
}

pseudonymize_id

Replaces a user identifier with a deterministic but irreversible hash.

use aether_compliance::{pseudonymize_id, generate_salt};

let salt = generate_salt();
let pseudonym = pseudonymize_id("user-12345", &salt);
// Returns a consistent hash that cannot be reversed to the original ID

RetentionSchedule

Defines when different categories of data should be automatically purged.

use aether_compliance::{RetentionSchedule, RetentionWindow, RetentionState};

let schedule = RetentionSchedule::new(vec![
    RetentionWindow {
        category: "chat_messages".into(),
        retention_days: 90,
    },
    RetentionWindow {
        category: "analytics".into(),
        retention_days: 365,
    },
]);

HoldManager

Manages legal holds that prevent data deletion during legal proceedings.

use aether_compliance::{HoldManager, Hold, HoldError};

let mut holds = HoldManager::new();
holds.create(Hold {
    user_id: user_id,
    case_reference: "CASE-2024-001".into(),
    reason: "Pending litigation".into(),
})?;
// While a hold is active, deletion requests for this user are paused

ComplianceKeystore

Manages encryption keys with purpose tagging and rotation support.

use aether_compliance::{ComplianceKeystore, KeyPurpose, KeystoreEntry};

let keystore = ComplianceKeystore::new();
let key = keystore.get_or_create(KeyPurpose::Pseudonymization)?;

Usage Examples

GDPR Deletion Request

use aether_compliance::{
    DeletionPipeline, DeleteRequest, DeleteScope, HoldManager,
    DeletionStatus,
};

let holds = HoldManager::new();
let pipeline = DeletionPipeline::new();

let request = DeleteRequest {
    user_id,
    scope: DeleteScope::Full,
    reason: "GDPR Article 17 request".into(),
};

// Check for legal holds before proceeding
if holds.has_active_hold(user_id) {
    // Pause deletion until hold is lifted
} else {
    let status = pipeline.execute(request)?;
}

Bulk Pseudonymization

use aether_compliance::{pseudonymize_rows, PseudonymizedRow, generate_salt};

let salt = generate_salt();
let rows = pseudonymize_rows(&analytics_data, &salt);
// All user identifiers are replaced with hashed tokens