feat(m0): bootstrap repo, design system, compose stack

- Repo scaffolding: .gitignore, .env.example, Makefile, docker-compose.yml,
  README.md, CHANGELOG.md, pre-commit config.
- Three-service stack: api (Flask 3), db (postgres:16-alpine), front (nginx
  serving the Vite bundle). Named volumes metamorph_db + metamorph_evidence.
- Backend skeleton: Flask app factory, JSON structured logging on stdout,
  GET /api/v1/health, multi-stage Dockerfile, pyproject.toml driven by uv,
  Pydantic Settings with secret guard rails (refuses to boot in non-dev with
  placeholders), APP_ENV gating.
- Frontend skeleton: Vite + React 18 + TypeScript strict + TailwindCSS, RTOps
  design tokens from tasks/design.md, self-hosted JetBrains Mono / IBM Plex
  Sans via @fontsource, base UI primitives (Card/Tag/SectionHeader/FlowNode/
  Button), home page wired to /api/v1/health.
- Engine-agnostic Makefile: auto-detects docker or podman, picks the matching
  compose driver. Targets: up/down/build/rebuild/dev/lint/fmt/test/migrate/
  seed-mitre/print-install-token/e2e/inspect-health.
- Playwright suite: e2e/tests/m0-smoke.spec.ts (8 tests) + HTML + JUnit
  reports + traces on retry.
- Docs: tasks/spec.md (finalized after Q&A), tasks/design.md, tasks/todo.md
  (14 milestones), tasks/testing-m0.md, tasks/lessons.md.

DoD: make up + make health + make e2e all pass on podman 5.x (Fedora) and
docker. TLS terminated by external reverse proxy (spec §6 NF-network).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Knacky
2026-05-11 06:16:00 +02:00
commit f1fdf27012
58 changed files with 5365 additions and 0 deletions

376
tasks/design.md Normal file
View File

@@ -0,0 +1,376 @@
# Design System — Red Team Operations Map
Reusable design spec extracted from `kypvas.github.io/red-team-map/`. Dark "operator briefing / terminal" aesthetic: information-dense, color-coded taxonomy, monospace-first, zero ornament.
---
## 1. Philosophy
- **Dark, flat, terminal-inspired.** No gradients, no drop shadows, no glows. Depth comes from 1px borders on slightly lighter card backgrounds.
- **Information over decoration.** Every visual element serves data density — cards, tags, colored borders, inline code.
- **Color as taxonomy.** 10 accent hues are not decoration — each one *means* a category (red = evasion/payload, cyan = lateral, purple = C2, etc.). Reuse hues consistently across projects so color carries meaning.
- **Monospace as identity.** `JetBrains Mono` for everything structural (titles, labels, code, tags). `IBM Plex Sans` only for prose body.
- **Comment-style section markers.** Headings begin with `//` — carries the "source code / operator notes" metaphor.
---
## 2. Color Tokens
All colors are declared as CSS custom properties on `:root`. Copy-paste verbatim:
```css
:root {
/* Surfaces */
--bg: #0a0e1a; /* page background — deep navy-black */
--bg-card: #111827; /* card / panel background */
--border: #1e2d3d; /* default 1px border, separators */
/* Text */
--text: #94a3b8; /* default body copy (slate) */
--text-bright: #f8fafc; /* titles, emphasis */
--text-dim: #64748b; /* metadata, subtitles, arrow labels */
/* #475569 used inline for code comments */
/* Accent palette — each one maps to a category */
--red: #ef4444; /* evasion, payload, privesc, danger */
--orange: #f59e0b; /* access, credentials, AD, MOTW */
--yellow: #eab308; /* exfil */
--green: #10b981; /* phishing, social */
--cyan: #06b6d4; /* lateral movement, default code highlight */
--blue: #3b82f6; /* infrastructure, cloud */
--purple: #8b5cf6; /* C2, macOS, tooling */
--pink: #ec4899; /* injection */
--rose: #f43f5e; /* OPSEC, vishing */
--teal: #14b8a6; /* persistence, linux */
}
```
### Usage pattern — tinted fills
Never use accent color as a solid background. Always as `rgba(accent, 0.100.15)` behind solid-colored text:
```css
.tag.c2 { background: rgba(139, 92, 246, 0.15); color: var(--purple); }
.tag.cred { background: rgba(245, 158, 11, 0.15); color: var(--orange); }
code { background: rgba(6, 182, 212, 0.08); color: var(--cyan); }
code.vuln { background: rgba(239, 68, 68, 0.10); color: var(--red); }
code.tool { background: rgba(139, 92, 246, 0.10); color: var(--purple); }
```
---
## 3. Typography
### Font stack
```html
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&family=IBM+Plex+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
```
- **`JetBrains Mono`** — headings, labels, code, tags, navigation, anything structural.
- **`IBM Plex Sans`** — prose body only (`<p>`, card descriptions).
- Weights used: Mono `300 / 400 / 500 / 600 / 700`, Plex Sans `300 / 400 / 500 / 600`.
### Scale
| Role | Family | Size | Weight | Extras |
|-----------------|-----------------|------|--------|---------------------------------|
| Page title (h1) | JetBrains Mono | 28px | 700 | `letter-spacing: -0.5px` |
| Subtitle | JetBrains Mono | 14px | 300 | color `--text-dim` |
| Section (h2) | JetBrains Mono | 18px | 600 | `border-bottom: 1px var(--border)`, `padding-bottom: 12px` |
| Card title (h3) | JetBrains Mono | 14px | 600 | color `--text-bright` |
| Card sub-label | JetBrains Mono | 10px | 400 | `letter-spacing: 0.5px`, `--text-dim` |
| Section desc | JetBrains Mono | 12px | 400 | `--text-dim` |
| Body copy | IBM Plex Sans | 12px | 400 | `line-height: 1.7` |
| Flow node | JetBrains Mono | 10px | 400 | |
| Arrow label | JetBrains Mono | 8px | 400 | `--text-dim` |
| Tag / pill | JetBrains Mono | 9px | 600 | `text-transform: uppercase; letter-spacing: 1px` |
| Inline code | JetBrains Mono | 10px | 400 | |
| `<pre>` block | JetBrains Mono | 11px | 400 | `line-height: 1.7` |
| Footer | JetBrains Mono | 11px | 400 | `--text-dim` |
### Global body
```css
body {
background: var(--bg);
color: var(--text);
font-family: 'IBM Plex Sans', sans-serif;
padding: 40px 60px;
line-height: 1.6;
}
```
---
## 4. Layout & Spacing
- **Container**: `max-width: 1400px; margin: 0 auto;`
- **Page padding**: `40px 60px` (desktop-first, no mobile breakpoints in the source)
- **Grid** for card collections:
```css
display: grid;
grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
gap: 16px;
```
- **Section rhythm**: `margin-top: 60px; margin-bottom: 30px` on section headers.
- **Separators**: thin hairlines only — `border-top: 1px solid var(--border); margin: 40px 0`.
- **Line-height**: 1.6 globally, 1.7 inside cards and `<pre>` blocks for dense technical content.
---
## 5. Components
### 5.1 Header / Hero
```html
<header>
<h1>Red Team <span>Operations</span> <span class="acc2">Architecture</span> Map v1.1</h1>
<div class="subtitle">Comprehensive Operator Reference — From Infrastructure to Impact</div>
</header>
```
```css
header { text-align: center; margin-bottom: 50px; }
header h1 { font: 700 28px 'JetBrains Mono'; color: var(--text-bright); letter-spacing: -0.5px; margin-bottom: 8px; }
header h1 span { color: var(--red); }
header h1 .acc2 { color: var(--purple); }
header .subtitle { font: 300 14px 'JetBrains Mono'; color: var(--text-dim); }
```
> **Pattern**: white title with two coloured accent words (red + purple). Reuse `<span>` to highlight 12 keywords only.
### 5.2 Section heading
```html
<div class="section-header">
<h2><span>//</span> Operation <span class="red">Flow Chains</span></h2>
<p class="section-desc">End-to-end attack chains ...</p>
</div>
```
```css
.section-header { margin-top: 60px; margin-bottom: 30px; }
.section-header h2 { font: 600 18px 'JetBrains Mono'; color: var(--text-bright);
padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.section-header h2 span { color: var(--cyan); } /* the "//" marker */
.section-header h2 .red { color: var(--red); } /* + .green / .orange / .purple / .pink / .teal / .yellow / .blue */
.section-desc { font: 12px 'JetBrains Mono'; color: var(--text-dim); margin-top: 8px; }
```
> **Signature move**: every h2 starts with a cyan `//` followed by a plain word and one colored word — source-code comment vibe.
### 5.3 Detail card
```css
.detail-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 10px;
padding: 20px;
}
.detail-card h3 { font: 600 14px 'JetBrains Mono'; color: var(--text-bright); margin-bottom: 4px; }
.detail-card .card-sub { font: 10px 'JetBrains Mono'; color: var(--text-dim); margin-bottom: 12px; letter-spacing: 0.5px; }
.detail-card .card-body { font-size: 12px; line-height: 1.7; }
/* accent-border variants */
.border-red { border-color: var(--red) !important; }
.border-cyan { border-color: var(--cyan) !important; }
/* ... one class per accent */
```
> Cards share identical chrome; they are **distinguished solely by border color**. That single accent ties card → category → tag → flow-node without repeating the hue anywhere else.
### 5.4 Tag / pill
```css
.tag {
font: 600 9px 'JetBrains Mono';
text-transform: uppercase;
letter-spacing: 1px;
padding: 3px 8px;
border-radius: 4px;
display: inline-block;
margin-bottom: 8px;
margin-right: 4px;
}
.tag.c2 { background: rgba(139, 92, 246, 0.15); color: var(--purple); }
.tag.evasion { background: rgba(239, 68, 68, 0.15); color: var(--red); }
.tag.lateral { background: rgba(6, 182, 212, 0.15); color: var(--cyan); }
/* ... one class per category */
```
### 5.5 Flow node + arrow
Nodes chain horizontally in a `flex` row with thin SVG arrows between them.
```css
.flow-block { margin-bottom: 18px; }
.flow-title { font: 600 12px 'JetBrains Mono'; margin-bottom: 10px; }
.flow-title.red { color: var(--red); } /* one per accent */
.flow-row { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; padding: 10px 0; }
.flow-node {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 6px;
padding: 8px 12px;
font: 10px 'JetBrains Mono';
color: var(--text);
white-space: nowrap;
flex-shrink: 0;
}
.flow-node.hl-red { border-color: var(--red); color: var(--red); }
.flow-node.hl-cyan { border-color: var(--cyan); color: var(--cyan); }
/* ... one per accent */
.flow-arrow { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; }
.flow-arrow svg { width: 36px; height: 20px; }
.flow-arrow .arrow-label { font: 8px 'JetBrains Mono'; color: var(--text-dim); margin-top: -2px; }
```
Arrow SVG template (inline, stroke colour = destination-node accent):
```html
<svg viewBox="0 0 36 20">
<line x1="0" y1="10" x2="31" y2="10"
stroke="#10b981" stroke-width="1.5"
marker-end="url(#arrowG)"/>
</svg>
```
### 5.6 Data-flow / code card
```css
.data-flow-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 10px;
padding: 24px;
margin-bottom: 20px;
}
.data-flow-card h4 { font: 600 13px 'JetBrains Mono'; color: var(--text-bright); margin-bottom: 12px; }
.data-flow-card pre { font: 11px 'JetBrains Mono'; line-height: 1.7; color: var(--text-dim); overflow-x: auto; }
.data-flow-card pre .key { color: var(--cyan); font-weight: 600; }
.data-flow-card pre .val { color: var(--text-bright); }
.data-flow-card pre .type { color: var(--blue); }
.data-flow-card pre .comment { color: #475569; font-style: italic; }
.data-flow-card pre .danger { color: var(--red); font-weight: 600; }
```
> Pseudo-syntax-highlighting via `<span class="key|val|type|comment|danger">` inside `<pre>` blocks — mimics an IDE theme without a real parser.
### 5.7 Inline code
```css
code { font: 10px 'JetBrains Mono'; padding: 2px 6px; border-radius: 3px;
background: rgba(6, 182, 212, 0.08); color: var(--cyan); }
code.vuln { background: rgba(239, 68, 68, 0.10); color: var(--red); }
code.tool { background: rgba(139, 92, 246, 0.10); color: var(--purple); }
```
### 5.8 List inside card
```css
.card-list { list-style: none; padding: 0; }
.card-list li { padding: 3px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.03); }
```
> Near-invisible divider (`rgba(255,255,255,0.03)`) — rhythm without visual noise.
### 5.9 Footer
```css
footer {
text-align: center;
margin-top: 60px;
padding: 30px 0;
border-top: 1px solid var(--border);
font: 11px 'JetBrains Mono';
color: var(--text-dim);
}
```
---
## 6. Borders, Radii, Elevation
| Element | Radius | Border |
|----------------|--------|------------------------------|
| Detail card | 10px | 1px solid var(--border) or accent |
| Data-flow card | 10px | 1px solid var(--border) |
| Flow node | 6px | 1px solid var(--border) or accent |
| Tag | 4px | none |
| Inline code | 3px | none |
- **No `box-shadow` anywhere.**
- **No gradients.** Surfaces are flat hex fills.
- **Depth cue** = border on a `#111827` panel over a `#0a0e1a` background. That's the whole elevation system.
---
## 7. Motion
The stylesheet defines **no transitions, no hovers, no animations**. Static document. If you add motion in derivative work, keep it restrained: ~120 ms fades on border-color at most. Don't introduce scale, shadow, or glow effects — they'd break the briefing aesthetic.
---
## 8. Iconography
No icon font, no Lucide/Heroicons. All pictograms are **inline SVG arrows** with `stroke-width: 1.5` and `<marker-end>` arrowheads, one per accent color. Tags replace icons: `[C2]`, `[EVASION]`, `[LATERAL]` carry the same recognition load.
If icons are ever added, use a thin (1.5px) monochrome line set (e.g. Lucide `strokeWidth={1.5}`) and color them with accent vars.
---
## 9. Reusable Starter Template
Drop-in `<head>` + body baseline for a new project in this style:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Project Name</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&family=IBM+Plex+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
<style>
:root {
--bg: #0a0e1a; --bg-card: #111827; --border: #1e2d3d;
--text: #94a3b8; --text-bright: #f8fafc; --text-dim: #64748b;
--red:#ef4444; --orange:#f59e0b; --yellow:#eab308; --green:#10b981;
--cyan:#06b6d4; --blue:#3b82f6; --purple:#8b5cf6; --pink:#ec4899;
--rose:#f43f5e; --teal:#14b8a6;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: var(--bg); color: var(--text); font-family: 'IBM Plex Sans', sans-serif; padding: 40px 60px; line-height: 1.6; }
.container { max-width: 1400px; margin: 0 auto; }
</style>
</head>
<body>
<div class="container">
<header>
<h1>Project <span style="color:var(--red)">Name</span> <span style="color:var(--purple)">Subtitle</span></h1>
<div class="subtitle">One-line mission statement</div>
</header>
<!-- sections with <h2>// Section <span class="red">Name</span></h2> ... -->
</div>
</body>
</html>
```
---
## 10. Checklist for "Does this match the style?"
- [ ] Background `#0a0e1a`, cards `#111827`, borders `#1e2d3d`.
- [ ] JetBrains Mono for structure, IBM Plex Sans for prose.
- [ ] Every section `<h2>` starts with a cyan `//`.
- [ ] Exactly one accent hue per category, reused across border + tag + code + flow node.
- [ ] Accent backgrounds are **tinted** (`rgba(accent, 0.100.15)`), never solid.
- [ ] Zero shadows, zero gradients, zero rounded > 10px.
- [ ] Tags are 9px uppercase mono with 1px letter-spacing.
- [ ] Container capped at 1400px, page padded `40px 60px`.
- [ ] No hover animations beyond border-color if any at all.