Secrets SSOT
Secrets SSOT
Section titled “Secrets SSOT”vox-secrets is the canonical source of truth for managed secret metadata and resolution precedence.
The encrypted local Clavis vault is the standard persistence mechanism. The
registry metadata in crates/vox-secrets/src/spec/ defines every accepted
managed secret name, and vox_secrets::resolve_secret(...) is the sole
consumer resolution API.
Naming Convention
Section titled “Naming Convention”VOX_*: Vox-owned platform contracts (mesh, runtime auth, DB, cloud orchestration, internal boundaries).
Non-secret environment parsing
Section titled “Non-secret environment parsing”Use vox_config::env_parse for numeric defaults and operator tuning (e.g. HTTP retry caps, timeouts expressed as plain integers). Do not route API keys or other credentials through those helpers — use vox_secrets::resolve_secret (and the SecretId inventory below) so precedence and aliases stay consistent.
vox-gamify free-tier AI: when FreeAiProvider::{Gemini,OpenRouter} carries an empty api_key, resolution goes through Secrets (GeminiApiKey, OpenRouterApiKey) — same canonical + compat env names as the rest of the repo; do not read GEMINI_API_KEY / OPENROUTER_API_KEY directly in new Gamify codepaths.
- Provider-native names (for example
OPENROUTER_API_KEY,OPENAI_API_KEY): upstream ecosystem names kept for compatibility. - Optional
VOX_*provider aliases are accepted as migration aids; canonical names remain stable.
Secret Inventory (Phase 0)
Section titled “Secret Inventory (Phase 0)”| Secret | Scope | Tier | Primary consumer surfaces |
|---|---|---|---|
OPENROUTER_API_KEY / GEMINI_API_KEY / OPENAI_API_KEY / ANTHROPIC_API_KEY | LLM inference | Minimal cloud LLM | vox-mcp, vox-actor-runtime, vox-cli doctor/status |
HF_TOKEN | LLM retrieval / HF router | Optional | vox-config, HF routes |
GROQ_API_KEY, CEREBRAS_API_KEY, MISTRAL_API_KEY, DEEPSEEK_API_KEY, SAMBANOVA_API_KEY, CUSTOM_OPENAI_API_KEY | Alternative LLM providers | Optional power-user | provider-specific runtime/mcp paths |
VOX_RUNPOD_API_KEY, VOX_VAST_API_KEY | Cloud GPU infra | Optional cloud GPU | vox-populi cloud providers |
TOGETHER_API_KEY | Remote fine-tune API | Optional cloud training | vox-cli train --provider together |
GITHUB_TOKEN | Publishing/review automation | Workflow-specific required | vox-cli review/publish; voxup channel::make_client (release/install auth, via SecretId::ForgeToken) |
VOX_NEWS_TWITTER_TOKEN, VOX_NEWS_OPENCOLLECTIVE_TOKEN, VOX_SOCIAL_REDDIT_*, VOX_SOCIAL_YOUTUBE_* | Scientia/news syndication | Optional (per channel) | vox-publisher resolves via Secrets SecretId specs; GitHub syndication also accepts VOX_NEWS_GITHUB_TOKEN as an alias of GITHUB_TOKEN |
ZENODO_ACCESS_TOKEN, OPENREVIEW_EMAIL, OPENREVIEW_ACCESS_TOKEN, OPENREVIEW_PASSWORD, CROSSREF_PLUS_API_KEY, DATACITE_REPOSITORY, DATACITE_PASSWORD, ORCID_CLIENT_ID, ORCID_CLIENT_SECRET, TAVILY_API_KEY, TAVILY_PROJECT, X_TAVILY_API_KEY, VOX_ARXIV_ASSIST_HANDOFF_SECRET (plus VOX_* aliases for DataCite, ORCID, Tavily where listed below) | Scholarly repository adapters | Optional (Workflow::Publish / publish_review bundle) | Zenodo / OpenReview / Crossref / DataCite / ORCID / Tavily clients resolve via Secrets; VOX-prefixed aliases accepted where listed |
VOX_DB_URL, VOX_DB_TOKEN | Remote Codex DB | Workflow-specific required | Codex / Arca remote DB flows |
VOX_APP_DB_URL | App data-plane SQL URL (postgres/mysql/libsql/sqlite) | Optional | vox-sql backend selection for app-plane execution |
VOX_TELEMETRY_UPLOAD_URL, VOX_TELEMETRY_UPLOAD_TOKEN | Optional telemetry ingest (explicit vox telemetry upload) | Optional | vox-cli resolves via SecretId::VoxTelemetryUploadUrl / VoxTelemetryUploadToken; see ADR 023 |
VOX_SEARCH_QDRANT_API_KEY | Qdrant HTTP api-key (optional RAG sidecar) | Optional | vox_search::vector_qdrant via SecretId::VoxSearchQdrantApiKey |
VOX_SEARCH_WEB_RESEARCH_DISABLED | Not a credential — an operator/test kill switch. When truthy (1/true/yes/on), forces SearchPolicy::web_research_enabled = false, so no search leg (SearXNG, Tavily, Wikipedia/arXiv/DuckDuckGo fallbacks) can reach a live network endpoint regardless of research intent. Default: unset, i.e. web research enabled | Optional (operator/CI/test hermeticity only) | vox_search::policy::SearchPolicy::from_env via SecretId::VoxSearchWebResearchDisabled; set by vox-orchestrator-mcp’s hermetic test init (src/lib.rs, tests/common/mod.rs) so no test process ever reaches a live search engine — never set by production code |
VOX_MESH_TOKEN | Populi control-plane auth (legacy full-access token) | Workflow-specific required (any mesh-class token) | Mesh transport/auth |
VOX_MESH_WORKER_TOKEN | Worker-scoped populi HTTP bearer | Optional (advance pools) | POST join/heartbeat/inbox/ack |
VOX_MESH_SUBMITTER_TOKEN | Submitter-scoped populi HTTP bearer | Optional | POST A2A deliver only |
VOX_MESH_ADMIN_TOKEN | Mesh admin bearer | Optional | Full HTTP surface when configured |
VOX_MESH_JWT_HMAC_SECRET | HS256 key for mesh JWT bearer | Optional | JWT claims role, jti, exp |
VOX_MESH_WORKER_RESULT_VERIFY_KEY | Ed25519 verify key (hex or Standard base64) | Optional | Signed job_result / job_fail payloads |
VOX_API_KEY, VOX_BEARER_TOKEN | Runtime ingress auth | Optional hardening | vox-actor-runtime auth gate |
VOX_MCP_HTTP_BEARER_TOKEN, VOX_MCP_HTTP_READ_BEARER_TOKEN | MCP HTTP gateway auth | Optional hardening | vox-mcp HTTP gateway auth surfaces |
V0_API_KEY, VOX_OPENCLAW_TOKEN | Auxiliary tooling | Optional | island generation / OpenClaw |
VOX_RESEARCH_TRIAL_SIGNING_KEY_HEX, VOX_RESEARCH_TRIAL_SIGNER_ALLOWLIST | Research-trial campaign and benchmark-bundle signing (one trust root, D-07): Ed25519 private key (hex) and CSV of hex Ed25519 public keys trusted to sign | Optional (required only to sign or run a campaign) | vox-cli-research trial runner (vox research eval --sign/--campaign) and Phase 12 eval bundles via vox_cli_research::trial_core, resolved through SecretId::VoxResearchTrialSigningKeyHex / VoxResearchTrialSignerAllowlist; the signing key is vault-only in strict mode; an unset allowlist trusts no signer |
*_TUNING_TEMPERATURE, *_TUNING_TOP_P | LLM inference overrides (Gemini, Ollama, OpenAI, Anthropic, Together) | Optional | Resolution precedence: Request > Env > Tool Default |
Managed Secret Env Names
Section titled “Managed Secret Env Names”{{#include ../../../contracts/secrets/managed-env-names.md}}
Resolution Precedence
Section titled “Resolution Precedence”For each managed secret ID:
- canonical env name
- non-deprecated aliases (including opt-in
VOX_*aliases) - deprecated aliases (returns
DeprecatedAliasUsedstatus) - configured external backend (
infisicalorvault, when enabled) - Clavis vault (the default managed local store)
- compatibility file stores (
~/.vox/auth.json, legacy~/.vox/auth_token,.vox/populi/mesh.envwhere applicable)
Local Clavis vault troubleshooting (Windows)
Section titled “Local Clavis vault troubleshooting (Windows)”| Symptom | Likely cause | Recovery |
|---|---|---|
invalid filename on backend-status | Stale vox.exe or file: URL passed to Turso | Rebuild vox-cli; set VOX_SECRETS_VAULT_PATH to a filesystem path (not a file: URL) |
decryption failed: aead::Error | OS keyring master drift vs vault ciphertext | Backup → delete .vox/clavis_vault.db → vox secrets import-env --file <env> |
| Secret status reports a missing value after storing | The vault account or profile differs from the active process | Check vox secrets backend-status, then use vox secrets status --workflow chat --mode cloud |
The OS keyring is used when available; Clavis also supports its encrypted local
master-key fallback. Never commit vault files or .env import fragments.
Required vs Optional Model
Section titled “Required vs Optional Model”vox secrets doctorevaluates blocking requirement groups (AnyOf/AllOf) per workflow/profile.Chat/Mcpblocking model in cloud mode is OpenRouter-first (OPENROUTER_API_KEY/VOX_OPENROUTER_API_KEY); alternate providers are optional capability keys.localmode requires no cloud key;autoresolves fromVOX_INFERENCE_PROFILE.- Optional keys are reported separately as capability unlocks (not startup blockers).
- OpenRouter does not replace RunPod/Vast keys: LLM gateway credentials and cloud GPU credentials are distinct domains.
Tavily web search (optional)
Section titled “Tavily web search (optional)”- Add the key (user action — agents never enter keys): create one at https://app.tavily.com, copy it, then run
pbpaste | vox secrets set TAVILY_API_KEY --stdinand confirmvox secrets get TAVILY_API_KEYshows a redactedtvly-…. Restart the daemon so the web dispatcher picks it up. - Free tier: 1,000 API credits per month. A
basicsearch costs 1 credit,advancedcosts 2 (VOX_SEARCH_TAVILY_DEPTH);/extractsnippet uplift costs 1 credit per 5 URLs. - Session budget:
VOX_SEARCH_TAVILY_BUDGET(default 50) caps credits per process (one daemon or CLI run). Once spent, the Tavily leg reportsbudget_exhaustedand makes no request; the research trace’s retrieval stage showstavily_credits: {used, remaining}. - Switches: a present key auto-enables the Tavily leg;
VOX_SEARCH_TAVILY_ENABLED=0turns it off (reported asdisabled).VOX_SEARCH_TAVILY_URLpoints the client at a mirror or mock.VOX_TAVILY_RESEARCH=1opts into the/researchtier, which is not auto-enabled by the key because its async polling is not implemented yet.
Canonical Bundles
Section titled “Canonical Bundles”minimal_local_dev: zero required cloud keys.minimal_cloud_dev: OpenRouter only.gpu_cloud: RunPod or Vast key (plus Together optional).publish_review: GitHub token required; Zenodo / OpenReview / Crossref / arXiv-assist secrets optional (see inventory table).mesh_roles: worker or submitter mesh token (seeSecretBundle::MeshRoles/ SSOT mesh section).
Transition and Deprecation Window Policy
Section titled “Transition and Deprecation Window Policy”- Add alias support first (no breakage).
- Emit
DeprecatedAliasUsedin doctor for legacy aliases. - Keep legacy aliases for at least two release trains after warning lands.
- Remove legacy aliases from docs examples first; remove runtime support only after explicit release note and CI parity update.
Command Surfaces
Section titled “Command Surfaces”vox secrets doctor --workflow <...> --profile <dev|ci|mobile|prod> --mode <auto|local|cloud> [--bundle <minimal-local-dev|minimal-cloud-dev|gpu-cloud|publish-review>]vox secrets set <CANONICAL_ENV_NAME> --stdinvox secrets get <CANONICAL_ENV_NAME>vox secrets backend-statusvox secrets migrate-auth-store
Copy an OpenRouter key, then run the following in PowerShell. The key travels from the clipboard through standard input and is never included in shell history or as a process argument:
Get-Clipboard | .\target\debug\vox.exe secrets set OPENROUTER_API_KEY --stdinOn macOS/Linux, pbpaste | vox secrets set OPENROUTER_API_KEY --stdin (or
xclip -o / wl-paste) does the same. When standard input is an interactive
terminal, set --stdin prompts on stderr and reads one line with echo disabled,
so you can paste the key and press Enter. Piped input is read to EOF. Leading
and trailing whitespace is trimmed; empty input is rejected.
~/.vox/auth.json is a legacy compatibility and migration source only. Normal
secret creation, replacement, and deletion use the Clavis vault through the
Secrets CLI or GUI. vox secrets migrate-auth-store moves recognized legacy
entries into Clavis and removes their auth.json records.
- FORGE_TOKEN
- GH_TOKEN
- GITLAB_TOKEN
- GL_TOKEN
- GOOGLE_AI_STUDIO_KEY
- HUGGING_FACE_HUB_TOKEN
- POPULI_API_KEY
- TURSO_AUTH_TOKEN
- TURSO_URL
- VOX_ANTHROPIC_API_KEY
- VOX_CEREBRAS_API_KEY
- VOX_CROSSREF_PLUS_API_KEY
- VOX_CUSTOM_OPENAI_API_KEY
- VOX_DEEPSEEK_API_KEY
- VOX_FORGE_TOKEN
- VOX_GEMINI_API_KEY
- VOX_GROQ_API_KEY
- VOX_HF_TOKEN
- VOX_MISTRAL_API_KEY
- VOX_OPENAI_API_KEY
- VOX_OPENREVIEW_EMAIL
- VOX_OPENREVIEW_PASSWORD
- VOX_POPULI_API_KEY
- VOX_SAMBANOVA_API_KEY
- VOX_SOCIAL_REDDIT_CLIENT_ID
- VOX_SOCIAL_REDDIT_CLIENT_SECRET
- VOX_SOCIAL_REDDIT_REFRESH_TOKEN
- VOX_SOCIAL_REDDIT_USER_AGENT
- VOX_SOCIAL_YOUTUBE_CLIENT_ID
- VOX_SOCIAL_YOUTUBE_CLIENT_SECRET
- VOX_SOCIAL_YOUTUBE_REFRESH_TOKEN
- VOX_TOGETHER_API_KEY
- VOX_TURSO_TOKEN
- VOX_TURSO_URL
- VOX_V0_API_KEY
- VOX_WEBHOOK_INGRESS_TOKEN
- VOX_WEBHOOK_SIGNING_SECRET
- VOX_ZENODO_ACCESS_TOKEN
- VOX_SOCIAL_MASTODON_TOKEN
- VOX_SOCIAL_MASTODON_DOMAIN
- VOX_SOCIAL_LINKEDIN_ACCESS_TOKEN
- VOX_SOCIAL_DISCORD_WEBHOOK_URL
- GEMINI_TUNING_TEMPERATURE
- GEMINI_TUNING_TOP_P
- OLLAMA_TUNING_TEMPERATURE
- OLLAMA_TUNING_TOP_P
- OPENAI_TUNING_TEMPERATURE
- OPENAI_TUNING_TOP_P
- ANTHROPIC_TUNING_TEMPERATURE
- ANTHROPIC_TUNING_TOP_P
- TOGETHER_TUNING_TEMPERATURE
- TOGETHER_TUNING_TOP_P