|
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> |
|---|
|
|
| alembic/versions/0002_notes_widen.py 0 → 100644 |
|---|
| gnexus_creds/api.py |
|---|
| gnexus_creds/backup.py |
|---|
| gnexus_creds/config.py |
|---|
| gnexus_creds/crypto.py |
|---|
| gnexus_creds/models.py |
|---|
| gnexus_creds/schemas.py |
|---|
| gnexus_creds/services.py |
|---|
| scripts/migrate-crypto.py 0 → 100644 |
|---|
| tests/test_api.py |
|---|
| tests/test_backup.py |
|---|
| tests/test_config.py |
|---|
| tests/test_core.py |
|---|
| tests/test_crypto.py 0 → 100644 |
|---|