Encryption at rest for the credentials a tenant pastes into the settings screen. Off unless you give it a key.
config :pixelex, secret_key: System.get_env("PIXELEX_SECRET_KEY")Generate one with:
:crypto.strong_rand_bytes(32) |> Base.encode64()Why this exists now and did not before
While credentials only arrived from config :pixelex, sites:, they lived
wherever the host already kept secrets and pixelex never owned them.
Pixelex.Dashboard.Settings changes that: it invites a tenant to paste a
long-lived ad-platform access token into a column pixelex writes. Owning the
write path means owning what the column looks like in a pg_dump.
AES-256-GCM, and the prefix
Ciphertext is stored as pxenc1:<base64(iv <> tag <> ciphertext)>. The
prefix is what makes turning encryption on a no-op migration: a plaintext
value has no prefix, decrypt/1 returns it unchanged, and it becomes
ciphertext the next time it is saved. There is no flag day.
The prefix is also the AAD, so a value cannot be moved between schemes.
A wrong key returns nil, not garbage
If the key is missing or rotated away, decrypt/1 yields nil rather than
the ciphertext. configured?/1 then reads false and the destination goes
quiet, which is the same behaviour as "not set up" — the platform's normal
state. Handing the ciphertext to Meta instead would mean an authenticated
integration that 401s forever while reporting itself as configured.
Summary
Functions
Decrypt a value. Plaintext passes through; an undecryptable value is nil.
True when a key is configured and values will actually be encrypted.
Encrypt a value. Without a key, returns it unchanged.
Is this value stored encrypted?
Functions
Decrypt a value. Plaintext passes through; an undecryptable value is nil.
@spec enabled?() :: boolean()
True when a key is configured and values will actually be encrypted.
Encrypt a value. Without a key, returns it unchanged.
Is this value stored encrypted?