SPEC.md phase 2: "après que la V1 soit terminée, nous ajouterons une couche permettant
de se connecter à un C2 (mythic ou maison) afin d'exécuter des simulations au travers du C2."
## §0 — Binding decisions (locked with user, 2026-06-10)
1.**C2 target**: Mythic 3.x, behind a thin `C2Adapter` interface (keeps the door open for a custom C2 later).
2.**Scope**: FULL bidirectional — execute + near-real-time tracking + history import. User explicitly overrode the "one-shot first" recommendation; overrun risk accepted (see R1).
3.**C2 config**: per-engagement (URL + API token). Token is write-only at the API level — never returned in clear.
4.**UI anchor**: execution lives in the simulation screen (Red Team card).
5.**Realtime mechanism**: short polling. Frontend: TanStack Query `refetchInterval` 2 500 ms while any attached task is incomplete. Backend: poll-on-read — refreshes non-completed tasks from Mythic when the task list is read. No scheduler, no new infra.
6.**Secret storage**: API token Fernet-encrypted in SQLite. Key from env var `MIMIC_ENCRYPTION_KEY` (mandatory to enable C2 features, never hardcoded — OPSEC rule).
7.**History import**: BOTH — auto-attach of tasks launched from Mimic AND manual browse/select of the callback's task history.
8.**Validation**: fully mocked — no dev Mythic instance available. pytest uses a mocked adapter; e2e uses a built-in `FakeAdapter` selected via `MIMIC_C2_ADAPTER=fake`.
9.**RBAC**: C2 is a RedTeam resource — admin + redteam full access, SOC gets 403 on every C2 endpoint (same precedent as Templates and Export).
10.**Workflow tie-in**: launching a C2 execution auto-transitions the simulation `pending → in_progress` (same rule as a manual RT edit).
11.**Output mapping**: when a task completes (or is imported), its output is APPENDED to `execution_result` prefixed by a `$ <command>` header line; `executed_at` is set from the first task's timestamp if empty; the command is appended to `commands` if not already present.
Implementations: `MythicAdapter` (requests, `verify_tls` flag from config — lab instances run self-signed), `FakeAdapter` (deterministic in-memory data, selected by `MIMIC_C2_ADAPTER=fake`, also powers e2e).
**Milestones:** M1 crypto service (Fernet) + migration + config CRUD + test endpoint → M2 callbacks + execute → M3 poll-on-read status/output + mapping → M4 history + import.
**Tests:** pytest with mocked adapter (~35-45 new), zero live HTTP. Crypto round-trip, RBAC 403 matrix, mapping idempotence, migration up/down.
## §3 — Frontend (frontend-builder)
- **Engagement detail/form**: "C2 configuration" card — URL, token (password input, write-only placeholder when `has_token`), verify-TLS checkbox, [Test connection] with result feedback. Admin+redteam only.
- **SimulationFormPage RT card**: [Execute via C2] button (hidden when no config; disabled when done) → modal: callback picker table (display_id, host, user, active, last_checkin — font-mono data cells) → commands textarea prefilled from `rt.commands` → Launch.
- **C2 tasks panel** (under RT card): table of attached tasks — command (mono), status badge (semantic tokens), completed_at (mono). `refetchInterval` 2 500 ms while any incomplete; stops when all done.
- **Import history modal**: callback picker → paginated task list with checkboxes → [Import selected].
- Terminal-SOC compliance: rounded-none, zero transitions, hairline borders, mono for data only. Status colors via `success`/`warn` semantic tokens.
- Vitest ~15-20 new tests. `data-testid` on every new interactive surface for e2e.
## §4 — Docs & hygiene
- **SPEC.md C2 section = FIRST commit** of the sprint (sprint 5/6 lesson: never close a sprint with SPEC uncommitted).
- README: `MIMIC_ENCRYPTION_KEY`, `MIMIC_C2_ADAPTER` env vars + docker compose example.
- CHANGELOG sprint 8 entry at close.
## §5 — Pipeline & sequencing
1. spec-reviewer pre-pass on this plan (before any code).
2. backend-builder M1+M2 → API contract frozen → frontend-builder starts (parallel with backend M3+M4).
3. design-reviewer on new UI surfaces (screenshots come from the Playwright run — e2e bootstraps its own users, which sidesteps the sprint-7 credentials wall).
4.**code-reviewer must be respawned** (killed 2026-06-10 after idle-loop malfunction) before the review phase.
5. test-verifier: new C2 Playwright specs (fake adapter) + **full 223-spec re-run** — also clears the sprint 7 e2e debt (suite never re-ran after the design refresh).
## §6 — Risks
- **R1 — scope**: full bidirectional in one sprint. Mitigation: M1→M4 are ordered; M4 (history import) is the cut line if we overrun. User accepted explicitly.
- **R2 — schema fidelity**: no live Mythic to validate against; adapter pinned to the official `MythicMeta/Mythic_Scripting` client source on **master @ 2026-06-10** (verified via raw.githubusercontent.com). First real connection may need a small patch. README records the exact source URL alongside the "may need a patch" note. Adapter must defensively handle `response_text` base64 decode failures (binary output): on `binascii.Error` keep raw bytes hex-encoded with a prefix `<binary> ` so `execution_result` never silently corrupts.
- **R3 — secret at rest**: Fernet + env key; key rotation out of scope (documented limitation).
- **R4 — polling load**: poll-on-read touches only incomplete tasks of the open simulation — bounded.
- **R5 — e2e drift**: sprint 7 redesign never re-validated by Playwright; the full re-run in §5.5 surfaces any breakage — budget fix time.
## §7 — Definition of Done
- pytest green (256 baseline on main + new), vitest green (139 baseline + new), Playwright full suite green (223 baseline + new C2 specs).