Commit Graph

119 Commits

Author SHA1 Message Date
kitos
c467459b51 fix(campaigns): filter existing-test picker to draft + not in any campaign
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Backend: add not_in_any_campaign filter to list_tests (subquery on
CampaignTest) and expose it as a query param on GET /tests.
Frontend: the 'Existing Test' tab now requests only
  state=draft & not_in_any_campaign=true
so tests already linked to any campaign or not in draft state
are never shown.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 09:55:02 +02:00
kitos
b19ecc0d5f feat(campaigns): prefix test names with [Campaign] on add
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- From template: name is pre-filled as '[Campaign] {template.name}'
  (user can edit before confirming).
- Existing test: renamed via PATCH /tests/{id} to prepend '[Campaign] '
  before being linked to the campaign, consistent with the APT-generated
  campaign flow.
  Idempotent — skips rename if the name already starts with '[Campaign]'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 09:19:07 +02:00
kitos
2910aea6b2 feat(campaigns): add 'From Template' tab in Add Test modal
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
The modal now has two tabs:
- 'From Template' (default): searchable/filterable template catalog
  → select template → customise name/platform/procedure/tool
  → 'Create & Add to Campaign' (two-step: POST /tests/from-template
    then POST /campaigns/{id}/tests)
- 'Existing Test': previous behaviour — add an already-created test

Both tabs share an added-count footer badge.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 09:10:03 +02:00
kitos
20075305a5 feat(review-queue): MITRE update review queue for leads
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- New /techniques/review-queue page: lists all techniques flagged for
  review after a MITRE ATT&CK sync, grouped by tactic. Leads and admins
  can mark each one reviewed inline without leaving the page.
- Sidebar: 'Review Queue' link (admin/red_lead/blue_lead only) with an
  amber badge showing the live pending count.
- TechniqueDetailPage: amber banner when review_required=true explaining
  what happened and who can act; 'Mark as Reviewed' button now amber
  coloured for visual distinction. 'Leads only' chip shown for blue_tech.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 08:58:32 +02:00
kitos
4881825fea fix(techniques): remove broken validate/reject buttons from associated tests
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
The tick/cross buttons navigated to /tests/:id/validate and /tests/:id/reject
which are non-existent routes (catch-all redirected to dashboard).
Removed both buttons; the View (FileText) icon is the correct entry point
to the test detail page where the full workflow lives.
2026-05-29 08:54:31 +02:00
kitos
de093778f6 feat(markdown): extract MITRE citations into collapsible sources section
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
(Citation: ...) patterns are stripped from body text, replaced with
Unicode superscript numbers (¹²³), and shown in a compact "Sources"
section below — collapsed when there are more than 3, expanded otherwise.
Deduplication ensures the same citation reference appears only once.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 08:44:52 +02:00
kitos
db208b9f5c feat(frontend): render markdown in description and summary fields
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- 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>
2026-05-29 08:38:53 +02:00
kitos
a8542512b4 fix(ui+backend): sidebar active state + technique status after test deletion
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- Sidebar: add `end` prop to child NavLinks so "All Tests" (/tests) is
  only highlighted when exactly on /tests, not on /tests/validated.
- Backend: recalculate technique status_global for all affected techniques
  when tests are deleted via delete_campaign(delete_tests=True), preventing
  stale coverage metrics on the dashboard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 17:55:04 +02:00
kitos
1120d8f2ce feat(tests): add Validated Tests as dedicated page, remove duplicate sidebar entry
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- New /tests/validated page with its own route and sidebar link, showing
  only validated tests with Attack and Detection result badges.
- Removed the duplicate "My Pending Tasks" sidebar entry (same as All Tests).
- All Tests table no longer shows validated tests; clicking the Validated
  counter card navigates to the new page instead.
- Validated option removed from the state filter dropdown in All Tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 17:18:21 +02:00
kitos
2eed763f9e feat(tests): separate validated tests section + waiting time column
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- Validated tests no longer appear in the active tests table; they are
  shown in a dedicated collapsible "Validated Tests" section at the bottom
  (with its own sortable table and count badge).
- Added "Waiting" column to the main table showing elapsed time since
  last update for blue_evaluating tests, sortable so Blue Team can
  prioritise the oldest pending evaluations.
- Sorting by Waiting pushes blue_evaluating rows to the top and orders
  them oldest-first by default.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 17:07:16 +02:00
kitos
8b035b5c5c fix(compliance): fix broken table layout and expand caused by nested tbody elements
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Rewrote ControlsTable with React fragments instead of nested <tbody> tags,
added ScoreBar component, improved status badges, filter header strip,
and grid layout for expanded technique cards.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:45:47 +02:00
kitos
b248c2816e fix(tests): apply user edits when creating test from template
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
The form captured name/description/platform/procedure/tool edits but
never sent them — the created test always used the raw template values.

- TestTemplateInstantiate schema: add optional override fields
  (name, description, platform, procedure_text, tool_used)
- create_test_from_template service: accept *_override kwargs;
  use override value when provided, fall back to template value
- Router: pass all override fields from payload to service
- Frontend API createTestFromTemplate: accept overrides object, spread into body
- TestFromTemplateForm: pass all form state values as overrides

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:38:40 +02:00
kitos
fa8e7f311b feat(techniques): show detection rules on technique detail page
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Backend:
- technique_query_service.get_technique_detail() now queries DetectionRule
  by mitre_technique_id == mitre_id (same field the heatmap uses)
- Rules sorted: critical → high → medium → low → informational, then alphabetically
- Returns: id, title, description, source, source_url, rule_format,
  severity, platforms, false_positive_rate

Frontend:
- New DetectionRulesSection component with expandable rows per rule
- Color-coded severity dots and badges (red/orange/yellow/blue/gray)
- Source badges (sigma=purple, elastic=blue, splunk=orange, custom=cyan)
- Shows format, false positive rate, platforms, source link on expand
- Empty state when no rules exist

Fixes: T1189 showed green in heatmap but no rules on detail page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:26:46 +02:00
kitos
2371318e9e fix(heatmap): detection rules layer uses absolute rule count, not relative max
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Before: score = (rules/max_rules)*50 + (evaluated/rules)*50
  -> everything red because relative to the 1 technique with most rules

After: score = min(rules/4 * 100, 100)  — absolute thresholds
  0 rules  = gray  (not covered)
  1 rule   = red   (25 — minimal)
  2 rules  = orange (50 — some)
  3 rules  = yellow (75 — good)
  4+ rules = green  (100 — well covered)

Also update HeatmapLegend labels to show actual rule counts instead of
meaningless percentage ranges.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:11:29 +02:00
kitos
8024f32954 feat(dashboard): auto-compute risk scores + refresh button on Critical Gaps
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- Auto-trigger POST /risk/compute on first load if no profiles exist
- Add "Refresh scores" button next to Critical Gaps header (spins while computing)
- Add computeRiskScores() to frontend/src/api/risk.ts
- After compute, invalidate risk-profiles query so table updates immediately

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 15:58:49 +02:00
kitos
45b13bccde feat(dashboard): sort Critical Gaps by risk score instead of MITRE ID
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- Create frontend/src/api/risk.ts with getRiskProfiles() API function
- Executive Dashboard fetches risk profiles and builds a techniqueId→profile map
- Critical Gaps sorted by risk_score DESC (highest risk shown first)
- Ties resolved: not_covered before not_evaluated; unscored techniques last
- Table now shows Risk Score (0-100, color-coded) and Risk Level badge per row
- Column renamed to "Critical Gaps — Top 10 by Risk Priority"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 15:42:52 +02:00
kitos
2e5b47a4a2 feat(campaigns): delete campaign button + defer Jira to Activate
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- Backend: add DELETE /campaigns/{id}?delete_tests=bool endpoint
- Backend: add delete_campaign() service — handles draft-only restriction,
  optional test deletion, nullifies child campaign FKs
- Backend: remove early Jira ticket creation from POST /campaigns,
  POST /campaigns/{id}/tests, and POST /campaigns/from-threat-actor
- Backend: activate endpoint now creates campaign Jira ticket if missing,
  then creates test tickets (all deferred from creation to activation)
- Frontend: add deleteCampaign() API function to campaigns.ts
- Frontend: two-step confirmation dialog on CampaignDetailPage —
  first confirms deletion, then asks whether to also delete associated tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 14:36:25 +02:00
kitos
664210be3d fix(types): add tempo_worklog_id to Worklog interface
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 14:10:58 +02:00
kitos
d3baa9c032 feat(tests): remove Time Log, move Tempo sync to Phase Timeline
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- Remove WorklogTimeline (manual time log) from test detail page
- TestPhaseTimeline now accepts testId, fetches its own worklogs,
  and shows Tempo sync status on the Red Team Execution row:
    • green badge if already synced (with worklog ID tooltip)
    • 'Sync to Tempo' button (blue) if not yet synced
- Add POST /tests/{id}/sync-tempo backend endpoint for manual sync:
  finds unsynced red_team_execution worklogs and pushes them to Tempo

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 14:09:16 +02:00
kitos
986e91a88a feat(evidence): inline preview for images and text/JSON files
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Adds a View button (eye icon) on each evidence card for previewable file
types. Opens a full-screen modal:
- Images (png/jpg/gif/webp/svg/…): rendered directly via <img> tag
- JSON: fetched authenticated, pretty-printed in green mono
- Text/log/md/csv/xml/yaml/…: fetched authenticated, shown in <pre>

Non-previewable files only show the Download button as before.
Modal closes on Escape or backdrop click.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 13:49:35 +02:00
kitos
0955f35015 fix(tempo,jira,tests,ui): fix 4 pending issues
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- tempo: remove unsupported `workType` kwarg from create_worklog call;
  tempoapiclient v4 does not accept it → was causing every Tempo sync to fail
- tests: set created_at=datetime.utcnow() explicitly on test creation (both
  create_test and create_test_from_template) since the DB column has no
  server default, causing 'Created —' in the UI
- jira: remove duplicate Proof of Concept section from ticket description body;
  PoC already lives in customfield_10309, no need to repeat it in description
- ui: add TestPhaseTimeline component (read-only) showing RT execution time,
  blue queue time, blue evaluation time and lead validation timestamps derived
  from test phase timestamps; placed above WorklogTimeline in test detail page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 11:38:29 +02:00
kitos
c886b6e8bb fix(jira,evidence,tempo,settings): 4-issue fix batch
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Jira — PoC custom field:
- Add customfield_10309 (Proof of Concept) to issue fields when creating
  test tickets so the attack procedure appears in the dedicated Jira field

Tempo — blue team exclusion:
- Remove blue_team_evaluation from _TEMPO_ACTIVITY_TYPES; blue team time
  is tracked internally (worklogs) for SLA but never sent to Tempo since
  blue team has no Jira access

Evidence — uploaded_at NULL fix:
- Set uploaded_at=datetime.utcnow() explicitly in upload_evidence router;
  the DB column has no server default so it was saving as NULL

Evidence — presigned URL browser access:
- Add MINIO_PUBLIC_ENDPOINT setting (config.py, docker-compose.prod.yml)
- storage.py uses a dedicated _public_client for presigned URL generation
  so browsers receive URLs with the publicly accessible hostname instead of
  the internal Docker service name (minio:9000)
- Expose MinIO port 9000 in docker-compose.prod.yml

Evidence — Jira attachment:
- After upload to MinIO, call jira.add_attachment() to attach the file to
  the linked Jira ticket (non-fatal; errors are logged and swallowed)

Settings — hide Jira/Tempo from blue team:
- ProfileSection checks user role; blue_lead and blue_tech do not see the
  Jira Integration or Tempo Integration personal settings sections

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 11:06:31 +02:00
kitos
323964ed9d fix(settings): rename Campaign Parent Ticket label to Parent Ticket
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
The field is the general parent (e.g. OFS-20795) under which campaigns
are created directly. 'Campaign Parent Ticket' was misleading.
Standalone Tests Parent Ticket remains separate (e.g. OFS-20798).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:14:48 +02:00
kitos
eeee17d260 feat(jira+tests): 5 improvements from review
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
1. Jira status → In Progress on Start Execution
   - push_test_event calls set_issue_status("In Progress") when
     new_state == "red_executing" (non-fatal, separate try/except)

2. Jira assignee set on Start Execution
   - assign_issue() called with actor.jira_account_id when operator
     clicks Start (non-fatal)

3. Standalone tests parent ticket (OFS-20798)
   - New jira.parent_ticket_standalone config key
   - get_jira_parent_ticket_standalone() falls back to parent_ticket
   - auto_create_test_issue uses standalone parent for non-campaign tests
   - Exposed in /system/jira-config GET+PATCH and SettingsPage UI

4. Tests table: Created + Updated columns
   - Add Created column (created_at), fix Updated to show updated_at
   - Both use UTC-aware date parsing (append Z if no tz suffix)
   - updated_at added to Test TypeScript interface

5. Sortable columns in tests table
   - All 7 columns sortable: Name, Technique, State, Current Team,
     Platform, Created, Updated
   - Click to sort asc, click again to reverse; ChevronUp/Down indicator
   - Default sort: Created desc (newest first)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:07:46 +02:00
kitos
43c8b241dc fix(timer): treat backend timestamps as UTC to fix 2h offset
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
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>
2026-05-27 11:58:29 +02:00
kitos
398e279116 feat(tempo): blue team Tempo time from pick-up, not queue entry
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
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>
2026-05-27 11:50:15 +02:00
kitos
69d92f500a feat(tempo): per-user Tempo API token — same pattern as Jira token
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Each user can now store their own personal Tempo API token in their
profile settings. Time is logged using each user's own credentials.

Backend:
- Migration b044: adds tempo_api_token column to users table
- User model: adds tempo_api_token column
- UserPreferencesUpdate: adds tempo_api_token field (write-only)
- UserOut: adds tempo_api_token (excluded) + tempo_token_set bool;
  @model_validator derives both jira_token_set and tempo_token_set
- users router: handles tempo_api_token same as jira_api_token
  (empty string clears it, never returned in responses)
- tempo_service: refactored to per-user token; has_tempo_configured(),
  get_user_tempo_client(user) use user.tempo_api_token; global
  TEMPO_ENABLED still acts as kill-switch
- system router: /system/tempo-test now uses current user's personal
  token (any role); removed global TEMPO_API_TOKEN dependency

Frontend:
- settings.ts: UserPreferencesUpdate.tempo_api_token, UserMeOut.tempo_token_set
- SettingsPage ProfileSection: Tempo Integration section with password
  field, show/hide toggle, configured badge, and Test Tempo button —
  mirrors the Jira token UX exactly
- JiraConfigSection: removed stale global Tempo test block

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 10:46:38 +02:00
kitos
2337abe55e fix(jira): correct browse URL, rename Procedure to Proof of Concept; feat(tempo): debug endpoint + UI
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Jira URL fix:
- JiraLinkPanel now fetches the configured Jira base URL via getJiraConfig()
  instead of hardcoding https://jira.atlassian.com; falls back to the old
  value if config is not yet loaded

Description fix:
- _build_test_description: renamed 'h3. Procedure' -> 'h3. Proof of Concept'
  so the procedure/tool block maps to the correct Jira field label

Tempo debug:
- New POST /system/tempo-test endpoint: checks TEMPO_ENABLED, token,
  user jira_account_id, and makes a real API call; always returns HTTP 200
  with status field (Cloudflare-safe)
- docker-compose.prod.yml: added TEMPO_ENABLED, TEMPO_API_TOKEN,
  TEMPO_DEFAULT_WORK_TYPE env vars (default off, ready to enable)
- SettingsPage: added 'Test Tempo Connection' button in Jira admin tab
  with clear feedback showing what's missing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 10:33:57 +02:00
kitos
a04d5308ab fix(jira): always return HTTP 200 from jira-test + strip trailing slash
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- jira-test now returns {status: "ok"|"error", message: ...} with
  HTTP 200 so Cloudflare never intercepts the response
- jira_service strips trailing slash from URL before creating Jira
  client (avoids double-slash in REST paths)
- Frontend reads data.status field instead of HTTP status code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 17:42:12 +02:00
kitos
513a7b488b fix(settings): update cache immediately on save instead of invalidating
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Using setQueryData with the PATCH response means jira_token_set is
reflected in the UI instantly — no extra GET round-trip that could
leave the badge stale.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 17:20:40 +02:00
kitos
fd4a625760 fix(settings): use useEffect for jira field init, fix token save UX
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Replace render-body setState with useEffect so field initialisation
is idiomatic React and never races with user input. Also clarifies
placeholder text: empty token field = keep current, not clear it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 17:04:22 +02:00
kitos
217c4c88b2 feat(jira): add editable jira_email field per user
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Users can now set a separate Atlassian email for Jira authentication
in Settings → Profile → Jira Integration. Falls back to the Aegis
account email when not set, so existing setups are unaffected.

- Migration b043: adds jira_email column to users table
- User model/schema: expose jira_email read/write
- jira_service: _effective_jira_email() uses jira_email ?? email
- Frontend: replaces read-only email display with editable input

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 16:40:46 +02:00
kitos
f316a249cc feat(settings): Jira config UI — admin config tab + per-user token in Profile
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- backend: add parent_ticket field to JiraConfigOut/JiraConfigUpdate/_JIRA_KEYS
- backend: add get_jira_parent_ticket() helper in jira_service; use it in auto_create_test_issue() to set issue parent
- frontend/api: add jira_token_set to UserMeOut, jira_api_token to UserPreferencesUpdate, and full JiraConfigOut/Update types with getJiraConfig/updateJiraConfig/testJiraConnection functions
- frontend: expand ProfileSection with Jira API token password field (show/hide), token status badge, and account-id field
- frontend: add JiraConfigSection component (admin): enabled toggle, URL, project key, parent ticket, save + test connection
- frontend: add Jira tab (admin-only) with Link2 icon in SettingsPage sidebar
2026-05-26 16:23:24 +02:00
kitos
0e1b8e2b39 feat(settings): Settings page with email, webhooks, notifications, profile [FASE-8]
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- SystemConfig model + migration b033 for runtime key-value config
- GET/PATCH /system/email-config + POST /system/email-test (admin only)
- email_service reads SMTP config from DB (overrides .env)
- Webhooks now accessible to red_lead/blue_lead + admin
- GET /users/me already existed; /users/me/preferences already working
- SettingsPage with 4 role-aware tabs:
  * Profile & Jira: jira_account_id, user info
  * Notifications: role-specific email/in-app toggles (12 prefs)
  * Webhooks: full CRUD + test ping (leads + admin)
  * Email/SMTP: enable toggle, server config, test email (admin only)
- Added /settings route (all authenticated users)
- Settings link added to Sidebar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 15:10:31 +02:00
kitos
d6df7fdc09 fix(audit): show UTC suffix on timestamp display
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
2026-05-19 13:05:08 +02:00
kitos
7312f9664b fix(qa): CSP hash, remove pencil icon, fetch full template on modal open
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- nginx.conf: add new CSP script-src hash (sha256-Yvj83pg...) alongside previous one
- SystemPage: remove pencil icon from template name button, keep cyan underline style
- SystemPage: switch from selectedTemplate state to selectedTemplateId + useQuery
  for getTemplateById() — ensures full template data (description, attack_procedure,
  expected_detection, tool_suggested etc.) loads before modal opens
- DB backfill already applied via SQL: UPDATE audit_logs SET timestamp = NOW()
  WHERE timestamp IS NULL (358 rows fixed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:53:02 +02:00
kitos
63da22b77e fix(qa): 5 bug fixes — audit dates, CSP, template modal, MITRE sync timeout, data source auto-sync
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- 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>
2026-05-19 12:05:35 +02:00
kitos
2495423790 fix(auth,frontend): secure cookie HTTP fix, technique links y CSP
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- 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>
2026-05-19 09:28:39 +02:00
1249391ef0 feat(snapshots): evolution API, tactic breakdown and dashboard trend chart [FASE-5.2]
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
2026-05-18 15:07:12 +02:00
a4a2adccee feat(phase-39): role-based access control overhaul + forced password change
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
- 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
2026-02-18 10:37:02 +01:00
31e116b4ba feat(phase-37): timer pause/resume + professional reporting engine
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
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
2026-02-17 17:20:45 +01:00
febf460580 feat(phase-36): automatic Tempo time tracking via workflow buttons + fix campaign test management
- 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
2026-02-17 16:59:19 +01:00
9b98f60a9a feat(phase-35): Jira + Tempo integration with internal worklogs
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Full Jira/Tempo pipeline: link Aegis entities to Jira issues, auto-sync
status hourly, log time internally with integrity hashing, and optionally
push worklogs to Tempo.

- 1.1 JiraLink model + Worklog model: Alembic migration b020 with indexes,
  enums (jiralinkentitytype, jirasyncdirection), and integrity_hash column
- 1.2 Jira service: atlassian-python-api wrapper with lazy singleton client,
  search/create/sync operations, feature-flagged via JIRA_ENABLED
- 1.3 Jira router: CRUD endpoints for /jira/links, /jira/search,
  /jira/create-issue with audit logging and entity-to-issue auto-creation
- 1.4 Tempo service: worklog push via tempo-api-python-client, auto-log from
  test completions when TEMPO_ENABLED, graceful fallback on failure
- 1.5 Worklog service + router: immutable internal time records with SHA-256
  integrity hash, CRUD at /worklogs, /worklogs/{id}/verify endpoint
- 1.6 Frontend: JiraLinkPanel component (search, link, sync, unlink) and
  WorklogTimeline component (timeline view, manual log form) integrated into
  TestDetailPage sidebar, CampaignDetailPage grid, TechniqueDetailPage
- 1.7 Jira sync job: APScheduler hourly job syncs all links from Jira,
  registered in background scheduler alongside existing jobs
2026-02-17 15:57:39 +01:00
64d64080e0 fix: resolve 20 security vulnerabilities from comprehensive audit
Critical (1-3):
- Replace hardcoded admin credentials with secure auto-generation (seed.py)
- Enforce SECRET_KEY configuration, fail in production if missing (config.py)
- Add Zip Slip and Zip Bomb protection to all ZIP import services

High/Medium (4-9):
- Add 50MB file size limit and extension whitelist to evidence uploads
- Configure CORS origins via environment variable instead of hardcoded
- Migrate JWT storage from localStorage to HttpOnly cookies (frontend+backend)
- Add rate limiting (5/min) on login endpoint via slowapi
- Replace generic dict payloads with Pydantic schemas (mass assignment)

Medium (10-17):
- Check is_active on login to prevent disabled users from authenticating
- Sanitize exception messages in API responses (system, data_sources)
- Escape LIKE wildcards in all ilike search filters across 8 routers
- Run Docker container as non-root user (appuser)
- Make MINIO_SECURE configurable via environment variable
- Add password complexity policy (12+ chars, upper/lower/digit/special)
- Implement JWT token revocation via in-memory blacklist + reduce TTL to 15min
- Replace xml.etree with defusedxml to prevent Billion Laughs attacks

Low (18-20):
- Add security headers to Nginx (CSP, X-Frame-Options, HSTS-ready, etc.)
- Disable Swagger UI/ReDoc/OpenAPI in production
- Restrict /health endpoint to internal networks via Nginx ACL

Also: rewrite install.sh as interactive wizard for guided deployment,
fix test-from-template validation error (technique_id UUID vs MITRE ID)
2026-02-11 08:56:26 +01:00
38285f885c fix: TypeScript errors blocking production build
- Replace process.env.NODE_ENV with import.meta.env.DEV (Vite compatible)
- Fix undefined not assignable to boolean|null with nullish coalescing
2026-02-10 16:18:34 +01:00
8aec3581a0 feat: production deployment setup and hardcoded URL fixes
- Fix hardcoded localhost:8000 URLs in frontend to use relative /api/v1
  path (works with Nginx proxy in prod and VITE_API_URL in dev)
- Create production entrypoint (entrypoint.prod.sh) that runs migrations,
  seeds, and starts uvicorn with 4 workers (no --reload)
- Create comprehensive install.sh script for production deployment that
  generates secure .env, builds containers, waits for health, and
  optionally triggers initial MITRE sync
- Update docker-compose.prod.yml to use production entrypoint
- Update Dockerfile to make both entrypoints executable
- Remove init.ps1 (production will always be Linux)
- Update README with production deployment instructions
2026-02-10 16:04:16 +01:00
a3f83c316a fix: D3FEND ontology-based import, template management UX, and branding
- Rewrite D3FEND import to use tactic-level APIs for reliable technique
  fetching with proper ontology IRIs, descriptions, and tactic assignments
- Fix D3FEND technique URLs to use canonical IRI (no more 404s)
- All 255 D3FEND techniques now have descriptions from the official API
- Change Deactivate button color to red in template management table
- Add custom Aegis logo and favicon replacing default Vite assets
- Remove unused old API parsing code and clean up fallback list
2026-02-10 15:53:24 +01:00
c2e9c687f4 fix: D3FEND expandable cards, System page cleanup, and multi-source improvements
- Make D3FEND defense cards clickable with expandable details and external link
- Fix D3FEND URLs to use PascalCase technique names matching the ontology
- Remove duplicate Import Atomic Red Team from System page (use Data Sources)
- Add bulk Activate All / Deactivate All buttons with confirmation modal
- Fix template admin list to show both active and inactive templates
- Add PATCH /test-templates/bulk-activate backend endpoint
- Auto-seed data sources on container startup via entrypoint.sh
- Fix SigmaHQ, CALDERA, GTFOBins import issues
- Register D3FEND sync handler in data sources router
- Add CIS Controls v8 compliance framework import
- Expand Test Catalog source filters (CALDERA, LOLBAS, GTFOBins)
- Campaign Generate from Threat Actor now opens actor selector modal
- Add coverage snapshot creation button to Comparison page
- Update README with accurate data source and feature documentation
2026-02-10 13:22:23 +01:00
14f8485f06 feat(phase-33): final polish V3 - navigation, performance, and documentation (T-238 to T-240) 2026-02-10 09:21:35 +01:00
02034d60f0 feat(phase-31): add campaign scheduling and recurring automation (T-233 to T-234) 2026-02-10 08:38:00 +01:00