Files
Metamorph/tasks/design.md
Knacky f1fdf27012 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>
2026-05-11 06:16:00 +02:00

377 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.