# jonscafe/whaley architecture

> Architecture diagram of the GitHub repository jonscafe/whaley, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-10-01). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/jonscafe/whaley
- Repository: https://github.com/jonscafe/whaley

## Overview

Whaley is a Docker-based CTF challenge instancer. Participants authenticate (or use IP-based identity), request a challenge instance, and receive isolated containers with allocated ports; administrators manage challenges and inspect instances through a separate dashboard. The graph preserves the documented flag, firewall, monitoring, forensics, and packet-capture capabilities. Several feature-specific links rely on README descriptions because their implementation was not sampled; those links are dashed where the caller is not established by the available evidence.

Main entry points: [`app/docker_manager.py`](https://github.com/jonscafe/whaley/blob/main/app/docker_manager.py) (Instance orchestration), [`app/routers/monitoring.py`](https://github.com/jonscafe/whaley/blob/main/app/routers/monitoring.py) (Monitoring API), [`app/deps.py`](https://github.com/jonscafe/whaley/blob/main/app/deps.py) (Shared dependencies), [`app/routers/admin.py`](https://github.com/jonscafe/whaley/blob/main/app/routers/admin.py) (Admin API)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_api["Web interface"]
  node_web_ui["Web dashboard<br/>[app.js]"]
  node_app_entry["Application entry<br/>[main.py]"]
  node_instance_api["Instance API<br/>[instances.py]"]
  node_challenge_api["Challenge manager API<br/>[challenges.py]"]
  node_admin_api["Admin API<br/>[admin.py]"]
  node_monitor_api["Monitoring API<br/>[monitoring.py]"]
end

subgraph group_runtime["Instance runtime"]
  node_dependencies["Shared dependencies<br/>[deps.py]"]
  node_docker_manager["Instance orchestration<br/>[docker_manager.py]"]
  node_port_manager["Port allocation<br/>[port_manager.py]"]
  node_config["Runtime settings<br/>[config.py]"]
end

subgraph group_security["Identity and flags"]
  node_auth["Authentication<br/>[auth.py]"]
  node_flag_manager["Dynamic flags<br/>[flag_manager.py]"]
  node_firewall["Firewall limits"]
end

subgraph group_operations["Operations and forensics"]
  node_monitoring["Host and container metrics<br/>[monitoring.py]"]
  node_forensics["Instance forensics<br/>[forensics.py]"]
  node_pcap["Packet capture and flows<br/>[pcap_manager.py]"]
  node_ip_correlation["IP correlation<br/>[ip_correlation.py]"]
  node_event_logger["Event logging<br/>[logger.py]"]
end

subgraph group_state["Persistence"]
  node_database[("Relational database<br/>[connection.py]")]
  node_db_models["Persistent records<br/>[models.py]"]
end

node_participant(("Participant"))
node_administrator(("Administrator"))
node_docker["Docker Engine"]
node_ctfd["CTFd"]
node_redis[("Redis lock service")]

node_participant -->|"uses"| node_web_ui
node_administrator -->|"uses"| node_web_ui
node_web_ui -.->|"requests instances"| node_instance_api
node_web_ui -.->|"requests management"| node_admin_api
node_app_entry -->|"registers routes"| node_instance_api
node_app_entry -->|"registers routes"| node_admin_api
node_app_entry -->|"registers routes"| node_challenge_api
node_app_entry -->|"registers routes"| node_monitor_api
node_instance_api -->|"uses shared helpers"| node_dependencies
node_challenge_api -->|"uses shared helpers"| node_dependencies
node_admin_api -->|"uses shared helpers"| node_dependencies
node_monitor_api -->|"uses shared helpers"| node_dependencies
node_dependencies -->|"validates access"| node_auth
node_auth -->|"validates tokens"| node_ctfd
node_instance_api -.->|"spawns and stops"| node_docker_manager
node_dependencies -->|"shares manager"| node_docker_manager
node_docker_manager -->|"manages containers"| node_docker
node_docker_manager -->|"allocates ports"| node_port_manager
node_docker_manager -->|"injects flags"| node_flag_manager
node_docker_manager -->|"applies limits"| node_firewall
node_docker_manager -->|"configures capture"| node_pcap
node_admin_api -->|"manages mappings"| node_flag_manager
node_flag_manager -.->|"registers flags"| node_ctfd
node_admin_api -.->|"serves monitoring"| node_monitoring
node_monitor_api -->|"requests metrics"| node_monitoring
node_monitor_api -->|"requests captures"| node_forensics
node_monitor_api -->|"reports status"| node_firewall
node_monitor_api -->|"searches flows"| node_pcap
node_ip_correlation -->|"correlates traffic"| node_pcap
node_docker_manager -->|"captures on termination"| node_forensics
node_docker_manager -.->|"records events"| node_event_logger
node_port_manager -->|"persists allocations"| node_database
node_flag_manager -->|"persists mappings"| node_database
node_firewall -->|"stores rule state"| node_database
node_event_logger -->|"persists events"| node_database
node_database -->|"creates schema"| node_db_models
node_docker_manager -.->|"coordinates locks"| node_redis
node_port_manager -.->|"coordinates locks"| node_redis
node_config -->|"configures runtime"| node_docker_manager

click node_web_ui "https://github.com/jonscafe/whaley/blob/main/app/static/app.js"
click node_app_entry "https://github.com/jonscafe/whaley/blob/main/app/main.py"
click node_instance_api "https://github.com/jonscafe/whaley/blob/main/app/routers/instances.py"
click node_challenge_api "https://github.com/jonscafe/whaley/blob/main/app/routers/challenges.py"
click node_admin_api "https://github.com/jonscafe/whaley/blob/main/app/routers/admin.py"
click node_monitor_api "https://github.com/jonscafe/whaley/blob/main/app/routers/monitoring.py"
click node_auth "https://github.com/jonscafe/whaley/blob/main/app/auth.py"
click node_dependencies "https://github.com/jonscafe/whaley/blob/main/app/deps.py"
click node_docker_manager "https://github.com/jonscafe/whaley/blob/main/app/docker_manager.py"
click node_port_manager "https://github.com/jonscafe/whaley/blob/main/app/port_manager.py"
click node_flag_manager "https://github.com/jonscafe/whaley/blob/main/app/flag_manager.py"
click node_firewall "https://github.com/jonscafe/whaley/blob/main/app/firewall_manager.py"
click node_monitoring "https://github.com/jonscafe/whaley/blob/main/app/monitoring.py"
click node_forensics "https://github.com/jonscafe/whaley/blob/main/app/forensics.py"
click node_pcap "https://github.com/jonscafe/whaley/blob/main/app/pcap_manager.py"
click node_ip_correlation "https://github.com/jonscafe/whaley/blob/main/app/ip_correlation.py"
click node_event_logger "https://github.com/jonscafe/whaley/blob/main/app/logger.py"
click node_database "https://github.com/jonscafe/whaley/blob/main/app/database/connection.py"
click node_db_models "https://github.com/jonscafe/whaley/blob/main/app/database/models.py"
click node_config "https://github.com/jonscafe/whaley/blob/main/app/config.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_web_ui,node_app_entry,node_instance_api,node_challenge_api,node_admin_api,node_monitor_api toneBlue
class node_dependencies,node_docker_manager,node_port_manager,node_config,node_redis toneAmber
class node_auth,node_flag_manager,node_firewall toneMint
class node_monitoring,node_forensics,node_pcap,node_ip_correlation,node_event_logger toneRose
class node_database,node_db_models,node_participant,node_administrator,node_docker,node_ctfd toneIndigo
```

## Components

### Web interface

- [Web dashboard](https://github.com/jonscafe/whaley/blob/main/app/static/app.js): `app/static/app.js`
- [Application entry](https://github.com/jonscafe/whaley/blob/main/app/main.py): `app/main.py`
- [Instance API](https://github.com/jonscafe/whaley/blob/main/app/routers/instances.py): `app/routers/instances.py`
- [Challenge manager API](https://github.com/jonscafe/whaley/blob/main/app/routers/challenges.py): `app/routers/challenges.py`
- [Admin API](https://github.com/jonscafe/whaley/blob/main/app/routers/admin.py): `app/routers/admin.py`
- [Monitoring API](https://github.com/jonscafe/whaley/blob/main/app/routers/monitoring.py): `app/routers/monitoring.py`

### Instance runtime

- [Shared dependencies](https://github.com/jonscafe/whaley/blob/main/app/deps.py): `app/deps.py`
- [Instance orchestration](https://github.com/jonscafe/whaley/blob/main/app/docker_manager.py): `app/docker_manager.py`
- [Port allocation](https://github.com/jonscafe/whaley/blob/main/app/port_manager.py): `app/port_manager.py`
- [Runtime settings](https://github.com/jonscafe/whaley/blob/main/app/config.py): `app/config.py`

### Identity and flags

- [Authentication](https://github.com/jonscafe/whaley/blob/main/app/auth.py): `app/auth.py`
- [Dynamic flags](https://github.com/jonscafe/whaley/blob/main/app/flag_manager.py): `app/flag_manager.py`
- [Firewall limits](https://github.com/jonscafe/whaley/blob/main/app/firewall_manager.py): `app/firewall_manager.py`

### Operations and forensics

- [Host and container metrics](https://github.com/jonscafe/whaley/blob/main/app/monitoring.py): `app/monitoring.py`
- [Instance forensics](https://github.com/jonscafe/whaley/blob/main/app/forensics.py): `app/forensics.py`
- [Packet capture and flows](https://github.com/jonscafe/whaley/blob/main/app/pcap_manager.py): `app/pcap_manager.py`
- [IP correlation](https://github.com/jonscafe/whaley/blob/main/app/ip_correlation.py): `app/ip_correlation.py`
- [Event logging](https://github.com/jonscafe/whaley/blob/main/app/logger.py): `app/logger.py`

### Persistence

- [Relational database](https://github.com/jonscafe/whaley/blob/main/app/database/connection.py): `app/database/connection.py`
- [Persistent records](https://github.com/jonscafe/whaley/blob/main/app/database/models.py): `app/database/models.py`

### Other components

- **Participant**
- **Administrator**
- **Docker Engine**
- **CTFd**
- **Redis lock service**

## Connections

- Participant → Web dashboard: uses (evidence: `README.md`)
- Administrator → Web dashboard: uses (evidence: `README.md`)
- Web dashboard → Instance API: requests instances
- Web dashboard → Admin API: requests management
- Application entry → Instance API: registers routes (evidence: `app/main.py`)
- Application entry → Admin API: registers routes (evidence: `app/main.py`)
- Application entry → Challenge manager API: registers routes (evidence: `app/main.py`)
- Application entry → Monitoring API: registers routes (evidence: `app/main.py`)
- Instance API → Shared dependencies: uses shared helpers (evidence: `app/routers/instances.py`)
- Challenge manager API → Shared dependencies: uses shared helpers (evidence: `app/routers/challenges.py`)
- Admin API → Shared dependencies: uses shared helpers (evidence: `app/routers/admin.py`)
- Monitoring API → Shared dependencies: uses shared helpers (evidence: `app/routers/monitoring.py`)
- Shared dependencies → Authentication: validates access (evidence: `app/deps.py`)
- Authentication → CTFd: validates tokens (evidence: `app/auth.py`)
- Instance API → Instance orchestration: spawns and stops
- Shared dependencies → Instance orchestration: shares manager (evidence: `app/deps.py`)
- Instance orchestration → Docker Engine: manages containers (evidence: `app/docker_manager.py`)
- Instance orchestration → Port allocation: allocates ports (evidence: `app/docker_manager.py`)
- Instance orchestration → Dynamic flags: injects flags (evidence: `app/docker_manager.py`)
- Instance orchestration → Firewall limits: applies limits (evidence: `app/docker_manager.py`)
- Instance orchestration → Packet capture and flows: configures capture (evidence: `app/docker_manager.py`)
- Admin API → Dynamic flags: manages mappings (evidence: `app/routers/admin.py`)
- Dynamic flags → CTFd: registers flags (evidence: `README.md`)
- Admin API → Host and container metrics: serves monitoring
- Monitoring API → Host and container metrics: requests metrics (evidence: `app/routers/monitoring.py`)
- Monitoring API → Instance forensics: requests captures (evidence: `app/routers/monitoring.py`)
- Monitoring API → Firewall limits: reports status (evidence: `app/routers/monitoring.py`)
- Monitoring API → Packet capture and flows: searches flows (evidence: `app/routers/monitoring.py`)
- IP correlation → Packet capture and flows: correlates traffic (evidence: `app/ip_correlation.py`)
- Instance orchestration → Instance forensics: captures on termination (evidence: `app/docker_manager.py`)
- Instance orchestration → Event logging: records events
- Port allocation → Relational database: persists allocations (evidence: `app/port_manager.py`)
- Dynamic flags → Relational database: persists mappings (evidence: `app/flag_manager.py`)
- Firewall limits → Relational database: stores rule state (evidence: `app/firewall_manager.py`)
- Event logging → Relational database: persists events (evidence: `app/logger.py`)
- Relational database → Persistent records: creates schema (evidence: `app/database/connection.py`)
- Instance orchestration → Redis lock service: coordinates locks (evidence: `README.md`)
- Port allocation → Redis lock service: coordinates locks (evidence: `app/port_manager.py`)
- Runtime settings → Instance orchestration: configures runtime (evidence: `app/docker_manager.py`)
