Now that the secrets vault (#19, PR #31) is merged, credentials are still scattered across config fields, .env, and per-secret admin forms. This tracks migrating them onto the vault and collapsing the redundant UI.
${vault:NAME} already resolves at config load with .env fallback (core/config.py:43), and {{secret:NAME}} resolves in run_command — so this is mostly moving values + deleting UI, not new plumbing. .env stays a fallback throughout → migrate incrementally, no flag day.
Routing rule
- Infra vault (
${vault:}, machine-key, unseals at boot) for anything needed headless / at boot.
- Persona vault (
{{secret:}}, admin-login-unsealed) only for interactive website logins — already done.
- Email/CalDAV materialize before any admin login (himalaya TOML at boot) → infra, not persona.
To migrate
LLM provider keys → infra vault
- Fields:
core/config.py:66-74 (anthropic/openai/google/grok/deepseek_api_key + base_urls)
- Read:
core/llm.py:191-220; display api/admin.py:900-908
- Set UI: LLM tab + wizard
api/admin.py:1493-1525, 2499-2535, 106-122
- Move the 5 keys to infra vault; drop the key inputs. Keep base_urls (not secret).
Telegram bot token → infra vault
core/config.py:89; read at boot channels/telegram.py:46; UI api/admin.py:1991-2007
allowed_user_ids / whatsapp allowed_numbers are not secrets — leave.
Tavily search key → infra vault
core/config.py:244; read core/agent.py:350-352. Straightforward.
Email (IMAP/SMTP) passwords → infra vault (structured)
core/email_config.py:49; materialized into himalaya TOML email_config.py:79,88
- Caveat: materialization runs at boot (
materialize_himalaya_config) → machine-key infra, structured {username,password,host,port} per provider. UI api/admin.py:1730-1762, 2635-2676.
CalDAV / CardDAV passwords → infra vault (structured)
core/config.py:122-130; read by tool subprocesses tools/calendar_auth.py:103, tools/contacts.py:98
- Caveat: the tools read config directly, so they (not just
core/) must resolve from the vault. UI api/admin.py:1682-1729, 2678-2702.
GitHub PAT → infra vault
core/config.py:271 (tools.gh.token); injected as GH_TOKEN in core/tools.py:114-115. Drop the field, keep the test button.
Google OAuth tokens (calendar + contacts) → infra vault
core/config_store.py:60-64 (google_oauth_client_id/secret/token, contacts.google_oauth_token)
- Caveat (lower priority): these auto-refresh at runtime → migration needs vault writes on refresh, not just reads. More work than the static keys above.
UI collapse (cross-cutting)
- Once the vault owns the above, remove the per-secret inputs from LLM / channels / search / tools / email / calendar forms. The Secrets tab + wizard import become the single surface.
config_store.py:54-64 SECRET_KEYS shrinks.
Do NOT migrate (chicken-and-egg / not secrets)
admin.password_hash / admin.password_salt — this is the key that unseals the persona vault.
MPA_MASTER_KEY (core/vault.py:74) — the infra vault's own key.
- Non-secrets:
allowed_user_ids, allowed_numbers, base_urls, BROWSER_*, WACLI_*, MPA_BASE_URL.
Notes
- Tool scripts (
tools/calendar_*.py, tools/contacts.py) run as subprocesses and read config directly — they need vault access too.
- Suggested order: static keys first (LLM, Telegram, Tavily, gh — cheap/mechanical), then email + CalDAV (structured, boot-time), then Google OAuth (refresh writes), then UI collapse.
Refs #19.
Now that the secrets vault (#19, PR #31) is merged, credentials are still scattered across config fields,
.env, and per-secret admin forms. This tracks migrating them onto the vault and collapsing the redundant UI.${vault:NAME}already resolves at config load with.envfallback (core/config.py:43), and{{secret:NAME}}resolves inrun_command— so this is mostly moving values + deleting UI, not new plumbing..envstays a fallback throughout → migrate incrementally, no flag day.Routing rule
${vault:}, machine-key, unseals at boot) for anything needed headless / at boot.{{secret:}}, admin-login-unsealed) only for interactive website logins — already done.To migrate
LLM provider keys → infra vault
core/config.py:66-74(anthropic/openai/google/grok/deepseek_api_key+ base_urls)core/llm.py:191-220; displayapi/admin.py:900-908api/admin.py:1493-1525,2499-2535,106-122Telegram bot token → infra vault
core/config.py:89; read at bootchannels/telegram.py:46; UIapi/admin.py:1991-2007allowed_user_ids/ whatsappallowed_numbersare not secrets — leave.Tavily search key → infra vault
core/config.py:244; readcore/agent.py:350-352. Straightforward.Email (IMAP/SMTP) passwords → infra vault (structured)
core/email_config.py:49; materialized into himalaya TOMLemail_config.py:79,88materialize_himalaya_config) → machine-key infra, structured{username,password,host,port}per provider. UIapi/admin.py:1730-1762,2635-2676.CalDAV / CardDAV passwords → infra vault (structured)
core/config.py:122-130; read by tool subprocessestools/calendar_auth.py:103,tools/contacts.py:98core/) must resolve from the vault. UIapi/admin.py:1682-1729,2678-2702.GitHub PAT → infra vault
core/config.py:271(tools.gh.token); injected asGH_TOKENincore/tools.py:114-115. Drop the field, keep the test button.Google OAuth tokens (calendar + contacts) → infra vault
core/config_store.py:60-64(google_oauth_client_id/secret/token,contacts.google_oauth_token)UI collapse (cross-cutting)
config_store.py:54-64SECRET_KEYS shrinks.Do NOT migrate (chicken-and-egg / not secrets)
admin.password_hash/admin.password_salt— this is the key that unseals the persona vault.MPA_MASTER_KEY(core/vault.py:74) — the infra vault's own key.allowed_user_ids,allowed_numbers, base_urls,BROWSER_*,WACLI_*,MPA_BASE_URL.Notes
tools/calendar_*.py,tools/contacts.py) run as subprocesses and read config directly — they need vault access too.Refs #19.