Vault
Store CompozyOS-managed encrypted secrets with redacted CLI, HTTP, UDS, web, and session-scoped metadata surfaces.
The Vault is CompozyOS's encrypted store for daemon-managed secret material. Use it when CompozyOS should own the value lifecycle instead of reading a value from the daemon process environment.
Ref Model
CompozyOS accepts two secret ref families:
| Ref family | Owner | Runtime behavior |
|---|---|---|
env:NAME | Operator environment | CompozyOS reads NAME from the daemon process environment when a runtime boundary needs it. |
vault:<namespace>/<path> | CompozyOS Vault | CompozyOS stores the secret encrypted, resolves it only at internal launch/materialization boundaries, and redacts diagnostics. |
Supported Vault namespaces are:
| Namespace | Typical refs |
|---|---|
providers | vault:providers/openrouter/api-key |
profiles | vault:profiles/studio/providers/openrouter/api-key |
automation | vault:automation/deploy-webhook/signing-secret |
mcp | vault:mcp/global/github/env/GITHUB_TOKEN, vault:mcp/ws/acme/linear/oauth/client-secret |
hooks | vault:hooks/post-task/GITHUB_TOKEN |
extensions | vault:extensions/slack/app-token |
sessions | vault:sessions/sess_123/github-token |
Session Vault entries are normal Vault records under the sessions namespace. CompozyOS filters them by
the deterministic prefix vault:sessions/<session_id>/; there is no separate session-secret table.
Names must use a supported namespace. Each slash-separated path segment starts with a letter or
digit and contains only letters, digits, dots, underscores, or hyphens. The first segment after the
namespace must be lowercase. Profile refs additionally use
profiles/<profile>/{providers|extensions}/<owner>/<key> with a valid profile name.
Public Surfaces
Vault is agent-manageable through the same daemon surfaces as the rest of CompozyOS:
| Surface | Operations | Notes |
|---|---|---|
| CLI over UDS | compozy vault list, get, put, delete | put accepts secret material only through --value-stdin. |
| HTTP API | /api/vault/secrets and /api/vault/secrets/metadata | Web UI and external local clients use these routes. HTTP Vault routes use the daemon's privileged loopback guard. |
| UDS API | Same route shapes as HTTP | CLI and local agents use the Unix domain socket surface. |
| Web UI | Vault page | Lists metadata, filters by namespace or prefix, writes new values, and deletes refs. |
| Session inspector | Session Vault panel | Lists metadata for vault:sessions/<session_id>/ refs. |
The response shape is always redacted:
{
"secret": {
"ref": "vault:sessions/sess_123/github-token",
"namespace": "sessions",
"kind": "token",
"present": true,
"created_at": "2026-05-02T10:00:00Z",
"updated_at": "2026-05-02T10:00:00Z"
}
}Fields such as secret_value, encrypted_value, tokens, and API keys are never returned by list,
get, delete, settings read, CLI output, or web views.
MCP And Extension Bindings
Manual MCP settings accept write-only secret values and store them in the scoped mcp namespace.
Management reads expose configured keys and secret presence. The MCP executor resolves the stored
refs when it launches or calls a server; credentials remain isolated by scope and owner.
Extension manifest inputs use the extension's own scoped secret namespace. An input can bind an existing secret owned by that same extension instance. Manual MCP refs cannot be imported through an extension input. Existing manual MCP definitions and their credentials remain unchanged.
CLI Usage
List all redacted metadata:
compozy vault listFilter by namespace:
compozy vault list --namespace providers -o jsonFilter one session:
compozy vault list --prefix vault:sessions/sess_123/Store a secret without putting it in shell history:
printf "%s" "$TOKEN" |
compozy vault put vault:sessions/sess_123/github-token --kind token --value-stdinRead metadata for one ref:
compozy vault get vault:sessions/sess_123/github-tokenDelete one ref:
compozy vault delete vault:sessions/sess_123/github-tokencompozy vault put intentionally does not have a --value flag. Passing secret values through argv can
leak them through shell history or process inspection.
When --kind is omitted during rotation, CompozyOS preserves the existing kind metadata for that ref.
API Usage
HTTP and UDS expose the same route model:
| Method | Route | Purpose |
|---|---|---|
GET | /api/vault/secrets?prefix=&namespace= | List redacted metadata. |
GET | /api/vault/secrets/metadata?ref=... | Read redacted metadata for one ref. |
PUT | /api/vault/secrets | Store or replace one write-only secret value. |
DELETE | /api/vault/secrets?ref=... | Delete one ref. |
Write request:
{
"ref": "vault:sessions/sess_123/github-token",
"kind": "token",
"secret_value": "..."
}The daemon validates the ref grammar, namespace, and non-empty secret_value. After a successful
write it returns the persisted metadata row. The submitted value is registered with dynamic
redaction before storage, then unregistered when the same ref is deleted or replaced.
HTTP Vault routes are intended for the local web UI and local integrations, so CompozyOS applies the privileged loopback guard to metadata reads and mutations. Agents and local tools can use the UDS surface for the same route shapes without exposing the HTTP listener.
Web UI
Use the Vault page for global metadata inspection and write-only updates.
In New secret, the Name field accepts a path such as automation/editorial/notes-token;
the form adds vault: when omitted. The name's help explains the supported namespaces. An invalid
name is rejected with format guidance, and the dialog keeps the name, label, and entered value so
you can correct it without re-entering the secret.
The listing supports:
- namespace filtering
- prefix filtering
- namespace changes clear a prefix that belongs to a different namespace
- create/update by ref
- delete by ref
- replacement and deletion of the same selected ref are serialized
- loading, empty, error, pending-write, and pending-delete states
Session pages include a Vault tab in the inspector. It shows only entries below
vault:sessions/<session_id>/ and shortens the display label to the session-local suffix.
Operational Notes
The default key provider is file. It never queries the OS keyring, including during startup or
diagnostics. Existing installations keep their current behavior: COMPOZY_VAULT_KEY overrides the
file key; otherwise CompozyOS creates $COMPOZY_HOME/vault.key with 0600 permissions on first use.
Opt in to the OS keyring
For an existing file-backed Vault, unset COMPOZY_VAULT_KEY and run this command on the machine that
owns the CompozyOS home:
compozy vault key migrateThe command imports the existing key, reads it back, verifies that it decrypts every existing Vault record, and only then changes the home configuration to:
[vault]
key_provider = "os-keyring"This setting is machine-wide. Profile and workspace overrides are rejected. Changing the setting
without running migration fails before contacting the OS keyring. The migration records local
opt-in evidence in vault.keyring-ready; it contains no encryption key or secret value.
Migration retains vault.key and warns that the plaintext key copy remains on disk. To remove it
after verification, explicitly pass:
compozy vault key migrate --remove-file-keyRepeating migration is safe, including after file removal. A failed verification leaves the file key and provider selection unchanged. An unavailable or locked keyring never causes an automatic fallback to the file provider.
On macOS, the existing go-keyring integration uses /usr/bin/security. An unlocked login keychain
normally needs no prompt, but creating an entry or accessing a locked keychain can request permission
or a password. CompozyOS does not promise a prompt-free opt-in. The daemon reads the OS key only on
first use and retains it in memory for that process; it does not query the keyring for each secret.
After a failed initial keyring read, unlock the credential store and restart the daemon before retrying.
Return to the file provider
If you retained the original vault.key, set vault.key_provider back to "file" in the home
configuration. Do not substitute a newly generated key: existing records require the original key.
If you removed the file, restore the original key from a secure backup before selecting file.
Deleting a Vault ref removes the stored value. It does not rewrite existing configuration that still points at that ref, so dependent providers, MCP servers, hooks, automation triggers, or session-scoped consumers may report missing credentials until a new value is stored.
Related Pages
- config.toml documents refs used by provider, MCP, automation, hook, and extension configuration.
- mcp.json documents MCP
secret_envand OAuthclient_secret_ref. - API Reference lists the Vault route family.
- CLI Reference contains the generated
compozy vaultcommand pages.