feat: Add Linear action item syncing for incidents #139
3 issues
code-review: Found 3 issues (2 medium, 1 low)
Medium
Missing validation for empty salt_key when Linear OAuth is enabled - `src/firetower/config.py:78`
The salt_key field is required but can be set to an empty string, which would use a weak or default encryption key for OAuth tokens stored via django-fernet-encrypted-fields. Similar to the existing IAP validation pattern (lines 297-301 in settings.py), there should be validation that ensures salt_key is non-empty when Linear integration is enabled, since the LinearOAuthToken model uses EncryptedTextField.
Race condition in OAuth token refresh could cause concurrent request failures - `src/firetower/integrations/services/linear.py:105-113`
When multiple concurrent requests receive a 401 response, they all independently call _request_new_token(), which deletes all existing tokens and creates a new one within transaction.atomic(). While each individual transaction is atomic, the check-then-refresh pattern in _graphql (lines 105-113) is not protected. This could cause one request to delete a valid token that another concurrent request just created, leading to unnecessary token refreshes or intermittent failures under load.
Low
N+1 database queries during action item sync - `src/firetower/incidents/services.py:192-216`
The loop at lines 192-216 executes multiple database queries per issue: _resolve_assignee performs User.objects.filter() and ExternalProfile.objects.update_or_create(), then ActionItem.objects.update_or_create() runs for each issue. While bounded by Linear's API pagination (max ~1250 issues), this could cause performance issues for incidents with many action items.
Duration: 582.0s · Tokens: 1.7M in / 22.9k out · Cost: $3.21 (+merge: $0.00)
Annotations
Check warning on line 78 in src/firetower/config.py
github-actions / warden: code-review
Missing validation for empty salt_key when Linear OAuth is enabled
The `salt_key` field is required but can be set to an empty string, which would use a weak or default encryption key for OAuth tokens stored via `django-fernet-encrypted-fields`. Similar to the existing IAP validation pattern (lines 297-301 in settings.py), there should be validation that ensures `salt_key` is non-empty when Linear integration is enabled, since the LinearOAuthToken model uses EncryptedTextField.
Check warning on line 113 in src/firetower/integrations/services/linear.py
github-actions / warden: code-review
Race condition in OAuth token refresh could cause concurrent request failures
When multiple concurrent requests receive a 401 response, they all independently call `_request_new_token()`, which deletes all existing tokens and creates a new one within `transaction.atomic()`. While each individual transaction is atomic, the check-then-refresh pattern in `_graphql` (lines 105-113) is not protected. This could cause one request to delete a valid token that another concurrent request just created, leading to unnecessary token refreshes or intermittent failures under load.