-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Summary
Allow users to store arbitrary key-value pairs in the vault and make them accessible to skills at runtime. Currently, resolve_secrets() only handles a hardcoded set of known keys (ZEPH_CLAUDE_API_KEY, ZEPH_OPENAI_API_KEY, etc.). Skills that need to call external APIs (e.g., GitHub, Jira, weather services, custom webhooks) have no way to securely access credentials through the vault system.
Prior art
OpenClaw (TypeScript)
- Plaintext JSON store (
auth-profiles.json) + macOS Keychain for OAuth - Skills declare
requires.envin SKILL.md frontmatter — skill is excluded from system prompt if env vars are missing - Per-run
process.envinjection scoped to active skill; restored after execution primaryEnvalias:skills.entries.<name>.apiKeyauto-maps to the declared env var
ZeroClaw (Rust)
- ChaCha20-Poly1305 AEAD encryption at rest with per-value nonce
auth login/paste-token/logout/list/statusCLI for credential management- Skills do NOT declare secret dependencies — no runtime gating
- Automatic migration from legacy encryption scheme on read
Zeph advantages
- age encryption already built-in as a library (no external CLI dependency) —
AgeVaultProviderhandles keygen, encrypt/decrypt, atomic save - Proposed
ZEPH_SECRET_*prefix withcustom: HashMap<String, Secret>is more flexible than both: OpenClaw is tied to env vars, ZeroClaw to hardcoded config fields
Current behavior
resolve_secrets()inconfig/mod.rsmaps a fixed list of vault keys toConfig.secretsfields- Skills are Markdown documents injected into the system prompt — they have no direct access to vault or config
- To use an API key in a skill, users must manually export env vars or configure MCP server env in TOML
- No mechanism to declare required secrets in SKILL.md frontmatter
Proposed design
1. Custom secrets storage in Config
Add a custom field to ResolvedSecrets:
pub struct ResolvedSecrets {
// ... existing fields ...
pub custom: HashMap<String, Secret>,
}All vault keys with prefix ZEPH_SECRET_ are resolved into this map during resolve_secrets(). The prefix is stripped for the map key:
- Vault key
ZEPH_SECRET_GITHUB_TOKEN→custom["GITHUB_TOKEN"] - Vault key
ZEPH_SECRET_WEATHER_API_KEY→custom["WEATHER_API_KEY"]
2. SKILL.md frontmatter: requires-secrets
Add an optional requires-secrets field to skill metadata:
---
name: github-pr-review
description: Review GitHub pull requests
requires-secrets: GITHUB_TOKEN
allowed-tools: bash
---Comma-separated list of custom secret names. Behavior at skill activation time (inspired by OpenClaw):
- If any required secret is missing, the skill is excluded from the system prompt entirely — not just a warning. This prevents the LLM from attempting to use a skill without working credentials.
- A
tracing::warn!is emitted for observability.
3. Inject secrets into ShellExecutor environment
When a skill with requires-secrets is active, inject the corresponding secrets as environment variables into ShellExecutor calls scoped to that skill's tool invocations:
GITHUB_TOKENfromcustom["GITHUB_TOKEN"]→ set as env var for shell commands- Only inject secrets that the active skill explicitly declares (principle of least privilege)
- Redact these values in logs (already handled by
Secretwrapper andRedactLayer) - Restore environment after skill execution completes (scoped injection)
4. Vault CLI: vault set / vault get / vault list / vault remove
The AgeVaultProvider already supports arbitrary key-value storage (age encryption is built into the binary as a library, no external CLI required). Extend the CLI:
zeph vault list— show all stored key names (not values)zeph vault set <KEY> <VALUE>— already works at provider level, ensure it accepts bare names and auto-prefixesZEPH_SECRET_for custom keyszeph vault get <KEY>— print decrypted value (with confirmation prompt)zeph vault remove <KEY>— remove a key
5. TUI: Vault management panel
Add a dedicated vault/secrets panel to the TUI dashboard (feature-gated under tui):
- List view — table of all stored key names with masked values (
****), creation/update timestamps if available - Add secret — inline form: key name + value input (value masked during typing)
- Remove secret — select key, confirm deletion
- Reveal value — toggle to temporarily show decrypted value for a selected key (auto-hides after timeout or on blur)
- Skill linkage indicator — show which skills reference each key via
requires-secrets - Keyboard navigation consistent with existing TUI panels (Tab to switch panels, j/k or arrows to navigate, Enter to select,
dto delete,ato add) - All mutations go through
AgeVaultProvider+ triggerresolve_secrets()refresh
6. Interactive config wizard (--init)
Add a step to the wizard for adding custom secrets:
- Prompt: "Do you want to add custom API keys for skills?"
- Allow adding key-name + value pairs, stored via vault backend
Implementation plan
- Config changes — add
custom: HashMap<String, Secret>toResolvedSecrets, extendresolve_secrets()to scan vault forZEPH_SECRET_*prefix - SKILL.md parser — add
requires-secretstoSkillMeta, validate on load - Skill activation gate — exclude skills with missing required secrets from the system prompt (not just warn)
- ShellExecutor env injection — pass resolved custom secrets as scoped env vars to shell commands when the declaring skill is active; restore after execution
- Vault CLI — add
vault list,vault get,vault removesubcommands - TUI vault panel — list/add/remove/reveal secrets, skill linkage indicator
- Config wizard — add custom secrets step to
--init - Documentation — update
docs/and skill authoring guide
Acceptance criteria
-
zeph vault set ZEPH_SECRET_MY_KEY valuestores the key -
zeph vault listshows all stored key names -
zeph vault get ZEPH_SECRET_MY_KEYprints the decrypted value -
zeph vault remove ZEPH_SECRET_MY_KEYremoves the key -
resolve_secrets()populatesconfig.secrets.customfromZEPH_SECRET_*vault entries - SKILL.md
requires-secrets: MY_KEYis parsed and validated - Skills with missing required secrets are excluded from the system prompt
- Active skill's required secrets are injected as scoped env vars into ShellExecutor
- Environment is restored after skill execution completes
- Secret values are redacted in all log output
- TUI vault panel: list keys, add/remove secrets, reveal with auto-hide
- TUI vault panel: skill linkage indicator shows which skills use each key
- Unit tests for custom secret resolution, SKILL.md parsing, and activation gating