Files
Lumotia/docs/architecture-map/04-llm-formatting-mcp/cloud-providers-stubs.md
Jake 2491c7a7dd
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
agent: lumotia-rebrand — fix Codex cross-model review blockers
Codex independent review found 11 blockers post-cascade. All addressed.

CRITICAL (data-loss / crash):

10. crates/core/src/paths.rs — migrate_legacy_data_dir_inner used
    fs::rename which fails with EXDEV when source + target are on
    different filesystems (encrypted-home, bind mounts, separate
    $XDG_DATA_HOME partition). Combined with the Phase 5 QC fix that
    made migration errors fatal, this would crash on first launch
    for any user whose data dir spans filesystems. Added
    rename_or_copy_tree() that falls back to copy_dir_recursive +
    remove_dir_all on CrossesDevices / errno 18 (EXDEV). Symlinks
    preserved verbatim. Same fallback applied to magnotia.db ->
    lumotia.db inside the dir.

11. Added 4 unit tests: copy_dir_recursive preserves nested
    structure, rename_or_copy_tree same-filesystem happy path,
    is_cross_device classifies CrossesDevices kind + raw errno 18.

Doc residuals (blockers 1-9):

1. crates/cloud-providers/Cargo.toml — "Wyrdnote pending rebrand"
   description.
2. crates/cloud-providers/src/provider.rs — module docs + test
   fixture Wyrdnote refs.
3. crates/transcription/src/orchestrator.rs — module docs + test
   fixture Wyrdnote refs.
4. docs/roadmap/2026-05-10-pkm-phase-tooling-shortlist.md — phase
   name + outputs/wyrdnote path refs.
5. docs/architecture-map/04-llm-formatting-mcp/llm-tests.md —
   MAGNOTIA_LLM_TEST_MODEL env var.
6. .../cloud-providers-stubs.md — MAGNOTIA_API_KEY_*.
7. docs/architecture-map/03-audio-transcription/tests-and-fixtures.md
   — MAGNOTIA_WHISPER_*.
8. docs/gpu-tuning/plan.md — MAGNOTIA_BENCH_RUN.
9. docs/superpowers/specs/2026-05-09-battery-gpu-aware-thread-tuning-
   design.md + corresponding plan — MAGNOTIA_POWER_STATE_OVERRIDE,
   MAGNOTIA_INFERENCE_THREADS.

cargo test --workspace: 343 pass / 0 fail (up from 339; +4 EXDEV
fallback tests).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 13:39:21 +01:00

7.2 KiB

name, type, slice, last_verified
name type slice last_verified
Cloud providers (stub crate) architecture-map-page 04-llm-formatting-mcp 2026/05/09

Cloud providers (stub crate)

Where you are: Architecture mapLLM, Formatting, MCP → Cloud providers

Plain English summary. lumotia-cloud-providers is reserved scaffolding for future bring-your-own-key cloud STT integrations. Today, only an in-memory API key store is wired. No HTTP transports, no OpenAI client, no Anthropic client, no STT calls. The crate exists so the workspace shape is right when those features land.

At a glance

  • Crate: lumotia-cloud-providers
  • Paths:
    • crates/cloud-providers/Cargo.toml — 9 lines
    • crates/cloud-providers/src/lib.rs — 3 lines (re-exports)
    • crates/cloud-providers/src/keystore.rs — 77 LOC (the only real code)
  • LOC total: ~80
  • Public surface:
    • pub fn store_api_key(provider: &str, key: &str) (crates/cloud-providers/src/keystore.rs:15)
    • pub fn retrieve_api_key(provider: &str) -> Option<String> (crates/cloud-providers/src/keystore.rs:27)
    • Both re-exported at crate root via pub use keystore::{retrieve_api_key, store_api_key} (crates/cloud-providers/src/lib.rs:3).
  • External deps that matter: only lumotia-core (declared, not currently used by the keystore — reserved for the future provider implementations). std::env for the env-var fallback.
  • Tauri command that calls this (slice 2, best guess): no current call sites observed in src-tauri/src. The intended call sites are commands::cloud::store_api_key_cmd / _retrieve for any future provider configuration UI, but neither exists today.

What's in here

lib.rs (crates/cloud-providers/src/lib.rs:1)

Three lines:

pub mod keystore;

pub use keystore::{retrieve_api_key, store_api_key};

That is the entire public surface. Anything else is an implementation detail of the keystore.

keystore.rs — process-local API key store

store_api_key(provider, key) (crates/cloud-providers/src/keystore.rs:15):

  • Acquires the global Mutex<HashMap<String, String>> (api_key_store static, :37).
  • Inserts under the key provider_env_key(provider) which formats as LUMOTIA_API_KEY_{PROVIDER_UPPERCASED}.
  • Returns nothing — last-write-wins.

retrieve_api_key(provider) (crates/cloud-providers/src/keystore.rs:27):

  • Looks up the in-memory key first.
  • Falls back to std::env::var(env_key) if not present in memory.
  • Returns Option<String>.

The fallback is the why behind the LUMOTIA_API_KEY_<PROVIDER> naming convention: an operator can inject a key via the environment without going through the in-memory store, which is useful for headless / CI runs.

Documented TODO

crates/cloud-providers/src/keystore.rs:13:

TODO: Replace with the keyring crate (or platform-native credential storage) so keys persist across sessions and are accessed safely.

In-memory keys vanish on process exit — the user has to re-enter every key after every restart. The keyring crate (Linux: Secret Service / KWallet, macOS: Keychain, Windows: Credential Manager) is the clear next step. Not yet picked up.

Tests (crates/cloud-providers/src/keystore.rs:46)

  • stored_key_is_retrievable_without_env_mutation (:55) — store then retrieve.
  • providers_do_not_overlap (:65) — two providers stored independently.

A static atomic counter generates unique provider names per test so concurrent runs do not see each other's keys (unique_provider, :51).

What is not here

The crate's name and Cargo description ("BYOK cloud STT provider stubs and API key storage for Lumotia") imply a much larger surface. None of this exists yet:

  • No HTTP client. No reqwest dependency, no transport layer.
  • No OpenAI / Anthropic / Whisper API clients. No request/response types, no streaming code.
  • No STT request type. Nothing that converts a Vec<f32> of audio samples into a transcript via a remote provider.
  • No provider trait. No trait CloudProvider { async fn transcribe(...) } shape.
  • No persistent key storage. Documented as TODO.
  • No rate-limiting, retry, backoff. Reasonable for a stub crate.
  • No usage logging. Hard requirement for a feature that costs the user money — must come with the first real transport.

Data flow

Today:

caller (currently no in-tree caller)
  → store_api_key(provider, key)
       → api_key_store().lock().insert("LUMOTIA_API_KEY_{PROVIDER}", key)
  → retrieve_api_key(provider)
       → check in-memory map
       → fall back to std::env::var
       → return Option<String>

Intended (future):

Tauri command (commands::cloud::transcribe_cmd, hypothetical)
  → retrieve_api_key("openai") → Option<String>
  → reqwest POST to provider transcribe endpoint
  → parse provider response → lumotia_core::types::Segment list
  → return to caller, who feeds it into the formatting pipeline

The formatting pipeline does not need to change to consume cloud-transcribed segments — Segment is already the contract.

Watch-outs

  • Empty crate is intentional. Removing it would be premature; the workspace shape and the BYOK plan are both implied by its presence. But anyone doing slice analysis ("what does this crate do?") needs to know it does almost nothing today.
  • API keys vanish on restart. The TODO is explicit. Until keyring integration lands, every cloud-provider feature using these helpers will need to re-prompt the user on every startup or break for headless deployments. Acceptable for a stub; not acceptable for a shipped feature.
  • Env-var fallback is LUMOTIA_API_KEY_<PROVIDER>. Provider names are uppercased in the env-key construction. A provider name with hyphens or underscores will produce a slightly weird-looking env var; not broken, but worth knowing. provider = "open-ai" becomes LUMOTIA_API_KEY_OPEN-AI.
  • No threading concerns beyond the mutex. Mutex<HashMap> is fine here because keys are written rarely and read on the path of a network call that dwarfs any contention. The previous note in the doc-comment about "undefined behaviour of mutating process environment variables from arbitrary threads" refers to a discarded design that used std::env::set_var — that approach is unsound under the modern Rust memory model. The current in-memory map is the safe replacement.
  • lumotia-core dependency is declared but not currently used in this file. It is reserved for when the providers themselves arrive (they will likely consume Segment and tuning helpers).
  • Security of the in-memory map is process-lifetime only. A core dump or a memory-inspection attack reveals the keys. The keyring-backed replacement will inherit OS-level protections; until then the threat model is "user trusts their own machine".
  • No call sites in the Tauri binary today. Searching src-tauri/src for cloud_providers, store_api_key, or retrieve_api_key returns nothing. The crate is purely speculative scaffolding right now. Confirmed: the only references in the workspace are within the crate itself.

See also