Summary
Follow-up to PR #667, which added API plumbing to persist Organization.gemini_api_key from the Settings UI to the backend. That PR intentionally scoped out encryption-at-rest for this field, since the project does not yet have an established secrets manager or encrypted-field integration.
This issue tracks adding encryption-at-rest for gemini_api_key (and potentially other sensitive organization-level fields going forward).
Rationale
Storing API keys in plaintext in the database is a security risk. Once a secrets manager or encrypted-field strategy is chosen, this field (and similar sensitive fields) should be migrated to use it.
Affected areas
backend/users/models.py — Organization.gemini_api_key field definition
backend/users/views.py — AuthViewSet.me PATCH handling that reads/writes gemini_api_key
backend/users/serializers.py — OrganizationSerializer (currently excludes gemini_api_key from serialization)
- Possibly a new migration to convert the existing plaintext column to an encrypted field
Suggested approach
- Evaluate options: Django encrypted model fields (e.g.,
django-cryptography, django-fernet-fields), or an external secrets manager (e.g., Vault, AWS Secrets Manager, GCP Secret Manager) depending on deployment environment.
- Add the chosen encryption mechanism to
Organization.gemini_api_key.
- Write a data migration to encrypt existing plaintext values.
- Ensure decryption happens transparently wherever the key is read for AI feature calls.
- Update relevant tests.
Acceptance criteria
gemini_api_key is stored encrypted at rest in the database.
- Existing plaintext values are migrated without data loss.
- No plaintext key is ever exposed via API responses or logs.
- Documentation/README updated to note the encryption approach and any new env vars/config needed.
References
Summary
Follow-up to PR #667, which added API plumbing to persist
Organization.gemini_api_keyfrom the Settings UI to the backend. That PR intentionally scoped out encryption-at-rest for this field, since the project does not yet have an established secrets manager or encrypted-field integration.This issue tracks adding encryption-at-rest for
gemini_api_key(and potentially other sensitive organization-level fields going forward).Rationale
Storing API keys in plaintext in the database is a security risk. Once a secrets manager or encrypted-field strategy is chosen, this field (and similar sensitive fields) should be migrated to use it.
Affected areas
backend/users/models.py—Organization.gemini_api_keyfield definitionbackend/users/views.py—AuthViewSet.mePATCH handling that reads/writesgemini_api_keybackend/users/serializers.py—OrganizationSerializer(currently excludesgemini_api_keyfrom serialization)Suggested approach
django-cryptography,django-fernet-fields), or an external secrets manager (e.g., Vault, AWS Secrets Manager, GCP Secret Manager) depending on deployment environment.Organization.gemini_api_key.Acceptance criteria
gemini_api_keyis stored encrypted at rest in the database.References