Reference

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:

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.

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.

What the vault holds

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.

← Back to the vault