CyberPath
CyberPath is the security training and certification platform in the opensecstack (SIN) ecosystem. It delivers hands-on, lab-based cybersecurity training with cryptographically signed completion evidence anchored in the CITADEL WORM ledger — satisfying the immutable-record requirements that NIS2 Article 21(2)(g) auditors increasingly expect.
CyberPath ships at v1.0.0 (2026-05-09) under the Apache 2.0 licence.
Overview
NIS2 Article 21(2)(g) requires essential and important entities to provide cybersecurity training to staff with documented evidence of completion. Existing learning management systems treat completion as a mutable database row. CyberPath treats it as immutable, signed, audit-grade evidence:
- Every lesson completion references the exact content revision the learner saw (Module 8 content versioning — append-only snapshots).
- Every completion emits a
cyberpath.completionevent, HMAC-SHA256 signed, to the CITADEL WORM ledger via an async circuit-breaker queue. - Each track-level certificate carries an Ed25519 signature over a canonical certification body, with the signing key held in a KMS-backed secret store.
- NIS2 Compass can query
GET /api/v1/cyberpath/coverage/{user_id}to verify which Article 21 measures a user has produced training evidence for.
Key features
| Module | Description |
|---|---|
| Learning Path Engine | Track / module / lesson sequencing with prerequisites and per-learner progress tracking |
| Quiz & Assessment Engine | Knowledge-check assessments with randomised question banks and configurable pass thresholds |
| Docker-based labs | Per-session Docker containers with a browser terminal (xterm.js + WebSocket relay) for hands-on exercises requiring a full Linux environment |
| Wasm sandbox labs | Lower-overhead labs hosted by a Rust wasmtime runtime; pre-built lab images with SHA-256 checksums, per-session isolation, no host filesystem access, and resource caps via wasmtime fuel + memory limits |
| Certification issuance | Per-track certificates with Ed25519 signatures; key rotation procedure documented in docs/operator-handbook.md |
| CITADEL evidence emitter | Async cyberpath.completion event emission to CITADEL WORM; bounded queue + circuit breaker + 10 s drain on shutdown |
| NIS2 Compass coverage API | /api/v1/cyberpath/coverage/{user_id} — Article 21 measure coverage by user; /api/v1/cyberpath/recommend?gap=art21_g for gap-driven track recommendations |
| Content versioning | Immutable, append-only content snapshots; every completion record references the exact content_version_id the learner saw |
Architecture
The platform consists of three main runtime components and three outbound integration targets.
The Go API (chi router, pgx, zerolog, viper) runs on :8086 and owns all business logic: path sequencing, quiz scoring, lab session management, certificate issuance, and CITADEL event emission. It uses the same stack as VertGuard and APIGuard for ecosystem consistency.
The lab runtime sits behind the API over a WebSocket relay. For exercises that need a full Linux userspace the API spins up a per-session Docker container. For lighter exercises the Rust wasmtime host loads a pre-registered lab image, providing faster spinup (seconds vs. minutes) with strong isolation — no host filesystem access, bounded fuel and memory.
The React + Vite frontend (:3006) provides the learner dashboard, lesson runner, quiz UI, and the xterm.js browser terminal for lab sessions. The UI is bilingual (Albanian + English).
Outbound integrations:
- CITADEL — receives
cyberpath.completionevents asynchronously after every lesson completion. - NIS2 Compass — calls CyberPath synchronously to query coverage and fetch gap-driven track recommendations.
- IRFlow — pushes incident signals inbound to CyberPath; CyberPath maps incident type to a recommended training track.
The completions.evidence_hash column stores a BLAKE3 hash of the canonical evidence body submitted to CITADEL, enabling independent audit verification without re-fetching from the ledger.
Ports & endpoints
| Port | Service |
|---|---|
8086 | CyberPath REST API (Go) |
3006 | React learner dashboard (Vite / nginx) |
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/health | Liveness + DB ping |
GET | /api/v1/tracks | List learning tracks |
GET | /api/v1/tracks/{id} | Track detail |
POST | /api/v1/enrollments | Enroll the caller in a track |
POST | /api/v1/lessons/{id}/complete | Record lesson completion (emits CITADEL event) |
POST | /api/v1/quizzes/{id}/submit | Submit quiz answers, receive score |
POST | /api/v1/labs/{id}/start | Start a sandbox lab session (Docker or wasmtime) |
GET | /api/v1/cyberpath/coverage/{user_id} | NIS2 Article 21 measure coverage by user |
GET | /api/v1/cyberpath/recommend | Gap-driven track recommendation (?gap=art21_g) |
Integration
CyberPath authenticates users via sinauth SSO using the OAuth 2.0 authorization_code + PKCE (S256) flow. The API validates RS256-signed tokens against the sinauth JWKS endpoint at https://auth.sin.to/.well-known/jwks.json.
Minimum required environment variables:
CYBERPATH_DB_URL=postgres://cyberpath:cyberpath@postgres:5432/cyberpath CYBERPATH_HTTP_ADDR=:8086 CYBERPATH_CITADEL_API_URL=https://citadel.internal CYBERPATH_CITADEL_KEY_SECRET=<hmac secret> CYBERPATH_CITADEL_PROJECT_ID=<project id> CYBERPATH_NIS2COMPASS_API_URL=https://nis2.internal CYBERPATH_IRFLOW_API_URL=https://irflow.internal CYBERPATH_IRFLOW_KEY_SECRET=<hmac secret> CYBERPATH_LAB_RUNTIME=wasmtime CYBERPATH_CERT_SIGNING_KEY=<KMS reference>
Quick start with Docker Compose:
git clone https://github.com/opensecstack/opensecstack cd opensecstack/cyberpath cp .env.example .env docker compose up -d "cm"># Health check curl http://localhost:8086/api/v1/health "cm"># List available learning tracks curl http://localhost:8086/api/v1/tracks
Full documentation
The complete CyberPath reference — module list, CITADEL integration schema, NIS2 Compass integration, architecture, and operator handbook — is in the repository:
github.com/opensecstack/opensecstack/tree/main/cyberpath/docs