
# Prompt

Mimic est une application WebUI de type BAS (Breach and Attack Simulation), se basant sur la matrice MITRE ATT&CK. Cette application doit permettre de réaliser des tests en purple Team en fin de mission Read Team. Elle doit être simple et conviviale à utiliser. Elle remplace l'utilisation d'un fichier excel plat que l'on partage entre la redteam et les analystes SOC en fin de mission red team.

# Details
## Simulation
Une simulation est composée des champs suivants :
* Partie RedTeam :
  - Nom du test
  - Types d'attaque MITRE correspondants (multi-techniques — une simulation peut couvrir plusieurs TTPs) sélectionnables par autocomplete OU via la matrice ATT&CK affichée en modale. Sub-techniques (ex : T1059.001) supportées.
  - Description
  - Commandes exécutés (liste)
  - Pré-requis (champs texte)
  - Date et heure d'exécution
  - Résultat d'exécution
* Partie Analyste SOC :
  - Source des logs
  - Logs obtenues
  - Commentaires
  - Numéro incident correspondant
  
## Fonctionnement
La redteam peut modifier l'ensemble des champs d'une simulation, tandis que l'analyste SOC ne peut remplir que sa partie.
Un workflow de simulation doit être mis en place : Pending, In progress, Review required, Done.
Le workflow se mettra à jour de la manière suivante :
 - Création de la simulation : pending
 - La redteam saisit des informations dans la simulation : in progress (auto)
 - La redteam décide par une action manuelle de passer la simulation en status "review required" ce qui offre à la possibilité au SOC de remplir les informations nécessaire.
 - Le SOC (ou la redteam) décide par une action manuelle de passer la simulation en status "Done".
 - **Done est terminal** : aucune édition n'est possible sur une simulation Done. Pour reprendre, n'importe lequel des trois rôles (admin / redteam / soc) peut déclencher une action "Reopen" qui ramène la simulation à "review required" — les champs redeviennent éditables selon les règles habituelles. Cette transition est la seule autorisée à quitter Done.

Un engagement correspond à une mission redteam. Il est possible d'ajouter plusieurs test dans un engagement. **Le statut de l'engagement progresse automatiquement** : créer un engagement le met à "planned" ; dès qu'une simulation de cet engagement passe en "in progress" (auto-transition par la redteam ou manuelle), l'engagement passe à "active" — pas de retour arrière automatique. La transition vers "closed" reste manuelle.

## Templates de simulations
Un **template de simulation** est une simulation pré-remplie côté redteam (name + description + commandes + pré-requis + techniques MITRE + tactiques MITRE) qui sert de point de départ pour instancier rapidement des simulations dans un engagement. Le template ne contient PAS de partie SOC, ni de date d'exécution, ni de résultat d'exécution — ces champs restent par-instance.

L'instanciation d'un template dans un engagement crée une **nouvelle simulation indépendante** : le template et l'instance sont décorrélés, l'édition de l'un n'affecte pas l'autre. Aucune référence (FK `template_id`) n'est conservée sur la simulation instanciée.

**RBAC templates = ressource Red Team uniquement** : admin et redteam les gèrent (CRUD). SOC n'a aucun accès (pas de nav link, tous endpoints templates retournent 403). Les nouveaux noms de templates sont uniques pour la clarté UX du dropdown d'instanciation.

## Export d'engagement
Un engagement peut être exporté à tout moment dans 3 formats au choix : **Markdown** (handoff narratif), **CSV** (machine-readable, intégration tableurs), **PDF** (livrable client). Endpoint unique : `GET /api/engagements/<id>/export?format=md|csv|pdf`. Réservé aux rôles admin et redteam (livrable RedTeam, cohérent avec le RBAC Templates). Filename normalisé : `engagement-<id>-<slug>-YYYYMMDD.<ext>`.

**Schéma fixe à 7 colonnes** (en-têtes français) pour tous les formats — une ligne par simulation :

| # | Colonne | Source |
|---|---|---|
| 1 | Scénario | `simulation.name` |
| 2 | Test | `simulation.description` |
| 3 | Source de log | `simulation.log_source` |
| 4 | Commentaires SOC | `simulation.soc_comment` |
| 5 | Exécution | concat multi-ligne sans labels, ordre fixe : `executed_at` → `commands` → `execution_result` |
| 6 | Logs remontés au SIEM | `simulation.logs` |
| 7 | Cyber incident | `simulation.incident_number` |

CSV : exactement 1 ligne d'en-tête + 1 ligne par simulation. Markdown : en-tête engagement (name, dates, status, created_by) puis une table de 7 colonnes. PDF : même structure que le Markdown rendue via HTML→PDF (WeasyPrint). Le statut de la simulation, les techniques/tactiques MITRE, les prerequisites et les métadonnées (id, created_at) ne sont PAS exportés — l'export est un handoff focalisé RT↔SOC, pas un dump complet.

Prévoir un module d'authentification : dans un premier temps local à la bdd.

Dans un premier temps, il s'agit juste de notifier manuellement de l'exécution et les résultats des tests.
Dans un second temps, 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 simulation au travers du C2.

## Intégration C2 (Sprint 8+)

Couche d'intégration C2 permettant d'exécuter les commandes d'une simulation à travers un Command & Control distant, suivre l'avancement des tâches en quasi-temps réel, et importer l'historique d'exécutions existant. **Implémentation de référence : Mythic 3.x**, derrière une interface `C2Adapter` mince qui ne ferme pas la porte à un C2 maison ultérieur.

**RBAC C2 = ressource Red Team uniquement** (précédent Templates + Export) : admin et redteam ont accès complet (config + exécution + import). SOC retourne 403 sur tous les endpoints C2 (pas de nav link, pas d'affichage du panneau C2).

**Configuration par engagement** : chaque engagement possède au plus une `c2_config` (URL Mythic + API token + flag `verify_tls`). Le token est **chiffré au repos** via `cryptography.Fernet` ; la clé est dérivée de l'env var `MIMIC_ENCRYPTION_KEY` (variable obligatoire pour activer la fonctionnalité C2 — jamais hardcodée, conforme à la règle OPSEC zero-secret-in-code). Le token n'est jamais renvoyé en clair par l'API — `GET /api/engagements/<id>/c2-config` retourne `has_token: bool` uniquement. Mise à jour via `PUT` ; suppression via `DELETE`. La suppression d'un engagement supprime en cascade sa `c2_config`.

**Sélection d'adapter** via l'env var `MIMIC_C2_ADAPTER` :
- `mythic` (défaut) : adapter Mythic réel (GraphQL via Hasura).
- `fake` : adapter en mémoire déterministe utilisé pour la validation Playwright et le dev local sans instance Mythic.

**Modèle de données — additions** :

`c2_config` (1 ligne par engagement au max) :
| Colonne | Type | Notes |
|---|---|---|
| `id` | int PK | |
| `engagement_id` | int FK `engagements.id` ON DELETE CASCADE, **UNIQUE** | |
| `url` | text | endpoint Mythic, ex. `https://lab.internal:7443` |
| `api_token_encrypted` | text | Fernet ciphertext, jamais en clair |
| `verify_tls` | bool, défaut `false` | Désactivé par défaut — Mimic cible des labs Mythic avec certs auto-signés. Cocher pour forcer la vérification TLS en prod. |
| `created_at`, `updated_at` | datetime | |

`c2_task` (lien simulation ↔ tâche Mythic) :
| Colonne | Type | Notes |
|---|---|---|
| `id` | int PK | |
| `simulation_id` | int FK `simulations.id` ON DELETE CASCADE | |
| `mythic_task_display_id` | int | identifiant côté Mythic |
| `callback_display_id` | int | callback Mythic sur lequel la tâche tourne |
| `command` | text | commande envoyée |
| `params` | text nullable | paramètres associés |
| `status` | text | statut brut Mythic (`submitted`, `completed`, `error`, …) |
| `completed` | bool | `true` quand la tâche est terminée |
| `output` | text nullable | sortie décodée (base64 → utf-8 ; binaire → préfixe `<binary>` + hex) |
| `source` | enum `mimic` \| `import` | tâche lancée depuis Mimic ou importée a posteriori |
| `created_at` | datetime | |
| `completed_at` | datetime nullable | timestamp de complétion |

**Endpoints C2** (tous admin+redteam ; SOC = 403) :
- `GET /api/engagements/<id>/c2-config` — `{has_token, url, verify_tls}` (jamais le token en clair).
- `PUT /api/engagements/<id>/c2-config` — `{url, api_token?, verify_tls}`.
- `DELETE /api/engagements/<id>/c2-config`.
- `POST /api/engagements/<id>/c2-config/test` — test de connectivité via l'adapter, renvoie `{ok, error?}`.
- `GET /api/engagements/<id>/c2/callbacks` — callbacks actifs de l'instance Mythic configurée.
- `POST /api/simulations/<id>/c2/execute` `{callback_display_id, commands: [str]}` — une tâche Mythic par commande, stockées dans `c2_task` (source=`mimic`). **Auto-transition** : si la simulation est `pending`, elle passe à `in_progress` (même règle que l'édition manuelle RT — cf. § Fonctionnement).
- `GET /api/simulations/<id>/c2/tasks` — poll-on-read : à la lecture, rafraîchit le statut et l'output des `c2_task` non terminées depuis Mythic, applique le mapping de sortie (voir ci-dessous) à la simulation pour chaque tâche qui vient de se terminer (idempotent — appliqué une seule fois par tâche).
- `GET /api/engagements/<id>/c2/callbacks/<cid>/history?page=` — historique paginé des tâches d'un callback, pour l'import.
- `POST /api/simulations/<id>/c2/import` `{task_display_ids: [int]}` — import sélectif de tâches (source=`import`) + mapping de sortie.

**Mapping de sortie vers la simulation** (appliqué une fois par tâche, lors de la complétion ou de l'import) :
- `simulation.execution_result` reçoit en append le bloc `\n$ <command>\n<output>\n` (préserve l'existant, jamais d'écrasement).
- `simulation.executed_at` est renseigné depuis le timestamp de la première tâche complétée si le champ est vide ; sinon non modifié.
- `simulation.commands` reçoit en append la commande si elle n'y figure pas déjà (déduplication ligne par ligne).

**Suivi temps réel** : polling court — le frontend re-fetch `GET /api/simulations/<id>/c2/tasks` toutes les **2 500 ms** via TanStack Query `refetchInterval` tant qu'une tâche attachée n'est pas terminée ; le polling s'arrête automatiquement quand toutes les tâches sont `completed`. Pas d'infrastructure ajoutée côté serveur (pas de WebSocket, pas de scheduler).

**UI** : les contrôles C2 vivent dans la carte Red Team de l'écran simulation — bouton `[Execute via C2]` ouvrant une modale (picker de callback + textarea de commandes pré-remplie depuis `commands`), panneau des tâches attachées sous la carte, et modale d'import historique. Configuration C2 visible/éditable depuis l'écran de détail/édition d'engagement.

**Validation** : MVP entièrement mocké — pytest utilise un adapter mocké (zéro HTTP live), Playwright utilise l'adapter `fake` (déterministe). Le branchement contre une instance Mythic réelle est repoussé au premier usage opérationnel et peut nécessiter un patch mineur du contrat GraphQL.

## Stacks techniques
* **FrontEnd** : WebUI
  - Stacks standard : ReactJS, Vite, TailWind etc...
  - Evite l'utilisation de remote librairie un maximum, télécharge toujours les ressources en local si possible.
  - Design récent et UI respectant le fichier `DESIGN.md`
* **Backend** : Flask Python, Base de données SQLLite
* **Livrable** : Container compatible Docker/Podman et Makefile pour gérer les différents états des containers - `start`, `stop`, `restart`, `update`, `build`, etc.

## Points importants
* Ne prend pas d'initiative. Si tu doutes d'une fonctionnalité, pose les questions afin de pouvoir coder la fonctionnalité.
* **Focus sur la méthode KISS** : Keep It Simple and Stupid. Limite toi à des fonctionnalités simples sans entreprendre du coding couteux avec des fonctionnalités non demandées.

## Workflows
* Découpage en sprint
* Chaque sprint doit apporter une nouvelle fonctionnalité à tester sur l'UI
* A chaque sprint : Code + Test (Test unitaire python + Test pywright front) + Reviews (spec + design + code). Une fois les reviews OK, PR que je valide après test.
* **Séquence sprint (depuis sprint 4)** : spec-reviewer → backend-builder → frontend-builder (livre des screenshots obligatoires) → **design-reviewer (NOUVEAU sprint 4)** → code-reviewer → test-verifier → team-lead PR.
* **design-reviewer** revoit le diff frontend + screenshots du sprint courant, audit alignement / hiérarchie typo / usage tokens DESIGN.md / cohérence visuelle / responsive. Read-only, ne modifie rien.
* A chaque fin de sprint, avant mes tests, le team lead doit me faire un récapitulatif synthétique de ce qui a été fait et ce qui doit être testé (et comment le tester).
* **Création de PR** : à la fin du sprint, le team-lead ouvre la PR via `make open-pr SPRINT=N TITLE="..." BODY=path/to/body.md` (depuis sprint 4). Le script `scripts/open-pr.sh` parse `~/.git-credentials` et POST sur l'API Gitea.

# Team

Pour ce projet, j'ai besoin d'une équipe d'agent réparti de la manière suivante :
1. Team leader : **modèle Opus**
  - Lit les spec et réparti les tâches entre les différents agents
  - En charge de la livraison de son sprint et de la création des PR
  - Met à jour le README.md quand nécessaire
  - Met à jour le fichier SPEC.md quand de nouvelles fonctionnalités ou des précisions sont apportées à certains points
  - Réfléchit à l'aspect architecturale de l'application
  - Rédige et dispatch les technical briefs
2. Backend builder : **modèle Sonnet**
  - Développement backend uniquement
  - What it builds: → API routes → Services and business logic → Database access and migrations → Background jobs → Unit tests for everything it writes
  - What it cannot do: → Touch React components, pages, or client-side hooks (that's Agent 5) → Invent new dependencies without instruction → Modify files outside agreed scope → Stop without running typecheck, lint, and the test suite
  - After finishing, it returns a summary: → Every file added or edited → Every existing helper or pattern reused → Any CLAUDE.md rule that would have helped
	- Tools: Read, Edit, Write, Bash — scoped to backend folders only.
  - Livre un code simple à comprendre sans essayer de prévoir l'avenir (se limiter au scope)
  - Ne prend pas de décision ou d'hypothèse. Si des questions subsitent, il les remonte au team lead qui décidera de la position à prendre en fonction des contraintes énnoncés par le développeur.
  - Livre un code propre, avec les tests appropriés (success, failure, edge cases)
3. Front builder : **modèle Sonnet**
	- Développement frontend uniquement
	- It reads the Backend Builder's summary first.
	- It consumes the API exactly as the backend produced it.
	- It does not invent new endpoints.
	- If the API shape is wrong for the UI, it surfaces the mismatch as feedback — not as a patch.
	- Input it receives: → Approved technical brief → Researcher's findings → Backend Builder's summary (the API contract)
	- What it builds: → React components and pages → Client-side hooks and state → Loading and error states → Component and unit tests for everything it writes
	- What it cannot do: → Touch services, API routes, workers, or migrations (that's Agent 4) → Invent endpoints or response shapes → Add dependencies without instruction → Stop without running typecheck, lint, and the test suite
	- Tools: Read, Edit, Write, Bash — scoped to frontend folders only
  - Livre un code simple à comprendre sans essayer de prévoir l'avenir (se limiter au scope)
  - Ne prend pas de décision ou d'hypothèse. Si des questions subsitent, il les remonte au team lead qui décidera de la position à prendre en fonction des contraintes énnoncés par le développeur.
  - Livre un code propre, avec les tests appropriés (success, failure, edge cases)
4. Spec reviewer : **modèle Sonnet**
	- Avant chaque début de sprint, lit les plans du team leader et valide les tâches à donner au développeur
	- Si le plan s'éloigne des spec énoncés, le dire au team leader afin qu'il mette à jour son plan pour répondre aux besoins énoncés
5. Code reviewer : **modèle Opus**
  - A la fin de chaque sprint, avant de réaliser la PR, cet agent relit le code généré par le développeur sur le sprint courant (pas tout le code, juste celui du scope).
  - Utilise un maximum les LSP quand c'est possible
  - Vérifie si des optimisations ou des factorisations de code sont possibles suite aux nouvelles implémentations du développeur.
  - Dans le cas ou des erreurs ou des optimisations ou des factorisations sont possible, les remontés directement au développeur afin qu'il traite les erreurs et en informer le team lead.
  - Quand le code review est OK, en informer le test verifier pour qu'il réalise ses tests à son tour.
6. Test verifier : **modèle Sonnet**
	- The Test Verifier does one thing only: prove that the feature actually does what the user story said it should.
	- It writes acceptance tests. Not unit tests.
	- These test the feature from the outside — the way a real user would experience it.
	- Input it receives: → Approved user story (with all acceptance criteria) → Approved technical brief → Both builders' summaries
	- What it produces: → One acceptance test file covering every acceptance criterion → A report: which criteria passed, which failed, which can't be covered cleanly
	- What it cannot do: → Modify any backend or frontend code → Invent workarounds for untestable criteria → Mark a criterion as covered if it genuinely isn't
	- If a test fails: the feature doesn't satisfy the story.
	- It reports exactly which criterion failed.
	- It does not patch the code.
	- That goes back to the right builder.
	- Tools: Read, Edit, Write (test files only), Bash.
	- The rule: you don't have a feature until the acceptance tests pass.
	- Quand tout est ok pour le test verifier en informer le team lead afin qu'il prépare la PR.
6. Devil advocate : **modèle Opus**
  - Dans le cas de questions structurantes sur le projet, faire intervenir cet agent en tant que tierce personne n'ayant pas connaissance de tout le projet mais permettant d'avoir un regarde neuf sur ces questions.

# Décisions techniques

Décisions arrêtées avec l'utilisateur au démarrage du projet. Ces choix doivent guider les sprints et peuvent évoluer — toute évolution est tracée dans le `CHANGELOG.md`.

## Authentification & rôles
* **Trois rôles** : `admin`, `redteam`, `soc`.
  - `admin` : super-user. Gestion des comptes (CRUD users) **et** CRUD complet sur engagements/simulations (cumule les droits de redteam). Décision élargie le 2026-05-26 pour éviter qu'un admin doive se créer un second compte redteam pour gérer les engagements opérationnellement.
  - `redteam` : CRUD complet sur engagements et simulations (tous champs).
  - `soc` : lecture des simulations, écriture restreinte à la partie SOC (logs, sources, commentaires, n° incident).
* **Méthode** : JWT Bearer token (login `/api/auth/login` → access token). Refresh token à décider plus tard si besoin.
* **Mot de passe** : hash argon2 (ou bcrypt si argon2 indisponible).
* **Création de comptes** : par admin uniquement via UI. Pas de self-registration.
* **Bootstrap du 1er admin** : commande Flask `flask create-admin <user> <pass>` exposée via une target Makefile (`make create-admin USER=… PASS=…`) qui wrap `docker exec mimic flask create-admin …`. Aucun credential par défaut, aucun secret persisté en `.env`.

## Modèle de données — V1

### `User`
| Champ | Type | Notes |
|---|---|---|
| id | int (PK) | |
| username | str unique | |
| password_hash | str | argon2/bcrypt |
| role | enum(admin/redteam/soc) | |
| created_at | datetime | |

### `Engagement`
Modèle **minimal** Sprint 1 (extensible plus tard) :
| Champ | Type | Notes |
|---|---|---|
| id | int (PK) | |
| name | str | requis |
| description | text | optionnel |
| start_date | date | requis |
| end_date | date | optionnel, ≥ start_date |
| status | enum(planned/active/closed) | défaut `planned` |
| created_at | datetime | |
| created_by | FK User | |

### `Simulation` (Sprint 2+)
Conforme à la spec (partie RedTeam + partie SOC). Workflow Pending → In progress → Review required → Done. Détaillé dans le sprint correspondant.

## Référentiel MITRE ATT&CK
* **Bundle local** : JSON officiel STIX 2.1 MITRE Enterprise embarqué dans l'image (`backend/data/mitre/enterprise-attack.json`).
* Pas d'appel réseau au runtime. Seed/refresh manuel via `make update-mitre`.
* Utilisé au Sprint 2+ pour l'autocomplete des TTPs (T-id + nom + tactique).
* **Sprint 3+** : multi-techniques par simulation, sélectionnables via autocomplete OU matrice cliquable.
* **Sprint 4+** : sélection de tactiques (TA-id, ex `TA0007 Discovery`) en plus des techniques. Stockées dans un champ `tactic_ids` distinct, séparé sémantiquement de `technique_ids`.

## UI/UX
* **Theming** : light + dark + system (suit `prefers-color-scheme`). Toggle dans la topbar. Persistance localStorage clé `mimic-theme`. Défaut : `system`.
* **Boutons d'action** : icône (lucide-react ou unicode) + label court (≤ 8 chars) préférés aux phrases. Exceptions justifiées pour des libellés workflow-critiques sans icône évidente (ex : "Mark for review", "Clear all").
* **Modals** : focus trap V1 minimal (focus initial sur le champ principal, Tab cycle, Escape + backdrop click = Cancel). Full WAI-ARIA conformance reportée à un sprint a11y dédié.

## Stack technique précisée
* **Backend** : Python 3.12, Flask, SQLAlchemy, Alembic, pytest, ruff, mypy. Auth via `PyJWT` + middleware decorator.
* **Frontend** : React 18, Vite, TailwindCSS, TanStack Query, React Router, Vitest pour les unit tests composants.
* **Tests acceptance** : Playwright (TS), exécutés dans le container ou via runner CI.
* **Conteneurisation** : **Container unique** — Flask sert l'API sous `/api/*` et le build statique de Vite (`frontend/dist`) sous `/`. Un seul `Dockerfile` multistage (stage Node pour build front, stage Python pour run).
* **Makefile** : targets `build`, `start`, `stop`, `restart`, `update`, `logs`, `create-admin USER=… PASS=…`, `update-mitre`, `test-backend`, `test-frontend`, `test-e2e`.

## Arborescence cible
```
mimic/
├── backend/
│   ├── app/
│   │   ├── __init__.py        # create_app() factory
│   │   ├── config.py
│   │   ├── extensions.py      # db, migrate
│   │   ├── models/
│   │   ├── api/               # blueprints
│   │   ├── services/
│   │   ├── auth/              # jwt, decorators
│   │   └── cli.py             # flask create-admin
│   ├── migrations/            # alembic
│   ├── tests/
│   ├── data/mitre/
│   ├── pyproject.toml
│   └── requirements.txt
├── frontend/
│   ├── src/
│   │   ├── components/
│   │   ├── pages/
│   │   ├── hooks/
│   │   ├── api/               # client + types
│   │   └── styles/
│   ├── tests/
│   ├── package.json
│   ├── vite.config.ts
│   └── tailwind.config.ts
├── e2e/                       # Playwright tests
├── docker/
│   └── Dockerfile
├── tasks/                     # plans sprint, lessons
├── DESIGN.md
├── SPEC.md
├── README.md
├── CHANGELOG.md
└── Makefile
```

## Workflow git
* Branche par sprint : `sprint/<num>-<short-name>` (ex : `sprint/1-auth-engagements`).
* Sous-branches par builder si besoin : `sprint/1-auth-engagements/backend`, `…/frontend`.
* PR à la fin du sprint, validée par l'utilisateur après récap synthétique du team-lead.
