kveton adds encrypted BYOK storage for Anthropic and Gemini provider keys
CaseMark's mikeoss-casedotdev fork now lets users save their own Anthropic or Gemini keys alongside (or instead of) the Case.dev model gateway. Keys are encrypted at rest using the same helpers already in place for Case credentials, validated against a live `/v1/models` call on save, and stored with verification metadata. The model catalog then reads from whatever credentials are configured to decide which providers are selectable.
The core new file is backend/src/lib/providerCredentials.ts (385 lines). It handles the full credential lifecycle: encryption using encryptCaseApiKey/decryptCaseApiKey, a live model-list validation call on save, a provider_api_credentials Postgres table (migration 009), and status tracking with last4, verified_at, last_checked_at, and a capabilities jsonb blob ({ llm, model_count }).
Removing a key soft-deletes the row rather than deleting it - the review pass (2032ca81) changed clearProviderApiKey from a .delete() to an .update() that zeroes the key material, sets status: "invalid", and stamps revoked_at. This preserves the audit row without leaving a decryptable key behind.
The server fallback (honoring ANTHROPIC_API_KEY/GEMINI_API_KEY from .env) defaults to false in production. The initial commit had this enabled by default, but the review pass added a NODE_ENV === "production" hard block regardless of the env var, so staging and dev still work from .env while production requires a user-saved key.
The Account > Models page was reorganized into four sections (Case.dev, Model Providers, Model Defaults, Storage). Provider availability checks that were duplicated across ChatInput, TRChatPanel, TabularReviewView, and useSelectedModel got consolidated into a modelAvailability.ts helper.
Spotted something wrong? Or know the PR text has fresher detail than the writeup above?