feat: add credential server for secure API key storage
Summary
Implements a credential server that stores API keys server-side, eliminating the need to store credentials in the browser. This addresses the security concern that service worker separation is not enough to protect API keys from XSS attacks.
Architecture
Main Thread Web Worker Credential Server AI Provider
│ │ │ │
├─ postMessage ────────>│ │ │
│ ├─ fetch (+ cookie) ──────>│ │
│ │ ├─ decrypt creds │
│ │ ├─ fetch ─────────────>│
│ │ │<─ response ──────────┤
│ │<─ response ──────────────┤ │
│<─ postMessage ────────┤ │ │
Key Changes
-
New credential server (
src/credential-server/)- SQLite storage with encrypted credentials (AES-256-GCM)
- Setup page for API key entry (
/setup) - Proxy endpoint for API requests (
/proxy) - HTTP-only cookies for session management
-
ProxiedAnthropicProvider (
src/providers/ProxiedAnthropicProvider.ts)- Routes requests through credential server instead of directly to Anthropic
- Handles session authentication via cookies
-
Worker initialization
- Added
INITcommand to configure credential server URL - Worker uses
ProxiedAnthropicProviderwhen URL is configured
- Added
-
Docker support (
docker/credential-server/)- New Dockerfile and server.js entry point
- Volume mount for persistent SQLite database
Usage
- Deploy credential server with
CREDENTIAL_ENCRYPTION_SECRETenv var - Initialize ai-delegate with
credentialServerUrloption:await AiDelegate.init({ endpoint: '/ai-delegate', credentialServerUrl: 'https://creds.example.com' }); - Users visit
/setupon the credential server to enter their API key - Subsequent requests use session cookies automatically
Test Plan
-
Build passes -
Credential server starts successfully -
Setup page accepts and stores API key -
Proxy endpoint forwards requests correctly -
Session cookies work across requests
Closes #2 (closed)