Files
mimic-big/frontend/src/screens/login/LoginPage.tsx

313 lines
9.9 KiB
TypeScript
Raw Normal View History

feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
import { useState, type FormEvent } from 'react';
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
import { useNavigate } from 'react-router-dom';
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
import { useMutation, useQueryClient } from '@tanstack/react-query';
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
import { Logo } from '@/components/brand/Logo';
import { Button } from '@/components/ui/Button';
import { Pill } from '@/components/ui/Pill';
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
import { ApiClientError } from '@/lib/api';
import { login } from '@/session/sessionApi';
import { SESSION_QUERY_KEY } from '@/session/useSession';
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
type Mode = 'rt' | 'soc';
/**
* Login screen two distinct paths.
*
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
* Sprint 1 wires the RT operator path against POST /api/v1/auth/login.
* The SOC analyst path stays visible (so the masthead doesn't change) but
* is deferred to sprint 2 when the backend exposes /auth/soc/session.
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
*
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
* On success the server sets an HttpOnly session cookie; the response body
* is the User. We seed the TanStack Query cache directly so the next render
* pass already has the user, then navigate to /engagements (the post-login
* landing for RT). No localStorage, no client-side credential persistence.
*
* Error policy: we never echo the backend message verbatim (could leak
* "user not found" vs "wrong password"). 401 generic "Identifiants
* invalides". 4xx/5xx other → generic "Connexion impossible".
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
*/
export function LoginPage() {
const [mode, setMode] = useState<Mode>('rt');
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [errorMsg, setErrorMsg] = useState<string | null>(null);
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
const navigate = useNavigate();
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
const queryClient = useQueryClient();
const loginMutation = useMutation({
mutationFn: login,
onSuccess: (user) => {
queryClient.setQueryData(SESSION_QUERY_KEY, user);
setErrorMsg(null);
void navigate('/engagements', { replace: true });
},
onError: (err) => {
if (err instanceof ApiClientError && err.status === 401) {
setErrorMsg('Identifiants invalides.');
} else {
setErrorMsg('Connexion impossible. Réessayez dans un instant.');
}
},
});
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
const handleSubmit = (e: FormEvent) => {
e.preventDefault();
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
if (mode !== 'rt') return;
if (!username || !password) {
setErrorMsg('Nom dutilisateur et mot de passe requis.');
return;
}
loginMutation.mutate({ username, password });
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
};
return (
<div className="min-h-screen flex" style={{ backgroundColor: 'var(--surface-0)' }}>
<aside
className="hidden lg:flex flex-col justify-between w-[420px] border-r p-10"
style={{
borderColor: 'var(--line-default)',
backgroundColor: 'var(--surface-1)',
}}
>
<div className="space-y-10">
<Logo build="0.1.0" />
<div className="space-y-4">
<div className="label-system">// Mission brief</div>
<p className="text-fg-default" style={{ fontSize: '15px', lineHeight: 1.55 }}>
Internal Breach &amp; Attack Simulation platform.
<br />
<span className="text-fg-muted">
Replays red-team TTPs against client infrastructure in white-glove coordination
with the SOC. Outputs a measurable MITRE ATT&amp;CK coverage report per
engagement.
</span>
</p>
</div>
<div className="space-y-3 font-mono tabular text-fg-faint" style={{ fontSize: '11px' }}>
<div className="flex gap-3">
<span className="w-24 text-fg-subtle">deploy</span>
<span>RT infra · Caddy + TLS · OPSEC handled by RP</span>
</div>
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
<div className="flex gap-3">
<span className="w-24 text-fg-subtle">auth</span>
<span>local user/password v1 · OIDC v2</span>
</div>
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
</div>
</div>
<div className="space-y-2 font-mono text-fg-faint" style={{ fontSize: '10px' }}>
<div>// Mimic is for authorized engagements only.</div>
<div>// Access is logged, audited, and reviewed weekly.</div>
</div>
</aside>
<div className="flex-1 flex items-center justify-center px-8 py-16">
<div className="w-full max-w-[420px]">
<div className="flex items-center gap-1 mb-6" role="tablist" aria-label="Login mode">
<ModeTab
active={mode === 'rt'}
onClick={() => setMode('rt')}
tone="rt"
label="RT — operator"
hint="username + password"
/>
<ModeTab
active={mode === 'soc'}
onClick={() => setMode('soc')}
tone="soc"
label="SOC — analyst"
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
hint="session token (sprint 2)"
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
/>
</div>
<form
onSubmit={handleSubmit}
className="p-6 corner-mark"
style={{
backgroundColor: 'var(--surface-2)',
border: '1px solid var(--line-default)',
borderRadius: 'var(--radius-md)',
boxShadow: 'var(--shadow-panel)',
}}
>
<div className="flex items-center justify-between mb-4">
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
<h1
className="font-display text-fg-default"
style={{ fontSize: '15px', letterSpacing: '0.05em' }}
>
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
{mode === 'rt' ? 'Operator sign-in' : 'SOC session'}
</h1>
<Pill tone={mode}>{mode === 'rt' ? 'RT' : 'SOC'}</Pill>
</div>
{mode === 'rt' ? (
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
<div className="space-y-4">
<Field
label="Username"
name="username"
autoComplete="username"
value={username}
onChange={setUsername}
disabled={loginMutation.isPending}
/>
<Field
label="Password"
name="password"
type="password"
autoComplete="current-password"
value={password}
onChange={setPassword}
disabled={loginMutation.isPending}
/>
</div>
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
) : (
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
<SocPlaceholder />
)}
{errorMsg && mode === 'rt' && (
<p
role="alert"
className="mt-4 label-system"
style={{
color: 'var(--state-failed)',
border: '1px solid var(--state-failed)',
padding: '6px 10px',
borderRadius: 'var(--radius-sm)',
}}
>
{errorMsg}
</p>
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
)}
<div className="mt-6 flex items-center justify-between gap-3">
<p className="label-system text-fg-faint">
{mode === 'rt' ? 'OIDC Keycloak — v2' : 'Token delivered out-of-band'}
</p>
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
<Button
type="submit"
variant="primary"
disabled={mode !== 'rt' || loginMutation.isPending}
>
{loginMutation.isPending ? 'Authenticating …' : 'Enter Mimic →'}
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
</Button>
</div>
</form>
<p
className="mt-6 font-mono text-fg-faint text-center"
style={{ fontSize: '10.5px', letterSpacing: '0.08em' }}
>
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
mimic.rt.local · session cookie HttpOnly · audit log live
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
</p>
</div>
</div>
</div>
);
}
interface ModeTabProps {
active: boolean;
onClick: () => void;
tone: 'rt' | 'soc';
label: string;
hint: string;
}
function ModeTab({ active, onClick, tone, label, hint }: ModeTabProps) {
return (
<button
type="button"
role="tab"
aria-selected={active}
onClick={onClick}
className="flex-1 text-left px-3 py-2 transition-colors"
style={{
backgroundColor: active ? 'var(--surface-2)' : 'transparent',
border: '1px solid',
borderColor: active
? tone === 'rt'
? 'var(--accent-rt-muted)'
: 'var(--accent-soc-muted)'
: 'var(--line-default)',
borderRadius: 'var(--radius-sm)',
boxShadow: active ? 'var(--shadow-panel)' : 'none',
}}
>
<div
className="label-system"
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
style={{
color: active
? tone === 'rt'
? 'var(--accent-rt)'
: 'var(--accent-soc)'
: 'var(--fg-subtle)',
}}
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
>
{label}
</div>
<div className="font-mono text-fg-faint mt-1" style={{ fontSize: '10px' }}>
{hint}
</div>
</button>
);
}
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
function SocPlaceholder() {
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
return (
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
<p
className="font-mono text-fg-faint"
style={{ fontSize: '11px', lineHeight: 1.55 }}
>
SOC session sign-in lands in sprint 2 once the backend exposes
<br />
<code style={{ fontSize: '10.5px' }}>POST /api/v1/auth/soc/session</code>.
<br />
For now, use the RT path with a local account.
</p>
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
);
}
interface FieldProps {
label: string;
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
name: string;
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
type?: string;
autoComplete?: string;
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
value: string;
onChange: (next: string) => void;
disabled?: boolean;
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
}
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
function Field({ label, name, type = 'text', autoComplete, value, onChange, disabled }: FieldProps) {
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
return (
<div>
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
<label htmlFor={name} className="block label-system mb-1.5">
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
{label}
</label>
<input
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
id={name}
name={name}
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
type={type}
autoComplete={autoComplete}
feat(frontend): wire LoginPage + EngagementsPage + create dialog to backend LoginPage - RT mode now POSTs /api/v1/auth/login with controlled username/password fields. Success seeds the session cache via queryClient.setQueryData and navigates to /engagements. 401 surfaces as the generic "Identifiants invalides" — no echo of the backend detail (avoids user enumeration leaks). - SOC mode kept visually for masthead continuity but disabled with a "sprint 2" placeholder pointing at the deferred POST /api/v1/auth/soc/session endpoint. - Removed the sprint-0 mock role-picker. EngagementsPage - MOCK_ENGAGEMENTS dropped. useQuery against fetchEngagements (handles both bare-array and { items: [] } envelope shapes — backend has not pinned this yet). - Distinct loading / empty / error states. Error row surfaces an HTTP code and a Retry button. Empty state offers the create dialog. - Column shape aligned with the real Engagement schema (snake_case: name, client_name, c2_type, start_date, end_date). Dropped mock-only columns (operators, socAnalysts) — those land when backend exposes /engagements/:id/members and /engagements/:id/soc-sessions counts. engagementsApi.ts - fetchEngagements + createEngagement, both bound to /api/v1/engagements. - ENGAGEMENTS_QUERY_KEY exported so the dialog can invalidate without re-knowing the key. EngagementCreateDialog (frontend-design skill — new non-trivial component) - "Arm engagement" mission-control dialog. Backdrop is a graphite dim with a faint scanline overlay (no soft blur) — reads as "cockpit paused while you issue a command", not as a SaaS modal. - Surface --surface-3 with corner-marks and an amber hairline accent under the title; underline-style inputs that light amber on focus; label-system uppercase microtypography throughout. - Esc + outside-click close (suspended while the mutation is in flight). - Rudimentary tab focus trap. - 422 Pydantic errors map per-field via the last loc segment; 401/5xx surface as a generic top-of-form alert. - On 201 invalidates ['engagements'] and closes.
2026-05-23 04:26:48 +02:00
value={value}
onChange={(e) => onChange(e.target.value)}
disabled={disabled}
required
className="font-sans"
feat(frontend): wireframes for 5 MVP screens + audit (F0.3) Mock-data wireframes covering spec §5 / §9 surface area. All read from src/mocks/fixtures.ts — no backend wiring yet. Each screen is built from the design-system primitives (Panel, Pill, Button, label-system, status-dot) and adheres to the instrumentation-grade visual grammar. Screens: - /login LoginPage — RT vs SOC mode switch (segmented), role-tinted. RT form picks rt_operator / rt_lead at sign-in (mock only). SOC form takes a session token (out-of-band, D-006). Left rail carries mission brief + platform telemetry. - /engagements EngagementsPage — mission roster table (codename, client, status, c2_type, operators, SOC count, window). - /runs LiveCockpitPage — the cornerstone screen. 3-column layout: steps timeline | step detail (resolved command, output, evidence, detection) | side rail (DetectionPanel for SOC; EvidencePanel + DetectionPanel readonly + CleanupPanel for RT). Control bar (F6 pause/skip/retry/abort) is lead-RT-only. Stats header: steps done, detected/partial/missed counts. - /scenarios ScenarioComposerPage — 3-column composer: filterable TTP library | ordered steps with delays | inspector (params from params_schema_json, target host list, jinja2 cleanup template preview). c2_type locked at scenario level (D-F3 / H33). - /library TtpLibraryPage — catalog table with stealth-variant flagging, source provenance (custom/atr/mission), payload_type chip, tags. Import journal / ATR buttons. - /reports ReportPage — restricted MITRE matrix (techniques played only, H29), narration timeline, integrity hash footer (SHA-256, H19/H24/F9). PDF/JSON/MD export buttons. - /audit AuditPage — append-only journal viewer (lead RT only, F13). Tabular timestamp/actor/role/action/resource. UX guardrails baked in: - SOC analysts never see RT-only controls (conditional rendering, not just disabled state). UI layer mirrors backend RBAC but does not replace it. - Layout density and dark-first palette tuned for long purple sessions (sober contrast, no flash, status colors carry information without being shouted). - Live cockpit reserves a clear visual slot for cleanup-failed alerts (R-T5) — currently a Pill, real alert UX lands when the WebSocket is wired in sprint 1+.
2026-05-21 20:31:24 +02:00
style={{
width: '100%',
height: 32,
padding: '0 10px',
backgroundColor: 'var(--surface-inset)',
color: 'var(--fg-default)',
border: '1px solid var(--line-strong)',
borderRadius: 'var(--radius-sm)',
fontSize: 12.5,
}}
/>
</div>
);
}