Backend review fixes (stages B1/B2): salted master KDF, AAD-bound ciphertexts, hardened destructive endpoints
- crypto: master-key derivation is now scrypt (n=2^15) with a per-install
  salt (GNEXUS_CREDS_MASTER_KEY_SALT); plain sha256 kept as the legacy
  path so pre-salt data still decrypts; salt is mandatory in production
- crypto: encrypted field envelopes are now bound by aad to
  "<user_id>:<secret_id>:<version_id>" (pre-generated version ids) so a
  ciphertext transplanted between rows of the same user fails auth
  instead of silently decrypting; unbound legacy envelopes decrypt
  through a single fallback and are re-bound by scripts/migrate-crypto.py
- secrets.notes widened 140 -> 255 (model, schemas, alembic 0002)
- list_secrets: sort_by restricted to a column whitelist (422 otherwise);
  limit clamp aligned with the API layer (1..200)
- update_secret: tag normalization moved to schemas.normalize_tags; the
  metadata audit now records the tags diff BEFORE the rows change (the
  old value used to be read after the rows were cleared)
- DELETE /account-data now requires Scope.admin (ui channel unaffected)
  plus the sensitive rate limiter, and audits the deleted count
- POST /import caps payload.secrets at 1000
- POST /admin/restore takes a typed payload and resolves the filename
  against the backup listing; restore_backup itself refuses files
  outside the backup dir
- production settings: master_key_salt required, wildcard cors_origins
  rejected
- tests: 62 -> 78 (crypto KDF/aad, sort whitelist, notes cap, import cap,
  account-data scopes, restore validation, config prod rules)

Co-Authored-By: Claude Code <noreply@anthropic.com>
1 parent 6558eb8 commit ba31737f92554562fcc0d9233f1c827374bbd55b
@Eugene Sukhodolskiy Eugene Sukhodolskiy authored 22 hours ago
Showing 14 changed files
View
alembic/versions/0002_notes_widen.py 0 → 100644
View
gnexus_creds/api.py
View
gnexus_creds/backup.py
View
gnexus_creds/config.py
View
gnexus_creds/crypto.py
View
gnexus_creds/models.py
View
gnexus_creds/schemas.py
View
gnexus_creds/services.py
View
scripts/migrate-crypto.py 0 → 100644
View
tests/test_api.py
View
tests/test_backup.py
View
tests/test_config.py
View
tests/test_core.py
View
tests/test_crypto.py 0 → 100644