Commit Graph

68 Commits

Author SHA1 Message Date
Knacky
2a7d27bf02 fix(frontend): post-QA sprint 2 — i18n + alignment + textarea + action bar layout
- Translate all remaining French strings to English (toasts, buttons, banner)
- Fix UsersAdminPage create-form grid alignment: items-start + self-end on button wrapper
- Change execution_result from TextInput to TextArea (5 rows, multiline)
- Replace split Save RT / Save SOC footers + workflow div with a single sticky
  action bar (Save Red Team | Save SOC | Mark for review | Close | Delete)
- Update Vitest assertions to use English button labels

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 16:08:46 +02:00
52611337c2 Merge pull request 'fix(make): auto-detect docker/podman so Makefile works on either engine' (#4) from sprint/2-simulations into main
Reviewed-on: #4
2026-05-26 10:34:01 +00:00
Knacky
b3124ba4dd fix(make): auto-detect docker/podman so Makefile works on either engine
- Makefile: introduce CONTAINER_CMD ?= $(shell command -v docker || echo podman),
  replace all 12 hardcoded `docker` invocations with $(CONTAINER_CMD). User can
  override with `make <target> CONTAINER_CMD=podman` or env export.
- e2e/tests/us1-bootstrap-admin.spec.ts: AC-1.4 regex updated to match the new
  variable form `$(CONTAINER_CMD) exec … flask create-admin` (was hardcoded
  `docker exec`). RUNTIME default also auto-detects (same logic as Makefile)
  so the test exec'es the right engine without a MIMIC_CONTAINER_CMD export.
- e2e/tests/us6-deployment.spec.ts: same RUNTIME auto-detect so the make-dry-run
  regex assertions on lines 75 + 77 match what the Makefile actually emits on
  a podman-only host.
- README + CHANGELOG document the new behavior.

Fixes the user-reported issue: "Le makefile ne fonctionne pas sur ma machine
qui n'a que podman."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 12:20:29 +02:00
868097d78a Merge pull request 'sprint/2-simulations' (#3) from sprint/2-simulations into main
Reviewed-on: #3
2026-05-26 10:14:35 +00:00
Knacky
9ace9ac0d8 docs: sprint 2 wrap-up — README + CHANGELOG + lessons + plan final
- README: status bump to sprint 2, blueprints + workflow + MITRE section, test counts refreshed (131/63/68)
- CHANGELOG: sprint 2 entry under [Unreleased]; sprint 1 moved to its own [Sprint 1] section
- tasks/lessons.md: 5 lessons captured (3 frontend testing gotchas, agent-reuse via SendMessage, e2e refresh on placeholder supersession)
- tasks/todo.md: status flipped to 🟢 SPRINT COMPLET, execution sequence ticks updated with commit hashes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 11:41:23 +02:00
Knacky
54e90f78bb test(e2e): refresh us4 AC-4.9 — placeholder replaced by SimulationList (sprint 2)
The sprint 2 SimulationList component replaced the "Simulations à venir au
Sprint 2" placeholder. AC-4.9 now asserts the Simulations heading and the
"Nouvelle simulation" button are visible for redteam, in line with AC-7.5.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:37:51 +02:00
Knacky
da905cc0a0 test(e2e): sprint 2 acceptance tests — US-7 through US-12
Covers AC-7.1→AC-7.6, AC-8.1→AC-8.6, AC-9.1→AC-9.4, AC-10.1→AC-10.5,
AC-11.1→AC-11.5, AC-12.1→AC-12.4 (32 new tests, all passing).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:35:29 +02:00
Knacky
cf0e8a8a6b fix(frontend): sprint 2 review fixes — MitrePicker input retention + SPA navigation
- MitreTechniquePicker: use hasHydratedFromProps ref so onChange(null,null) on
  keystrokes does not propagate back and wipe inputValue mid-stroke
- SimulationList: replace window.location.href with useNavigate(); drop
  redundant stopPropagation on inner Link
- SimulationFormPage: hoist canSaveSoc flag; replace duplicated ternary
  expressions at onSubmit and button visibility guard
- SimulationFormPage: drop dead .replace(' ', 'T') on executed_at (isoformat
  always emits 'T')
- Tests: add regression for MitrePicker input retention and SimulationList
  SPA navigation (63 tests total)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:22:48 +02:00
Knacky
c9032a9057 fix(frontend): post-review fixes sprint 2
- MitreTechniquePicker: guard sync effect while dropdown open to prevent
  mid-stroke wipe when onChange(null,null) propagates back as null props
- SimulationList: replace window.location.href with navigate() to keep
  TanStack Query cache intact on row click
- SimulationFormPage: simplify redundant ternary on SOC form onSubmit
- SimulationFormPage: remove dead .replace(' ','T') on executed_at
  (backend already returns ISO 8601 with T separator)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:22:05 +02:00
Knacky
83bf60fb30 fix(backend): post-review fixes sprint 2
- test_simulations_patch: remove false dict return annotation on _patch helper
- simulation_workflow: validate executed_at upfront before any setattr (prevents partial mutation on bad payload)
- api/simulations: remove unreachable role check in update_simulation (all valid roles are admin/redteam/soc)
- Dockerfile: remove redundant COPY backend/data/ (already covered by COPY backend/)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:21:32 +02:00
Knacky
765bb5a1a4 feat(frontend): sprint 2 — simulations UI + MITRE picker
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 11:13:14 +02:00
Knacky
006c4c2c5f feat(backend): sprint 2 — simulations + MITRE ATT&CK
- Simulation model with full field set (redteam + SOC sides) and cascade delete
- Alembic migration 0002 for simulations table
- simulation_workflow service: PATCH RBAC field-level + auto-transition pending→in_progress + state machine
- mitre service: STIX bundle loader (boot-safe) + ranked search (exact-id > prefix-id > name)
- 7 new API endpoints: list/create/get/patch/delete simulations, transition, MITRE autocomplete
- serialize_simulation added to serializers.py
- Makefile update-mitre target with real curl + optional docker restart
- Dockerfile updated to copy backend/data/ into image
- MITRE enterprise-attack.json bundle committed (~45 MB)
- 67 new tests (total 130 passing), ruff clean, mypy introduces no new errors

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 10:59:14 +02:00
7fc79cc5a6 Merge pull request 'feat: sprint 1 — auth + CRUD engagements' (#2) from sprint/1-auth-engagements into main
Reviewed-on: #2
2026-05-26 07:48:20 +00:00
Knacky
5104f7c429 feat: sprint 1 — auth + CRUD engagements
Ship the first feature end-to-end on the UI: users log in with JWT,
admins manage user accounts, and any authenticated user (per RBAC)
can create, list, view, edit, and delete engagements.

Backend (Flask + SQLAlchemy + SQLite, 63 pytest)
- User / Engagement models, Alembic 0001 initial schema
- argon2 password hashing, JWT bearer (60-min TTL), @login_required
  and @role_required decorators
- 13 API endpoints under /api/*, including last-admin protection on
  DELETE/PATCH user and JSON 404 on unknown /api/* paths
- `flask create-admin` CLI with duplicate / short-password handling

Frontend (React + Vite + Tailwind + TanStack Query, 20 vitest)
- Inter font bundled locally (no CDN), DESIGN.md tokens in Tailwind
- LoginPage / EngagementsList / EngagementForm / EngagementDetail /
  UsersAdmin pages with role-aware UI
- Layout, ProtectedRoute, StatusBadge, FormField, LoadingState,
  ErrorState, EmptyState, Toast + provider
- Axios client: Bearer interceptor, 401 → purge + /login + "Session
  expirée" toast, 403 → "Accès refusé" toast (declarative <Navigate>
  for already-authed users, Fragment-keyed admin user rows)

Deployment
- Single multistage Dockerfile (node:20-alpine → python:3.12-slim)
- docker/entrypoint.sh runs `flask db upgrade` before `flask run`
- Makefile: build/start/stop/restart/update/logs/create-admin/
  update-mitre/test-{backend,frontend,e2e}/clean
- .env.example documenting MIMIC_JWT_SECRET / MIMIC_DB_PATH / MIMIC_PORT
- SQLite at /data/mimic.sqlite on named volume mimic-data

Acceptance suite (Playwright, 36 tests, all 27 ACs)
- e2e/ scaffold with playwright.config + auth/api fixtures
- One spec per user story (us1-bootstrap through us6-deployment)
- Portable via MIMIC_CONTAINER_CMD / MIMIC_BASE_URL (docker or podman)

Docs
- README.md with quick-start and architecture overview
- CHANGELOG.md updated with Sprint 1 deliverables
- pyrightconfig.json so the Python LSP sees backend/.venv and
  resolves the `backend.app.*` absolute imports

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 09:37:53 +02:00
be266d4879 Merge pull request 'chore: bootstrap project (sprint 0)' (#1) from chore/sprint-0-bootstrap into main
Reviewed-on: #1
2026-05-26 06:05:01 +00:00
Knacky
bd9c06e31b chore: bootstrap project (sprint 0)
Lay down the project foundation before Sprint 1 implementation:

- SPEC.md enriched with a "Décisions techniques" section that pins
  down 3-role auth (admin super-user / redteam / soc), JWT bearer,
  single-container Flask+React topology, minimal Engagement model,
  local MITRE STIX bundle, and the Makefile target list.
- .claude/agents/ defines the 6 sub-agents per SPEC.md § Team:
  backend-builder, frontend-builder, spec-reviewer (project override
  covering plan-vs-spec + code-vs-spec), code-reviewer, test-verifier,
  devil-advocate.
- tasks/todo.md holds the full Sprint 1 plan (Auth + CRUD Engagement)
  validated by spec-reviewer on 2026-05-26 after one round of fixes.
- CHANGELOG.md and tasks/lessons.md scaffolded.
- .gitignore covers Python, Node, Playwright, secrets, build artifacts
  and Claude Code worktrees.

No application code is shipped in this commit — Sprint 1 will be a
separate branch and PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 08:01:13 +02:00
Knacky
1194414b57 update SPEC.md 2026-05-25 20:09:56 +02:00
Knacky
c4ca8712b7 Initial commit 2026-05-25 19:34:22 +02:00