Phase 1 — Foundation (2/4)
Implement secure client-side API key management using localStorage.
Scope
src/lib/ai/storage.ts
getApiKey(provider): string | null
setApiKey(provider, key): void
removeApiKey(provider): void
clearAllApiKeys(): void
getSelectedProvider(): AIProvider | null
setSelectedProvider(provider): void
getSelectedModel(provider): string | null
setSelectedModel(provider, modelId): void
hasAnyKeyConfigured(): boolean
Storage Keys
ogcops-ai-provider → selected provider ID
ogcops-ai-model-{provider} → selected model per provider
ogcops-ai-key-{provider} → API key per provider
Behavior
- Each provider stores its key independently — switching providers preserves other keys
- Model selection is per-provider — remembered when switching back
hasAnyKeyConfigured() used to conditionally show AI features in the UI
- All functions are synchronous (localStorage is sync)
Security Considerations
- Keys stored in localStorage only — no cookies, no sessionStorage
- Keys never included in URL params (unlike other OGCOPS state)
clearAllApiKeys() removes every ogcops-ai-* entry
- No encryption (localStorage is already accessible to same-origin JS — encryption would be security theater)
Acceptance Criteria
Phase 1 — Foundation (2/4)
Implement secure client-side API key management using localStorage.
Scope
src/lib/ai/storage.tsgetApiKey(provider): string | nullsetApiKey(provider, key): voidremoveApiKey(provider): voidclearAllApiKeys(): voidgetSelectedProvider(): AIProvider | nullsetSelectedProvider(provider): voidgetSelectedModel(provider): string | nullsetSelectedModel(provider, modelId): voidhasAnyKeyConfigured(): booleanStorage Keys
Behavior
hasAnyKeyConfigured()used to conditionally show AI features in the UISecurity Considerations
clearAllApiKeys()removes everyogcops-ai-*entryAcceptance Criteria
clearAllApiKeys()removes all AI-related localStorage entries