Field-level encryption, in process.
Sensitive telemetry variables are sealed one at a time, in memory, before any line touches disk or a log aggregator. The wire carries ciphertext. Public fields stay readable.
What field-level encryption means here
Field-level encryption seals individual values inside a record rather than the record as a whole. A log entry is a structure with named fields. Some fields are operational and safe to read in the clear, like an event name or a timestamp. Others carry sensitive data, like an email address or a card number. TN encrypts only the sensitive fields, and it does so per field, not per line.
The unit of access is the encryption group. Each sensitive field
is classified into a named group, such as pii or
payments. A group has a set of readers and a key. When
an entry is written, every classified field is sealed to the key of
its group. A reader holding the group key can open the fields in
that group and nothing else. Fields with no classification fall
under the project default, which can treat unclassified values as
sealed until they are assigned a group.
Sealed at the callsite
Encryption happens in the same process that emits the log entry. The library reads the cleartext value already present in memory, wraps it with the active group key, and writes the sealed result. The write path does not involve a network call or an external service. There is no plaintext staging file, no sidecar, and no transit hop where the value sits readable.
Each sealed field is encoded as a JWE envelope. JWE, JSON Web Encryption, is the IETF standard for representing encrypted content as a self-describing JSON structure that names the key and the algorithm used to produce it (RFC 7516). The payload is sealed with AES, the symmetric cipher standardized as FIPS 197. Because the envelope is self-describing, a reader can select the right key and algorithm from the record alone.
Latency added per sealed field is on the order of a few hundred microseconds, depending on group size and recipient count.
The threat the boundary moves
Most log exposure does not happen through a dramatic breach. It happens because cleartext is written first and protected second. Once a sensitive value lands in a line, every system that line flows through inherits the value:
- Log aggregators. A line shipped to a centralized logging platform is now readable by anyone with query access to that platform, which is usually far wider than the set of people allowed to see the underlying value.
- Third-party sinks. Observability vendors, error trackers, and analytics pipelines receive a copy. The value now lives under a second vendor's access model and retention policy, outside your direct control.
- Over-broad internal access. Plaintext in a shared index means any engineer running a search sees production personal data, whether or not their role requires it.
Field-level encryption moves the protection boundary to the point of emission. The value is sealed before it leaves the process, so every downstream system receives ciphertext. An aggregator stores a JWE envelope. A vendor sink ingests a JWE envelope. An internal search returns a JWE envelope. The cleartext never enters those systems, so it cannot be exposed by them.
What is the difference between field-level encryption and redaction?
Redaction removes the value. Field-level encryption keeps it, readable by the parties you choose. A redacted field is gone for everyone, including the auditor or partner who has a legitimate need to read it, and including you. A sealed field is still present in the record as ciphertext. Grant the group key to a reader and the value opens for them; withhold it and the same record shows them only the envelope.
The practical consequence is that redaction forces a choice at write time between keeping data and protecting it. Sealing defers that choice to read time and makes it per reader. One record can be fully legible to a finance reviewer, partly legible to a partner, and opaque to a log aggregator, with no second copy and no second permission system.
A worked example
Take an order event. The order ID is public. The customer email
is classified into the pii group and the card detail
into the payments group. The call site looks the same
as an ordinary log line:
# email -> "pii" group, card_last4 -> "payments" group tn.log("order.placed", order_id=order.id, email=user.email, card_last4=user.card_last4)
Before the line is persisted, the library seals each classified field to its group key. The record on disk keeps the public field in the clear and replaces each sensitive field with a JWE envelope:
// .tn/log/order.placed.ndjson { "event": "order.placed", "ts": "2026-04-29T18:22:14Z", "order_id": "ord_8fKq", "pii": "eyJhbGciOiJBMjU2R0NNS1ciLCJlbmMiOiJBMjU2R0NN...", "payments": "eyJhbGciOiJBMjU2R0NNS1ciLCJlbmMiOiJBMjU2R0NN...", "sig": "ed25519:4mP9R7tYx...kQ2xJ9" }
The order_id stays plaintext for everyone. The
pii and payments values are sealed
envelopes that only the readers of those groups can open. The whole
row is signed, so any reader can prove it came from you even if
they cannot read every field.
Why compliance frameworks care
Several obligations turn on where sensitive data sits in the clear and who can reach it. Sealing values at the source maps directly onto those obligations.
- PCI DSS v4.0 Requirement 3. The standard requires that stored account data be protected, and it treats strong cryptography rendering data unreadable as the core control for primary account number storage. Sealing payment fields into a JWE envelope before they are written means the stored form is ciphertext, not cleartext. See the PCI SSC document library.
- GDPR Article 32. Security of processing names encryption of personal data as an appropriate technical measure. Per-field sealing applies that measure to the exact values that are personal data and leaves the rest readable (Article 32).
- Data minimization, GDPR Article 5. Minimization is about who can reach what, not only what you collect. A field that is sealed to a named group is not exposed to readers outside that group, so an aggregator or a broad internal search reaches only ciphertext.
Rotation and recovery
Each group has a current key and a stack of retired keys. A rotation generates a new current key and distributes it to the remaining readers in the group.
New entries encrypt to the current key. Past entries continue to decrypt with the key that was active when they were written, identified by a key ID embedded in the envelope. A reader removed from a group retains access to entries written while they were a member, but not to entries written after the rotation.
Where the vault sits
The vault stores group keys wrapped with the local unlock secret. Restoring on a different machine downloads the wrapped bundle and unwraps it with the same secret, after which the library has full access to the local keystore.
The TN library reads and writes from the local keystore directly. Vault sync runs as a background process and is not on the critical path for logging. The library continues to operate if the vault is unreachable.
In process
Wrapping happens in the same process that emits the line.
Per reader
Each authorized reader holds their own unwrap key.
Per group
Groups rotate together. One command, one new key, fresh ciphertext from there on.
The hosted vault stores encrypted key backups, encrypted by your local unlock secret. Your logs and your cleartext stay in your process. The vault is a backup.