Fixes applied: - BLOCKER §2 : EngagementDetailPage.test.tsx → "nouveau" (n'existe pas encore), pas "existant — adapter". - WARN §1 : "Première ligne du summary" obligatoire pour backend-builder avec le path final EXACT (anti-URL-drift, lesson sprint 5). - WARN §0/§1 : slug avec NFKD-strip pour accents + fallback "unnamed" pour edge case nom 100% non-alphanum. - WARN §2 : ExportEngagementButton les DEUX moitiés ouvrent le dropdown (pas d'action par défaut — différence vs NewSimulationDropdown). - WARN §2 : exports.ts throw Error sur non-2xx pour pipeline toast. - WARN §1 : created_by rendu username-only en MD/CSV (pas la dict). - WARN §1 : PDF généré depuis les DONNÉES (pas depuis le string Markdown). NITs incorporés : - gdk-pixbuf-2.0-0 retiré du set minimal (text-only PDF), avec note pour confirmer via weasyprint --info. - data-testid="export-dropdown" sur le wrapper pour AC-30.1. - AC-29.3 : compter rows via csv.reader, pas file.split. - §0 point 14 : style explicite btn-outline (cohérence header). - Test MITRE-bundle-not-loaded ajouté à test_export_render.py. Plan prêt pour spec-reviewer Pass 2.
Mimic
Mimic is a Breach and Attack Simulation (BAS) web UI built on the MITRE ATT&CK matrix. It replaces the flat Excel spreadsheets that red-teams and SOC analysts pass around at the end of an engagement, providing a shared workspace for Purple Team handoffs.
Status: Sprint 5 — Simulation templates. Admin/redteam can now create reusable simulation templates (name + description + commands + prerequisites + MITRE techniques + tactics) and instantiate them inside an engagement in one click. Template and instance are fully decoupled — editing one never affects the other. SOC has no access to templates.
Quick start
Prerequisites: Docker (or Podman) + GNU Make. Linux/macOS host.
# 1. Configure secrets
cp .env.example .env
# Edit .env and set MIMIC_JWT_SECRET to a strong random value:
# sed -i "s|replace-me-with-a-strong-random-secret|$(openssl rand -hex 32)|" .env
# 2. Build and start the container
make build
make start
# 3. Bootstrap the first admin (run once, the container must be up)
make create-admin USER=alice PASS=changeme8
# 4. Open the UI
xdg-open http://localhost:5000 # Linux
# or visit http://localhost:5000 manually
Log in with the credentials from step 3. The admin can create additional users (redteam / soc) from /admin/users.
To stop or restart:
make stop
make restart # stop + start, preserves the SQLite volume
make logs # tail container logs
To override the host port:
make start PORT=8080
Architecture
Single-container deployment. A multistage Dockerfile builds the Vite frontend, then copies the static assets into the Flask backend image so Flask serves both the API (under /api/*) and the SPA (everything else).
┌───────────────────────────────────────────┐
│ Container: mimic:latest │
│ │
│ Flask (Python 3.12) │
│ ├── /api/* ── blueprints (auth, users, │
│ │ engagements, simulations,│
│ │ mitre) │
│ └── / ── SPA fallback → React build │
│ │
│ SQLAlchemy ── SQLite at /data/mimic.sqlite │
│ (volume: mimic-data)│
└───────────────────────────────────────────┘
- Auth: JWT Bearer tokens (HS256, 60-min TTL). Stateless — no refresh tokens, no server-side session.
- Roles:
admin(super-user — cumulates redteam rights on engagements/simulations),redteam(CRUD engagements + simulations, full field access),soc(read everything, write-only on the SOC half of simulations once the redteam marks themreview_required). - Password hashing: argon2 via
argon2-cffi. - Migrations: Alembic, applied automatically by the container entrypoint (
flask db upgrade && flask run). - MITRE ATT&CK: STIX 2.1 Enterprise bundle committed at
backend/data/mitre/enterprise-attack.jsonand indexed at app boot.make update-mitrere-fetches the latest bundle and (if the container is running) restarts it to reload the index. The endpointGET /api/mitre/techniques?q=powers the autocomplete on simulations. - Simulation workflow: Pending → In progress (auto-transition when redteam saves any non-empty field) → Review required (manual, redteam) → Done (manual, redteam or SOC). The state machine is enforced server-side; the UI surfaces the appropriate transition button per role + current state.
See SPEC.md § "Décisions techniques" for the full architecture rationale and DESIGN.md for the UI design system.
Project layout
mimic/
├── backend/ # Flask app, SQLAlchemy models, Alembic migrations, pytest suite
├── frontend/ # Vite + React + Tailwind + TanStack Query, Vitest suite
├── e2e/ # Playwright acceptance tests (one spec per user story)
├── docker/ # Dockerfile (multistage) + entrypoint.sh
├── tasks/ # Sprint plans (tasks/todo.md) and lessons (tasks/lessons.md)
├── .claude/agents/ # Sub-agent definitions for the team (read-only at runtime)
├── Makefile # all operational entry points
├── SPEC.md # functional + technical spec
├── DESIGN.md # UI design system (palette, typography, components)
└── CHANGELOG.md
Make targets
| Target | What it does |
|---|---|
make build |
Build the mimic:latest container image (multistage: Node → Python). Uses docker if installed, otherwise podman — override with make build CONTAINER_CMD=podman |
make start |
Start the container (port from PORT, default 5000; mounts mimic-data volume) |
make stop |
Stop and remove the container |
make restart |
make stop && make start — preserves the SQLite volume |
make update |
git pull && make build && make restart |
make logs |
docker logs -f mimic |
make create-admin USER=… PASS=… |
Run flask create-admin inside the container |
make update-mitre |
Fetch the latest MITRE STIX 2.1 Enterprise bundle into backend/data/mitre/; auto-restart the container if running. Commit the resulting file change manually. |
make test-backend |
pytest -q inside the container |
make test-frontend |
npm run test -- --run in frontend/ |
make test-e2e |
Playwright acceptance suite (container must be running) |
make clean |
Remove container + volume + Python/Node caches |
make open-pr TITLE="…" BODY=path |
Open a PR on the Gitea repo for the current branch via the REST API. Reads credentials from ~/.git-credentials (same source as git push) — no token in env. Wraps scripts/open-pr.sh. Defaults BASE=main. |
Development (without Docker)
Backend:
cd backend
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
export MIMIC_JWT_SECRET=dev-secret
export MIMIC_DB_PATH=./mimic.sqlite
flask --app backend.app:create_app db upgrade
flask --app backend.app:create_app run --port 5000
Frontend:
cd frontend
npm install
npm run dev # http://localhost:5173 with /api proxied to :5000
Tests:
cd backend && pytest -q # 226 tests
cd frontend && npm run test -- --run # 121 tests
cd e2e && npx playwright test # 201 tests (needs container up — use MIMIC_BASE_URL=http://127.0.0.1:5000 if localhost resolves to IPv6)
Documentation
SPEC.md— functional spec, technical decisions, agent teamDESIGN.md— UI design systemCHANGELOG.md— sprint-by-sprint changestasks/todo.md— current sprint plan
License
Internal project — not yet open-sourced.