Compliances
A compliance declares how a field must be handled — at rest, on read, in logs, in exports and in indexes.
fields: - name: national_id type: string compliances: [pii]That single tag is not a label. It applies a protection bundle.
Classify, and the defaults follow
Section titled “Classify, and the defaults follow”Tagging a field with a classification — pii, phi, pci or gdpr — automatically applies:
| Dimension | Default | Why |
|---|---|---|
| At rest | encrypted | Ciphertext in the column |
| On read | mask | Output shows a masked representation |
| Logs | nolog | The value never enters a log line |
| Exports | noexport | Never appears in a schema or data export |
| Indexes | noindex | Only when encrypted or tokenized — a plaintext index over ciphertext would defeat the encryption |
The reasoning is worth stating plainly: a schema author should not be able to leave regulated data unprotected by forgetting a directive. Classification is the thing people remember; the bundle is what they forget.
Overriding a default
Section titled “Overriding a default”Each dimension is applied only if you have not already expressed a conflicting directive for that dimension. The dimensions are independent, so overriding one leaves the rest in place.
| Dimension | Directives (mutually exclusive) |
|---|---|
| On read | mask · redact · hidden |
| At rest | encrypted · tokenize · hash |
compliances: [pii, redact] # redacted on read, still encrypted, nolog, noexportcompliances: [pii, tokenize] # tokenized at rest, still masked on readnolog and noexport are additive. They never conflict with anything, so for a classified
field they always apply — you cannot accidentally turn them off by adding another directive.
The directives
Section titled “The directives”On read
Section titled “On read”| Directive | Effect |
|---|---|
mask | Output shows a masked representation |
redact | Output shows a redaction marker |
hidden | The field is omitted from output entirely |
At rest
Section titled “At rest”| Directive | Effect |
|---|---|
encrypted | Ciphertext in the column |
tokenize | Stored as a token; the value lives elsewhere |
hash | One-way. The original is not recoverable |
Always additive
Section titled “Always additive”| Directive | Effect |
|---|---|
nolog | Never enters a log line |
noexport | Never appears in a schema or data export |
noindex | No index is emitted over the column |
Classifications
Section titled “Classifications”| Directive | Means |
|---|---|
pii | Personally identifiable information |
phi | Protected health information |
pci | Payment card data |
gdpr | In scope for GDPR |
| Directive | Effect |
|---|---|
searchable | See below |
retention | Marks the field for the retention runner. Parsed here, enforced there |
Keeping a classified field searchable
Section titled “Keeping a classified field searchable”Encryption and querying pull in opposite directions. An encrypted email column cannot be looked up by value.
searchable is the escape hatch: it suppresses default encryption for a classified field that
must remain queryable.
- name: email type: string compliances: [pii, searchable]Mask, nolog and noexport still apply. The value is still masked on read, still kept out of logs
and exports — only the at-rest encryption is dropped, and only because you asked.
One resolution point
Section titled “One resolution point”Everything that needs a field’s posture goes through the same resolution: read masking, at-rest encryption on both write and read, the schema exporters, and the index emitter during migration.
That matters because it is the only way the policy stays coherent. If masking resolved compliances differently from export, a field could be masked in an API response and plain in a CSV — which is exactly the failure this design exists to prevent.
A deployment without keys
Section titled “A deployment without keys”Default encryption is a no-op at runtime when no key provider is configured — the encrypting hook skips.
That keeps the policy from breaking a deployment that has not set up keys yet. It also means a
classified field can be sitting in plaintext while the schema says encrypted, so verify key
configuration before treating classification as protection.
Compliance versus transform
Section titled “Compliance versus transform”They are easy to confuse and do different jobs.
| Compliance | Transform | |
|---|---|---|
| Governs | Who may see the value | What the value is |
| Applied | At read, write, export and index, per policy | On write, in declared order |
hash | Protection policy — a bundle dimension | A function that rewrites the stored value |
| Reversible | encrypted and tokenize are | Only if the function is |
A masked field still stores the real value. A mask_partial transform changes what is stored. Reach
for the compliance when the requirement is about access, and the transform when it is about content.
See also
Section titled “See also”- Field protection — how masking and encryption behave at runtime
- Transforms — normalising content
- Retention — what
retentionfeeds - Row-level security — restricting rows rather than fields