PII Handling¶
Overview¶
Floh provides field-level encryption at rest for Personally Identifiable Information (PII) stored in user profiles. This ensures that PII is protected even if the database is compromised.
What Is Encrypted¶
Standard PII Fields¶
The following user profile columns are individually encrypted using AES-256-GCM:
phone_numberemployee_id
Each value is stored in the format iv:authTag:ciphertext using the shared encryptValue utility from packages/server/src/shared/encryption.ts.
Custom PII Attributes¶
Profile attribute definitions can be marked as PII (is_pii = true). All PII-flagged custom attributes are:
- Serialized into a single JSON blob
- Encrypted as one AES-256-GCM ciphertext
- Stored in the
pii_attributestext column onuser_profile
Non-PII custom attributes remain as queryable, indexable plaintext JSONB in custom_attributes.
Encryption Key¶
PII encryption uses the same key as connector secrets and workflow variables:
- Environment variable:
CONNECTOR_ENCRYPTION_KEY(64-character hex string representing a 256-bit key) - Key rotation: supported via
CONNECTOR_ENCRYPTION_KEY_PREVIOUSfor gradual re-encryption
See Encryption Keys for key management details.
Access Control¶
Permission: user:read_pii¶
A dedicated permission controls PII visibility in API responses:
Has user:read_pii |
Behavior |
|---|---|
| Yes | PII fields are decrypted and returned in plaintext |
| No | PII fields return "********" (SECRET_MASK) |
By default, only the admin role includes user:read_pii.
Audit Logging¶
Every API request that returns decrypted PII is logged via the AuditService:
- Action:
user.pii_accessed - Entity:
user_profile - Entity ID: the user's ID
- Actor: the requesting user's display name and ID
- IP Address: the request origin
Workflow Context¶
Workflow variables have full access to profile data including PII fields (decrypted in-memory). Workflows are trusted execution contexts — PII is available through:
{{user.profile.phoneNumber}}
{{user.profile.employeeId}}
{{user.profile.customAttributes.<pii_field>}}
The profile_update step type can write to both PII and non-PII fields.
Logging Safety¶
PII values must never appear in logs. The existing logging safety rules apply:
- Never log raw profile field values
- Never log decrypted PII blob contents
- Log only sanitized metadata (field names, user IDs, operation types)