Sprint 0 backend skeleton: Python 3.12 / Flask / SQLAlchemy 2 / Pydantic 2 / Alembic / pytest. Data model §8 complete, C2Connector ABC, Jinja2 sandbox with google-re2 regex_extract (D-011), CAS gzip blob storage (D-012), local auth + group-based RBAC (D-003/D-008), F11 tenant scoping, audit log infrastructure with hash chain anticipated (D-013). Quality gates: ruff/mypy strict/56 unit tests passing. LGTM code-reviewer after 2 rounds of remediation (B1 BLOCKER + 6 MAJOR addressed). Co-Authored-By: backend <backend@mimic.local> * origin/feature/backend-skeleton: docs(backend): track sprint-0 follow-ups + flag integration migration gap feat(backend): wire created_by_id, audit log, F11 scope into CRUD (MA4/5/6) fix(backend): freeze F11 matrix inline in the initial migration (MA3) fix(backend): stream store_blob and enforce max_bytes mid-write (MA2) fix(backend): stop seeding the audit-writer role via postgres-init (MA1) fix(backend): make google-re2 a hard dependency, drop re fallback (B1) chore(backend): mypy strict clean + ruff format pass feat(backend): add content-addressed gzip blob store (D-012) fix(backend): align regex_extract + outputs.blob() with D-011/D-012 fix(backend): align with D-008/D-009 (drop ttp_version, seed F11 matrix) docs: update CHANGELOG + tasks for the backend skeleton sprint 0 test(backend): add pytest baseline (B0.8) feat(backend): add Flask app factory, audit writer, flat CRUD + CLI (B0.7) feat(backend): add local auth + group-based RBAC matching F11 (B0.6) feat(backend): add Jinja2 sandbox + regex_extract filter (B0.5) feat(backend): add C2Connector ABC + payload mapping + factory (B0.4) feat(backend): add §8 data model + Alembic baseline (B0.2, B0.3) chore(backend): bootstrap Python 3.12+ project skeleton (B0.1)
7.0 KiB
7.0 KiB
Sprint 0 — Mimic
Repo skeleton + foundational modules. Nothing that depends on PR1/PR2/PR3.
Backend (backend) — done in feature/backend-skeleton
- B0.1 —
backend/Python 3.12+ project:pyproject.toml(ruff, mypy strict, pytest, coverage 70 %),Makefile(Docker/Podman auto), multi-stageDockerfile,docker-compose.ymlfor Postgres dev DB,.env.example. - B0.2 — Alembic baseline migration
202605210001_initial_schemacreates every table, enum, index, and the idempotent grants for the audit write-only Postgres role. Nottp_versiontable (D-009). Groupsrt_operator,rt_lead,soc_analystseeded with the exact F11 permission matrix (D-008). - B0.3 — SQLAlchemy 2 typed mapped classes for every spec §8 aggregate (engagement, host, user/group RBAC, ttp, scenario/scenario_step, run/run_step/cleanup, detection, evidence, report, soc_session, c2_credential, audit_log).
- B0.4 —
C2ConnectorABC + dataclasses +payload_typeenum + factory keyed onc2_type. Mythic payload map populated; Home stays empty until PR2. - B0.5 — Jinja2 SandboxedEnvironment,
regex_extractfilter (google-re2hard dependency per D-011, raisesRuntimeErrorat boot if absent — norefallback), fail-loud no-match,{{ outputs.text }}/{{ outputs.blob() }}accessors reading gzip-compressed blobs with 10 MB cap. - B0.6 — bcrypt password helpers + SOC opaque token (256-bit url-safe, bcrypt-hashed) +
group-based RBAC matrix matching F11 +
@require_permdecorator. - B0.7 — Flat CRUD blueprints for engagements / hosts / TTPs / scenarios (incl. step
composition with F3 invariant
host.c2_type == scenario.c2_type). - B0.8 — pytest baseline: unit tests passing, integration scaffold ready
(testcontainers Postgres +
/healthzsmoke).
Backend follow-ups (sprint 1+)
Tracked from code-review verdict on feature/backend-skeleton @ 12d131c:
MINOR (8) — to schedule
- M1 — Replace
parse_uuidinteger-ish lookup withwerkzeugUUID converter on the routes (<uuid:eid>) to avoid the 404 on malformed strings being hidden by the 400 path. - M2 — Add OpenAPI generation (Pydantic 2 +
flask-pydantic-openapior hand-rolled). - M3 — Wire
flask-limiterfor/auth/local/login(NF-network). - M4 — Replace string-based
Engagement.statussetter with a typed transition method. - M5 — Introduce per-engagement read view that pre-joins
engagement_memberfor RT operator dashboards (current per-request join is fine for v1 traffic, but re-evaluate at scale). - M6 —
mimic-cli user createdoes not handle the SOC user-type (intended, but document and gate explicitly with a clean error message). - M7 — Add a
mimic-cliengagement add-member <uid> --role rt_operatorshortcut so the F11 scoping in MA6 is reachable from the CLI without manual SQL. - M8 — (fixed in MA1 follow-up commit) Initial migration docstring no longer
references
ttp_version.
NIT (6) — opportunistic
- N1 — Sort imports inside
mimic.db.models.__init__alphabetically for diff stability. - N2 — Extract the
_engagement_or_404duplicated body into a shared helper. - N3 — Replace the inline
Permission.TTP_PROMOTE not in permscheck inttps.pywith a second@require_perm-style decorator. - N4 — (fixed)
gunicornadded topyproject.tomldependencies. - N5 — Replace bare
getattr(current_user, "groups", frozenset())accesses by a thincurrent_groups()helper. - N6 —
tests/integration/conftest.pyusesdb.create_all()instead of running Alembic. Marked with a TODO; switch over once the F11 seed must be exercised in integration. Plan: convert toalembic upgrade headonce the audit role bootstrap lives in the playbook (D-010).
Frontend (ux-frontend)
- F0.1 —
frontend/Vite + React + TypeScript strict + Tailwind 4 + TanStack Query 5, eslint strict + prettier, Playwright skeleton. - F0.2 — Design system provisional: semantic tokens in
theme.css(status colors, RT accent, data mono / UI sans), dark-first palette, placeholder logo. - F0.3 — Wireframes (via
frontend-designskill) on mock data: Login + engagement selection, Live cockpit, Scenario composer, Report + MITRE matrix, TTP library + import. - F0.4 — Routing skeleton + role-aware layout shell (no real auth wired yet).
- F0.5 — Push
feature/frontend-skeleton, open PR for code-reviewer. - F0.6 — Polish M1-M3 from code-review (single SessionProvider, typo, fallback removal).
Frontend follow-ups (sprint 1+, non-blocking, from review NITs)
- N1 — Tighten
readMockSessionpayload validation when real auth wires up (currently checks onlyrole; should validate the fullSessionUsershape). - N2 — Replace the UI-side recomposition of the
MIMIC-RUN:marker in the cockpit's "Resolved command" panel withresolvedCommandTextreturned by the backend (run_step_cleanup.resolved_command_textfor cleanup, equivalent field for steps when exposed). - N3 — Wire
StatusRail.linkStateto the real WebSocket connection state once Flask-SocketIO is reachable (currently hardcoded'up'). - N4 — Unify
router.tsxand any future router helpers undersrc/routing/(single naming, no split between root file and folder). Addressed in F0.6:src/routing/Root.tsxintroduced;router.tsxleft at top level as the app-level entry that other code imports — split kept minimal. - N5 — Actually import Recharts somewhere (likely the MITRE matrix or a latency chart) since it's declared in README + package.json but not yet used.
- N6 — When vendoring IBM Plex woff2 into
public/fonts/, addpublic/fonts/LICENSE.txt(OFL-1.1) for license compliance. - N7 — Add
frontend/.env.exampleexposingVITE_API_BASE_URLandVITE_WS_URLonce the backend publishes endpoints.
Spec / Docs (spec-analyst)
- S0.1 — Cross-check the data model in B0.2 against §8 of the spec; report deltas before merge.
- S0.2 — Cross-check the RBAC matrix in B0.6 against F11; report deltas before merge.
- S0.3 — Maintain
tasks/spec-decisions.mdas new arbitrations land. - S0.4 — Open
docs/architecture.mdonce backend layout is committed.
Review (code-reviewer)
- R0.1 — Review each PR per the published charter; block on security/OPSEC violations.
- R0.2 — Verify mypy strict and ruff clean before approving any backend PR.
- R0.3 — Verify TS strict, no
useEffect(fetch), exhaustive deps before approving any frontend PR.
Conventions
- Branches:
feature/<scope>,fix/<scope>,docs/<scope>,chore/<scope>. Long-lived:main. - Commits: Conventional Commits (
feat:,fix:,chore:,docs:,test:,refactor:). - PRs: each branch → review (
code-reviewer) → team-lead merges. - No direct push to
main.