# ADR-007: Multi-Layer Data Encryption Strategy

**Status**: Accepted | **Date**: 2025-01-16 | **Supersedes**: None

## Context

Provisioning stores sensitive data: API credentials, database passwords, private keys,
and configuration secrets. Data protection is required both in transit and at rest.

## Decision

Implement four encryption layers:
1. **Encryption at Rest** - Database encryption, file encryption
2. **Encryption in Transit** - TLS 1.3, mTLS for service communication
3. **Field-Level Encryption** - Sensitive fields encrypted within application
4. **End-to-End Encryption** - User data encrypted by client before sending

## Architecture

### Layer 1: At-Rest Encryption

**Database Encryption** (SurrealDB):
```sql
-- All secrets table encrypted with AES-256-GCM
CREATE TABLE secrets (
    id: string,
    name: string,
    value: string ENCRYPT_AES256,      -- Encrypted at database level
    key_id: string,                     -- Which key encrypted this
    created_at: datetime,
    rotated_at: datetime
)
```

**File Encryption** (Persistent state):
```rust
// Orchestrator file-based state: encrypted with rotating keys
let encrypted_state = AES256GCM::encrypt(
    plaintext_state,
    key_from_vault,
    random_nonce
);

fs::write("orchestrator/state.enc", encrypted_state)?;
```

**Backup Encryption**:
```bash
# Backups automatically encrypted with PQC hybrid encryption
provisioning backup create --type full --encryption hybrid
# Output: backup-2025-01-16-ENCRYPTED.tar.gz
# Encrypted with CRYSTALS-Kyber + AES-256
```

### Layer 2: Encryption in Transit

**TLS 1.3** (Service to Service):
```rust
// All REST API endpoints TLS 1.3 only
let server = HttpServer::new( | | {
    App::new()
        .wrap(
            middleware::DefaultHeaders::new()
                .add(("Strict-Transport-Security", "max-age=31536000"))
        )
})
.bind_openssl("0.0.0.0:443", ssl_acceptor)?
.run()
.await?;
```

**mTLS** (Service-to-Service Authentication):
```text
Control-Center → Vault-Service
  1. Verify Service certificate signed by internal CA
  2. Verify certificate chain and revocation status
  3. Check certificate common-name matches expected service
  4. Proceed with encrypted communication
```

**Certificate Management**:
```bash
# Automatic certificate generation and rotation
provisioning cert generate --service vault-service --ttl 90d --auto-renew
provisioning cert rotate --all-services --force

# Certificate verification
provisioning cert verify --service orchestrator
# Output:
# Service: orchestrator
# Certificate: vault-orchestrator.cert.pem
# Valid: 2025-01-16 to 2025-04-16
# Chain: ✓ Valid | Revocation: ✓ Checked
```

### Layer 3: Field-Level Encryption

Sensitive fields encrypted within application logic:

```rust
// vault-service encrypts before storing
pub struct Secret {
    #[encrypt]  // Custom derive macro
    pub value: String,

    pub key_id: String,  // Unencrypted reference
    pub created_at: DateTime<Utc>,
}

impl Serialize for Secret {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        // Encrypt value field during serialization
        let encrypted = vault.encrypt(&self.value)?;
        SerializeState {
            value: encrypted,
            key_id: &self.key_id,
            created_at: self.created_at,
        }.serialize(serializer)
    }
}
```

**Searchable Encryption** (for indexed fields):
```rust
// Hash values for indexing without decryption
let search_hash = HMAC_SHA256(secret_value, search_key);
db.create_index(search_hash);  // Index encrypted values

// Search works on hash
let results = db.query_by_index(search_hash);
```

### Layer 4: End-to-End Encryption

User's client-side encryption:

```nushell
# User encrypts locally, only encrypted value sent
let secret = "api-key-12345"
let encrypted = provisioning secret encrypt --plaintext $secret --user-key-id mykey
provisioning secret upload --encrypted $encrypted

# Only user with private key can decrypt
provisioning secret decrypt --encrypted-value $encrypted --user-key-id mykey
```

## Key Rotation

**Automatic Rotation**:
```bash
# Rotate encryption keys every 90 days
provisioning key rotate --policy auto --interval 90d

# Timeline:
# Day 1: New key generated, becomes "active"
# Day 1-90: Old key still used for decryption
# Day 90: Old key marked "retired", new key only for encryption
# Day 180: Old key deleted from vault (audit trail kept)
```

**Re-encryption During Rotation**:
```text
Old Key: secret-key-2024
  ↓ decrypt
Plaintext (never stored)
  ↓ encrypt
New Key: secret-key-2025
  ↓ store
Database updated with new ciphertext
```

## Data Classification

| Classification | At-Rest | In-Transit | Field-Level | E2E |
| ---------------- | --------- | ----------- | ------------- | ----- |
| Public | Optional | TLS 1.3 | No | No |
| Internal | AES-256 | TLS 1.3 + mTLS | Optional | No |
| Confidential | AES-256 | TLS 1.3 + mTLS | Yes | Optional |
| Restricted | Hybrid PQC | TLS 1.3 + mTLS | Yes | Yes |

## Performance Optimization

**Caching** (reduce decryption overhead):
```rust
// Cache decrypted secrets with TTL
let cache = LruCache::new(1000);
cache.insert(key_id, (plaintext, expiration));

// Subsequent requests use cache
if let Some((value, exp)) = cache.get(key_id) {
    if exp > now() {
        return Ok(value);  // No decryption overhead
    }
}
```

**Lazy Decryption**:
```rust
// Don't decrypt until actually accessed
pub struct EncryptedSecret {
    ciphertext: Vec<u8>,
    key_id: String,
}

impl EncryptedSecret {
    pub fn decrypt_on_read(&self, vault: &Vault) -> Result<String> {
        vault.decrypt(&self.ciphertext, &self.key_id)
    }
}
```

## Compliance

- **FIPS 140-2**: Encryption algorithms validated
- **PCI DSS**: Encryption for payment data
- **GDPR**: Data protection by design
- **HIPAA**: Encryption for healthcare data
- **SOC2**: Encryption controls and key management

## Consequences

- **Positive**:
  - Defense in depth (multiple encryption layers)
  - Quantum-safe (hybrid PQC)
  - Compliance-ready
  - Transparent to most operations

- **Negative**:
  - Performance overhead (1-5% latency increase)
  - Operational complexity (key management)
  - Storage overhead (encrypted data ~10% larger)
  - Debugging harder (encrypted data opaque)

## Related ADRs

- [ADR-006: Post-Quantum Cryptography](./adr-006-post-quantum-cryptography.md)
- [ADR-008: Secret Management and Rotation](./adr-008-secret-rotation.md)
