Backend:
- campaign_service.generate_campaign_from_threat_actor: accept optional
start_date kwarg and set it on the Campaign model
- campaigns router: new GenerateFromActorPayload schema, /from-threat-actor
endpoint now accepts optional body with start_date
Frontend:
- generateCampaignFromThreatActor API: accept optional options param
- Generate Campaign modal: date picker + warning message, same UX as the
manual create form
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1. metrics_query_service: use NULLS LAST in get_recent_tests() so tests
with actual dates always appear before NULL-dated ones.
2. campaign_service: set created_at=datetime.utcnow() when creating tests
from campaigns (was missing, leaving 21 tests with NULL created_at).
Fixed existing NULL values directly in production DB.
3. DashboardPage: add isError handling to all V2 metric widgets
(pipeline, team activity, validation rate, recent tests).
- Add retry:2 to all secondary metric queries so transient failures
are retried before showing empty state.
- Show 'Could not load X — refresh' instead of empty/misleading
'No tests created yet' when a query actually fails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Foundational changes required before any new feature work can begin.
- 0.1 Redis infrastructure: add redis:7-alpine to docker-compose dev and prod,
REDIS_URL config, singleton client in app/infrastructure/redis_client.py
- 0.2 Token blacklist on Redis SEC-001: replace in-memory dict with Redis SETEX
keyed by jti, auto-expiring TTL derived from token exp
- 0.3 Database indexes SR-006: Alembic migration b019 with 5 composite indexes
for scoring, MTTD/MTTR, remediation, and notification queries
- 0.4 Domain exceptions TD-003: app/domain/exceptions.py with typed errors,
error_handler middleware mapping them to HTTP, services decoupled from FastAPI
- 0.5 Fix silenced exceptions TD-007: replace 4 bare except-pass blocks in
test_workflow_service with logger.warning with exc_info
- 0.6 CI pipeline TD-009: GitHub Actions workflow with Postgres and Redis
service containers, ruff lint, pytest; ruff.toml for baseline config