R-Dash LLM auth: per-provider API keys (ADR-0027) supersede OAuth bridge (ADR-0026)
Decision
Deployed product LLM authentication uses per-provider API keys (RDASH_LLM_API_KEY + RDASH_LLM_PROVIDER + RDASH_LLM_MODEL) routed through Pydantic Settings + secret:// URI resolution. Provider guard fails closed for any non-anthropic value until adapter lands. OAuth bridge from ADR-0026 (the _assert_prod_oauth_or_override guard + RDASH_AI_OAUTH_PENDING_ACK env var) is REMOVED. Backward-compat fallback from ANTHROPIC_API_KEY / ANTHROPIC_TOKEN retained for mid-migration v1.2.x deployments.
Rationale
AJ explicit directive 2026-05-15: “If I want to use an LLM, I will use the API, not OAuth. OAuth is a personal subscription, which is not required.” Personal-usage feedback rule (feedback_fixed_cost_oauth_only.md) was scope-clarified to bind only AJ’s interactive Claude Code, not deployed products. Deployed products have product-side cost discipline (workspace_credit_cap + agent_sessions.estimated_cost_inr rollup) — OAuth’s fixed-ceiling argument doesn’t apply. Standard per-token API keys are the universal contract every provider exposes. Operationally trivial: one Secret, one env var, drops in alongside RDASH_JWT_SECRET / RDASH_DATA_ENCRYPTION_KEY.
Alternatives Rejected
- Keep ADR-0026 OAuth-pending guard, document the misapplication — REJECTED: adds friction without security benefit for a product. 2) Drop guard entirely, no key check — REJECTED: 16-char minimum catches silent-empty-secret deploys (real failure mode). 3) Provider-specific env vars (ANTHROPIC_API_KEY / OPENAI_API_KEY / MOONSHOT_API_KEY) without unification — REJECTED: operators rotating providers would have to swap variable names.
Outcome
Pending