M1 — Single SessionProvider via nested router. The previous router had two route entries with `path: '/'` (Navigate, AppShell) plus a separate `/login` entry, each wrapped in its own RootLayout. That instantiated SessionProvider three times, forking state the moment session writes diverged across siblings. Replaced by one Root route with SessionProvider + <Outlet />, and index/login/AppShell-children nested underneath. RootLayout (the per-tree wrapper) is now obsolete and deleted; the new Root component lives in src/routing/Root.tsx (addresses NIT N4 as a side effect). M2 — Typo: "pollign" → "polling" in LiveCockpitPage masthead. M3 — Replace asymmetric `?? 'rt_operator'` / `?? 'soc_analyst'` fallbacks in LiveCockpitPage with an explicit `if (!user) return null;` guard placed after all hooks (rules-of-hooks). AppShell already redirects unauthenticated visitors to /login, so the guard documents the invariant rather than introducing one. NITs N1-N3, N5-N7 recorded in tasks/todo.md as sprint 1+ follow-ups.
4.6 KiB
4.6 KiB
Sprint 0 — Mimic
Repo skeleton + foundational modules. Nothing that depends on PR1/PR2/PR3.
Backend (backend)
- B0.1 —
backend/Python project:pyproject.toml(ruff, mypy strict, pytest, coverage),Makefile,Dockerfile,docker-compose.ymlfor Postgres dev DB. - B0.2 — Alembic init + complete initial migration covering the §8 schema (incl.
c2_credential,user,group,user_group,permission,group_permission,soc_session, audit_log with write-only Postgres role). Nottp_versiontable (D-009). Seed groupsrt_operator,rt_lead,soc_analystwith F11 permissions (D-008). - B0.3 — SQLAlchemy 2 typed mapped classes for every table + repositories scaffold.
- B0.4 —
C2ConnectorABC + dataclasses (Payload,TaskHandle,TaskResult) + enumpayload_type+ factory keyed onc2_type. No real implementation. - B0.5 — Jinja2 SandboxedEnvironment +
regex_extractfilter viagoogle-re2+{{outputs.text}}and{{outputs.blob(key)}}accessors with 10 MB cap. - B0.6 — Local auth (login/password bcrypt + Flask server-side sessions) + RBAC group-based decorators + F11 permission matrix declared in code.
- B0.7 — Flat CRUD endpoints (engagements, hosts, TTPs, scenarios) — no orchestration, no WebSocket, no reporting yet.
- B0.8 — pytest baseline: unit (SQLite) + integration scaffold (testcontainers Postgres).
Frontend (ux-frontend)
- F0.1 —
frontend/Vite + React + TypeScript strict + Tailwind 4 + TanStack Query 5, eslint strict + prettier, Playwright skeleton. - F0.2 — Design system provisional: semantic tokens in
theme.css(status colors, RT accent, data mono / UI sans), dark-first palette, placeholder logo. - F0.3 — Wireframes (via
frontend-designskill) on mock data: Login + engagement selection, Live cockpit, Scenario composer, Report + MITRE matrix, TTP library + import. - F0.4 — Routing skeleton + role-aware layout shell (no real auth wired yet).
- F0.5 — Push
feature/frontend-skeleton, open PR for code-reviewer. - F0.6 — Polish M1-M3 from code-review (single SessionProvider, typo, fallback removal).
Frontend follow-ups (sprint 1+, non-blocking, from review NITs)
- N1 — Tighten
readMockSessionpayload validation when real auth wires up (currently checks onlyrole; should validate the fullSessionUsershape). - N2 — Replace the UI-side recomposition of the
MIMIC-RUN:marker in the cockpit's "Resolved command" panel withresolvedCommandTextreturned by the backend (run_step_cleanup.resolved_command_textfor cleanup, equivalent field for steps when exposed). - N3 — Wire
StatusRail.linkStateto the real WebSocket connection state once Flask-SocketIO is reachable (currently hardcoded'up'). - N4 — Unify
router.tsxand any future router helpers undersrc/routing/(single naming, no split between root file and folder). Addressed in F0.6:src/routing/Root.tsxintroduced;router.tsxleft at top level as the app-level entry that other code imports — split kept minimal. - N5 — Actually import Recharts somewhere (likely the MITRE matrix or a latency chart) since it's declared in README + package.json but not yet used.
- N6 — When vendoring IBM Plex woff2 into
public/fonts/, addpublic/fonts/LICENSE.txt(OFL-1.1) for license compliance. - N7 — Add
frontend/.env.exampleexposingVITE_API_BASE_URLandVITE_WS_URLonce the backend publishes endpoints.
Spec / Docs (spec-analyst)
- S0.1 — Cross-check the data model in B0.2 against §8 of the spec; report deltas before merge.
- S0.2 — Cross-check the RBAC matrix in B0.6 against F11; report deltas before merge.
- S0.3 — Maintain
tasks/spec-decisions.mdas new arbitrations land. - S0.4 — Open
docs/architecture.mdonce backend layout is committed.
Review (code-reviewer)
- R0.1 — Review each PR per the published charter; block on security/OPSEC violations.
- R0.2 — Verify mypy strict and ruff clean before approving any backend PR.
- R0.3 — Verify TS strict, no
useEffect(fetch), exhaustive deps before approving any frontend PR.
Conventions
- Branches:
feature/<scope>,fix/<scope>,docs/<scope>,chore/<scope>. Long-lived:main. - Commits: Conventional Commits (
feat:,fix:,chore:,docs:,test:,refactor:). - PRs: each branch → review (
code-reviewer) → team-lead merges. - No direct push to
main.