# Privacy & Compliance Architecture

This document describes the technical privacy controls built into the `amplitude-ai` SDK and maps them to common compliance frameworks (GDPR, HIPAA, SOC2). It is intended for security reviews and compliance audits — not as legal advice.

## Data Flow Overview

All `[Agent]` events flow through the customer's existing Amplitude SDK pipeline. The `amplitude-ai` SDK never opens its own network connections — it delegates all event delivery to the `Amplitude` instance the customer provides.

```
┌─────────────────────────────────────────────────────┐
│  Customer's Environment                             │
│                                                     │
│  LLM Call ──► amplitude-ai SDK ──► Amplitude SDK ───┼──► Amplitude Servers
│                    │                                │    (US or EU)
│                    ▼                                │
│            Privacy Controls                         │
│            ┌──────────────┐                         │
│            │ content_mode │                         │
│            │ redact_pii   │                         │
│            │ custom_regex │                         │
│            └──────────────┘                         │
└─────────────────────────────────────────────────────┘
```

**Key architectural property:** Privacy controls are applied _before_ the event leaves the customer's process. Content is never sent unfiltered and then redacted server-side.

## Privacy Tiers (`content_mode`)

The SDK supports three privacy tiers via the `content_mode` configuration. Each tier controls what data is included in event properties.

### `full` (default)

Maximum analytics value. Raw text is sent alongside metrics.

| Data Category | Included | Notes |
|---|---|---|
| Message text | Yes | Via `$llm_message.text` |
| Token counts | Yes | Input, output, total, reasoning, cache |
| Latency / TTFB | Yes | |
| Cost (USD) | Yes | |
| Model name / provider | Yes | |
| Reasoning content | Yes | Truncated at 10,000 characters |
| Tool input / output | Yes | |
| PII | Depends | Scrubbed if `redact_pii=True` |

```python
ai = AmplitudeAI(amplitude=amp, config=AIConfig(content_mode=ContentMode.FULL))
```

### `metadata_only`

Zero content leaves the customer's environment. Only operational metrics are sent.

| Data Category | Included | Notes |
|---|---|---|
| Message text | No | |
| Token counts | Yes | |
| Latency / TTFB | Yes | |
| Cost (USD) | Yes | |
| Model name / provider | Yes | |
| Reasoning content | No | Only `[Agent] Has Reasoning` boolean |
| Tool input / output | No | |

```python
ai = AmplitudeAI(amplitude=amp, config=AIConfig(content_mode=ContentMode.METADATA_ONLY))
```

### `customer_enriched`

The customer runs their own classification pipeline and provides structured labels. No raw content is sent.

| Data Category | Included | Notes |
|---|---|---|
| Message text | No | |
| Token counts | Yes | |
| Latency / TTFB | Yes | |
| Cost (USD) | Yes | |
| Model name / provider | Yes | |
| Reasoning content | No | Only `[Agent] Has Reasoning` boolean |
| Customer classifications | Yes | Via `SessionEnrichments` |

```python
ai = AmplitudeAI(
    amplitude=amp,
    config=AIConfig(content_mode=ContentMode.CUSTOMER_ENRICHED),
)

# Customer provides their own classifications
ai.track_session_enrichment(
    user_id="user-1",
    session_id="sess-1",
    enrichments=SessionEnrichments(
        topic_classifications={"intent": TopicClassification(l1="billing")},
    ),
)
```

## PII Redaction

When `redact_pii=True` and `content_mode="full"`, the SDK scrubs common PII patterns from all text content before it leaves the process.

### Built-in Patterns

| Pattern | Replacement | Example |
|---|---|---|
| Email addresses | `[email]` | `user@example.com` → `[email]` |
| US phone numbers | `[phone]` | `(555) 123-4567` → `[phone]` |
| Credit card numbers | `[credit_card]` | `4111-1111-1111-1111` → `[credit_card]` |
| Social Security Numbers | `[ssn]` | `123-45-6789` → `[ssn]` |
| Base64 data URLs | `[base64 image redacted]` | `data:image/png;base64,...` → `[base64 image redacted]` |
| Raw base64 strings | `[base64 image redacted]` | Long base64 blobs → `[base64 image redacted]` |

### Custom Patterns

Add organization-specific patterns:

```python
ai = AmplitudeAI(
    amplitude=amp,
    config=AIConfig(
        redact_pii=True,
        custom_redaction_patterns=[
            r"MRN-\d{8}",          # Medical record numbers
            r"ACCT-[A-Z0-9]{12}",  # Internal account IDs
        ],
    ),
)
```

### Scope

PII redaction is applied to:
- User message content
- AI response content
- Reasoning / thinking content
- Tool inputs and outputs
- Score comments

PII redaction is NOT applied to (these are operational metadata, not content):
- Model names and provider identifiers
- Token counts, latency, and cost metrics
- Session IDs, trace IDs, message IDs
- Agent IDs and component types

## GDPR Compliance Mapping

| GDPR Principle | SDK Feature | Configuration |
|---|---|---|
| **Data minimization** (Art. 5(1)(c)) | `metadata_only` mode sends zero content | `content_mode=ContentMode.METADATA_ONLY` |
| **Purpose limitation** (Art. 5(1)(b)) | Events are strictly operational (LLM observability) | N/A — architectural |
| **Pseudonymization** (Art. 4(5)) | PII redaction scrubs personal data from content | `redact_pii=True` with `content_mode=ContentMode.FULL` |
| **Right to erasure** (Art. 17) | Amplitude platform provides user deletion API | Use Amplitude's [User Privacy API](https://www.docs.developers.amplitude.com/analytics/apis/user-privacy-api/) |
| **Data residency** | EU data center routing | `amplitude.configuration.server_zone = "EU"` |
| **Lawful basis** | Legitimate interest for operational metrics (metadata_only) | Legal team decision |
| **Data protection by design** (Art. 25) | Privacy controls applied client-side before transmission | All modes |

## HIPAA Compliance Mapping

| HIPAA Rule | SDK Feature | Configuration |
|---|---|---|
| **Minimum Necessary Standard** | `metadata_only` mode — zero PHI transmitted | `content_mode=ContentMode.METADATA_ONLY` |
| **PHI safeguards** | PII redaction removes identifying information | `redact_pii=True` with custom patterns for PHI |
| **Business Associate Agreement** | Required between customer and Amplitude | Contact Amplitude sales for BAA |
| **Audit controls** | Per-event delivery callbacks for audit logging | `on_event_callback` in `AIConfig` |
| **Encryption in transit** | Amplitude SDK uses HTTPS for all transmissions | Default — no configuration needed |

**Recommended HIPAA configuration:**

```python
ai = AmplitudeAI(
    amplitude=amp,
    config=AIConfig(
        content_mode=ContentMode.METADATA_ONLY,  # No PHI transmitted
        on_event_callback=my_audit_logger,        # Audit trail
    ),
)
```

For use cases that require content analysis with PHI present, use `customer_enriched` mode: run classification in your own HIPAA-compliant environment, then send only the labels to Amplitude.

## SOC2 Compliance Mapping

| SOC2 Control | SDK Feature | Details |
|---|---|---|
| **CC6.1 — Encryption** | HTTPS transport | Amplitude SDK enforces TLS for all API calls |
| **CC6.3 — Access controls** | API key scoping | Each project has its own API key; events are isolated |
| **CC7.2 — Monitoring** | Per-event callbacks | `on_event_callback` provides real-time delivery status |
| **CC8.1 — Change management** | Versioned SDK | `[Agent] SDK Version` property on every event |
| **CC6.7 — Data classification** | Privacy tiers | `content_mode` controls data sensitivity level |

## Per-Event Delivery Callbacks

For audit logging and compliance monitoring, the SDK supports a callback on every event:

```python
def audit_callback(event, status_code, message):
    """Log every event for compliance audit trail."""
    audit_log.info(
        f"Event: {event.event_type}, "
        f"User: {event.user_id}, "
        f"Status: {status_code}, "
        f"Message: {message}"
    )

ai = AmplitudeAI(
    amplitude=amp,
    config=AIConfig(on_event_callback=audit_callback),
)
```

The callback fires for both successful deliveries (`status_code=200`) and failures, providing a complete audit trail.

## Reasoning Content Privacy

Models with extended thinking (OpenAI o-series, Anthropic Claude with extended thinking, Google Gemini with thinking) produce internal chain-of-thought content. This content receives the same privacy treatment as message content:

| Mode | Reasoning behavior |
|---|---|
| `full` | Raw text included, truncated at 10,000 characters |
| `metadata_only` | Only `[Agent] Has Reasoning = true` boolean |
| `customer_enriched` | Only `[Agent] Has Reasoning = true` boolean |

Reasoning tokens (`[Agent] Reasoning Tokens`) are always included regardless of privacy tier, as they are operational metrics, not content.

## Score / Feedback Privacy

User feedback tracked via `score()` follows the same privacy tiers:

- `full`: Comment text is included as `[Agent] Comment`
- `metadata_only` / `customer_enriched`: Comment is omitted; score name and numeric value are always included (they are metadata, not content)

## Security Properties

| Property | Details |
|---|---|
| **No direct network access** | The SDK delegates all I/O to the customer's `Amplitude` instance |
| **No persistent storage** | The SDK holds no state on disk; events are queued in-memory by the Amplitude SDK |
| **No third-party dependencies for privacy** | All redaction and hashing is implemented in pure Python (hashlib, re) |
| **Client-side enforcement** | Privacy controls execute in the customer's process before any data is transmitted |
| **Deterministic behavior** | Same input + same config = same output. No probabilistic redaction. |
