Skip to content
varsafe
Esc
navigateopen⌘Jpreview
On this page

Core Concepts

The varsafe mental model — teams, projects, environments, secrets, context resolution, and how injection works.

CLI v7.2.7

Organizational Model

Four things nest, each one inside the one before it: a team owns projects, a project has environments, and an environment holds secrets. Every secret has exactly one home — the same key name in three environments means three separate values under three separate access rules.

Team

acme

Project

api-backend

development

DATABASE_URL
JWT_SECRET
REDIS_URL

staging

DATABASE_URL
JWT_SECRET
REDIS_URL

production

DATABASE_URL
JWT_SECRET
REDIS_URL

Project

web-dashboard

Teams

A team is a group of people who collaborate on the same projects.

  • Teams own projects
  • Teams have members with roles — and a user can belong to multiple teams
  • Access to secrets flows through team membership
  • Billing is managed at the team level
  • Teams on the Team plan can configure SSO (SAML 2.0 / OIDC) for domain-based login

Projects

Each project has:

  • A name (typically matching your repository)
  • An owning team
  • Multiple environments
  • Its own secret history

Environments

Every project has environments for different deployment stages:

Environment Purpose Default Protected
development Local development No
staging Pre-production testing No
production Live systems Yes

You can also create custom environments for specific needs (e.g., qa, demo, feature-x), and protect or unprotect any environment in its settings.

Each environment also has a server-managed keypair used to produce encrypted .env exports — files that are useless to anyone who obtains them without access to your team. The private key is held and KMS-protected by varsafe, not by you, so this is not end-to-end encryption; see the access model.

Secrets

Secrets are key-value pairs stored securely:

  • Key: starts with an uppercase letter, then uppercase letters, digits, and underscores (e.g., DATABASE_URL); up to 255 characters
  • Value: encrypted, up to 64 KB
  • Version: auto-incremented on each change
  • History: full change history with rollback capability

Values are stored, not interpreted

A secret’s value is bytes. varsafe stores what you give it and returns exactly that — it does not expand ${...}, read your shell environment, or substitute anything into a value. A secret whose value is ${DB_PASS} is a secret whose value is the eight characters ${DB_PASS}, forever, on every read.

This matters when secrets hold templates as data: a Grafana dashboard, a Kubernetes manifest, another tool’s config file. Those pass through untouched.

Composed secrets

A secret can opt in to being a pointer instead of a value:

DATABASE_URL = postgres://${DB_USER}:${DB_PASS}@db.internal/app

This is a different kind of secret, marked as such when you create it — never inferred from what the value happens to look like. Rotating DB_PASS changes every secret that references it, so a password lives in one place rather than in every connection string that embeds it. Reads return the resolved value; only an explicit request returns the source.

Secrets created before composition existed are literal, and stayed literal — nothing was reinterpreted. See Composed Secrets.


CLI-First Architecture

varsafe is designed around the CLI workflow:

Under the hood, a single varsafe run does four things:

  1. Authenticate — CLI presents your session token or API token over TLS
  2. Fetch — API retrieves your secrets from the vault, where they are encrypted at rest (vault + KMS)
  3. Return — Secrets travel back to the CLI over TLS
  4. Inject — CLI sets secrets as environment variables in the spawned process — nothing is written to disk

The dashboard exists for management tasks (creating teams, inviting members, viewing audit logs) but the primary developer interaction is through the CLI.


Context Management

Most commands need to know which project and environment you mean. Four sources, checked in order — the first that answers wins.

1

Explicit flags

`-p` and `-e` always win, and never change what is saved.

-p / -e

2

Local .varsafe file

A small context file in your repository, found by searching from the current directory up to the git root.

./.varsafe

3

Global saved context

Set with `varsafe use`, stored in the CLI’s local database.

varsafe use

4

Auto-selection, or a prompt

Selected automatically when only one option exists; otherwise the CLI asks rather than guessing.

interactive

# Set your working context
varsafe use -p my-api -e development

# Now these commands use that context automatically
varsafe list
varsafe run -- npm run dev
varsafe export -o .env

When you run varsafe use inside a git repository, the context is written to a .varsafe file in the repo — teammates and future shells in that repo pick it up automatically. Outside a repository, the context is saved globally.

Override context anytime with flags:

varsafe list -p my-api -e staging

Ephemeral Injection

Secrets are never written to disk by default. Instead, they’re injected directly into your process’s environment:

varsafe run -- npm run dev

Four steps between your keystroke and a running process. On your machine the values live only in process memory — the CLI’s and the child’s — and are never written to disk.

1

Authenticate

The CLI presents its credential to the varsafe API over an encrypted connection.

TLS

2

Fetch

The API reads the secrets for the resolved project and environment — they are encrypted at rest in the vault and decrypted server-side — and returns them over the same encrypted connection.

encrypted at rest

3

Spawn the child

The command after `--` is executed directly with the secrets in its environment — no shell in between, so nothing lands in shell history.

execve

4

Exit with the child

When your process ends the environment goes with it, and `varsafe run` returns the child’s own exit code.

no files

When your app terminates, the secrets are gone — no files left behind.


Access Control Model

Access follows this hierarchy:

Six roles exist: owner, admin, developer, operator, viewer, and billing. Owners and admins manage the team and write everywhere; developers write to non-protected environments; operators and viewers are read-only; billing members manage billing without secret access. The full permissions matrix lives in the roles reference.

API Tokens

Use API tokens instead of user sessions for non-interactive access:

  • CI/CD pipelines — Inject secrets during build and deploy
  • Automation scripts — Scheduled jobs, cron tasks, infrastructure tooling
  • Server-side applications — Backend services that need secrets at startup
  • Development tooling — Custom scripts, internal CLIs, or IDE integrations

Token properties:

  • Scoped to a specific team
  • Prefixed vs_at_ so scanners can recognize them
  • Separate audit trail (shows as a service account)
  • Optional expiration date; revocable at any time

See API tokens for creation and usage.


Version History

Every secret change is tracked. Operation types include:

  • create — New secrets added
  • update — Secret values changed
  • delete — Secrets removed
  • rotate — Secret rotated

Rollback

You can roll back an environment to any previous state via the dashboard:

  1. Go to Secrets → History
  2. Select the operation to roll back
  3. Review the preview showing what will change
  4. Confirm rollback

Audit Trail

Every action is logged. An audit event looks like this (illustrative):

{
  "action": "secret.accessed",
  "actor": "alice@example.com",
  "project": "api-backend",
  "environment": "production",
  "secretKeys": ["DATABASE_URL", "API_KEY"],
  "ip": "192.168.1.100",
  "source": "cli",
  "timestamp": "2026-02-15T10:30:00Z"
}

Audit logs are:

  • Append-only — Events are added, never edited
  • Complete — Every action is logged
  • Queryable — Filter by team, project, actor, or time range
  • Exportable — Download for compliance reviews

Audit retention is plan-gated:

  • Developer plan: 7 days
  • Team plan: 90 days

Session Management

varsafe uses opaque session tokens for authentication:

  • High-entropy tokens generated with secure randomness
  • Hashed before storage — the raw token is never stored server-side
  • Instantly revocable — no waiting for token expiry
  • Session metadata includes IP, user agent, and timestamp

When you revoke a session, it’s immediately invalid everywhere. See the security model for the full picture.