# sam-raiden/rootcodesnmap architecture

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

- Interactive diagram: https://gitdiagram.com/sam-raiden/rootcodesnmap
- Repository: https://github.com/sam-raiden/rootcodesnmap

## Overview

#### Purpose and Entry Points
This repository is an asynchronous FastAPI microservice that exposes Nmap network scanning as a JSON API. The application entry point is `app/main.py`, typically served as `uvicorn app.main:app`. Its public control surface is defined in `app/api/scan.py`: `POST /scan/network`, plus health and version endpoints.

#### API and Schema Boundary
Request and response contracts isolate HTTP concerns from scanning internals. `app/schemas/request.py` defines the Pydantic scan request model and validator bindings; `app/schemas/response.py` defines the standardized scanner response, host, and port shapes. Route handlers in `app/api/scan.py` convert validated requests into service calls and map execution/parsing failures to HTTP responses.

#### Input Security Gate
Validation is the primary trust boundary before any subprocess invocation. `app/utils/validator.py` validates targets, CIDR/hostname forms, ports and scan types, and rejects CLI-injection-shaped input. Runtime policy such as scan timeout, allowed scan types, port bounds, and logging settings is centralized in `app/config.py`.

#### Command Construction
`app/services/command_builder.py` translates a validated `ScanRequest` into an argument vector for Nmap rather than composing a shell command. It selects scan flags, optional service and OS detection, port parameters, and XML-to-stdout output (`-oX -`). This preserves a strict boundary between user data and executable arguments.

#### Scan Execution Runtime
`app/services/executor.py` runs Nmap asynchronously through `asyncio.create_subprocess_exec`, captures stdout/stderr, and enforces configured timeouts. Nmap is an external host/container dependency and must be available on `PATH`. The executor returns raw scan output for parsing while surfacing timeout or process failures to the API layer.

#### XML Parsing and Response Formatting
The scan result pipeline is: Nmap XML stdout → structured host/port data → platform JSON response. `app/services/parser.py` uses `lxml.etree` to extract host status, address, hostname, OS guesses, and service/version information. `app/services/formatter.py` converts those parsed structures into the response schema, including scan duration and scanner identity.

#### Deployment and Privilege Boundary
The service is containerized by `Dockerfile` and runnable through `docker-compose.yml`. Nmap SYN scans and OS detection require raw sockets; the documented deployment model runs the container as root with narrowly granted `NET_RAW` and `NET_ADMIN` capabilities, not full privileged mode. The API server is therefore an execution boundary that should only be exposed to callers authorized to initiate network scans.

#### Observability and Verification
Application logging is provided through `app/utils/logger.py`, with output intended for container stdout. The architecture is verified at its major boundaries: request/API behavior, command safety, XML interpretation, and validation in `tests/test_api.py`, `tests/test_command_builder.py`, `tests/test_parser.py`, and `tests/test_validator.py`.

Main entry points: [`app/api/scan.py`](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/api/scan.py) (Scan routes), [`app/services/executor.py`](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/services/executor.py) (Async executor), [`app/services/command_builder.py`](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/services/command_builder.py) (Command builder), [`Dockerfile`](https://github.com/sam-raiden/rootcodesnmap/blob/main/Dockerfile) (Container deployment)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_api["HTTP API"]
  node_main["FastAPI app<br/>application entry<br/>[main.py]"]
  node_routes["Scan routes<br/>HTTP handlers<br/>[scan.py]"]
  node_request_schema["Scan request<br/>Pydantic contract<br/>[request.py]"]
  node_validator{{"Input validator<br/>security gate<br/>[validator.py]"}}
  node_config["Runtime policy<br/>configuration<br/>[config.py]"]
  node_response_schema["Scanner response<br/>response contract<br/>[response.py]"]
  node_logger["Application logging<br/>observability<br/>[logger.py]"]
end

subgraph group_scan["Scan pipeline"]
  node_command_builder["Command builder<br/>argument builder<br/>[command_builder.py]"]
  node_executor["Async executor<br/>subprocess runtime<br/>[executor.py]"]
  node_nmap{{"Nmap<br/>external scanner"}}
  node_parser["XML parser<br/>result parser<br/>[parser.py]"]
  node_formatter["Response formatter<br/>response mapper<br/>[formatter.py]"]
end

subgraph group_deploy["Deployment"]
  node_container["Container deployment<br/>container runtime"]
  node_compose["Compose runtime<br/>deployment orchestration<br/>[docker-compose.yml]"]
end

node_client(("Authorized caller<br/>external client"))

node_client -->|"HTTP requests"| node_main
node_main -->|"registers"| node_routes
node_routes -->|"validates request"| node_request_schema
node_request_schema -->|"validator bindings"| node_validator
node_routes -->|"reads policy"| node_config
node_routes -->|"submits validated scan"| node_command_builder
node_command_builder -->|"uses scan policy"| node_config
node_command_builder -->|"argument vector"| node_executor
node_executor -->|"uses timeout"| node_config
node_executor -->|"executes"| node_nmap
node_nmap -->|"XML stdout and stderr"| node_executor
node_executor -->|"raw XML"| node_parser
node_parser -->|"structured scan data"| node_formatter
node_formatter -->|"formats"| node_response_schema
node_response_schema -->|"HTTP JSON"| node_routes
node_routes -.->|"logs outcomes"| node_logger
node_compose -->|"runs"| node_container
node_container -.->|"serves application"| node_main
node_container -.->|"provides binary and capabilities"| node_nmap

click node_main "https://github.com/sam-raiden/rootcodesnmap/blob/main/app/main.py"
click node_routes "https://github.com/sam-raiden/rootcodesnmap/blob/main/app/api/scan.py"
click node_request_schema "https://github.com/sam-raiden/rootcodesnmap/blob/main/app/schemas/request.py"
click node_validator "https://github.com/sam-raiden/rootcodesnmap/blob/main/app/utils/validator.py"
click node_config "https://github.com/sam-raiden/rootcodesnmap/blob/main/app/config.py"
click node_command_builder "https://github.com/sam-raiden/rootcodesnmap/blob/main/app/services/command_builder.py"
click node_executor "https://github.com/sam-raiden/rootcodesnmap/blob/main/app/services/executor.py"
click node_parser "https://github.com/sam-raiden/rootcodesnmap/blob/main/app/services/parser.py"
click node_formatter "https://github.com/sam-raiden/rootcodesnmap/blob/main/app/services/formatter.py"
click node_response_schema "https://github.com/sam-raiden/rootcodesnmap/blob/main/app/schemas/response.py"
click node_logger "https://github.com/sam-raiden/rootcodesnmap/blob/main/app/utils/logger.py"
click node_container "https://github.com/sam-raiden/rootcodesnmap/blob/main/Dockerfile"
click node_compose "https://github.com/sam-raiden/rootcodesnmap/blob/main/docker-compose.yml"

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_main,node_routes,node_request_schema,node_validator,node_config,node_response_schema,node_logger toneBlue
class node_command_builder,node_executor,node_nmap,node_parser,node_formatter toneAmber
class node_container,node_compose toneMint
class node_client toneNeutral
```

## Components

### HTTP API

- [FastAPI app](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/main.py): application entry · `app/main.py`
- [Scan routes](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/api/scan.py): HTTP handlers · Provides POST /scan/network plus health and version endpoints. · `app/api/scan.py`
- [Scan request](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/schemas/request.py): Pydantic contract · `app/schemas/request.py`
- [Input validator](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/utils/validator.py): security gate · Rejects invalid targets, ports, scan types, and injection-shaped input. · `app/utils/validator.py`
- [Runtime policy](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/config.py): configuration · Centralizes timeouts, allowed scan types, port bounds, and logging settings. · `app/config.py`
- [Scanner response](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/schemas/response.py): response contract · `app/schemas/response.py`
- [Application logging](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/utils/logger.py): observability · Writes application logs to container stdout. · `app/utils/logger.py`

### Scan pipeline

- [Command builder](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/services/command_builder.py): argument builder · Builds an Nmap argument vector without a shell. · `app/services/command_builder.py`
- [Async executor](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/services/executor.py): subprocess runtime · Runs Nmap, captures output, and enforces timeouts. · `app/services/executor.py`
- **Nmap**: external scanner · Must be available on PATH and emits XML to stdout.
- [XML parser](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/services/parser.py): result parser · Extracts hosts, ports, services, OS guesses, and status from Nmap XML. · `app/services/parser.py`
- [Response formatter](https://github.com/sam-raiden/rootcodesnmap/blob/main/app/services/formatter.py): response mapper · Adds scan duration and scanner identity to parsed results. · `app/services/formatter.py`

### Deployment

- [Container deployment](https://github.com/sam-raiden/rootcodesnmap/blob/main/Dockerfile): container runtime · Runs with NET_RAW and NET_ADMIN capabilities rather than full privileged mode. · `Dockerfile`
- [Compose runtime](https://github.com/sam-raiden/rootcodesnmap/blob/main/docker-compose.yml): deployment orchestration · `docker-compose.yml`

### Other components

- **Authorized caller**: external client · Initiates network scans through the API.

## Connections

- Authorized caller → FastAPI app: HTTP requests
- FastAPI app → Scan routes: registers
- Scan routes → Scan request: validates request
- Scan request → Input validator: validator bindings
- Scan routes → Runtime policy: reads policy
- Scan routes → Command builder: submits validated scan
- Command builder → Runtime policy: uses scan policy
- Command builder → Async executor: argument vector
- Async executor → Runtime policy: uses timeout
- Async executor → Nmap: executes
- Nmap → Async executor: XML stdout and stderr
- Async executor → XML parser: raw XML
- XML parser → Response formatter: structured scan data
- Response formatter → Scanner response: formats
- Scanner response → Scan routes: HTTP JSON
- Scan routes → Application logging: logs outcomes
- Compose runtime → Container deployment: runs
- Container deployment → FastAPI app: serves application
- Container deployment → Nmap: provides binary and capabilities
