# Metamorph Collaborative purple-team platform. Red team logs the tests they execute (procedure, command, timestamp); blue team annotates each test with detection evidence (alerts, logs, files). At the end of an engagement, Metamorph generates a standalone reveal.js slide deck classified by MITRE ATT&CK tactic. > **Status**: M0–M4 delivered (bootstrap → DB schema → auth → RBAC → MITRE ATT&CK reference). See `tasks/spec.md` for the full specification and `tasks/todo.md` for the milestone-by-milestone plan. ## Stack - **Backend**: Python 3.12, Flask 3, SQLAlchemy 2 + Alembic (M1+), PostgreSQL 16. - **Frontend**: React 18 + TypeScript + Vite + TailwindCSS (RTOps design tokens, see `tasks/design.md`). - **Auth (M2+)**: JWT access (1h) + refresh (30d), Argon2id, invite-link enrollment. - **RBAC (M3+)**: atomic permissions (31 codes) bundled into custom groups; 3 system groups seeded (`admin` / `redteam` / `blueteam`). - **MITRE ATT&CK (M4+)**: Enterprise reference catalogue pinned to v19.0, seedable via `make seed-mitre`. - **Delivery**: docker-compose. TLS termination is expected to be handled by an external reverse proxy in production. ## Quickstart Works with **Docker** *or* **Podman**. The Makefile auto-detects the available engine and picks the matching compose driver (`docker compose`, `podman compose`, or `podman-compose`). Requires one of: - Docker Engine 24+ with the Compose v2 plugin, **or** - Podman 4.0+ with `podman compose` (or the legacy `podman-compose` ≥ 1.0.6) ```bash git clone cd Metamorph make engine # confirm which engine the Makefile picked up make env # creates .env from .env.example $EDITOR .env # set strong values for POSTGRES_PASSWORD and JWT_SECRET make up # builds and starts api + db + front make logs # tail logs ``` Override the auto-detection if you have both engines installed: ```bash make up ENGINE=podman # force podman + auto-pick its compose driver make up ENGINE=docker COMPOSE="docker compose" COMPOSE=podman-compose make up # force the legacy wrapper specifically ``` Then: - Front: - API health: (proxied) or ### First-time setup ```bash make migrate # apply DB schema make print-install-token # prints the bootstrap admin token (logs banner) # visit http://localhost:8080/setup, paste the token, create the admin account make seed-mitre # populate the MITRE ATT&CK reference (~50 MB, ~1 s) ``` The MITRE bundle is cached in the named volume `metamorph_mitre` (`/data/mitre/.json` inside the api container). For air-gapped operators, pre-populate the volume with your own STIX 2.1 file and run `podman compose exec api flask --app app.cli metamorph seed-mitre --source /data/mitre/your-file.json --skip-checksum`. To stop: ```bash make down # keep volumes make clean # also drop volumes (DESTRUCTIVE) ``` ## Local dev (no Docker) Requires: - [uv](https://github.com/astral-sh/uv) for Python deps - Node.js 20+ and `npm` - A reachable Postgres (or `make up db` to run only the db container) ```bash make dev-api # in one terminal make dev-front # in another ``` ## Environment variables See `.env.example`. The most important ones: | Variable | Purpose | |--------------------|------------------------------------------------------| | `APP_ENV` | `dev` allows placeholder secrets; anything else (prod/staging) refuses to boot with defaults | | `POSTGRES_*` | DB credentials (used by `db` and `api`) | | `JWT_SECRET` | HS256 signing key — generate 64+ random bytes (`python -c "import secrets; print(secrets.token_urlsafe(64))"`) | | `LOG_LEVEL` | `DEBUG` / `INFO` / `WARNING` / `ERROR` | | `FRONT_ORIGIN` | Allowed CORS origin for the SPA | | `EVIDENCE_DIR` | Path inside the api container where uploads land | | `HOST_API_PORT` | Host port mapped to the api (default 8000) | | `HOST_FRONT_PORT` | Host port mapped to the front nginx (default 8080) | ## Testing - **Manual + automated checklist for the current milestone**: see [`tasks/testing-m.md`](tasks/testing-m4.md) (current: `testing-m4.md`). - **Backend unit tests**: `make test-api` - **End-to-end (Playwright)**: `make e2e-install` (once), then `make up && make e2e`. Reports land in `e2e/playwright-report/` (HTML + JUnit XML); open with `make e2e-report`. ## Pre-commit hooks After cloning, install hooks once: ```bash pipx install pre-commit # or: pip install --user pre-commit pre-commit install pre-commit run --all-files # initial sweep ``` The hooks run `ruff` + `ruff-format` on the backend and `eslint` / `tsc --noEmit` / `prettier --check` on the frontend (see `.pre-commit-config.yaml`). ## Project layout ``` . ├── backend/ # Flask API │ └── app/ │ ├── api/ # HTTP layer (blueprints) │ ├── core/ # config, logging, errors │ ├── db/ # SQLAlchemy session, migrations (M1+) │ ├── models/ # ORM models (M1+) │ ├── services/ # domain logic (M2+) │ └── i18n/ # message catalogs (M13) ├── frontend/ # Vite + React + TS + Tailwind │ └── src/components/ui/ # RTOps design system primitives ├── tasks/ │ ├── spec.md # source of truth for requirements │ ├── design.md # RTOps design system │ ├── todo.md # milestone plan │ └── lessons.md # session retrospectives ├── docker-compose.yml ├── Makefile └── CHANGELOG.md ``` ## Roadmap See `tasks/todo.md`. Current milestone: **M4 — MITRE ATT&CK Enterprise**. Next: M5 (test & scenario templates). ## License TBD.