- audit_service: set timestamp=datetime.now(utc) explicitly so DB never stores NULL
- AuditLogPage: formatDate handles null/undefined timestamps (was showing Jan 1 1970)
- nginx.conf: add CSP script-src hash for inline script (sha256-31OgE8E9...)
- system.py: MITRE sync now runs in BackgroundTasks — returns immediately, no more 120s timeout
- mitre_sync_job.py: add _run_data_sources_sync job (every 6h) that checks sync_frequency
and auto-syncs overdue enabled data sources
- SystemPage: MITRE sync result shows "started" vs "complete" message
- test-templates.ts: add updateTemplate() API function
- SystemPage: template name cell is now clickable — opens TemplateDetailModal with
full edit form (name, description, procedure, detection, platform, severity, tool)
and Save / Activate / Deactivate / Close buttons
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Algunos registros de audit_log tienen timestamp=NULL en DB.
AuditLogOut tenia timestamp: datetime (no opcional) causando
ValidationError -> 500 Internal Server Error al listar el audit log.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- auth: desacopla SECURE_COOKIES de AEGIS_ENV para que el login
funcione sobre HTTP (SECURE_COOKIES=false en servidor local)
- TechniqueCell: button -> Link para href real (right-click, a11y)
- TechniquesPage: añade Link en celda MITRE ID en vista lista
- nginx CSP: amplía connect-src con ws:/wss: para evitar bloqueos
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Revoke tokens by jti in a dedicated Redis DB, honor TTL from JWT exp on logout, reject revoked tokens in get_current_user, and add FakeRedis-backed API tests.
Add Redis 7 to Docker Compose with healthcheck and persistence, separate logical DBs for blacklist and cache, singleton redis client helpers, and unit tests with fakeredis.
Move layer dispatch, entity-not-found checks, and validation from router to heatmap_service. Router now only validates requests, calls service, and formats responses (no HTTPException, no business logic). Service raises EntityNotFoundError/BusinessRuleViolation instead of returning None. Add build_navigator_export() for centralized dispatch. 29 new tests (253 total, 0 failures).
validate_as_red/blue_lead now delegate to TestEntity. check_dual_validation routes through entity instead of assigning test.state directly. Side effects dispatched via domain events. Entity raises InvalidOperationError for backward compat. Removed 4 dead V1 xfail tests, fixed 2 real test issues. 224 passed, 0 xfailed.
- Add test_test_entity.py with 46 pure unit tests covering the full domain entity
- Fix _FakeSettings in 11 test files (REPORT_TEMPLATES_DIR, JIRA, TEMPO)
- Fix stale db.commit assertions to db.flush after UoW refactor
- Add missing mock fields for TestEntity.from_orm compatibility
- Make database.py skip pool args for SQLite in test environment
- Disable slowapi rate limiter in test client fixture
- Inject test engine into app.database to fix threading errors
- Update role assertions to match current require_any_role policy
- Mark 6 legacy V1 endpoint tests as xfail (replaced by V2 workflow)
str() on models.enums.TestState produces 'TestState.red_executing' instead of 'red_executing'. Use .value to extract the plain string before constructing the domain TestState.
transition_state() now hydrates a TestEntity from the ORM model and delegates state validation to entity.transition_to(). The entity is authoritative for which transitions are valid; VALID_TRANSITIONS and can_transition() are kept for backward compatibility.
Also adds public transition_to() method to TestEntity as the stable API surface for callers that need a single validated transition without lifecycle side-effects.