Skip to content

Architecture

Kris Armstrong edited this page May 19, 2026 · 1 revision

Architecture

High level

┌──────────────────┐   HTTPS 8080   ┌──────────────────────────────┐
│ Browser          │ ◄────────────► │ The Stem (Go single binary)  │
│ React + Vite SPA │                │  ├─ REST API (api/v1/*)      │
└──────────────────┘                │  ├─ Embedded React build     │
                                    │  ├─ TestMaster + Reflector   │
                                    │  ├─ Module engines           │
                                    │  └─ Dataplane                │
                                    └──────────────────────────────┘
                                              │
                                ┌─────────────┴────────────┐
                                ▼                          ▼
                        Pure-Go (gopacket)         C dataplane (linux+cgo)
                        Test Master traffic        Reflector (libreflector)
                        works on all platforms     Linux only

The same Go binary serves the API + embedded UI and drives either the test-master traffic generator (always available) or the reflector dataplane (Linux+CGO only).

Repo layout

stem/
├── cmd/stem/                  # CLI entry point
├── internal/
│   ├── api/                   # HTTP handlers + middleware
│   ├── api/ui/                # Vite output (gitignored except .gitkeep)
│   ├── modules/               # Module layer (Benchmark, ServiceTest, …)
│   ├── reflector/             # Packet reflector (pure-Go interface + C dataplane bindings)
│   ├── reflector/dataplane/   # CGO bindings to libreflector.a
│   ├── services/              # TestMaster + per-module executors
│   ├── testmaster/            # Test execution orchestrator
│   ├── license/               # License manager
│   ├── version/               # Build metadata
│   └── api/ui/                # Embedded Vite output
├── src/dataplane/             # C source (C23): DPDK / AF_PACKET / AF_XDP
├── include/                   # C headers
├── ui/                        # React + TypeScript frontend
└── deploy/                    # systemd, launchd, package metadata

Module layer

Six modules. Each implements the same Go interface:

type Module interface {
    Name() string
    DisplayName() string
    Description() string
    Color() string
    Standard() string
    TestTypes() []string
    CanRun(testType string) bool
}
Module Standard Test types
Reflector Loopback reflect
Benchmark RFC 2544 throughput, latency, frame_loss, back_to_back
ServiceTest Y.1564 / MEF y1564_config, y1564_perf, mef_*
TrafficGen Custom custom_stream
Measure Y.1731 y1731_delay, y1731_loss, y1731_slm, y1731_loopback
Certify RFC 2889 / 6349 / TSN rfc2889_*, rfc6349_*, tsn_*

See Modules for the detailed surface of each.

Frontend stack

  • React 19 + TypeScript 5.9 (strict)
  • Tailwind v4 (CSS-first @theme)
  • Biome
  • Playwright
  • react-i18next (en + es). Industry-standard terms — RFC 2544, Y.1564, Y.1731, DHCP, DNS, MEF, TSN, MTU, VLAN — kept verbatim, never translated.

Build pipeline

ui/src/             → React source
                          ↓ npm run build
internal/api/ui/    → Vite output (go:embed picks up from here)
                          ↓ go build
stem                → single binary, UI embedded

Build metadata embedded via ldflags: version, commit, buildTime, uiBuildHash. Exposed at /__version (unauthenticated).

CGO vs pure-Go

Mode CGO Reason
Default macOS / non-Linux build CGO_ENABLED=0 gopacket fully works without libpcap-static; smaller binary
Linux build CGO_ENABLED=1 libreflector.a from src/dataplane/ linked in for the reflector role

Tests that exercise the C path are isolated behind a Y1731Dataplane interface and mocked in unit tests; integration is opt-in via build tags.

Supply chain

Identical to seed + niac: cosign keyless signature, syft SBOM, SLSA L3 attestation. See Releases & Versioning.

Clone this wiki locally