Per-project and per-folder key separation explained
HIIE doesn't encrypt everything with one shared key. Each project and folder gets its own distinct encryption key, so a key that unlocks one tenant's data can't unlock another's.
How keys are derived
Every key is a 256-bit key derived with PBKDF2 (100,000 iterations, SHA-256) from a single server-only master key (the KEK). The derivation uses the bucket identifier as the salt, in the form hiie:bucket:<bucket>. Because each project and folder has a different bucket id, each one ends up with a different derived key.
Why this matters
With per-bucket key separation, one tenant's ciphertext cannot be decrypted with another tenant's key. Even if data from two projects were somehow mixed, the wrong key simply won't decrypt the wrong bucket.
Bucket binding as an extra check
Key separation is reinforced by AES-GCM additional authenticated data (AAD): the bucket id is bound into each encryption operation. Decryption throws an error if the bucket (AAD) or the key doesn't match, so cross-bucket reads fail rather than returning garbled or unintended data.
What lives in separate buckets
Project content is scoped to project/folder buckets. Account-level credentials, such as your bring-your-own provider keys, live in a separate account-scoped Vault bucket. Each bucket gets its own derived key under the same KEK.
This design means the security boundary isn't just a database query filter — it's enforced cryptographically at the key level. For more on the trust model, see the article on what "operator-decryptable" means.