Skip to content
Get early access

Entry types and masking

Every entry has a key, a value, an optional note, and one of three types.

Type Rendering For
secret masked API keys, passwords, tokens. The default
url masked connection strings — they usually embed credentials
env shown non-sensitive config: LOG_LEVEL=debug, FEATURE_FLAG=on

The vocabulary is closed. Three types cover the actual distinction that matters — should this be visible on screen by default — and an open taxonomy would just become a tagging system nobody maintains.

This is the important thing on this page.

A masked value is masked on screen. It is not more encrypted, not stored differently, and not withheld from anyone who has access to the environment. If you can read the environment, you can read every value in it, whatever its type.

What masking protects against is the mundane and real: someone glancing at your screen, a screen share you forgot was running, a screenshot in a bug report. That is a genuine class of leak and worth defaulting against — but it is a display posture, and calling it security would be a lie.

Concretely: env-typed entries render unmasked because they are not secrets. That changes nothing about how the value is stored, transmitted, or handled in memory.

The note field is treated like a value: masked, revealed only on request, and never fetched in bulk. People put “this is the read-replica, the primary is in the other project” in notes — and also, sometimes, half a credential. Treating notes as non-sensitive because they’re “just documentation” would be exactly the wrong assumption.

The type lives inside the encrypted payload, which means anyone with a write grant can change it. Re-typing an entry from secret to env would make it render unmasked on your screen at your next pull.

They learn nothing by doing this — a write grant already means they can read every value. The hazard is control over what your screen shows, which is the shoulder-surf and screen-share class again.

So a key that was re-typed from masked to unmasked by someone else’s change does not silently start showing. It stays masked behind an explicit “re-typed by a collaborator — show?” affordance. A change in display posture becomes a visible event rather than a surprise.

Two honest limits on that:

  • A fresh device is blind to it. With no local history to compare against, the first pull on a new machine renders whatever the payload says. There’s nothing to detect a change relative to.
  • The acknowledgement is session-only. It doesn’t persist across a restart yet, because the local file format is frozen at v1 and adding a slot is a format change.

Both are listed in the threat model.

Values can be multi-line — a PEM key, a JSON service-account blob. They’re summarised in the table rather than expanded, so one certificate doesn’t push everything else off screen.

Limits: 1 MiB per value, 4,096 bytes per note, 1,024 bytes per key, 10,000 entries per environment. Values must be valid UTF-8; a binary file is not an environment variable, and the refusal is immediate rather than a corrupted value later.

Keys are normalised toward SCREAMING_SNAKE_CASE with an advisory prompt rather than a hard rule — it is a convention, not a requirement, and some tools genuinely want lowercase.

Duplicate keys within an environment are refused outright. Two entries with the same name is an ambiguity with no good resolution.