Backend (reopen_test):
- Preserve red/blue validation NOTES — teams see exactly what to fix
without losing the rejection context. Previously both notes were cleared.
- Preserve all content fields: procedure_text, tool_used, red_summary,
attack_success, blue_summary, detection_result (already the case).
- Preserve evidences (separate table, unaffected — already the case).
- Still clear: validation statuses + who/when validated (fresh re-validation
required). Phase timing reset so the new execution starts clean.
Frontend:
- Button label: 'Reopen Test' → 'Continue Test' (more accurate intent)
- Dialog title: 'Reopen Test' → 'Continue Test'
- Dialog message: replaces alarming 'workflow will be restarted / clear all'
with accurate description of what is preserved vs reset
- Toast: explains what to do next
red_tech can only edit procedure/tool/summary when the test is in
red_executing state (after pressing Start Execution). In draft state they
see a read-only view and an orange hint 'Press Start Execution to begin
editing — the timer must be running first.'
blue_tech can only edit when blue_work_started_at is set (after pressing
Start Evaluation). Before that they see an indigo hint 'Press Start
Evaluation to begin editing — pick up the test first.'
red_lead, blue_lead and admin are unaffected — they retain full edit
access in all applicable states including draft.
Backend:
- submit_red_evidence: raises InvalidOperationError if no Red Team
evidence file has been uploaded for the test
- submit_blue_evidence: raises InvalidOperationError if no Blue Team
evidence file has been uploaded
Frontend:
- 'Submit to Blue Team' button: disabled + '⚠ Upload evidence first'
hint when test.red_evidences is empty
- 'Submit for Review' button: same for test.blue_evidences
- Native tooltip on disabled buttons explains the requirement
- Buttons re-enable automatically after the first file is uploaded
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New shared MarkdownText component (react-markdown + remark-gfm)
that renders links, bold, italic, lists, code, blockquotes.
External links open in a new tab with rel=noopener.
- Applied to: technique description, threat actor description,
test description, campaign description, detection rule descriptions,
D3FEND defense descriptions, red/blue summaries and validation notes.
- procedure_text (code/commands) stays in <pre> — not processed as MD.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend returns naive UTC datetimes without 'Z' suffix. JavaScript
new Date("2026-05-27T09:29:18") parses as local time (UTC+2 in Spain),
making the timer start at 02:00:06 instead of 00:00:00.
Fix: append 'Z' to any timestamp string that lacks timezone info before
passing it to new Date(), so the browser always interprets it as UTC.
Applied to both startedAt and pausedAt in LiveTimer.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously blue_started_at was set when the RED team submitted evidence
(= queue open time), so Tempo was getting total queue wait time instead
of actual work time.
Changes:
- DB: add blue_work_started_at column (migration b045), set when a blue
tech explicitly picks up the test (mirrors red_started_at for red team)
- Workflow: new start_blue_work() function + POST /tests/{id}/start-blue-work
endpoint (blue_tech / blue_lead roles). Cannot be called twice.
- submit_blue_evidence: uses blue_work_started_at (when available) as the
phase start for the Tempo worklog, falls back to blue_started_at
- reopen_test: clears blue_work_started_at alongside other timing fields
- Tempo: both red_team_execution and blue_team_evaluation now synced;
correct work_date and description per activity type
- Frontend: "Start Evaluation" button shown in blue_evaluating state when
blue_work_started_at is null; live timer shows from pick-up time
What each timestamp tracks:
blue_started_at = queue entry (SLA / internal tracking)
blue_work_started_at = pick-up by blue tech (Tempo start)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add must_change_password field to User model with migration b023
- Add POST /auth/change-password endpoint with password policy validation
- Add require_password_changed dependency to block requests until password is changed
- Add ChangePasswordModal with live password policy checklist (forced on first login)
- Show password policy in CreateUserModal and EditUserModal
- Fix backend permissions: tests, campaigns, templates, reports, evidence, worklogs
- red_tech/blue_tech: execute only, cannot create tests/campaigns/templates
- red_lead/blue_lead: create/edit tests/campaigns/templates, generate reports, no system access
- viewer: read-only everywhere, can generate reports
- Fix frontend role checks across TestDetailPage, TestDetailHeader, TeamTabs, TestsPage, CampaignsPage, CampaignDetailPage, Sidebar
Pause/Resume timer:
- Add paused_at, red_paused_seconds, blue_paused_seconds fields to Test model
- Add pause_timer/resume_timer workflow functions with accumulated pause tracking
- Auto-resume on phase submit; subtract paused time from worklog duration
- Add POST /tests/{id}/pause-timer and resume-timer endpoints
- Update LiveTimer component with pause/resume button and paused visual state
- Wire pause/resume mutations through TestDetailPage and TestDetailHeader
Professional Reporting Engine - Fase 2:
- Add ReportEngine service with Jinja2 HTML rendering, WeasyPrint PDF, and docxtpl DOCX
- Add corporate CSS stylesheet with cover page, data tables, stats grid, findings
- Create purple_campaign, coverage_report, and executive_summary HTML templates
- Add report_generation_service collecting domain data for each report type
- Add professional_reports router: GET /reports/generate/purple-campaign/{id}, coverage-summary, executive-summary
- Add analytics router with flat JSON endpoints for PowerBI: /coverage, /tests, /trends, /operators
- Add advanced_metrics router: /coverage-by-tactic, /never-tested, /avg-validation-time, /detection-rate-trend
- Add weasyprint and docxtpl to requirements.txt
- Add REPORT_TEMPLATES_DIR, REPORT_OUTPUT_DIR, COMPANY_NAME, COMPANY_LOGO_PATH to config
- Add red_started_at/blue_started_at timing fields to Test model with Alembic migration
- Modify workflow transitions to auto-create integrity-hashed worklogs: Start Execution records red_started_at, Submit to Blue Team stops Red timer and creates worklog then starts Blue timer, Submit for Review stops Blue timer and creates worklog
- Auto-sync worklogs to Tempo when test has a Jira link
- Add LiveTimer component showing real-time elapsed counter during active phases
- Clear timing fields on test reopen
- Fix campaign test management: replace broken navigate-to-tests flow with AddTestToCampaignModal that lets users search and add existing tests directly from the campaign detail page
T-115: TestDetailHeader with progress bar, contextual action buttons, and dual validation indicators
T-116: TeamTabs component with Red Team, Blue Team, Summary, and Timeline tabs
T-117: Redesigned TestDetailPage integrating new components with react-query mutations, toast notifications, and role/state-based permissions
T-118: ValidationModal for dual Red Lead / Blue Lead approval with required notes on rejection