# Advanced — CSFLE and Queryable Encryption **Capabilities:** `MongoCapability.CSFLE`, `MongoCapability.QUERYABLE_ENCRYPTION` **Properties:** `ca-skeleton.persistence-mongo.advanced.csfle.enabled`, `ca-skeleton.persistence-mongo.advanced.queryable-encryption.enabled` **Status:** Advanced. ## Requirements | | | |---|---| | Topology | Replica set or sharded cluster. | | Server | MongoDB 7.0 or 8.0 (see §4 for the 8.0 query-type limits). | | Privilege | `MongoPrincipalRole.ENCRYPTION_ADMIN` for the key vault; the application role never holds it. | | Environment | A real KMS and key vault. A local key provider does not exercise any of the failure modes that matter. | ## 1. CSFLE `MongoCsfleProfile` binds a collection to its `MongoCsfleFieldPolicy` list, a key vault `MongoCredentialReference` and the key vault namespace. `MongoCsfleClientFactory` builds the encrypted client; `MongoDataKeyResolver` resolves data keys. `MongoCsfleMode`: | Mode | Queryable | Trade-off | |---|---|---| | `RANDOMIZED` | no | Same plaintext encrypts differently each time. The safe default. | | `DETERMINISTIC` | equality only | Same plaintext always yields the same ciphertext, so equality works — and so does frequency analysis. | | `UNINDEXED` | no | Stored encrypted, excluded from any index. | `MongoCsfleFieldPolicy.forPii(field, queryable)` defaults to `RANDOMIZED` when the field is not queried. Deterministic encryption requires a written `equalityQueryJustification`; the constructor refuses a blank one, naming frequency analysis. A low-cardinality deterministic field (a status, a country, a boolean) leaks its distribution to anyone who can read the collection, which is the party encryption was protecting against. ## 2. Queryable Encryption `MongoQueryableEncryptionProfile` binds a collection to `MongoEncryptedFieldDescriptor` entries. `MongoQueryableEncryptionQueryType` has exactly two values: - `EQUALITY` - `RANGE` — must declare its domain (`min`, `max`). The constructor refuses a range field without one, because changing the domain later means re-encrypting the field. `MongoQueryableEncryptionCollectionManager` owns the collection's lifecycle, because a QE collection is not just a collection: it carries metadata collections. ## 3. Metadata ownership `MongoEncryptionMetadataOwnership` maps `customers` to `enxcol_.customers.esc` and `enxcol_.customers.ecoc`, and reports `__safeContent__`-prefixed indexes as `MongoMetadataOwnership.ENCRYPTION_MANAGED`. These are never application-owned and never droppable by drift reconciliation. A drift tool that drops `enxcol_.customers.ecoc` corrupts the collection's queryability. This is the single most important integration point between encryption and [ADR-MONGO-004](../../adr/ADR-MONGO-004-index-schema-admin-plane.md). ## 4. Unsupported combinations Refused at declaration, not discovered at runtime: | Combination | Why | |---|---| | CSFLE **and** QE on the same collection | Two incompatible encryption schemes over one namespace. Both profile constructors refuse it. | | CSFLE on a time series collection | `requireNotTimeSeries(true)` raises `MongoOperationRejectedException`. | | QE `prefix` / `suffix` / `substring` | Not available on the platform's 8.0 baseline. The factory methods throw `UnsupportedOperationException` rather than returning a profile that fails later. | | Deterministic CSFLE without a justification | `IllegalArgumentException` naming frequency analysis. | | Range QE without a declared domain | `IllegalArgumentException` naming re-encryption. | ## 5. Failure recovery | Symptom | Cause | Action | |---|---|---| | `MongoEncryptionException` on read | Wrong data key, or the key vault is unreachable | Check KMS reachability and the key vault credential. Data is intact; the client cannot decrypt it. | | `MongoEncryptionException` on write | KMS permission revoked mid-operation | Restore the grant. Writes fail closed — nothing was written in plaintext. | | Queries return nothing on a deterministic field | The field was re-keyed | Equality matching is over ciphertext; a new key produces different ciphertext. Re-encrypt the field. | | QE queries fail after a drift reconciliation | A metadata collection was dropped | Restore from backup. This is why ownership gates drops. | **Key rotation.** Rotating the customer master key re-wraps the data keys and does not require re-encrypting documents. Rotating a *data* key does require re-encrypting every document that used it. These are different operations with different costs, and confusing them is how a rotation becomes an outage. ## 6. Promotion evidence Per [ADR-MONGO-ADV-001](../../adr/ADR-MONGO-ADV-001-capability-promotion.md), promotion requires the real KMS and key vault, plus negative cases that fail closed: wrong key, missing permission, rotation mid-operation (`MongoAtlasCapabilityContractSuite.kmsFailureModes`). A local key provider certifies none of these — it never rejects anything.