Understanding Selkie

A comprehensive guide to the zero-trust access and secret management platform where the backend never sees your plaintext secrets.

What is Selkie?

Selkie is a zero-trust access management system designed for organizations that grant developers access to multiple infrastructures, platforms, environments, and client systems.

Core Mission

Track who has access to what, with which credentials, since when — while fully isolating secret decryption from server control.

Critical Guarantee

The backend never sees plaintext secrets or user private keys. All decryption happens exclusively client-side.

Key Features

🔐

Client-Side Encryption

All cryptographic operations happen in your browser or CLI

📝

Immutable Versioning

Every change creates a new version for complete audit trails

🔌

Plugin Architecture

Extensible system for SSH, AWS, Kubernetes integrations

👁️

Complete Audit Logs

Every action is logged for forensic analysis

Paranoid Mode

True zero-trust where even admins cannot recover secrets

🔄

Secret Rotation

Track secret age with version history

System Philosophy & Goals

Selkie is built on eleven core principles that guide every design decision:

1. Zero-Knowledge Backend

Secrets stored in the database and processed by the backend must remain encrypted. A full compromise of the database and backend server does not give attackers access to credentials.

2. Immutable Secret Versions

Any change creates a new secret version. Historical versions remain for audit and forensic purposes. This ensures perfect reconstruction of who had access to which secret at any point in time.

3. Flexible Object Model

Selkie models abstract resources called "objects" which carry type information, fields, and secret versions. Types define schemas and optional triggers. Plugins can introduce new types.

4. Cryptographic Access Grants

Users gain access to objects through assignments. Assignments create cryptographic grants for specific secret versions. Revoking assignments removes future access.

5. Plugin-Based External Actions

The base system only manages objects, secrets, and ACLs. All real-world access modifications (SSH authorized_keys, AWS IAM revocation, etc.) are implemented through plugins.

6. Complete Audit Trail

Every access, rotation, assignment, or compromise must be stored as an auditable event. Operators can see the age of secrets, recent rotations, and compromise history.

7. Client-Side Cryptography

Clients (CLI & Web) perform: user keypair generation, DEK generation, secret encryption, DEK wrapping, and secret decryption. The backend never decrypts anything.

8. Schema-Driven Object Types

Different types (SSH access, AWS keys, username/password, etc.) define field and secret schemas using JSONSchema. New types may be added at runtime through plugins.

9. Dual Recovery Modes

Each object individually controls whether its secrets are recoverable or paranoid. Non-paranoid objects can be recovered by administrators via OMK. Paranoid objects are recoverable ONLY by the user — true zero-trust.

10. Secret Age Visibility

Secret version age is displayed prominently. Rotations are encouraged and monitored. Stale secrets must be clearly identifiable.

11. Server-Side Plugin Secrets

Server-side plugins may access specific secrets through an explicit assignment model using a Plugin Master Key (PMK). This enables automation while maintaining zero-trust for user secrets.

High-Level Architecture

Monorepo Structure

Selkie is organized as a monorepo containing all components:

selkie/
├── packages/
│   ├── backend/     # NestJS API server
│   ├── web/         # Next.js web client
│   ├── cli/         # Node.js CLI client
│   └── shared/      # Shared TypeScript types & crypto utilities
├── plugins/         # Server-side plugins
│   ├── ssh-access/
│   ├── aws-iam/
│   └── ...
└── docs/            # Documentation

Component Overview

Backend (NestJS)

  • User management
  • Object creation & storage
  • Secret version management
  • Assignment & access grants
  • Event emission & audit logs
  • Plugin loading & execution
  • Never decrypts anything

Web Client (Next.js)

  • Browser-based secret decryption
  • Object browser & management
  • Assignment UI
  • Audit history viewing
  • Daemon detection for automation
  • Zero-trust operations

CLI Client (Node.js)

  • Command-line secret management
  • Keypair generation
  • Automation & scripting
  • Direct plugin execution
  • Secure token storage

Selkie Daemon (optional)

  • Local background service
  • Bridges Web UI to local operations
  • Executes client-side plugins
  • Maintains keys in memory
  • Localhost-only API

Cryptographic Model

Selkie's cryptographic design separates the user password from the keys that encrypt secrets, creating multiple layers of protection.

Key Components

KEK

Key Encryption Key - Derived from the user's password using Argon2id. Never stored anywhere. Used only to encrypt/decrypt the UMK.

UMK

User Master Key - Random 256-bit key generated for each user. Stored encrypted by KEK. Used to encrypt the user's private key.

A_pub/A_priv

User Keypair - RSA-4096 asymmetric keypair. Private key encrypted with UMK. Public key used by others to wrap DEKs for this user.

DEK

Data Encryption Key - Random 256-bit symmetric key generated per secret version. Encrypts the actual secret using AES-256-GCM.

OMK

Org Master Key - System-wide RSA-4096 keypair. Enables break-glass recovery for non-paranoid objects only. Generated once at system init.

PMK

Plugin Master Key - System-wide keypair for server-side plugin access to designated secrets. Enables automation while keeping user secrets secure.

Secret Decryption Flow

Client-Side Decryption Steps

1

User logs in

Receives encrypted UMK, encrypted private key, and KDF parameters

2

Derive KEK

Client derives KEK from password using Argon2id with stored parameters

3

Decrypt UMK

Use KEK to decrypt the User Master Key

4

Decrypt Private Key

Use UMK to decrypt user's private key (A_priv)

5

Fetch Secret

Receive ciphertext, nonce, and wrapped DEK for user

6

Unwrap DEK

Use private key to decrypt the wrapped DEK

7

Decrypt Secret

Use DEK with AES-256-GCM to decrypt the plaintext secret

Zero-Knowledge Guarantee

The backend never sees: KEK, UMK plaintext, private key plaintext, DEK plaintext, or any secret material. All decryption happens exclusively in the client.

BIP39 Mnemonic Backup

User Recovery

Only the UMK is encoded into the mnemonic backup (not the private key).

Recovery process:

  1. Restore UMK from mnemonic words
  2. Re-encrypt UMK with new password
  3. Fetch encrypted private key from server
  4. Decrypt private key using restored UMK
  5. Regain access to all secrets

OMK Recovery

OMK mnemonic is generated once at system initialization and shown only once to the administrator.

This enables break-glass recovery of non-paranoid objects only. Paranoid objects remain unrecoverable even with OMK.

Security Model

Paranoid vs Non-Paranoid Objects

Each object in Selkie has a paranoid boolean flag that fundamentally changes its security properties:

Non-Paranoid (Default)

  • Uploads wrappedDekForUser
  • Uploads wrappedDekForOMK
  • Recoverable by user via their mnemonic
  • Recoverable by admin via OMK mnemonic
  • Suitable for team credentials

Paranoid Mode

  • Uploads wrappedDekForUser only
  • No OMK-wrapped DEK exists
  • Recoverable ONLY by user
  • Admins cannot recover even with OMK
  • True zero-trust for sensitive secrets

What the Backend Never Sees

KEK (Key Encryption Key)
UMK plaintext
User private keys
DEK plaintext
Plain secret material
User passwords

What the Backend Stores

User public keys
Encrypted private keys
Encrypted UMK
KDF parameters
Ciphertext + AEAD params
Wrapped DEKs per user

Trust Distribution

Complete Trust Isolation

Server-side plugins: Trusted by organization, orchestrate events, limited secret access via PMK

Client-side plugins: Trusted by user, execute with user's decrypted keys locally

Selkie Daemon: Trusted local process, acts as user's agent for automation

Backend: Zero-knowledge, never sees plaintext material, manages encrypted data only

Groups — Organizing Objects

Groups provide a hierarchical structure for organizing objects by client, project, environment, or any logical boundary. Groups enable bulk assignment management and improve user experience when managing large numbers of secrets.

Group Concepts

📁

Hierarchical Organization

Groups can contain objects and other groups, creating nested hierarchies like "Acme Corp → Production → AWS"

🔗

Bulk Assignment

Assign users to groups instead of individual objects for efficient access management

🛡️

Security Preserved

Groups are organizational only — they don't affect the cryptographic model or paranoid settings

📊

Group Statistics

View object counts, stale secrets, and compromised items at the group level

Inheritance Depth

When assigning users to groups, you choose how deep the access extends:

Direct Only

  • Access only to objects directly in this group
  • Does NOT include objects in subgroups
  • Best for limited, specific access
  • User must be assigned to each subgroup separately

Recursive

  • Access to objects in this group AND all subgroups
  • Includes all nested subgroups at any depth
  • Best for broad access to an entire hierarchy
  • Automatically includes future subgroups

Group Assignment Operations

Assigning Users to Groups

When assigning a user to a group, you can optionally grant access to existing objects and secrets:

Group assignment only:Creates the assignment but doesn't grant access to existing secrets. User will get access when secrets are rotated.
Grant access to objects and secrets:Creates assignment AND re-encrypts DEKs for all existing secrets, granting immediate access.

Removing Users from Groups

When removing a user from a group, you choose what to revoke:

Group membership only:Removes group assignment but keeps existing object and secret access intact.
Remove all access:Removes group assignment AND revokes all object assignments and secret access grants in the group scope.

Security Considerations

  • Groups do NOT bypass the cryptographic model — individual SecretAccessGrants are still the source of truth
  • Paranoid objects in groups still require individual user mnemonics for recovery
  • OMK recovery operates at the object level, not group level
  • Group assignments are a convenience layer — actual access is cryptographically enforced per-user

Dual Plugin Architecture

Selkie features a dual plugin architecture: server-side plugins for orchestration and client-side plugins for privileged automation requiring decrypted secrets.

Server-Side Plugins

Backend Plugin Capabilities

  • Define new object types (SSH access, AWS IAM, etc.)
  • Define field and secret schemas
  • Register event handlers for orchestration
  • Access plugin-designated secrets via PMK
  • Never see user secrets directly

Server plugins are loaded from the plugins/ directory and can listen to events like object.assigned,secret.rotated, etc.

Client-Side Plugins

Local Execution Capabilities

  • Add/remove SSH authorized_keys on servers
  • Rotate AWS IAM access keys
  • Manage Kubernetes RBAC entries
  • Call corporate APIs with credentials
  • Any operation requiring plaintext secrets

Client plugins execute on the user's machine where secrets are decrypted, preserving Selkie's core zero-trust model.

Plugin Master Key (PMK)

Server-Side Secret Access

The PMK enables server-side plugins to access specific secrets for automation:

  • Slack webhook URLs for notifications
  • Cloud provider API keys for automation
  • Monitoring service tokens
  • Internal API keys for integrations

Plugin secrets are less secure than user secrets but more secure than .env files — they're encrypted at rest, require explicit assignment, and are fully audited.

Selkie Daemon

Browser-Only Mode

Default experience for most users:

  • Secrets decrypt in browser memory
  • View, copy, rotate, manage secrets
  • Manage assignments
  • View audit history
  • No automation features

Daemon-Enhanced Mode

Power user experience:

  • Web UI detects running daemon
  • Enables privileged automation
  • SSH provisioning, IAM rotation
  • Plugin actions execute locally
  • Zero-trust maintained

Client Applications

CLI Client

# Installation
npm install -g selkie-cli

# Login
selkie login

# List objects
selkie objects list

# Get a secret
selkie secrets get <object-id>

# Rotate a secret
selkie secrets rotate <object-id>

# Assign user to object
selkie assign <object-id> --user <email> --role CONSUMER

CLI Features

  • Keypair generation
  • KEK derivation & UMK decryption
  • Secret encryption & decryption
  • Object creation & management
  • Secret rotation
  • Assignment management
  • Direct plugin execution
  • Secure token storage in OS keychain

Web Client

Full-featured browser application with zero-trust decryption:

Dashboard

Compromised and stale secret warnings, quick stats

Object Browser

View and manage all objects you have access to

Secret Modal

Secure reveal with glass blur effect, copy protection

Audit History

Complete timeline of access and modifications

Assignments

Manage who has access to what

Version History

Previous versions read-only, rotation timeline

Data Model (MongoDB)

Selkie uses MongoDB with the following core collections:

Users Collection

User identity, authentication, and encrypted crypto context:

email, displayName, passwordHash, encrypted_UMK, encryptedPrivateKey, publicKey, status, timestamps

SystemConfig Collection

Single document with system-wide configuration:

organizationName, organizationSlug, wrappedOMK, omk_publicKey, securityPolicies, timestamps

ObjectTypes Collection

Schema definitions for each object type:

name, fieldSchema (JSONSchema), secretSchema (JSONSchema), pluginMetadata, timestamps

Objects Collection

The resources being managed:

type, name, fields, currentSecretVersion, status, paranoid, compromisedAt, createdBy, timestamps

SecretVersions Collection

Immutable encrypted secrets:

objectId, version, ciphertext, nonce, algorithm, schemaVersion, status, createdBy, timestamps

SecretAccessGrants Collection

Per-user DEK wraps:

secretVersionId, userId, wrappedDekForUser, wrappedDekForOMK (if not paranoid), timestamps

ObjectAssignments Collection

User-to-object access mapping:

objectId, userId, role (OWNER/MAINTAINER/CONSUMER), createdAt, removedAt

AuditEvents Collection

Immutable event log:

eventType, actorUserId, objectId, secretVersionId, payload, timestamp

Core Operational Flows

User Registration

1

Generate Keys (Client)

Create random UMK, generate RSA-4096 keypair

2

Derive KEK (Client)

Use Argon2id with password to derive KEK

3

Encrypt Keys (Client)

Encrypt UMK with KEK, encrypt private key with UMK

4

Send to Backend

Upload encrypted UMK + encrypted private key + public key

5

Store User (Backend)

Store user with password hash and KDF parameters

6

Show Mnemonic (Client)

Display BIP39 recovery words for UMK backup

Creating Objects with Secrets

1

Fetch Type Schema

Get field and secret schema for the object type

2

Validate Fields

Ensure all fields match the type schema

3

Generate DEK (Client)

Create random 256-bit Data Encryption Key

4

Encrypt Secret (Client)

Use DEK with AES-256-GCM to encrypt secret data

5

Wrap DEKs (Client)

Encrypt DEK with user's public key (and OMK if not paranoid)

6

Send to Backend

Upload ciphertext, nonce, wrapped DEKs

7

Store (Backend)

Create object, secret version, and access grants

Secret Rotation

1

Generate New DEK

Client creates fresh 256-bit key

2

Encrypt New Secret

Use new DEK to encrypt updated secret value

3

Wrap for All Users

Encrypt DEK with each assigned user's public key

4

Upload New Version

Backend creates new SecretVersion, updates currentVersion

5

Emit Event

Backend emits secret.rotated for plugin handlers

Assigning Users

1

Create Assignment

Backend records user-object-role mapping

2

Generate DEK Wrap

Client wraps current DEK with new user's public key

3

Store Access Grant

Backend stores wrapped DEK for the new user

4

Emit Event

Backend emits object.assigned

5

Plugin Actions

Plugins may trigger external actions (SSH key provisioning, etc.)

Future Roadmap

Selkie is built to evolve without breaking cryptographic assumptions:

Near-Term

  • Additional object type plugins
  • More integration plugins
  • Enhanced audit dashboards
  • Team management features

Mid-Term

  • Multi-factor crypto authentication
  • Hardware-backed UMK decryption (YubiKey)
  • Client plugin marketplace
  • Kubernetes & cloud provider agents

Long-Term

  • Multi-organization support
  • Multi-region deployments
  • Browser extension for daemon-less operations
  • Mobile app with limited plugin support

Always Maintained

  • Zero-trust guarantees
  • Backward compatibility
  • No migration breaking crypto
  • Client-side decryption only

Ready to Get Started?

Experience zero-trust secret management where you control the keys and the backend never sees your secrets.