- CHANGELOG.md: detail every B0.1..B0.8 deliverable + spec deltas D-008 (ttp_version coexists), D-009 (audit hash chain v1), D-010 (no type_annotation_map on declarative base). - tasks/todo.md: tick every B0.x item. - tasks/spec-decisions.md: log D-008, D-009, D-010 alongside the pre-existing D-001..D-007.
4.2 KiB
4.2 KiB
Changelog
All notable changes to Mimic. Format inspired by Keep a Changelog (https://keepachangelog.com).
Versioning starts at 0.1.0 when sprint 0 lands.
[Unreleased]
Team decisions (2026-05-21)
- Q1 — SOC client collaboration in the live cockpit is assumed valid (no PoC sheet).
- Q2 — Mimic is deployed on RT infrastructure (not at client). SOC client connects over the internet through the existing RT reverse proxy (out of Mimic scope).
- Q3 — Project framed as "improve the existing shared sheet workflow", not "rebuild Caldera".
- T2 — C2 credentials stored in a dedicated
c2_credentialtable with version + retirement (Fernet-encryptedconfig_json). Active row per engagement =retired_at IS NULL, max version. - T3 — Jinja templating exposes two accessors:
{{outputs.text}}(stdout) and{{outputs.blob("key")}}(binary, 10 MB cap, UTF-8 with latin-1 fallback). - T4 —
soc_session.token_opaquestores a bcrypt hash; the clear token is delivered out-of-band and never re-displayable. - Auth — v1: local user/password (bcrypt + Flask session). v2: Keycloak OIDC mapping onto the same group model. RBAC is group-based from day one.
Sprint 0 in progress
Repo skeleton, data model, C2Connector ABC, Jinja2 sandbox, local auth + RBAC, flat CRUD,
UX wireframes (mock data). No real connector, no reporting until PR1/PR2/PR3 land.
Backend skeleton (feature/backend-skeleton)
backend/Python 3.12+ project:pyproject.toml(ruff, mypy strict, pytest, coverage 70 %),Makefile(Docker/Podman auto-detect), multi-stageDockerfile,docker-compose.ymlfor Postgres dev DB,.env.example.- Full §8 data model in SQLAlchemy 2 typed mapped classes:
engagement,c2_credential,host,user,group,permission,group_permission,user_group,engagement_member,ttp,scenario,scenario_step,run,run_step,run_step_cleanup,detection,evidence,report,soc_session,audit_log. Nottp_versiontable (D-009 / H32 reaffirmed). - Alembic baseline migration
202605210001_initial_schema: every table + enum + index + idempotentaudit_loggrants for the write-only Postgres role. Seeds the three F11 groups (rt_operator,rt_lead,soc_analyst) and their permission set (D-008). C2ConnectorABC +Payload/TaskHandle/TaskResult/TaskStatusdataclasses +PayloadTypeenum +ConnectorFactorykeyed onc2_type. Mythic payload map populated; Home stays empty until PR2.- Jinja2
SandboxedEnvironment+regex_extractfilter (google-re2 withrefallback) +{{ outputs.text }}/{{ outputs.blob() }}accessors (10 MB cap, UTF-8 → latin-1). - Group-based RBAC:
Permission+GroupName+GROUP_PERMISSIONSmirror the F11 matrix;@require_permdecorator +AuthUserFlask-Login wrapper that resolves the permission set from the user's groups. - bcrypt password helpers + SOC opaque token (256-bit url-safe, bcrypt-hashed at rest, plain returned once).
- Hash-chained append-only audit writer (sprint 0 fills
prev_hash/row_hashat insert; verifier shipped in v2). - Flat CRUD blueprints: engagements / hosts / TTPs / scenarios + scenario steps. F3 invariant enforced (host.c2_type must match scenario.c2_type at compose time).
mimic-cli(click):user create,db dump,db restore.- pytest baseline: 38 unit tests passing, integration scaffold ready for testcontainers
Postgres (
/healthzsmoke included).
Spec deltas applied in this sprint
Authoritative decisions implemented per tasks/spec-decisions.md:
- D-008 — Seeded groups = exactly the three F11 roles, permission matrix from F11.
- D-009 — No
ttp_versiontable (H32 reaffirmed). - D-011 —
regex_extractfails loudly on no-match (raisesTemplateError). - D-012 —
output_blob_refstored inMIMIC_BLOB_ROOT(CAS gzip layout); evidence files live underMIMIC_EVIDENCE_ROOT(flat per-engagement).
Implementation arbitrations logged in this sprint:
- D-013 —
audit_loghash chain (prev_hash/row_hash) shipped v1. - D-014 — UUID columns use SQLAlchemy 2 native
Uuidmapping; notype_annotation_mapon the declarative base (Flask-SQLAlchemy incompatibility).