Example Usage & Recipes
This page provides concrete examples for common Sigyn workflows.
Quick Shortcuts
Using Short Aliases
Every major command has a short alias for fast typing:
# These pairs are equivalent:
sigyn secret list --env dev → sigyn s list -e dev
sigyn vault list → sigyn v list
sigyn env diff dev staging → sigyn e diff dev staging
sigyn audit tail → sigyn a tail
sigyn sync push → sigyn sy push
sigyn run -e dev -- ./app → sigyn r -e dev -- ./app
Top-Level get/set
Skip the secret subcommand for the most common operations:
# Instead of: sigyn secret get DATABASE_URL -e dev
sigyn get DATABASE_URL -e dev
# Instead of: sigyn secret set API_KEY 'new-key' -e prod
sigyn set API_KEY 'new-key' -e prod
# Copy a secret to clipboard
sigyn get API_KEY -e prod --copy
Quick Listing with ls
sigyn ls # list secrets in default env
sigyn ls prod # list secrets in prod (prefix matching)
sigyn ls --vaults # list all vaults
sigyn ls --envs # list all environments
sigyn ls dev --reveal # show secret values
Environment Prefix Matching
Type just enough of the environment name to be unambiguous:
sigyn get API_KEY -e d # resolves to 'dev'
sigyn get API_KEY -e p # resolves to 'prod'
sigyn get API_KEY -e st # resolves to 'staging'
sigyn run -e p -- ./deploy # run with prod secrets
Context for Repeated Operations
Set a persistent context to avoid typing --vault and --env repeatedly:
sigyn context set myapp prod
sigyn get DATABASE_URL # uses myapp vault, prod env
sigyn ls # lists prod secrets
sigyn run -- ./deploy.sh # runs with prod secrets
sigyn context clear # go back to defaults
Inline Secret Refs in Commands
Reference secrets directly in command arguments with {{KEY}}:
sigyn run -e prod -- curl -H "Authorization: Bearer {{API_KEY}}" https://api.example.com
sigyn run -e dev -- psql "{{DATABASE_URL}}"
Watch Mode for Development
Automatically restart your app when secrets change:
sigyn watch -e dev -- npm run dev
sigyn watch -e dev --interval 5 -- cargo run
Useful during development when a teammate updates shared secrets — your local server restarts with the new values automatically.
Working with AI Coding Agents
AI coding assistants (Claude Code, GitHub Copilot, Cursor, Windsurf, etc.) run in your terminal and can read environment variables, .env files, and process listings. Sigyn keeps secrets invisible to them.
The Problem
# DON'T DO THIS — any AI agent in your terminal can read these:
export DATABASE_URL="postgres://prod:[email protected]/myapp"
echo "API_KEY=sk-live-abc123" >> .env
source .env
AI agents can see secrets via env, printenv, cat .env, or /proc/self/environ. Even if the agent doesn’t deliberately exfiltrate them, secrets may appear in conversation logs, tool outputs, or error messages.
Solution 1: Process Injection (Recommended)
Run your app with injected secrets in one terminal, your AI agent in another:
# Terminal 1 — app runs with secrets, isolated from your shell
sigyn run -e dev -- npm run dev
# Terminal 2 — AI agent has no access to the secrets
claude # or cursor, copilot, etc.
Secrets are injected only into the child process (npm run dev). Your shell — where the AI agent runs — never sees them.
Solution 2: Clean Environment
Use --clean to strip the entire parent environment, injecting only vault secrets:
sigyn run --clean -e dev -- ./myapp
This prevents even inherited environment variables (like AWS_SECRET_ACCESS_KEY from a previous aws configure) from being visible.
Solution 3: Unix Socket (Maximum Security)
For zero-exposure secret access, serve secrets over a Unix socket:
# Start the socket server (owner-only permissions, 0600)
sigyn run serve -e prod --socket /tmp/sigyn.sock &
# Your app reads secrets from the socket at runtime
# No environment variables, no files, no process listing exposure
Solution 4: Named Commands in .sigyn.toml
Set up your project so developers never need to type secrets or export them:
# .sigyn.toml
[project]
vault = "myapp"
env = "dev"
[commands]
dev = "npm run dev"
test = "npm test"
migrate = "npx prisma migrate deploy"
sigyn run dev # secrets injected, never in your shell
sigyn run test # same — AI agent can't see them
Quick Comparison
| Method | Secrets in env? | Secrets on disk? | Agent can read? |
|---|---|---|---|
.env + source | Yes | Yes | Yes |
export KEY=val | Yes | No | Yes |
sigyn run exec | Child only | No | No |
sigyn run --clean | Child only | No | No |
sigyn run serve | Never | No | No |
Letting AI Agents Run and Debug Your App
The previous section covers keeping secrets away from agents entirely. But what if you need the agent to actually run your app (which needs secrets) for debugging?
Strategy 1: Dev Environment with Non-Sensitive Credentials
The simplest approach — use local/dummy credentials in dev that aren’t actually secrets:
# These dev values aren't sensitive — it's fine if the agent sees them
sigyn secret set DATABASE_URL "postgres://localhost/myapp_dev" -e dev
sigyn secret set REDIS_URL "redis://localhost:6379" -e dev
sigyn secret set API_KEY "sk-test-not-a-real-key" -e dev
Configure .sigyn.toml so the agent just runs commands:
[project]
vault = "myapp"
env = "dev"
[commands]
dev = "npm run dev"
test = "npm test"
The agent can run sigyn run dev, see the app output, debug errors — and the dev credentials aren’t worth protecting because they only work against localhost.
Keep real credentials in staging/prod environments only. The agent works in dev where exposure doesn’t matter.
Strategy 2: Sigyn Run with Output Isolation
Let the agent invoke sigyn run but prevent it from reading individual secret values:
# Agent CAN do this (runs the app, sees stdout/stderr):
sigyn run -e dev -- npm run dev
# Agent CANNOT do this (requires interactive passphrase):
sigyn secret get DATABASE_URL -e dev
# ^ Blocked because the agent doesn't have your passphrase
As long as you don’t cache your passphrase in the agent’s terminal session (don’t run eval $(sigyn agent start) there), the agent can only run pre-configured commands — not extract individual secrets.
Strategy 3: Named Commands as an Allowlist
Define exactly which commands the agent is allowed to run:
# .sigyn.toml
[project]
vault = "myapp"
env = "dev"
[commands]
dev = "npm run dev"
test = "npm test"
lint = "npm run lint"
migrate = "npx prisma migrate dev"
debug = "node --inspect ./src/index.js"
The agent can run sigyn run dev, sigyn run test, sigyn run debug — but can’t invent new commands that extract secrets. Combined with not having the passphrase cached, this acts as an effective allowlist.
Strategy 4: Socket Server for Running Apps
Start the socket server yourself, then let the agent restart the app as needed:
# You start the socket server (once, in your terminal):
sigyn run serve -e dev --socket /tmp/sigyn-dev.sock &
# Your app reads secrets from the socket at runtime.
# The agent can restart the app, read logs, debug — but
# the secret values only flow through the socket, never
# through environment variables the agent could inspect.
This requires your app to support reading from a Unix socket (via SIGYN_SOCK env var), but provides the strongest isolation.
What to Watch Out For
Even with these strategies, secrets can leak through:
- Application logs — if your app logs
Connected to postgres://user:password@host, the agent sees it in stdout. Configure your app to redact credentials from logs. - Error messages — database connection errors often include the connection string. Use structured error handling that strips credentials.
- Core dumps / stack traces — these can contain in-memory secrets. Disable core dumps in dev.
Recommended Setup
For most teams, Strategy 1 + Strategy 2 is the sweet spot:
# 1. Use non-sensitive dev credentials
sigyn secret set DATABASE_URL "postgres://localhost/myapp_dev" -e dev
# 2. Keep real secrets in staging/prod only
sigyn secret set DATABASE_URL "postgres://prod:[email protected]/myapp" -e prod
# 3. Agent works in dev — can run and debug freely
# .sigyn.toml points to dev by default
# Agent runs: sigyn run dev
# 4. You deploy to prod yourself — agent never touches it
sigyn run -e prod -- ./deploy.sh
CI/CD Integration
For full CI/CD documentation including the GitHub Action reference, all export modes, security best practices, and troubleshooting, see the dedicated CI/CD Integration page.
Quick example:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Load secrets
uses: tonybenoy/sigyn/action@main
with:
bundle: ${{ secrets.SIGYN_CI_BUNDLE }}
passphrase: ${{ secrets.SIGYN_PASSPHRASE }}
vault-ssh-key: ${{ secrets.VAULT_SSH_KEY }}
vault-repo: [email protected]:myorg/sigyn-vaults.git
vault: myapp
environment: prod
- name: Deploy
run: ./deploy.sh
Advanced Process Injection
Using with Docker
Injecting secrets into a Docker container without ever writing them to a .env file:
sigyn run exec --env prod -- docker run --env-file <(sigyn run export --format docker) my-app:latest
Or more simply if you want all Sigyn secrets to be env vars in the container:
sigyn run exec --env prod -- docker run my-app:latest
Shell Alias for Development
Add this to your .bashrc or .zshrc to always run your local dev server with Sigyn secrets:
alias dev='sigyn run -e dev -- npm run dev'
Or better yet, use a .sigyn.toml project config with named commands:
# .sigyn.toml
[project]
vault = "myapp"
env = "dev"
[commands]
dev = "npm run dev"
Then just run sigyn run dev – no alias needed.
Team Onboarding and Offboarding
Onboarding a New Team Member
Step 1 — New member creates their identity:
# Bob runs this on his machine
sigyn identity create --name bob --email [email protected]
sigyn identity export --name bob > bob.pub
# Send bob.pub to the team lead (Alice) via a secure channel
Step 2 — Team lead creates a scoped invitation:
# Alice imports Bob's public key and creates an invitation
sigyn identity import bob.pub
sigyn delegation invite create \
--role contributor \
--envs dev,staging \
--patterns '*'
# Produces invitation-<id>.json — send it to Bob
Step 3 — New member clones the vault, accepts, and verifies access:
# Bob clones and accepts in one step
sigyn vault clone [email protected]:team/secrets.git --invitation ./invitation-abc123.json
# Or separately:
# sigyn vault clone [email protected]:team/secrets.git
# sigyn delegation invite accept ./invitation-abc123.json
# Pull the vault to get encrypted secrets
sigyn sync pull
# Verify access works
sigyn policy check $(sigyn identity show bob --json | jq -r .fingerprint) read --env dev
# Result: ALLOW
sigyn policy check $(sigyn identity show bob --json | jq -r .fingerprint) write --env prod
# Result: DENY (not in allowed envs)
Offboarding a Team Member
When someone leaves the team, revoke their access and clean up the delegation tree.
Step 1 — Inspect the delegation tree to understand impact:
sigyn delegation tree
# alice (a1b2c3d4...) [owner]
# bob (e5f6a7b8...) [contributor]
# carol (c9d0e1f2...) [readonly] <-- Bob invited Carol
# dave (a3b4c5d6...) [admin]
Step 2 — Revoke with cascade (removes Bob and everyone Bob invited):
sigyn delegation revoke e5f6a7b8... --cascade
# Revoked: bob (e5f6a7b8...), carol (c9d0e1f2...)
# Master key rotated.
Step 3 — Push changes and rotate high-value secrets:
sigyn sync push
# Rotate any secrets Bob had access to
sigyn rotate key DB_PASSWORD --env dev
sigyn rotate key DB_PASSWORD --env staging
sigyn rotate key API_KEY --env dev
sigyn rotate key API_KEY --env staging
If Carol should keep access, re-invite her directly before revoking Bob,
or use sigyn delegation revoke e5f6a7b8... (without --cascade) and
manually reassign Carol’s delegation.
Contractor and Temporary Access
Granting Time-Limited Access
Create a time-limited invitation with scoped permissions for a contractor:
sigyn delegation invite create \
--role contributor \
--envs dev \
--patterns "STRIPE_*,PAYMENT_*" \
--expires 90d
# Produces invitation-<id>.json — send to the contractor
The invitation (and resulting access) expires automatically after 90 days.
Verifying Contractor Constraints
After the contractor accepts, verify what they can and cannot do:
# Allowed: read payment secrets in dev
sigyn policy check <contractor-fp> read --env dev --key STRIPE_SECRET_KEY
# Result: ALLOW
# Denied: access production
sigyn policy check <contractor-fp> read --env prod --key STRIPE_SECRET_KEY
# Result: DENY (env not allowed)
# Denied: access secrets outside their pattern
sigyn policy check <contractor-fp> read --env dev --key DATABASE_URL
# Result: DENY (key does not match allowed patterns)
Cleanup
When the contract ends, either wait for auto-expiry or revoke explicitly:
sigyn delegation revoke <contractor-fp>
sigyn sync push
Complex Policies
Restricting a Member to Specific Keys
Add a member who can only see database-related secrets in the staging environment:
sigyn policy member-add <fingerprint>
--role readonly
--envs staging
--patterns "DB_*,POSTGRES_*"
Implementing a “Break Glass” Auditor
An auditor who can see everything but only in an emergency (monitored via audit logs):
sigyn policy member-add <fingerprint>
--role auditor
--envs '*'
--patterns '*'
MFA Enforcement
Requiring MFA for All Members
Enable MFA globally by setting require_mfa: true in the vault’s global constraints.
Every non-owner member will be prompted for a TOTP code on their first access (then
a 1-hour session grace period kicks in).
First, have each team member enroll:
sigyn mfa setup -i alice
Then set the policy constraint (as vault owner):
# In the vault policy, set global_constraints.require_mfa = true
sigyn policy show --vault myapp # verify current policy
MFA for Specific Members
You can also require MFA only for certain members by setting require_mfa: true on
their individual member constraints rather than globally. This is useful for
restricting high-privilege roles while leaving read-only members unaffected.
Generating New Backup Codes
If a team member loses their backup codes, they can generate a fresh set (the old codes are immediately invalidated):
sigyn mfa backup -i alice
Secret Rotation
Manual Rotation of a Database Password
- Rotate the secret in Sigyn:
sigyn rotate key DB_PASSWORD --env prod - Export the new value to update your cloud provider (e.g., AWS RDS):
NEW_PASS=$(sigyn secret get DB_PASSWORD --env prod) aws rds modify-db-instance --db-instance-identifier mydb --master-user-password "$NEW_PASS"
Rotation Schedules with Hooks
Rotation hooks are executed directly (no shell) after Sigyn rotates a secret.
The new secret value is passed via stdin, not as an environment variable. This
prevents the secret from being visible in /proc/<pid>/environ. The environment
name is available as $SIGYN_ENV.
Hook commands are validated when saved to policy: shell metacharacters
(;, |, &, $, `, \, >, <, (, )) are rejected, and the
command name must not contain path traversal (..). Maximum command length is
512 characters.
Automated Database Password Rotation
Create a hook script that reads the new secret from stdin and updates AWS RDS:
#!/usr/bin/env bash
# hooks/rotate-db.sh — called after sigyn rotates DB_PASSWORD
# The new secret value is passed via stdin.
set -euo pipefail
NEW_PASS=$(cat) # read new secret from stdin
aws rds modify-db-instance \
--db-instance-identifier mydb \
--master-user-password "$NEW_PASS"
echo "RDS password updated successfully"
Set a weekly rotation schedule with the hook:
sigyn rotate schedule set -v myapp \
--key DB_PASSWORD \
--cron "0 0 * * MON" \
--grace-hours 48 \
--hooks hooks/rotate-db.sh
Verify the schedule is active:
sigyn rotate schedule list -v myapp
# KEY CRON GRACE HOOKS NEXT RUN
# DB_PASSWORD 0 0 * * MON 48h rotate-db.sh 2026-03-02 00:00 UTC
Test it manually to make sure the hook works end-to-end:
sigyn rotate key DB_PASSWORD --env prod
Monthly Redis Auth Token Rotation
#!/usr/bin/env bash
# hooks/rotate-redis.sh
# The new secret value is passed via stdin.
set -euo pipefail
NEW_TOKEN=$(cat) # read new secret from stdin
redis-cli -h redis.internal CONFIG SET requirepass "$NEW_TOKEN"
echo "Redis auth token updated"
sigyn rotate schedule set -v myapp \
--key REDIS_AUTH_TOKEN \
--cron "0 2 1 * *" \
--grace-hours 24 \
--hooks hooks/rotate-redis.sh
First-Time Setup
Using the Onboard Wizard
The fastest way to get started is the guided wizard:
sigyn onboard
This walks you through:
- Creating an identity (if none exists)
- Creating a vault (auto-detects project name)
- Importing
.envfiles found in the current directory - Setting up
.sigyn.toml
In CI or non-interactive environments, it prints a checklist instead:
sigyn onboard
# Sigyn Setup Checklist
# ─────────────────────────────────
# ✓ Identity created
# ✗ Vault created
# → sigyn vault create <name>
# ✗ Project config (.sigyn.toml)
# → sigyn project init
Smarter Init
sigyn init now offers to create missing identity and vault interactively:
sigyn init
# No identities found. Create one now? [Y/n]
# Identity name: alice
# ...
# No vaults found. Create one now? [Y/n]
# Vault name: myapp (detected from Cargo.toml)
# ...
# ✓ Configuration initialized
Environment Comparison and Cloning
Comparing Environments
Before promoting, check what differs between environments:
# Summary of differences (values hidden)
sigyn env diff dev staging
# - OLD_DEBUG_KEY (removed)
# + NEW_STAGING_KEY (added)
# ~ DATABASE_URL (changed)
# See actual values
sigyn env diff dev staging --reveal
# Machine-readable output
sigyn env diff dev prod --json
Cloning an Environment
Quickly create a copy of an environment for testing:
sigyn env clone dev qa
# ✓ Cloned 'dev' → 'qa' (12 secrets)
# Now customize the QA-specific values
sigyn secret set DATABASE_URL "postgres://qa-db/myapp" --env qa
Batch Editing and Cross-Environment Search
Editing Secrets in Your Editor
Open all secrets in an environment for bulk editing:
sigyn secret edit --env dev
# Opens $EDITOR with:
# DATABASE_URL=postgres://localhost/myapp
# API_KEY=sk-abc123
# FEATURE_FLAG=true
#
# Make changes, save, close. Sigyn shows a diff and confirms.
Searching Across Environments
Find secrets matching a pattern across all environments in a vault:
# Find all database-related secrets
sigyn secret search 'DB_*'
# [dev] DB_HOST = ••••••••
# [dev] DB_PORT = ••••••••
# [staging] DB_HOST = ••••••••
# [prod] DB_HOST = ••••••••
# Show actual values
sigyn secret search 'API_*' --reveal
Passphrase Agent (Session Caching)
Avoiding Repeated Passphrase Prompts
When running multiple commands in a session, use the passphrase agent to cache
your decrypted key in memory — similar to ssh-agent or gpg-agent.
# Start the agent (prints a shell-eval-able export)
eval $(sigyn agent start)
# First command prompts for your passphrase — then caches it
sigyn secret list -v myapp -e dev
# Subsequent commands skip the passphrase prompt entirely
sigyn secret set API_KEY="new-key" -e dev
sigyn vault create new-project -i alice
sigyn delegation tree
Custom Timeout
By default, cached keys expire after 30 minutes. Adjust with --timeout:
# Cache keys for 2 hours
eval $(sigyn agent start --timeout 120)
# Cache keys for 5 minutes (for quick scripted workflows)
eval $(sigyn agent start --timeout 5)
Locking and Stopping
# Clear cached keys but keep daemon running (next command re-prompts)
sigyn agent lock
# Check agent status
sigyn agent status
# Stop the daemon entirely and zeroize all keys
sigyn agent stop
Agent + Batch Operations
The agent is especially useful when combined with batch commands in a multi-step workflow:
eval $(sigyn agent start)
# All of these run without re-prompting for the passphrase
sigyn vault create api worker web --org acme
sigyn env create dev staging prod
sigyn secret set DB_URL="postgres://localhost" REDIS="redis://localhost" -e dev
sigyn secret import .env.production -e prod --force
sigyn delegation revoke abc123 def456 --cascade
sigyn sync push
Shell Profile Integration
Add this to your .bashrc or .zshrc to auto-start the agent on login:
if [ -z "$SIGYN_AGENT_SOCK" ]; then
eval $(sigyn agent start --timeout 60)
fi
Webhook Notifications
Setting Up Notifications
Configure a webhook to get notified when secrets change. Webhook URLs must use HTTPS (HTTP is only allowed for localhost during development):
sigyn notification configure
# Webhook URL: https://hooks.slack.com/services/T.../B.../xxx
# Select events: * (all events)
# Shared secret: (optional — used to compute HMAC signature)
# ✓ Webhook configured
When a shared secret is configured, each webhook POST includes an X-Sigyn-Signature
header containing an HMAC (blake3 keyed hash) of the JSON payload body. Verify this
on the receiving end to authenticate that the request came from Sigyn.
Testing Notifications
Send a test event to verify your webhook works:
sigyn notification test
# ✓ https://hooks.slack.com/services/T.../B.../xxx
# ✓ Test sent to 1 webhook(s)
Listing Configured Webhooks
sigyn notification list
# Configured Webhooks
# ────────────────────────────────────────────────────────────
# 1. https://hooks.slack.com/services/T.../B.../xxx
# Events: *
Auto-Sync
Enable auto-sync to automatically push changes after every write:
sigyn sync configure --auto-sync true
# Now every secret set/remove/generate automatically pushes
sigyn secret set API_KEY "new-value" --env dev
# ✓ Set 'API_KEY' in env 'dev'
# note: auto-syncing...
Environment Promotion Workflow
Promoting Secrets Through the Pipeline
A typical workflow: set secrets in dev, then promote through staging to production.
Step 1 — Set secrets in dev:
# Batch set — all at once
sigyn secret set API_KEY="dev-key-abc123" DATABASE_URL="postgres://localhost/myapp_dev" FEATURE_FLAG="true" --env dev
Step 2 — Promote all secrets from dev to staging:
# Preview what will change first
sigyn env promote --from dev --to staging --dry-run
# Would promote: API_KEY, DATABASE_URL, FEATURE_FLAG
# Would overwrite: (none)
# Apply the promotion
sigyn env promote --from dev --to staging
Step 3 — Override staging-specific values:
sigyn secret set DATABASE_URL "postgres://staging-db.internal/myapp" --env staging
Step 4 — Selectively promote to production:
# Only promote specific keys (not DATABASE_URL, which differs per environment)
sigyn env promote --from staging --to prod --keys API_KEY,FEATURE_FLAG
# Production DATABASE_URL is managed separately
sigyn secret set DATABASE_URL "postgres://prod-db.internal/myapp" --env prod
Adding a QA Environment
# Option 1: Clone dev (copies all secrets in one step)
sigyn env clone dev qa
# Option 2: Create empty and promote selectively
sigyn env create qa
sigyn env promote --from dev --to qa
# Either way, QA team can now work with a snapshot of dev secrets
Multi-Project Organization
Scenario
You have one organization with multiple projects — say 3 backend services and 1
frontend app — each with their own environments and secrets. You want centralized
access control, minimal GitHub repos for sync, and per-project .sigyn.toml configs
so developers just cd into a repo and go.
1. Set up the org hierarchy
sigyn org create acme
sigyn org node create backend --parent acme --type division
sigyn org node create frontend --parent acme --type division
This gives you:
acme (org)
├── backend (division)
└── frontend (division)
2. Create a vault per project, linked to the org
# Batch create — multiple vaults in one command
sigyn vault create api-service auth-service worker-service --org acme/backend
sigyn vault create dashboard --org acme/frontend
Each vault has independent environments (dev, staging, prod), secrets, and
member lists — but inherits org-level policies and git remote configuration.
3. Configure git sync once at the org level
sigyn org sync configure --path acme \
--remote-url [email protected]:acme-corp/secrets.git
All 4 vaults inherit this single remote. If the frontend team later needs a separate repo, override at the child level:
sigyn org sync configure --path acme/frontend \
--remote-url [email protected]:acme-corp/frontend-secrets.git
Now acme/backend still inherits the org remote, while acme/frontend uses its own.
4. Add a .sigyn.toml to each project repo
In api-service/:
[project]
vault = "api-service"
env = "dev"
identity = "alice"
[commands]
dev = "cargo run"
migrate = "sqlx migrate run"
In dashboard/:
[project]
vault = "dashboard"
env = "dev"
identity = "alice"
[commands]
dev = "npm run dev"
build = "npm run build"
5. Day-to-day usage
# In api-service/ — secrets come from the api-service vault, dev env
sigyn secret set DATABASE_URL "postgres://localhost/api"
sigyn run dev
# In dashboard/ — secrets come from the dashboard vault, dev env
sigyn secret set VITE_API_URL "http://localhost:8080"
sigyn run dev
# Switch to staging for a deploy
sigyn run exec --env staging -- ./deploy.sh
6. Team access control
Add an org-wide admin who can access all vaults:
sigyn org policy member-add <bob-fp> --role admin --path acme
Add a frontend contractor who can only access dashboard secrets in dev:
sigyn org policy member-add <carol-fp> --role contributor \
--path acme/frontend --envs dev
Check effective permissions:
sigyn org policy effective <carol-fp> --path acme/frontend
# Role: Contributor
# Envs: dev
# Patterns: *
7. Sync everything
sigyn sync push --vault api-service
sigyn sync push --vault auth-service
sigyn sync push --vault worker-service
sigyn sync push --vault dashboard
Why this works
- One or two GitHub repos instead of one per vault — git remote inheritance means you set it once at the org level.
- Per-project isolation — each vault has its own master key, so compromising one doesn’t affect the others.
- Per-project
.sigyn.toml— developers justcdinto a repo andsigyn run devpicks up the right vault, env, and identity automatically. - Cascading RBAC — add someone at
acmeand they get access everywhere; add them atacme/frontendand they only see frontend vaults. - Independent environments —
api-servicecan be onstagingwhiledashboardis still ondev.
Monorepo with Shared Secrets
Scenario
You have a monorepo with 3 services (API, worker, web frontend) that share some infrastructure secrets (database URL, Redis URL) but also have service-specific secrets (API keys, signing tokens). You want each service to see only what it needs while avoiding duplication of shared values.
1. Create the vaults
sigyn vault create shared-infra api-service worker-service web-frontend
2. Populate shared and per-service secrets
# Batch set — multiple KEY=VALUE pairs per command
sigyn secret set DATABASE_URL="postgres://db.internal/myapp" REDIS_URL="redis://redis.internal:6379" -v shared-infra -e prod
sigyn secret set STRIPE_SECRET_KEY="sk_live_..." JWT_SECRET="..." -v api-service -e prod
sigyn secret set QUEUE_URL="https://sqs.us-east-1.amazonaws.com/..." DEAD_LETTER_ARN="arn:aws:sqs:..." -v worker-service -e prod
sigyn secret set NEXT_PUBLIC_API_URL="https://api.example.com" -v web-frontend -e prod
# Or import from a .env file
sigyn secret import .env.production -v api-service -e prod --force
3. Per-directory .sigyn.toml files
In services/api/.sigyn.toml:
[project]
vault = "api-service"
env = "dev"
[commands]
dev = "cargo run"
In services/worker/.sigyn.toml:
[project]
vault = "worker-service"
env = "dev"
[commands]
dev = "cargo run"
In services/web/.sigyn.toml:
[project]
vault = "web-frontend"
env = "dev"
[commands]
dev = "npm run dev"
4. Compose shared + service secrets at runtime
Use sigyn run export to merge secrets from multiple vaults:
# In services/api/ — load shared infra secrets, then layer on API-specific ones
eval $(sigyn run export -v shared-infra --env prod --format shell)
exec sigyn run exec --env prod -- ./api-server
Or in a wrapper script (services/api/start.sh):
#!/usr/bin/env bash
set -euo pipefail
# Export shared secrets into the environment
eval $(sigyn run export -v shared-infra --env "${SIGYN_ENV:-dev}" --format shell)
# Run with service-specific secrets layered on top
sigyn run exec --env "${SIGYN_ENV:-dev}" -- "$@"
# Usage
cd services/api && ./start.sh cargo run
Emergency Breach Response
Full Breach — All Secrets Compromised
If you suspect a broad compromise (e.g., vault key leaked), use breach mode to rotate everything and revoke all delegated members in one step.
Step 1 — Activate breach mode:
sigyn rotate breach-mode --force
# All secrets rotated across all environments.
# All delegated members revoked.
# Master key rotated.
Step 2 — Push the rotated vault:
sigyn sync push
Step 3 — Verify the delegation tree is clean:
sigyn delegation tree
# alice (a1b2c3d4...) [owner]
# (no delegated members)
Step 4 — Update external systems with new secret values:
# Update RDS
NEW_DB_PASS=$(sigyn secret get DB_PASSWORD --env prod)
aws rds modify-db-instance --db-instance-identifier mydb --master-user-password "$NEW_DB_PASS"
# Update Redis
NEW_REDIS_TOKEN=$(sigyn secret get REDIS_AUTH_TOKEN --env prod)
redis-cli -h redis.internal CONFIG SET requirepass "$NEW_REDIS_TOKEN"
# Repeat for all external integrations...
Step 5 — Re-onboard trusted team members:
# Create new invitations for each trusted member
sigyn delegation invite create --role admin --envs '*'
sigyn delegation invite create --role contributor --envs dev,staging
# Send invitations via a verified secure channel
Step 6 — Audit, verify, and witness:
# Export the audit log for incident documentation
sigyn audit export --output incident-audit.json --format json
# Verify the audit chain is intact
sigyn audit verify
# Have a second team member countersign the recovery
sigyn audit witness
Targeted Response — Single Member Compromise
If only one member’s key was compromised (e.g., stolen laptop), you can scope the response to just that member:
# Revoke the compromised member and their delegates
sigyn delegation revoke <compromised-fp> --cascade
sigyn sync push
# Rotate only the secrets that member had access to
sigyn rotate key DB_PASSWORD --env dev
sigyn rotate key DB_PASSWORD --env staging
sigyn rotate key API_KEY --env dev
# Monitor for suspicious activity
sigyn audit tail -n 100
sigyn audit query --actor <compromised-fp>
Disaster Recovery
Creating Paper Backups
- Create 5 shards, requiring 3 to recover:
sigyn-recovery split --identity alice --threshold 3 --total 5 --output ./shards - Print them (or generate QR codes) to store in physical safes:
sigyn-recovery print-shards ./shards/*.json
Recovering a Vault
If Alice loses her laptop, she can reconstruct her identity on a new machine:
sigyn-recovery restore shard1.json shard2.json shard3.json --output recovered_identity.toml
sigyn identity import recovered_identity.toml
Auditing and Compliance
Verifying Audit Chain Integrity
Before any compliance review, verify the hash chain has not been tampered with:
sigyn audit verify
# Audit chain OK: 1,247 entries verified, no breaks detected.
Querying Access Patterns
Search the audit log for specific access patterns:
# All production access events
sigyn audit query --env prod
# All actions by a specific member
sigyn audit query --actor a1b2c3d4...
# Combine filters
sigyn audit query --actor a1b2c3d4... --env prod
Exporting for Compliance
Export the full audit trail for external compliance tools or auditors:
# JSON for programmatic analysis
sigyn audit export --output audit-q1-2026.json --format json
# CSV for spreadsheet review
sigyn audit export --output audit-q1-2026.csv --format csv
Witness Countersigning
After sensitive operations (rotation, member changes, breach response), have a second team member countersign the audit entry:
# After a rotation or breach response, the second admin runs:
sigyn audit witness
# Countersigned entry #1247 with fingerprint e5f6a7b8...
Git Anchoring
Anchor the audit trail to a git commit for external tamper-evidence:
sigyn audit anchor -v myapp
# Anchored audit hash abc123... to git commit def456...
Periodic Compliance Script
Automate weekly compliance checks with a cron job:
#!/usr/bin/env bash
# compliance-check.sh — run weekly via cron
set -euo pipefail
echo "=== Sigyn Compliance Check $(date -I) ==="
# Verify audit chain integrity
sigyn audit verify
# Check for secrets due for rotation
sigyn rotate due --env prod --max-age 90
# Export audit log for the past week
sigyn audit export --output "/var/log/sigyn/audit-$(date -I).json" --format json
# Anchor to git
sigyn audit anchor -v myapp
echo "=== Compliance check complete ==="
0 6 * * MON /opt/scripts/compliance-check.sh >> /var/log/sigyn/compliance.log 2>&1
Scripting with Sigyn
Bulk Update from a CSV
# From a .env file (preferred)
sigyn secret import secrets.env --env dev
# From CSV with shell loop
while IFS=, read -r key value; do
sigyn secret set "$key" "$value" --env dev
done < secrets.csv
Checking for Expiring Secrets
Find secrets that haven’t been rotated in 6 months:
sigyn rotate due --env prod --max-age 180