Concepts

Core concepts behind SikkerKey's security model.

Vault

Your vault is your account's encrypted secrets storage. Each user gets a unique vault ID (e.g. vault_a1b2c3d4e5f6g7h8) that machines use to identify which vault they belong to. A machine can be registered with multiple vaults, each with its own keypair and identity.

Projects

Projects group secrets and machines into logical environments. A project might represent:

  • An environment: production, staging, development
  • A service: payment-api, auth-service
  • A team: backend, infrastructure

Each project has its own independent encryption key. Secrets belong to exactly one project. Machines can be added to multiple projects, but their secret access is still per-secret within each project.

Secret Types

SikkerKey has four secret types.

Secrets

A single encrypted value with a name. API keys, passwords, connection strings, tokens. Read with getSecret(). Optionally enable automatic rotation so SikkerKey generates a new value on a schedule.

Structured Secrets

Multiple named fields encrypted as a single blob (e.g. host, username, password). Individual fields can be read via getFields() or getField() without parsing the full value:

creds = sk.get_fields("sk_db_prod")
host = creds["host"]
password = creds["password"]

Optionally enable automatic rotation on a per-field basis. You choose which fields rotate (e.g. password) and which stay static (e.g. host, username).

Managed Secrets

Database credentials that SikkerKey rotates on a schedule and pushes to your database automatically. Always structured with username and password fields. A CLI agent runs locally next to your database, monitors for rotations, and applies the new password via the appropriate SQL command (e.g. ALTER ROLE for PostgreSQL). The database is never exposed to the internet.

TTL Secrets

One-time self-destructing secrets for sharing credentials with people who don't have access to your vault. You paste or generate a value, set a self-destruct timer (1 minute to 24 hours), and get a link plus a passphrase. The recipient opens the link, enters the passphrase, and sees the secret. It's then permanently destroyed. A wrong passphrase also destroys it immediately. TTL secrets are encrypted with AES-256-GCM at rest, the passphrase is hashed with Argon2id, and machines cannot access them. They exist for human-to-human credential handoff, not programmatic access.

Encryption

SikkerKey uses envelope encryption with three layers:

  1. Each secret gets a random AES-256-GCM data key
  2. The data key encrypts the secret value, with the secret ID bound as Additional Authenticated Data (AAD)
  3. The project's master key encrypts the data key
  4. Both encrypted blobs are stored

The AAD binding means an encrypted value cannot be swapped between secrets. Decryption fails if the secret ID doesn't match.

Every change creates a new version. Previous versions are preserved for rollback, subject to your plan's version retention limit.

Automatic Rotation

Any secret or structured secret can optionally have automatic rotation enabled. You configure:

  • Interval: how often to rotate (minimum 5 minutes)
  • Length: generated value length (default 32)
  • Charset: symbols (default), alphanumeric, numbers, or uuid
  • Fields (structured secrets only): which fields rotate, others stay static

Secrets with active rotation cannot be manually replaced or rotated. Each rotation creates a new version.

Managed secrets always have rotation enabled.

Soft Delete

Deleted secrets are moved to trash and remain recoverable for 30 days. After 30 days, the secret and all its version history are permanently deleted. Machine access grants and rotation schedules are removed immediately on deletion.

Machines

A machine is any server, container, or process that needs to read secrets. During bootstrap:

  1. The machine generates an Ed25519 keypair locally
  2. The public key is sent to SikkerKey
  3. The private key stays on the machine at ~/.sikkerkey/vaults/{vaultId}/private.pem

The private key is never transmitted. SikkerKey only stores the public key.

Newly registered machines start as pending. They cannot authenticate until the vault owner approves them from the dashboard. Machines can be disabled at any time, immediately revoking their ability to authenticate.

Machine Authentication

Every request is signed with the machine's private key. No tokens, no API keys, no sessions.

HeaderPurpose
X-Machine-IdIdentifies the machine
X-TimestampPrevents replay (5-minute window)
X-NonceSingle-use, prevents duplicate requests
X-SignatureEd25519 signature of method:path:timestamp:nonce:bodyHash

The server verifies:

  1. Lockout: 3 failed attempts from the same IP within 5 minutes triggers a 30-minute lockout
  2. Machine status: must be approved and enabled
  3. Signature: verified against the stored public key
  4. Timestamp: must be within 5 minutes of server time
  5. Nonce: must not have been used before (tracked in the database, survives restarts)
  6. Account status: the vault owner's account must be active

An intercepted request is useless. The timestamp expires, the nonce is consumed, and the signature can't be forged without the private key.

Access Requirements

For a machine to read a single secret, all of the following must be true:

  1. Valid Ed25519 signature with a fresh nonce
  2. Machine is approved and enabled
  3. Vault owner's account is active
  4. Machine is added to the project containing the secret
  5. Machine has an explicit grant to that specific secret

There is no wildcard access, no "grant all", no inheritance. Each machine-to-secret relationship is explicit.

Teams

Vault owners can invite other SikkerKey users by email. When the invite is accepted, the user becomes a team member of that vault.

Secret Access

Adding a team member to a project gives them full secret management within that project: view metadata, create, delete, replace, version history, and notes. There are no granular secret-level permissions. Project membership is the access boundary.

Important: "view" means secret metadata (name, note, version, machine count). The dashboard never displays decrypted secret values. Reading the actual plaintext always requires an authenticated machine with an explicit per-secret grant.

A team member can only see the projects they've been added to. Each project's encryption is independent, so access to one project reveals nothing about another.

Machine Permissions

Machine permissions are separate and must be explicitly granted per project:

PermissionAllows
machine_viewSee machines in the project
machine_addAdd their own machines to the project
machine_removeRemove machines from the project
machine_configureChange which secrets a machine can access

A team member with no machine permissions can still fully manage secrets in their assigned projects.

Suspension

When a vault owner's account is suspended, all access to that vault is blocked immediately. Team members cannot access the vault's projects or secrets. Machine authentication is blocked. Team members are not informed of the suspension reason.

Audit Log

Every action is recorded in an append-only audit log with a severity level:

SeverityExamples
CriticalAuth failures, project deletions, 2FA disabled, vault destroyed
HighMachine registrations, secret deletions, permission grants, password changes
MediumProject changes, team invites, agent status changes, sync config deletions
LowMachine approvals, bootstrap tokens
InfoSecret reads, logins, secret creates, sync config reads

Each entry records the user ID, machine ID, secret ID, action, severity, source IP, detail string, and timestamp.

Audit entries are pushed to the dashboard in real time via server-sent events. Email alerts can be configured per-action so you're notified immediately when critical events occur.

Audit log retention is based on your subscription plan and is pruned automatically.