# PII Inventory

Owner: trust & safety team Last reviewed: 2026-07-20

Tables in the V1 Postgres clusters that hold personally identifiable information
(PII), organised by domain. This doc is the source of truth for:

- GDPR data-subject-access-request (DSAR) fulfilment — see
  [gdpr-endpoints.md](gdpr-endpoints.md) for the per-domain export endpoint.
- GDPR deletion fulfilment — same registry, deletion column.
- Data-retention sweepers — see
  [../operations/log-retention.md](../operations/log-retention.md).
- Encryption-at-rest review — every row should map to a known encryption posture
  (TDE / column-level / application-level).

## PII categories

| Code      | Category                                                 | Sensitivity |
| --------- | -------------------------------------------------------- | ----------- |
| `IDENT`   | Name, email, phone, address                              | High        |
| `AUTHN`   | Password hash, MFA secret, recovery codes                | Critical    |
| `SESS`    | Session tokens, refresh tokens                           | Critical    |
| `PAY`     | Billing details, payment method ids, transaction history | Critical    |
| `BIO`     | Biometric data (voice prints, face embeddings)           | Critical    |
| `LOC`     | Geolocation samples                                      | High        |
| `BHV`     | Behavioural / interaction logs                           | Medium      |
| `CONTENT` | User-generated text, images, recordings                  | Medium      |
| `CONSENT` | Consent records (immutable audit)                        | Medium      |

## Inventory by domain

### yemaya (identity)

| Table                 | PII                  | Encryption                   | Retention                     | Notes                   |
| --------------------- | -------------------- | ---------------------------- | ----------------------------- | ----------------------- |
| `users`               | IDENT, AUTHN         | TDE + column-level for AUTHN | Lifetime + 90 d post-deletion | Canonical user table    |
| `sessions`            | SESS                 | TDE                          | 30 d                          | Auto-purged by sweeper  |
| `audit_logs`          | BHV, IDENT (by ref)  | TDE                          | 90 d hot, 7 yr cold           | See log-retention.md    |
| `email_verifications` | IDENT                | TDE                          | 7 d                           | Short-lived             |
| `oauth_links`         | IDENT (provider sub) | TDE                          | Lifetime + 90 d               | Linked OAuth identities |

### iris (assistant)

| Table               | PII                     | Encryption             | Retention                   | Notes                  |
| ------------------- | ----------------------- | ---------------------- | --------------------------- | ---------------------- |
| `iris_auth_user`    | IDENT, AUTHN            | TDE + column for AUTHN | Lifetime + 90 d             | iris/api auth surface  |
| `consent_records`   | CONSENT, IDENT (by ref) | TDE                    | 7 yr (audit)                | Immutable; GDPR Art 30 |
| `continuity_states` | BHV, CONTENT            | TDE                    | Per consent (24 h to 12 mo) | User-controlled        |
| `memory_scopes`     | CONTENT                 | TDE                    | Per consent                 | User-controlled        |

### lilith (creator platform)

| Table                            | PII     | Encryption                     | Retention                  | Notes                              |
| -------------------------------- | ------- | ------------------------------ | -------------------------- | ---------------------------------- |
| `auth_tokens`                    | SESS    | TDE                            | 30 d                       | Sweeper purges                     |
| `oauth_state_tokens` (in-memory) | SESS    | Process memory                 | 10 min                     | Bounded Map; capped at 10k entries |
| `personas`                       | CONTENT | TDE                            | Per consent                |                                    |
| `voice_profiles`                 | BIO     | TDE + column-level             | Per consent (90 d default) | Voice clone consent required       |
| `payment_methods`                | PAY     | TDE + column-level (PCI scope) | Per consent                | Stored via PSP token, never raw    |

### aphrodite (creator monetisation)

| Table             | PII       | Encryption | Retention                | Notes                                  |
| ----------------- | --------- | ---------- | ------------------------ | -------------------------------------- |
| `transactions`    | PAY       | TDE        | 10 yr (PCI / tax)        | Immutable                              |
| `payouts`         | PAY       | TDE        | 10 yr                    | Immutable                              |
| `viewer_sessions` | SESS, LOC | TDE        | 30 d                     | Region-derived only, no precise coords |
| `chat_messages`   | CONTENT   | TDE        | Per consent / per stream | Moderation pulls historical            |

### tara (meditation)

| Table                 | PII                    | Encryption | Retention       | Notes                       |
| --------------------- | ---------------------- | ---------- | --------------- | --------------------------- |
| `users`               | IDENT                  | TDE        | Lifetime + 90 d |                             |
| `ritual_sessions`     | BHV, BIO (HRV samples) | TDE        | Per consent     | Biometric capture is opt-in |
| `continuation_states` | BHV                    | TDE        | Per consent     |                             |

### oshun BFF (customer continuity and internal governance)

| Logical partition                                             | PII                          | Encryption                 | Retention                     | Notes                                                                                                                                                                                                                                                                                             |
| ------------------------------------------------------------- | ---------------------------- | -------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `admin_store_snapshots:tutor-session-memories`                | BHV, CONTENT                 | PostgreSQL at-rest control | 30 d from session activity    | Exact-owner `continuity_state` export; coupled memory/mastery/diffs; signed erasure + fence                                                                                                                                                                                                       |
| `admin_store_snapshots:metis-ingest-jobs`                     | BHV, CONTENT                 | PostgreSQL at-rest control | Active account lifecycle      | Raw pasted text excluded; minimized URL/PDF reference; `saved_claim_passage` export/erasure                                                                                                                                                                                                       |
| `admin_store_snapshots:themis-moderation-appeals`             | BHV, CONTENT, IDENT (by ref) | PostgreSQL at-rest control | 5 yr after subject redaction  | Customer-exportable `support_case`; appellant evidence plus operator outcome; subject pseudonymization removes narratives and exact appeal/action/statement identifiers; legal-hold aware                                                                                                         |
| `admin_store_snapshots:dsa-decisions`                         | BHV, CONTENT, IDENT (by ref) | PostgreSQL at-rest control | 7 yr after subject redaction  | Internal, non-exportable `review_package`; statement and appeal narratives are redacted; Themis outcome projection is replayable before erasure; legal-hold aware                                                                                                                                 |
| `admin_store_snapshots:operator-incidents`                    | BHV, CONTENT, IDENT (by ref) | PostgreSQL at-rest control | 7 yr after operator redaction | Internal, non-exportable `review_package`; exact lifecycle actors/acknowledgements are pseudonymized, authored detail and exact assignee references are removed, and the retained pseudonym is irreversibly unlinked after hold-aware expiry. The catalog and assignee labels are fixture-backed. |
| `admin_store_snapshots:citation-drift-resolutions`            | BHV, CONTENT, IDENT (by ref) | PostgreSQL at-rest control | 7 yr after operator redaction | Internal, non-exportable `review_package`; terminal decision identity and rationale are pseudonymized/redacted, audit correlation is removed, and a pending cross-store decision is reconciled against the incident authority before erasure. Strict schema v1; legal-hold aware.                 |
| `admin_store_snapshots:citation-drift-source-classifications` | BHV, CONTENT, IDENT (by ref) | PostgreSQL at-rest control | 7 yr after operator redaction | Internal, non-exportable `review_package`; exact source-reviewer identity is pseudonymized, authored rationale and audit correlation are removed, and a persistent subject fence prevents recreation. Strict schema v1; legal-hold aware.                                                         |
| `admin_store_snapshots:metis-byom-decisions`                  | BHV, CONTENT, IDENT (by ref) | PostgreSQL at-rest control | 7 yr after operator redaction | Internal, non-exportable `review_package`; exact-operator pseudonymization and rationale removal; legal-hold aware. No source-to-learner ownership mapping is persisted.                                                                                                                          |
| `admin_store_snapshots:operator-inbox-decisions`              | BHV, CONTENT, IDENT (by ref) | PostgreSQL at-rest control | 7 yr after operator redaction | Internal, non-exportable `review_package`; exact-reviewer pseudonymization; rationale and authored assignment removed; exact assignee-value matches scrubbed; legal-hold aware. The free-form assignee label is not an authoritative account mapping.                                             |

### veritas (newsroom)

| Table                  | PII                 | Encryption | Retention            | Notes                   |
| ---------------------- | ------------------- | ---------- | -------------------- | ----------------------- |
| `journalists`          | IDENT               | TDE        | Lifetime + 90 d      | Staff users             |
| `editorial_audit_logs` | BHV, IDENT (by ref) | TDE        | 365 d hot, 7 yr cold | Privileged-user actions |

### maat (executive dashboard)

| Table        | PII   | Encryption | Retention            | Notes                   |
| ------------ | ----- | ---------- | -------------------- | ----------------------- |
| `users`      | IDENT | TDE        | Lifetime + 90 d      | Board / executive users |
| `audit_logs` | BHV   | TDE        | 365 d hot, 7 yr cold | All admin actions       |

## What's NOT PII

For clarity:

- Service-to-service API keys → secrets, not PII (managed in Secrets Manager).
- Random correlation IDs → not PII.
- Aggregated metrics → not PII as long as the aggregation level is documented in
  the SLO doc.

## Adding new PII columns

When a new column holds PII:

1. Add it to the relevant table row above.
2. Pick the encryption posture from the column above.
3. Pick the retention from the matrix in
   [../operations/log-retention.md](../operations/log-retention.md).
4. Update [gdpr-endpoints.md](gdpr-endpoints.md) if the column needs to flow
   into export / deletion.
5. If the column is biometric, payment, or auth-credential, get sign-off from
   the trust & safety team.
