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+.
This commit is contained in:
60
frontend/src/mocks/session.ts
Normal file
60
frontend/src/mocks/session.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import type { SessionUser } from '@/types/roles';
|
||||
|
||||
/**
|
||||
* Sprint 0 mock — no backend yet. The session is selected from /login
|
||||
* and persisted in sessionStorage so route navigations preserve role.
|
||||
* Real auth lands later (D-003: local user/password v1, Keycloak OIDC v2).
|
||||
*/
|
||||
|
||||
const STORAGE_KEY = 'mimic.mock.session';
|
||||
|
||||
export const MOCK_SESSIONS: Record<string, SessionUser> = {
|
||||
rt_operator: {
|
||||
id: 'usr_001',
|
||||
displayName: 'M. Dubreuil',
|
||||
role: 'rt_operator',
|
||||
engagementId: 'eng_42',
|
||||
engagementName: 'Démo Client X',
|
||||
},
|
||||
rt_lead: {
|
||||
id: 'usr_002',
|
||||
displayName: 'A. Verlhac',
|
||||
role: 'rt_lead',
|
||||
engagementId: 'eng_42',
|
||||
engagementName: 'Démo Client X',
|
||||
},
|
||||
soc_analyst: {
|
||||
id: 'usr_soc_07',
|
||||
displayName: 'SOC · session #07',
|
||||
role: 'soc_analyst',
|
||||
engagementId: 'eng_42',
|
||||
engagementName: 'Démo Client X',
|
||||
},
|
||||
};
|
||||
|
||||
export function readMockSession(): SessionUser | null {
|
||||
try {
|
||||
const raw = sessionStorage.getItem(STORAGE_KEY);
|
||||
if (!raw) return null;
|
||||
const parsed: unknown = JSON.parse(raw);
|
||||
if (
|
||||
typeof parsed === 'object' &&
|
||||
parsed !== null &&
|
||||
'role' in parsed &&
|
||||
typeof (parsed as SessionUser).role === 'string'
|
||||
) {
|
||||
return parsed as SessionUser;
|
||||
}
|
||||
return null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function writeMockSession(user: SessionUser): void {
|
||||
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(user));
|
||||
}
|
||||
|
||||
export function clearMockSession(): void {
|
||||
sessionStorage.removeItem(STORAGE_KEY);
|
||||
}
|
||||
Reference in New Issue
Block a user