The Training Tracker is a read-only dashboard that displays student lab completion progress across all CRC CyberLab pods. It queries AWX verification job artifacts and renders per-pod, per-family lab status for all six CMMC Level 1 families.
| URL | Purpose |
|---|---|
https://training.status.tcecure.com/training/status |
Main dashboard (all pods) |
https://training.status.tcecure.com/pod/XX |
Per-pod detail (redirects to /training/status/pod/XX) |
https://training.status.tcecure.com/api/training-status |
Public API endpoint (JSON, unauthenticated) |
https://training.status.tcecure.com/api/v1/pods/XX/progress |
Authenticated per-pod progress API used by the DigitalRCC portal |
last_run field in the API response| Family | Verify Template ID | Labs | Status |
|---|---|---|---|
| Access Control (AC) | 13 | 12 (L1.1 – L4.3) | Live |
| Identification & Authentication (IA) | 16 | 12 (M1-L1 – M4-L3) | Live |
| System & Information Integrity (SI) | 19 | 12 (SI-M1-L1 – SI-M4-L3) | Live |
| System & Communications Protection (SC) | 22 | 12 (M1-L1 – M4-L3) | Live |
| Media Protection (MP) | 28 | 3 (M1-L1 – M1-L3) | Live |
| Physical Protection (PE) | 31 | 6 (M1-L1 – M3-L2) | Live |
| Total | 57 |
Student Browser
|
v
Reverse Proxy (VM 101, crc-proxy-gateway-01, 192.168.1.55)
|
| training.status.tcecure.com -> 192.168.1.61:4000
v
Portal (Next.js on nginx, 192.168.1.61:4000)
|
| /api/training-status -> MCP /lab-status (Bearer PORTAL_SECRET)
v
MCP Backend (FastAPI :8000, 192.168.1.61)
|
| AWX API v2 queries per-family verify templates
v
AWX (K3s, 192.168.1.103:30080)
|
| Reads job artifacts from latest successful verify runs
v
Lab Results (per-pod PASS/FAIL per lab)
https://training.status.tcecure.com/pod/XX192.168.1.55) routes to the portal at 192.168.1.61:4000/api/training-status (public, no auth)/lab-status with PORTAL_SECRET| Status | Meaning |
|---|---|
| PASS | Student completed the lab objective correctly |
| FAIL | Verification found the misconfiguration still present, or evidence is missing/misnamed |
| NOT SEEDED | Lab has not been seeded for this pod |
| Not yet verified | No verify job has been run |
| AWX unreachable | MCP could not contact the AWX API |
Steps waived for the current cohort (IA M2-L1, IA M3-L2, MP M1-L1/M1-L2) are credited by the verifier itself once the waiver flags are synced into the AWX project, so they show as PASS — see Current Cohort Lab Notices.
Families are worked in order AC → IA → SI → SC → MP → PE. AWX template 24 (Auto-Advance Families) runs every 30 minutes: when every lab in a family passes for a pod, it records the family as complete, unlocks the next family, and triggers completion certificate generation.
GET /api/training-status returns:
{
"pods": {
"pod01": {
"L1.1": {"completed": true, "reason": "PASS", "course": "AC"},
"M1-L1": {"completed": false, "reason": "FAIL", "course": "IA"},
"SI-M1-L1": {"completed": false, "reason": "FAIL", "course": "SI"}
}
},
"last_run": "2026-08-15T05:00:00Z",
"courses": {
"AC": {"name": "Access Control", "labs": ["L1.1", "..."]},
"IA": {"name": "Identification and Authentication", "labs": ["M1-L1", "..."]},
"SI": {"name": "System and Information Integrity", "labs": ["SI-M1-L1", "..."]},
"SC": {"name": "System and Communications Protection", "labs": ["M1-L1", "..."]},
"MP": {"name": "Media Protection", "labs": ["M1-L1", "..."]},
"PE": {"name": "Physical Protection", "labs": ["M1-L1", "..."]}
}
}
A second, authenticated read-only endpoint feeds the student dashboard on
https://my.digitalrcc.com/student. It is deployed and live on the tracker host.
GET https://training.status.tcecure.com/api/v1/pods/<NN>/progress
Authorization: Bearer <token>
| Property | Behaviour |
|---|---|
| Method | GET only — anything else returns 405 |
| Scope | Single pod, taken from the path; unknown pod → 404 |
| Auth | Bearer token; missing or wrong → 401. Token unset on the host → 503 |
| Contents | Pod name, student number, checkedAt, integer percentages 0–100, six module entries (AC/IA/SI/SC/MP/PE), trackerUrl |
| Excluded | No email, no passwords, no lab credentials, no other pod's data |
| Statuses | not_started, in_progress, completed, unavailable |
| Outage | A verifier/AWX outage returns HTTP 200 with status: "unavailable" — never a false 0% |
| CORS | No CORS header on purpose — call it server-side, which also means no CSP change |
Environment variables:
| Where | Variable | Purpose |
|---|---|---|
| Tracker host (192.168.1.61) | POD_PROGRESS_API_TOKEN |
The expected bearer token |
Vercel project drcc-web |
TRAINING_TRACKER_BASE_URL |
https://training.status.tcecure.com |
Vercel project drcc-web |
TRAINING_TRACKER_API_TOKEN |
Same token, stored sensitive, server-side only |
The token value exists only on the tracker host and in Vercel — never in git, wiki
or chat. The tracker is publicly reachable over HTTPS with a valid Let's Encrypt
certificate, so no push poller and no firewall change are needed. Contract detail
lives in docs/pod-progress-api.md in ebarlowjr2/tcecure_cyberlab; the portal
side is documented on Portal Integration.
| Component | Location | Repo |
|---|---|---|
| MCP Backend | mcp/main.py |
ebarlowjr2/tcecure_cyberlab |
| Portal Frontend | portal/src/app/training/status/ |
ebarlowjr2/tcecure_cyberlab |
| API Route | portal/src/app/api/training-status/route.ts |
ebarlowjr2/tcecure_cyberlab |
| Pod Detail Page | portal/src/app/training/status/pod/[id]/page.tsx |
ebarlowjr2/tcecure_cyberlab |
The MCP backend reads these environment variables:
| Variable | Default | Purpose |
|---|---|---|
AWX_URL |
http://192.168.1.103:30080/api/v2 |
AWX API base URL |
AWX_TOKEN |
(none) | AWX API authentication token |
PORTAL_SECRET |
(none) | Shared secret for portal-to-MCP auth |
The portal and MCP run on the same host (192.168.1.61):
ebarlowjr2/tcecure_cyberlabnpm run build in portal/mcp/https://training.status.tcecure.com/api/training-statusAdding a family to the tracker means adding its verify template ID and lab list to VERIFY_TEMPLATES / the course maps in mcp/main.py, then redeploying.
https://training.status.tcecure.com/pod/XX (see the Student Quick Start)