Docupdate 0.9.4.1 (#55)
This commit is contained in:
51
ROADMAP.md
51
ROADMAP.md
@@ -185,7 +185,7 @@ instead of being hidden or auto-formatted without user agency.
|
||||
|
||||
---
|
||||
|
||||
## v0.9.4 — API Key Encryption + Vault
|
||||
## ✅ v0.9.4 — API Key Encryption + Vault
|
||||
|
||||
Two-tier encryption with a trust boundary between organizational keys (admin-
|
||||
accessible) and personal BYOK keys (user-only). Personal keys are protected
|
||||
@@ -277,7 +277,7 @@ non-existent account password). Builtin auth users never see this term.
|
||||
- `UnwrapUEK(ciphertext, nonce, pdk) → (uek, error)`
|
||||
- `Encrypt(plaintext, key) → (ciphertext, nonce, error)`
|
||||
- `Decrypt(ciphertext, nonce, key) → (plaintext, error)`
|
||||
- `DeriveEnvKey(envVar) → key` (SHA-256 of env var, simple deterministic)
|
||||
- `DeriveEnvKey(envVar) → key` (HKDF-SHA256 with domain separation context)
|
||||
|
||||
**Session UEK caching** — UEK stored in a sync.Map keyed by user ID, evicted
|
||||
on logout / token expiry. Completion handler retrieves UEK from cache to
|
||||
@@ -318,30 +318,45 @@ func (s *Store) DecryptAPIKey(config ApiConfig, uekCache *sync.Map) (string, err
|
||||
### Checklist
|
||||
|
||||
**Crypto core**
|
||||
- [ ] `server/crypto/vault.go` — Argon2id derivation, AES-256-GCM wrap/unwrap
|
||||
- [ ] `server/crypto/vault_test.go` — round-trip, wrong-password, corruption
|
||||
- [ ] Env-var key derivation + validation on startup
|
||||
- [x] `server/crypto/vault.go` — Argon2id derivation, AES-256-GCM wrap/unwrap
|
||||
- [x] `server/crypto/vault_test.go` — round-trip, wrong-password, corruption (11 tests)
|
||||
- [x] Env-var key derivation + validation on startup (HKDF-SHA256 with domain separation)
|
||||
- [x] `server/crypto/cache.go` — UEK cache with copy-on-read/write, memory zeroing
|
||||
- [x] `server/crypto/resolver.go` — KeyResolver routes decrypt/encrypt by key_scope
|
||||
- [x] `server/crypto/backfill.go` — startup migration for plaintext → encrypted keys
|
||||
|
||||
**Schema + migration**
|
||||
- [ ] Migration: add encrypted columns, backfill existing keys, drop plaintext
|
||||
- [ ] `ENCRYPTION_KEY` enforcement (refuse to start if keys exist but no env var)
|
||||
- [x] Migration 003_vault.sql: encrypted columns, key_scope backfill
|
||||
- [x] `ENCRYPTION_KEY` enforcement (refuse to start if keys exist but no env var)
|
||||
- [x] Unencrypted fallback when `ENCRYPTION_KEY` not set (raw bytes, graceful degradation)
|
||||
|
||||
**Auth integration**
|
||||
- [ ] UEK generation on user creation (builtin auth)
|
||||
- [ ] UEK unwrap on login, cache in session
|
||||
- [ ] UEK re-wrap on password change
|
||||
- [ ] UEK destruction on admin password reset (with confirmation)
|
||||
- [ ] Vault passphrase prompt for mTLS/OIDC (when personal providers enabled)
|
||||
- [x] UEK generation on user creation (builtin auth)
|
||||
- [x] UEK unwrap on login, cache in session
|
||||
- [x] UEK eviction on logout (memory zeroing)
|
||||
- [ ] UEK re-wrap on password change _(deferred — Settings handler)_
|
||||
- [ ] UEK destruction on admin password reset with confirmation _(deferred)_
|
||||
- [ ] Vault passphrase prompt for mTLS/OIDC _(deferred — v0.20.0 dependency)_
|
||||
|
||||
**Provider key lifecycle**
|
||||
- [ ] Encrypt on provider create/update
|
||||
- [ ] Decrypt on completion request (per key_scope)
|
||||
- [ ] `ErrVaultLocked` handling (prompt user to unlock)
|
||||
- [x] Encrypt on provider create/update (all 6 write paths: admin global, personal, team)
|
||||
- [x] Decrypt on completion request (all 4 read paths: completion, admin fetch, personal fetch, team fetch)
|
||||
- [x] `ErrVaultLocked` handling (prompt user to unlock)
|
||||
|
||||
**Admin tooling**
|
||||
- [ ] `switchboard vault rekey` CLI command
|
||||
- [ ] Admin UI: encryption status indicator
|
||||
- [ ] Admin UI: password reset warning
|
||||
- [ ] `switchboard vault rekey` CLI command _(deferred)_
|
||||
- [ ] Admin UI: encryption status indicator _(deferred)_
|
||||
- [ ] Admin UI: password reset warning _(deferred)_
|
||||
|
||||
**CI/CD**
|
||||
- [x] `ENCRYPTION_KEY` Gitea secret → k8s `switchboard-encryption` secret sync
|
||||
- [x] Backend k8s manifest: optional `secretKeyRef` for `ENCRYPTION_KEY`
|
||||
- [x] Pipeline version bump to v0.9.4
|
||||
|
||||
**Security fix (bonus)**
|
||||
- [x] DOMPurify: strict `ALLOWED_TAGS` allowlist (was permissive `ADD_TAGS` default)
|
||||
- [x] Think-block placeholder `\n\n` padding (prevents fence fusion with `</think>`)
|
||||
- [x] Unclosed code fence auto-close before `marked.parse` (streaming protection)
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user