Runtime

Building a Web-Based 3D Cyber Kill Chain Simulation with Virtual Reality Support

Report summary

A credible cyber kill chain simulator should be designed as an instructional, event-driven digital environment , not as an attack-execution platform. Its purpose is to let learners observe how adversary behavior progresses, identify indicators, make defensive decisions, and inspect the consequences

Status
Research archive item
Category
Runtime
Length
7,286 words
Reading time
34 minutes
Report type
strategy

Key topics

  • Runtime
  • AI
  • TypeScript
  • Angular
  • RxJS
  • Privacy
  • Physics
  • Semantic Systems

Research provenance

Archive status
Research archive item
Content identity
sha256:51ee61c88d90a49fb1428126db9c5c0b9bb5822c1d9417952f7ac5e795516bb8

For citation, use the report title and canonical URL. Archival presence does not establish authorship or promote report statements into portfolio evidence.

Source availability: 46 citation markers in the source export have no recoverable source links. Those markers are omitted from this reader; any supplied bibliography and ordinary links remain. Check the original sources before relying on the cited claims.

This page renders the archived Markdown as safe, formatted HTML. It is background research and does not become a portfolio claim without evidence review.

Full report

On this page

Executive summary

A credible cyber kill chain simulator should be designed as an instructional, event-driven digital environment, not as an attack-execution platform. Its purpose is to let learners observe how adversary behavior progresses, identify indicators, make defensive decisions, and inspect the consequences of those decisions across a spatialized timeline or network. The safest and most maintainable implementation separates a PHP control plane from a JavaScript visualization and interaction plane.

The recommended baseline is:

LayerRecommended baselineRationale
Browser applicationTypeScript, three.js r185, WebXR, Vite, and either React 19.2 or Vue 3three.js provides direct control over rendering, WebXR interaction, scene optimization, and custom instructional visualizations without the abstraction ceiling of a declarative engine. three.js r185 was current as of July 2026.
PHP applicationPHP 8.5 on the latest security patch, with Laravel 13 for delivery speed or Symfony 7.4 LTS for longer supportPHP 8.5 is the current supported branch; Laravel provides rapid API, authentication, queue, rate-limit, and broadcasting integration, while Symfony 7.4 is the more conservative long-term-support choice.
PersistencePostgreSQL plus JSONB; Redis for cache, queues, presence, and fan-outThe domain contains strongly relational objects—runs, stages, actors, participants—and evolving event payloads that benefit from JSON documents.
Real-time transportREST for resources and commands, WebSocket for live state, SSE as a simpler one-way fallbackWebSocket supports bidirectional browser/server communication; SSE provides reconnectable server-to-browser delivery and is appropriate for guided playback or instructor feeds.
Asset deliveryglTF/GLB, KTX2 textures, object storage, and a CDNglTF is intended as an efficient runtime asset-delivery format; KTX2/Basis compression reduces texture transfer and GPU memory pressure.
Cyber-content modelLockheed Martin Cyber Kill Chain for the narrative sequence; MITRE ATT&CK for behavior-level annotationThe kill chain supplies an understandable ordered storyline, while ATT&CK supplies a more granular, empirically curated taxonomy. MITRE explicitly describes the two as complementary rather than interchangeable.
ObservabilityOpenTelemetry-compatible logs, spans, and semantic eventsOpenTelemetry distinguishes duration-bearing spans from point-in-time events and provides a vendor-neutral telemetry model.

The simulation should maintain an authoritative server-side event stream. Clients send constrained instructional commands such as advance_stage, inspect_indicator, or apply_control; the PHP service checks authorization and scenario rules, appends an immutable event, and broadcasts the resulting state delta. A client must never be allowed to submit scripts, shell commands, arbitrary URLs, executable malware, or instructions to contact real systems.

A useful first release is a single-user, synthetic phishing-to-impact scenario that supports both desktop and headset use, seven Lockheed stages, ATT&CK annotations, guided instruction, two or three intervention points, deterministic replay, basic learner metrics, and a small instructor dashboard. A reasonable planning estimate is 12–16 person-weeks, corresponding to approximately six to eight calendar weeks for two engineers with part-time involvement from a cybersecurity subject-matter expert and an instructional or UX designer. Multiuser synchronization, voice, scenario authoring, enterprise identity, and formal learning evaluation should follow after the core event model has stabilized.

The principal architectural risk is not rendering. It is allowing instructional scenario content, real-time messages, uploaded models, or facilitator privileges to become an execution or injection channel. The principal pedagogical risk is producing an impressive spatial spectacle that overloads learners without improving causal understanding. Immersive-learning research indicates that presence and agency can increase engagement, but also that visual complexity and unguided autonomy can increase extraneous cognitive load; reflection prompts and instructional scaffolding are therefore essential.

Scope, assumptions, threat model, and ethical boundaries

Unspecified assumptions. No hosting provider, database engine, identity provider, headset family, classroom size, or regulatory jurisdiction was specified. This report therefore assumes a browser-accessible deployment over HTTPS; modern WebXR-capable headsets; desktop fallback for users without headsets; PostgreSQL as a reference database rather than a mandatory dependency; object storage for 3D assets; and an initial concurrency target in the tens or low hundreds of users rather than a globally distributed consumer game. Estimates assume that 3D models are stylized and reusable rather than custom photorealistic productions.

The system should represent adversary behavior at the level needed to teach recognition, causality, detection, and defensive response. It should not contain operational exploit chains, functional payloads, credential-harvesting infrastructure, arbitrary command execution, malware deployment, public command-and-control endpoints, or automation against third-party networks. MITRE ATT&CK can support threat modeling, defensive assessment, red-team planning, and adversary emulation, but the simulation should consume ATT&CK as a taxonomy and content reference—not turn ATT&CK procedures into directly executable abilities.

Threat model

Threat actor or failure modeAssets at riskRepresentative abuse caseRequired controls
Malicious unauthenticated userAvailability, public assets, account endpointsAPI enumeration, credential stuffing, resource exhaustion, oversized model downloadsAuthentication, bot protection where appropriate, per-route rate limits, CDN controls, request-size limits, generic error responses
Malicious learnerRun integrity, other learners’ data, facilitator controlsSending forged stage transitions, reading another class’s run, replaying commands, injecting labels or URLsObject-level authorization on every run, membership checks, idempotency keys, sequence validation, strict JSON schemas, output encoding
Compromised facilitator accountScenario integrity, participant telemetry, administrative functionsModifying scenarios, revealing answers, exporting learner data, launching unauthorized sessionsStrong authentication, short sessions, least privilege, step-up authentication for exports, immutable audit records
Malicious scenario authorBrowser security and ethical boundaryUploading script-bearing content, remote textures, hostile glTF extensions, realistic exploit instructionsContent security policy, asset transcoding and quarantine, extension allowlists, no executable fields, editorial review, publishing workflow
Realtime protocol attackerRun integrity and availabilityCross-site WebSocket hijacking, message flooding, sequence replay, oversized framesOrigin validation, authenticated upgrade, per-connection quotas, message-size caps, heartbeat timeouts, monotonic sequence numbers
Dependency or build compromiseApplication code and learner devicesCompromised npm or Composer dependency, modified 3D asset, poisoned build artifactLockfiles, pinned versions, software bills of materials, signed builds, dependency scanning, reproducible deployment pipeline
Over-privileged telemetry operatorLearner privacyReconstructing identity or behavior from head, hand, gaze, voice, or room dataData minimization, pseudonymous identifiers, short retention, aggregation, access logging, explicit consent where required
Denial-of-service conditionPHP workers, database, WebSocket gateway, GPU memoryReconnect storms, telemetry floods, high-poly asset exhaustion, adversarial scene complexityBackpressure, circuit breakers, queue limits, asset budgets, scene validators, degraded read-only mode

This threat model should be revisited whenever the product adds user-generated scenarios, live cyber-range integrations, voice, gaze tracking, artificial-intelligence-generated content, or cross-organization collaboration. Those additions materially change both the attack surface and the legal basis for data processing.

In the United States, the Computer Fraud and Abuse Act addresses unauthorized access and damage involving protected computers. A training environment should therefore define explicit authorization boundaries and ensure that neither client nor server can initiate actions against systems outside the controlled simulation or a separately authorized cyber range. Written scope, approved targets, permitted actions, dates, contacts, and stop conditions should be established for any lab integration.

CISA’s vulnerability-disclosure policy template illustrates the importance of clearly specifying which systems and conduct are authorized. A comparable simulation policy should state that scenarios are fictional or sanitized, external probing is prohibited, exported material remains non-operational, and users must not substitute real targets, credentials, domains, or malware.

Where learner telemetry constitutes personal data, privacy law may require a lawful basis, transparency, purpose limitation, minimization, retention limits, and rights-handling processes. The European Union’s GDPR is the obvious example, although education, employment, biometric, child-privacy, state, and sector-specific laws may impose additional requirements. Head pose, hand movement, gaze, voice, accessibility settings, and performance history can be more identifying or sensitive than conventional clickstream data and should not be collected merely because an XR API makes collection possible.

Recommended non-negotiable content controls are:

  • Use reserved domains such as .invalid, synthetic IP ranges, fictional identities, and nonfunctional hashes.
  • Store descriptive ATT&CK references, defensive observations, and abstract effects rather than executable commands.
  • Prevent scenario authors from adding JavaScript, shell syntax, executable attachments, arbitrary HTML, external model URLs, or unreviewed WebRTC endpoints.
  • Require a two-person review for scenarios marked realistic, organization-specific, exportable, or linked to a cyber range.
  • Display an instructional-use notice and a visible distinction between simulated evidence and real indicators.
  • Treat ATT&CK names, logos, and attribution according to MITRE’s legal and branding guidance.

Canonical models and simulation-stage mapping

The 2011 Hutchins, Cloppert, and Amin paper introduced an intrusion kill chain centered on seven phases: reconnaissance, weaponization, delivery, exploitation, installation, command and control, and actions on objectives. Its defensive value is the proposition that disrupting one or more links can prevent an intrusion from reaching its objective, while observations from each campaign can improve later defenses.

MITRE ATT&CK is structured differently. Tactics describe adversary objectives, while techniques and sub-techniques describe behaviors used to accomplish those objectives. MITRE’s design paper characterizes ATT&CK as a mid-level, empirically grounded model based substantially on publicly reported behavior, and cautions against treating coverage as a checklist or inferring attribution from techniques alone.

A simulation should therefore use:

  • Lockheed stages as the learner-facing narrative spine.
  • ATT&CK tactics and techniques as annotations, branching behavior, evidence, and assessment labels.
  • Scenario-specific states for detection, containment, recovery, and reflection, which are not merely adversary stages.
  • Explicit version pinning so that a scenario does not silently change when the ATT&CK knowledge base changes.

ATT&CK v19.1 was the current content version on July 31, 2026. MITRE provides current and historical data through STIX and TAXII, so each published scenario should record the ATT&CK release and object versions against which it was authored.

The following is a teaching-oriented crosswalk, not a one-to-one ontology. MITRE notes that ATT&CK tactics are lower-level objectives and are not constrained to a single linear order, whereas a kill chain is ordered. One ATT&CK behavior may appear in several narrative stages, and later tactics may loop back or occur concurrently.

Lockheed stageRepresentative ATT&CK mappingSuggested 3D representationLearner objective
ReconnaissanceReconnaissance, such as gathering target and infrastructure informationExternal observation zone around a protected enterprise; public-facing assets illuminate as information is gatheredIdentify exposed information, distinguish benign observation from suspicious collection, select exposure-reduction controls
WeaponizationResource Development, including acquiring infrastructure, accounts, or capabilitiesAn abstract “assembly” area that links capability, infrastructure, lure, and intended victim; no executable artifactsUnderstand that campaigns require preparation and that defenders may detect infrastructure or impersonation before delivery
DeliveryInitial Access, especially phishing or trusted-relationship pathsA message, removable medium, web request, or supply-chain object moving across a boundaryRecognize ingress channels, inspect evidence, choose filtering, verification, or isolation controls
ExploitationInitial Access plus Execution; sometimes Privilege EscalationA vulnerable service or user action produces a visible state transition, process node, or privilege boundary changeConnect vulnerability, user action, execution, and control failure without exposing functional exploit code
InstallationPersistence and Defense EvasionPersistent node or hidden path appears; defensive visibility changesIdentify persistence, tampering, suspicious services, and opportunities for host isolation or restoration
Command and ControlCommand and ControlPeriodic beacon-like edges to a fictional external controller, with timing and protocol evidenceDistinguish normal traffic from anomalous communication and select blocking, sinkholing, or segmentation responses
Actions on ObjectivesDiscovery, Credential Access, Lateral Movement, Collection, Exfiltration, and ImpactBranching paths across identity, data, and service zones; consequences depend on prior interventionsReason about blast radius, protect objectives, prioritize containment, preserve evidence, and initiate recovery

The stage engine should support directed graphs rather than a rigid seven-element array. The primary scenario can still display seven numbered narrative locations, but its internal state should permit concurrent actions, loops, aborted attempts, skipped stages, alternate delivery paths, defender interventions, and recovery branches. A useful state-transition record contains:

current stage + preconditions + adversary event + evidence generated
+ learner decision + defensive control + probabilistic/deterministic outcome
+ next-stage candidates + assessment feedback

For teaching clarity, separate three synchronized timelines:

  1. Adversary timeline: what the simulated actor attempted.
  2. Observable timeline: what logs, alerts, indicators, or user reports became available.
  3. Defender timeline: what the learner or simulated security team knew and did.

This separation avoids teaching the unrealistic assumption that defenders see the attacker’s ground truth in real time. It also supports exercises in which a learner must distinguish evidence from hindsight.

Data model, schemas, and event semantics

The recommended persistence model combines a relational scenario catalog with an append-only run event stream. Relational constraints protect identities, membership, ordering, and publication state; JSONB accommodates evolving scenario configuration and event-specific evidence. The browser should receive a purpose-built simulation representation rather than an unrestricted copy of the database.

STIX 2.1 is useful at the interchange boundary because it provides a standardized language for cyber-threat intelligence, and MITRE distributes ATT&CK as STIX 2.0 and 2.1. The internal simulation schema should not simply duplicate STIX: instructional concepts such as learner prompts, spatial transforms, reveal conditions, scores, comfort settings, and replay sequence numbers are outside its principal purpose. Store STIX identifiers and selected normalized relationships while retaining a simulation-specific model.

OpenTelemetry should similarly be treated as an observability envelope rather than the authoritative scenario domain. Use spans for operations with duration—asset loading, scenario initialization, API processing—and events or logs for point-in-time occurrences such as stage transitions or interaction failures.

Reference relational schema

TableImportant fieldsPurpose and constraints
usersid UUID, auth_subject, email, display_name, status, created_atLocal identity projection. auth_subject should be unique; sensitive profile data should remain in the identity provider where possible.
roles and user_rolesrole_code, user_id, scope_type, scope_idSupports global and scenario/run-scoped roles such as learner, facilitator, author, reviewer, and administrator.
scenariosid, slug, title, version, status, attack_content_version, threat_model JSONB, settings JSONB, created_by, timestampsImmutable published versions are preferable. Editing should create a draft successor rather than mutate a scenario used by completed runs.
stagesid, scenario_id, code, ordinal, lockheed_stage, title, description, entry_conditions JSONB, completion_conditions JSONB, spatial_anchor JSONBDefines learner-facing narrative stages. ordinal is for display, not the only transition rule.
stage_attack_refsstage_id, attack_object_id, object_type, object_version, relationship_typePins tactics, techniques, mitigations, or other ATT&CK objects to a scenario version.
stage_transitionsid, from_stage_id, to_stage_id, trigger_type, condition JSONB, probability, prioritySupports branches, loops, interventions, and alternate paths. Deterministic educational scenarios can use probability 1.0.
actorsid, scenario_id, actor_type, name, trust_zone, metadata JSONBRepresents fictional adversaries, defenders, users, services, and automated agents. Avoid unsupported real-world attribution.
entitiesid, scenario_id, entity_type, name, asset_uri, transform JSONB, properties JSONBSpatial and logical objects such as hosts, identities, messages, controls, data stores, and network zones.
indicatorsid, scenario_id, indicator_type, display_value, normalized_hash, is_synthetic, stix_id, sensitivity, metadata JSONBStore redacted or hashed values when full values are unnecessary. Enforce is_synthetic for distributable scenarios.
runsid, scenario_id, scenario_version, mode, status, facilitator_id, seed, current_seq, started_at, ended_atRuntime aggregate and current sequence. seed enables deterministic probabilistic replay.
run_participantsrun_id, user_id, run_role, joined_at, last_seen_at, consent_versionAuthoritative membership and telemetry-consent reference.
simulation_eventsid, run_id, seq, event_type, stage_id, actor_id, entity_id, occurred_at, received_at, payload JSONB, visibility, correlation_id, causation_id, integrity_hashAppend-only source of truth. Unique constraint on (run_id, seq) and preferably (run_id, idempotency_key).
run_snapshotsrun_id, through_seq, state JSONB, created_at, schema_versionReduces replay time. A snapshot is derived data and can be rebuilt from events.
learner_responsesid, run_id, participant_id, prompt_id, response JSONB, correctness, latency_ms, event_seqKeeps assessment records linked to the exact scenario state.
telemetry_eventsid, run_id, participant_id, event_name, occurred_at, duration_ms, attributes JSONB, retention_untilOperational and learning telemetry. Do not place raw pose streams here by default.
audit_logid, principal_id, action, resource_type, resource_id, result, ip_hash, user_agent_hash, occurred_atSecurity and governance evidence. Protect from normal application modification.

Sample ER diagram

erDiagram
    USERS ||--o{ USER_ROLES : receives
    ROLES ||--o{ USER_ROLES : defines
    USERS ||--o{ SCENARIOS : authors
    USERS ||--o{ RUNS : facilitates

    SCENARIOS ||--|{ STAGES : contains
    SCENARIOS ||--o{ ACTORS : defines
    SCENARIOS ||--o{ ENTITIES : contains
    SCENARIOS ||--o{ INDICATORS : contains
    STAGES ||--o{ STAGE_ATTACK_REFS : maps_to
    STAGES ||--o{ STAGE_TRANSITIONS : originates
    STAGES ||--o{ STAGE_TRANSITIONS : targets

    SCENARIOS ||--o{ RUNS : instantiates
    RUNS ||--o{ RUN_PARTICIPANTS : includes
    USERS ||--o{ RUN_PARTICIPANTS : joins

    RUNS ||--|{ SIMULATION_EVENTS : records
    RUNS ||--o{ RUN_SNAPSHOTS : snapshots
    RUNS ||--o{ LEARNER_RESPONSES : assesses
    RUNS ||--o{ TELEMETRY_EVENTS : measures

    STAGES ||--o{ SIMULATION_EVENTS : contextualizes
    ACTORS ||--o{ SIMULATION_EVENTS : performs
    ENTITIES ||--o{ SIMULATION_EVENTS : affects
    USERS ||--o{ AUDIT_LOG : generates

Canonical event envelope

All runtime events should share a stable envelope. Event-specific data belongs under payload, and schemas should be versioned independently of scenario content.

{
  "schema_version": "1.0",
  "event_id": "019bf87e-c03b-7ce4-a81d-27f68ed31220",
  "run_id": "019bf85a-a54d-70fe-a63a-d68af741f028",
  "sequence": 42,
  "event_type": "indicator.observed",
  "occurred_at": "2026-07-31T19:42:17.431Z",
  "correlation_id": "019bf877-d10e-7acd-949a-e337e4d45eb7",
  "causation_id": "019bf87b-2c30-78c2-97af-cbe901d39e92",
  "stage": {
    "code": "delivery",
    "lockheed_stage": "delivery",
    "attack_content_version": "19.1",
    "attack_tactics": ["TA0001"],
    "attack_techniques": ["T1566.002"]
  },
  "actor_ref": "actor:fictional-red-team",
  "target_ref": "entity:mail-gateway",
  "payload": {
    "indicator_type": "url",
    "display_value": "hxxps://benefits-update.training.invalid/",
    "is_synthetic": true,
    "confidence": 0.95,
    "evidence_refs": [
      "evidence:mail-header-017",
      "evidence:proxy-log-009"
    ],
    "available_defensive_actions": [
      "quarantine_message",
      "block_synthetic_domain",
      "notify_recipient"
    ]
  },
  "visibility": {
    "learner": true,
    "facilitator": true,
    "adversary_ground_truth": false
  },
  "integrity": {
    "previous_event_hash": "sha256:3d76...f05a",
    "event_hash": "sha256:b40c...a277"
  }
}

The sequence controls replay and gap detection; it is not a global timestamp. occurred_at records simulated or real runtime time, while the database should separately retain receipt time. The integrity chain is optional but useful for assessed exercises. It is not a substitute for database access control or signed audit storage.

API surface

Method and pathPurposeImportant behavior
GET /api/v1/scenarios/{scenario}Retrieve published metadata and stage graphExclude facilitator-only solutions and unrevealed evidence
POST /api/v1/runsCreate a run from a fixed scenario versionRequire facilitator or self-study permission; capture mode and deterministic seed
POST /api/v1/runs/{run}/joinJoin an authorized runReturn participant role, snapshot URL, last sequence, and realtime ticket
GET /api/v1/runs/{run}/snapshotRetrieve current materialized stateInclude through_seq; support ETag and compressed responses
GET /api/v1/runs/{run}/events?after_seq=42Recover missed deltasEnforce run membership and visibility filtering
POST /api/v1/runs/{run}/commandsSubmit constrained learner or facilitator intentRequire idempotency key; return accepted sequence or rule violation
POST /api/v1/telemetry/batchSubmit privacy-filtered telemetrySize, event-count, attribute, and rate limits; reject unrecognized dimensions
GET /api/v1/runs/{run}/metricsRetrieve authorized summariesLearners see their metrics; facilitators see approved cohort aggregates
WS /ws/runs/{run}Receive state deltas, presence, and facilitator messagesAuthenticate the upgrade and authorize every subscription

Architecture, integration patterns, and core flows

Reference architecture

flowchart LR
    subgraph Browser["JavaScript / TypeScript browser client"]
        UI["React, Vue, or Angular UI shell"]
        Scene["three.js / Babylon.js / A-Frame scene"]
        XR["WebXR input and session manager"]
        Store["Client state store and replay reducer"]
        Cache["IndexedDB and asset cache"]
        Worker["Web Worker for event processing"]
        UI <--> Store
        Scene <--> Store
        XR --> Scene
        Worker <--> Store
        Cache <--> Store
    end

    subgraph Edge["Edge services"]
        CDN["CDN / static asset delivery"]
        Proxy["TLS reverse proxy / WAF"]
    end

    subgraph PHP["PHP application"]
        API["REST or GraphQL API"]
        Auth["Authentication and authorization"]
        Domain["Scenario and run domain services"]
        Ingest["Telemetry ingestion"]
        Queue["Background jobs"]
        Audit["Audit service"]
        Outbox["Transactional outbox"]
    end

    subgraph Realtime["Realtime tier"]
        WS["WebSocket gateway"]
        SSE["Optional SSE endpoint"]
        Bus["Redis streams / pub-sub"]
    end

    subgraph Data["Data services"]
        DB["PostgreSQL"]
        Redis["Redis cache / presence"]
        Objects["Object storage: GLB, KTX2, audio"]
        OTel["OpenTelemetry collector"]
    end

    Browser -->|HTTPS REST / GraphQL| Proxy
    Proxy --> API
    Browser <-->|WSS deltas and commands| WS
    Browser -->|Assets| CDN
    CDN --> Objects

    API --> Auth
    API --> Domain
    API --> Ingest
    Domain --> DB
    Domain --> Outbox
    Outbox --> Bus
    Bus --> WS
    Bus --> SSE
    WS --> Redis
    Queue --> DB
    Ingest --> OTel
    Audit --> DB

Server-side PHP responsibilities

The PHP application should own security and domain authority:

  • Authentication integration, account projection, run membership, RBAC, and resource-level authorization.
  • Scenario publication, schema validation, ATT&CK version pinning, and content review state.
  • Run creation, transition-rule evaluation, random-seed control, scoring, and authoritative sequence assignment.
  • Durable append-only event persistence and snapshot creation.
  • Signed or authorized asset manifests, not direct arbitrary storage paths.
  • Telemetry filtering, retention enforcement, aggregation, and export authorization.
  • Audit logs, administrative workflows, queues, notifications, and integration adapters.
  • Generation of short-lived WebSocket subscription tickets where the realtime tier is separate.

Laravel 13 includes first-party broadcasting integration and can use Laravel Reverb for WebSocket communication; its rate-limiting abstraction also fits command and telemetry endpoints. Laravel Octane can run on long-lived application servers when higher PHP throughput is necessary, although long-lived workers require careful avoidance of request-state leakage.

Client-side JavaScript responsibilities

The browser should own presentation and immediate interaction, but not authority:

  • WebGL scene construction, rendering, animation, spatial audio, label management, and adaptive quality.
  • WebXR session lifecycle, controller/hand input, ray interaction, teleportation, snap turning, and seated mode.
  • Local interpolation and prediction for presentation-only movement.
  • Deterministic reduction of server events into local scene state.
  • Gap detection, reconnection, snapshot recovery, and offline asset caching.
  • Accessibility and desktop parity.
  • Privacy-preserving derivation of coarse interaction metrics before transmission.
  • Visual distinction between adversary ground truth, defender observations, instructional overlays, and learner decisions.

WebXR defines browser interfaces for immersive sessions, poses, views, and input; it is the standards layer rather than a scene engine. The current WebXR Device API was a Candidate Recommendation Draft in June 2026, so applications should feature-detect capabilities rather than infer them from headset names.

Integration-pattern comparison

PatternBest useAdvantagesLimitationsRecommendation
RESTScenario resources, run lifecycle, commands, snapshots, exportsStraightforward authorization, HTTP caching, mature PHP tooling, easy observabilityOverfetching can occur; polling is inefficient for live stateMake this the default control-plane interface
GraphQLComplex authoring tools, filtered scenario catalogs, analytics dashboardsClient-selected fields, typed schema, convenient aggregation across related resourcesField-level authorization and query-cost control are demanding; subscriptions add infrastructure complexityOptional for administrative and authoring surfaces, not necessary for the MVP
WebSocketMultiuser state, facilitator control, presence, live event deltasFull-duplex, low-overhead messages after upgrade, natural fit for live sessionsPersistent connection operations, backpressure, authorization, origin checks, reconnect, and fan-out are nontrivialPreferred realtime channel after the single-user prototype
Server-Sent EventsGuided playback, instructor announcements, read-only event streamsSimple HTTP semantics, automatic reconnect behavior, Last-Event-ID recovery, proxy-friendlyServer-to-client only; commands still require HTTPStrong MVP option where participants mostly receive state
WebRTCVoice, optional video, or peer media/data experimentsBrowser-native real-time media and peer communicationRequires signaling and network traversal infrastructure; peer state is harder to audit and governUse for voice or media only, not as the authoritative simulation protocol
Batch uploadTelemetry, delayed metrics, device diagnosticsReduces request overhead and avoids per-frame trafficData may be delayed or lost on abrupt exitSend small bounded batches with sendBeacon or normal authenticated POST

GraphQL’s current specification was published in September 2025. WebSocket is standardized by RFC 6455; SSE’s EventSource model includes automatic reconnection and last-event identifiers; WebRTC is a W3C Recommendation for browser real-time media communication.

Authoritative state synchronization

A robust synchronization sequence is:

  1. The client retrieves a snapshot with through_seq = N.
  2. The client opens the realtime connection and requests events after N.
  3. A learner interaction produces a command, not a claimed state transition.
  4. The PHP domain service verifies membership, role, current run version, command schema, idempotency key, and transition preconditions.
  5. Within one database transaction, the service assigns N+1, writes the event, updates the run sequence, and writes an outbox record.
  6. An outbox consumer publishes the committed event to the realtime bus.
  7. Clients apply events in sequence order. A gap triggers GET .../events?after_seq=...; a large gap or schema mismatch triggers a fresh snapshot.
  8. Periodic snapshots make long runs inexpensive to resume.

Client interpolation may smooth moving avatars or animated packets, but learning-critical values—stage, score, evidence visibility, action outcome, timing, and completion—must remain server-authoritative. Never send state at the display refresh rate. Broadcast semantic changes and low-frequency participant poses separately.

PHP endpoint example

The following Laravel-style endpoint accepts only allowlisted instructional commands. Authentication middleware, policy checks, an idempotency key, transactional locking, and after-commit broadcasting prevent the client from directly choosing authoritative state.

<?php

use App\Http\Controllers\RunCommandController;
use Illuminate\Support\Facades\Route;

Route::middleware(['auth:sanctum', 'throttle:simulation-commands'])
    ->post('/v1/runs/{run}/commands', [RunCommandController::class, 'store']);
<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Events\SimulationEventCommitted;
use App\Models\Run;
use App\Models\SimulationEvent;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;

final class RunCommandController extends Controller
{
    public function store(Request $request, Run $run): JsonResponse
    {
        Gate::authorize('submitCommand', $run);

        $data = $request->validate([
            'command_id' => ['required', 'uuid'],
            'type' => [
                'required',
                Rule::in([
                    'advance_stage',
                    'inspect_indicator',
                    'apply_control',
                    'answer_prompt',
                    'acknowledge_briefing',
                ]),
            ],
            'expected_sequence' => ['required', 'integer', 'min:0'],
            'payload' => ['present', 'array'],
        ]);

        $event = DB::transaction(function () use ($run, $data): SimulationEvent {
            /** @var Run $lockedRun */
            $lockedRun = Run::query()
                ->whereKey($run->getKey())
                ->lockForUpdate()
                ->firstOrFail();

            $existing = SimulationEvent::query()
                ->where('run_id', $lockedRun->id)
                ->where('idempotency_key', $data['command_id'])
                ->first();

            if ($existing !== null) {
                return $existing;
            }

            abort_if(
                $lockedRun->current_seq !== $data['expected_sequence'],
                409,
                'The run has advanced; refresh state and retry.'
            );

            // The domain service should validate scenario rules and convert the
            // command into a permitted event. It must never execute payload text.
            $result = app(\App\Domain\Simulation\CommandHandler::class)
                ->handle($lockedRun, $data['type'], $data['payload']);

            $nextSequence = $lockedRun->current_seq + 1;

            $event = SimulationEvent::query()->create([
                'id' => (string) Str::uuid7(),
                'run_id' => $lockedRun->id,
                'seq' => $nextSequence,
                'event_type' => $result->eventType,
                'stage_id' => $result->stageId,
                'occurred_at' => now(),
                'payload' => $result->safePayload,
                'visibility' => $result->visibility,
                'idempotency_key' => $data['command_id'],
                'correlation_id' => $result->correlationId,
                'causation_id' => $data['command_id'],
            ]);

            $lockedRun->forceFill(['current_seq' => $nextSequence])->save();

            DB::afterCommit(
                static fn () => broadcast(
                    new SimulationEventCommitted($event->id)
                )
            );

            return $event;
        }, attempts: 3);

        return response()->json([
            'accepted' => true,
            'event_id' => $event->id,
            'sequence' => $event->seq,
        ], 202);
    }
}

In production, the event and outbox record should preferably be written in the same transaction, with an independent worker handling publication. Broadcasting directly after commit is sufficient for a prototype, but an outbox is more resilient when the realtime broker is temporarily unavailable.

JavaScript VR-rendering example

This compact three.js example fetches a snapshot, renders stage nodes, enables WebXR, applies ordered realtime events, and submits a constrained command when the user selects a stage. Production code should add labels, recovery logic, accessibility controls, error telemetry, resource disposal, and explicit asset budgets.

import * as THREE from 'three';
import { VRButton } from 'three/addons/webxr/VRButton.js';

const runId = document.body.dataset.runId;
const apiBase = '/api/v1';

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x10131a);

const camera = new THREE.PerspectiveCamera(
  65,
  window.innerWidth / window.innerHeight,
  0.1,
  100
);
camera.position.set(0, 1.6, 4);

const renderer = new THREE.WebGLRenderer({
  antialias: true,
  powerPreference: 'high-performance'
});
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.xr.enabled = true;

document.body.append(renderer.domElement, VRButton.createButton(renderer));

scene.add(new THREE.HemisphereLight(0xffffff, 0x303040, 2));

const stageMeshes = new Map();
let currentSequence = 0;

function setStageState(mesh, state) {
  const active = state === 'active';
  const completed = state === 'completed';

  mesh.scale.setScalar(active ? 1.25 : 1);
  mesh.material.emissive.setHex(active ? 0x3355aa : 0x000000);
  mesh.material.opacity = completed ? 0.55 : 1;
  mesh.userData.state = state;
}

function renderSnapshot(snapshot) {
  currentSequence = snapshot.through_seq;

  for (const [index, stage] of snapshot.stages.entries()) {
    const geometry = new THREE.BoxGeometry(0.8, 0.8, 0.8);
    const material = new THREE.MeshStandardMaterial({
      color: 0x4d83b8,
      transparent: true
    });

    const mesh = new THREE.Mesh(geometry, material);
    mesh.position.set((index - snapshot.stages.length / 2) * 1.25, 1.4, 0);
    mesh.userData.stageCode = stage.code;

    setStageState(mesh, stage.state);
    stageMeshes.set(stage.code, mesh);
    scene.add(mesh);
  }
}

function applyEvent(event) {
  if (event.sequence !== currentSequence + 1) {
    recoverEvents(currentSequence).catch(console.error);
    return;
  }

  currentSequence = event.sequence;

  if (event.event_type === 'stage.transitioned') {
    const previous = stageMeshes.get(event.payload.from_stage);
    const next = stageMeshes.get(event.payload.to_stage);

    if (previous) setStageState(previous, 'completed');
    if (next) setStageState(next, 'active');
  }

  if (event.event_type === 'indicator.observed') {
    const target = stageMeshes.get(event.stage.code);
    if (target) {
      target.rotation.y += Math.PI / 4;
    }
  }
}

async function recoverEvents(afterSequence) {
  const response = await fetch(
    `${apiBase}/runs/${runId}/events?after_seq=${afterSequence}`,
    { credentials: 'include' }
  );

  if (!response.ok) throw new Error('Unable to recover run events');

  const body = await response.json();
  for (const event of body.events) applyEvent(event);
}

async function submitCommand(type, payload = {}) {
  const response = await fetch(`${apiBase}/runs/${runId}/commands`, {
    method: 'POST',
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json',
      'Idempotency-Key': crypto.randomUUID()
    },
    body: JSON.stringify({
      command_id: crypto.randomUUID(),
      type,
      expected_sequence: currentSequence,
      payload
    })
  });

  if (response.status === 409) {
    await recoverEvents(currentSequence);
    return;
  }

  if (!response.ok) throw new Error('Command rejected');
}

const raycaster = new THREE.Raycaster();
const tempMatrix = new THREE.Matrix4();
const controller = renderer.xr.getController(0);

controller.addEventListener('select', () => {
  tempMatrix.identity().extractRotation(controller.matrixWorld);
  raycaster.ray.origin.setFromMatrixPosition(controller.matrixWorld);
  raycaster.ray.direction.set(0, 0, -1).applyMatrix4(tempMatrix);

  const hits = raycaster.intersectObjects([...stageMeshes.values()]);
  const selected = hits[0]?.object;

  if (selected) {
    submitCommand('inspect_indicator', {
      stage_code: selected.userData.stageCode
    }).catch(console.error);
  }
});

scene.add(controller);

const snapshotResponse = await fetch(
  `${apiBase}/runs/${runId}/snapshot`,
  { credentials: 'include' }
);
if (!snapshotResponse.ok) throw new Error('Unable to load run');
renderSnapshot(await snapshotResponse.json());

const socket = new WebSocket(
  `wss://${location.host}/ws/runs/${encodeURIComponent(runId)}`
);

socket.addEventListener('message', ({ data }) => {
  const message = JSON.parse(data);
  if (message.type === 'simulation.event') applyEvent(message.event);
});

renderer.setAnimationLoop(() => renderer.render(scene, camera));

WebGL 2 provides the underlying browser rendering context used by engines such as three.js and Babylon.js, while WebXR supplies immersive display and input integration. Raw WebGL and raw WebXR are standards layers; most projects should use an engine unless highly specialized rendering requirements justify writing substantial infrastructure.

Framework and version recommendations

Versions below are a July 31, 2026 baseline, not permanent pins. Production builds should use the latest compatible security patch, commit Composer and npm lockfiles, test upgrades in CI, and record dependencies in a software bill of materials.

Rendering and XR frameworks

FrameworkRecommended version lineAdvantagesDisadvantagesBest fit
three.jsr185Flexible scene graph, broad examples and loader ecosystem, direct WebXR integration, strong control over instancing, custom shaders, picking, and optimizationRequires more application architecture, GUI, collision, accessibility, and tooling work than a full enginePreferred for a custom instructional visualization with a capable JavaScript team
Babylon.js9.19.xMore integrated game-engine experience, inspector, GUI, asset management, physics options, WebXR helpers, scene optimization facilitiesLarger and more opinionated abstraction surface; engine conventions can be excessive for a modest visualizationStrongest alternative when the team wants an integrated engine rather than a renderer toolkit
A-Frame1.8.xDeclarative HTML-like authoring, low entry barrier, rapid WebXR prototype development, component modelLess direct control for complex data-driven scenes; abstraction and underlying three.js version can lag; large applications may need substantial custom componentsBest for proof-of-concept, museum-style guided tours, or a small team new to 3D
Raw WebXR plus WebGL 2Current specificationsMaximum control and few framework assumptionsRequires extensive work for scene graphs, loaders, materials, input abstractions, interaction, optimization, and compatibilityOnly for research prototypes or highly specialized engines
WebGPU pathFeature-detected, optionalFuture-facing rendering and compute capabilitiesXR and browser/device support must be verified; using it as the only backend would reduce reachTreat as an optional later optimization, not the MVP compatibility baseline

three.js r185 was released in July 2026. Babylon.js 9.19.0 was released on July 30, 2026. A-Frame 1.8.0 was released in June 2026, updated its underlying three.js dependency to r184, and included controller and strict-CSP fixes.

Recommendation: choose three.js unless rapid declarative prototyping is more important than long-term control. Choose Babylon.js when its integrated GUI, inspector, engine utilities, and WebXR feature set replace enough custom work to justify its larger abstraction. Use A-Frame for a time-boxed prototype or simple guided exhibit, but conduct an architectural review before scaling it into a complex authoring and multiuser platform.

Application-shell frameworks

FrameworkRecommended lineAdvantagesDisadvantagesRecommendation
React19.2, latest patched releaseLarge ecosystem, mature state libraries, good fit for dashboards and authoring toolsCareless component rerendering can interfere with scene ownership; avoid mapping every 3D object to a DOM componentSuitable default, with the 3D canvas managed imperatively and React Server Components excluded from the client-only XR surface
VueVue 3, latest stable patch, built with ViteLower ceremony, approachable reactivity, effective for compact UI shellsSmaller enterprise ecosystem than React or Angular in some organizationsExcellent for a small team and a clean separation between DOM UI and 3D scene
Angular22.1 lineStrong conventions, dependency injection, routing, forms, testing, and RxJS-based event handlingHighest framework weight and learning overhead; lifecycle integration with a render loop needs disciplineAppropriate where Angular is already an organizational standard
No large UI frameworkNative modules, web components, small state storeMinimal runtime and direct controlAuthoring and administration screens become harder to maintainReasonable for the first single-scene technical prototype

React’s documented current line was 19.2, while Angular 22.1 was current in late July 2026. React has also published security fixes affecting some server-component configurations, reinforcing the need to remain on patched releases and to avoid unnecessary server-component exposure in a client-rendered XR application. Vue CLI is in maintenance mode; new Vue projects should use Vite-based tooling.

Do not let the UI framework own high-frequency scene state. Maintain the 3D scene through an engine adapter, update it from semantic state changes, and leave the engine’s render loop outside React, Vue, or Angular change-detection cycles.

PHP and realtime choices

TechnologyRecommended lineAdvantagesDisadvantagesPosition
PHP8.5.x, latest security patchCurrent language improvements and supported lifecycleRequires dependency compatibility testing, especially for older enterprise packagesDefault runtime
Laravel13.xFast delivery, expressive validation and policies, queues, cache, rate limiting, broadcasting, Reverb integrationAnnual major releases and convention-heavy design; long-running worker discipline is required with Octane/ReverbPreferred for MVP and product teams prioritizing speed
Symfony7.4 LTSModular components, explicit architecture, long security-support horizonMore initial assembly and configurationPreferred for conservative institutional or enterprise deployment
Symfony8.1.xLatest framework featuresShorter maintenance horizon than the LTS branchUse when the team intentionally follows frequent upgrades
Laravel ReverbVersion compatible with Laravel 13First-party Laravel broadcasting and WebSocket integrationOperating persistent sockets still demands capacity planning and monitoringDefault realtime option for an all-PHP Laravel stack
Ratchet or OpenSwooleLatest supported compatible versionsPHP-native persistent WebSocket/event-loop alternativesSmaller operational talent pool and more custom integration than standard request/response PHPConsider for specialist PHP teams
Node.js bridgeNode 24 LTSMature realtime and media ecosystem; useful for signaling, protocol translation, or isolated socket workloadsAdds another runtime, deployment path, dependency tree, and observability surfaceAdd only when it clearly reduces complexity elsewhere

PHP 8.5 was the current supported release line, with PHP 8.5.9 published on July 30, 2026. Symfony listed 8.1 as stable and 7.4 as its LTS branch, with 7.4 security support extending to November 2029. Node’s own guidance says production applications should use Active or Maintenance LTS; Node 24 was an LTS line in July 2026, while Node 26 remained Current.

Recommended deployment profiles:

ProfileStack
Fastest safe MVPPHP 8.5, Laravel 13, PostgreSQL, REST, SSE initially, A-Frame 1.8 or three.js r185, Vite
Recommended product architecturePHP 8.5, Laravel 13 or Symfony 7.4 LTS, PostgreSQL, Redis, transactional outbox, WebSocket, three.js r185, TypeScript, React or Vue
Enterprise institutional deploymentPHP 8.5, Symfony 7.4 LTS, organization OIDC provider, PostgreSQL, Redis, managed object storage/CDN, separate WebSocket tier, centralized OpenTelemetry
Media-rich multiuser extensionProduct architecture plus Node 24 LTS WebRTC signaling/media bridge; authoritative simulation state remains in PHP-backed services

UX, performance, security, and validation

Instructional and interaction design

Immersion should make causality spatially understandable rather than merely decorative. CAMIL identifies presence and agency as important affordances of immersive learning, but also observes that highly engaging environments can increase cognitive load and weaken self-regulation unless learners receive structure and reflection opportunities.

ModeInteraction patternTeaching purposeDesign requirement
Guided tourNarrated progression, highlighted evidence, constrained choices, pause-and-explain momentsNovice orientation and conceptual understandingOne instructional focus at a time; optional captions; explicit transition summaries
Branching scenarioLearner selects defensive controls and sees consequencesCausal reasoning and decision practiceExplain why an action succeeded, failed, or arrived too late
Analysis modeFreeze, rewind, filter, compare ground truth with observable evidenceIncident reconstruction and ATT&CK mappingPreserve sequence and provenance; show uncertainty rather than omniscient conclusions
SandboxLearner rearranges controls, changes visibility, and reruns safe simulationsSystems thinking and experimentationBound all inputs to a declarative scenario model; no arbitrary scripting
Facilitated multiuser exerciseParticipants occupy analyst, incident commander, identity, network, or endpoint rolesTeam communication and coordinationShared authoritative state, role-specific visibility, facilitator pause/rollback, moderated communication
Desktop companionKeyboard, mouse, touch, and accessible two-dimensional viewsAccess and broader deploymentFunctional parity for all learning-critical operations

Useful spatial patterns include:

  • A stage corridor or radial timeline for the high-level Lockheed sequence.
  • A network-and-identity graph showing assets, trust zones, lateral paths, and blast radius.
  • An evidence lens that reveals only the logs and indicators available to a defender at that moment.
  • A time scrubber for pause, rewind, replay, and counterfactual comparison.
  • Intervention portals where the learner chooses controls and predicts consequences before seeing the outcome.
  • A ground-truth toggle available only after the decision, preventing hindsight from contaminating assessment.
  • Debrief boards that map decisions to ATT&CK techniques, mitigations, observations, and missed opportunities.
  • Teleport locomotion, snap turning, seated mode, adjustable height, captions, nonspatial audio alternatives, reduced-motion mode, and desktop parity.

A 2026 cybersecurity-education study reported stronger retention and spatial presence for its immersive VR condition than its textbook, video, and desktop-VR comparisons, while also presenting desktop VR as a more accessible alternative. This is promising evidence, but it should not be generalized to every design; the simulation still requires controlled evaluation against a non-VR version.

Performance and scalability

WebXR applications are latency-sensitive because the browser must continuously produce views corresponding to tracked poses. Stable frame pacing is more important than visual richness. Quality should degrade predictably before frame rate becomes uncomfortable.

Recommended rendering budgets and techniques include:

  • Use glTF/GLB as the delivery format, KTX2-compressed textures, and optionally Draco or Meshopt geometry compression. Draco reduces transfer size but adds client decoding work, so profile total load time rather than optimizing file size alone.
  • Use instancing for repeated endpoints, packets, indicators, and topology markers. three.js documents InstancedMesh as a way to reduce draw calls for repeated geometry.
  • Apply level of detail, frustum culling, distance-based label suppression, pooled effects, light baking, and limits on real-time shadows.
  • Split scenarios into stage- or zone-specific asset bundles and preload the next likely branch.
  • Parse large event batches and calculate graph layouts in Web Workers.
  • Keep React, Vue, or Angular updates away from the per-frame rendering path.
  • Reduce pixel ratio, shadow quality, particles, postprocessing, and annotation density dynamically when measured frame time exceeds the device budget.
  • Dispose of geometries, materials, textures, audio buffers, event listeners, and XR input objects when changing scenarios.
  • Use engine-level tools such as Babylon’s scene optimizer when choosing Babylon.js.

On the server side:

  • Keep ordinary PHP API instances stateless and horizontally scalable.
  • Store sessions, rate-limit counters, presence, and fan-out metadata outside individual application instances.
  • Partition or index events by run and sequence; archive completed-run telemetry separately from active events.
  • Use snapshots so a reconnect does not replay an entire long exercise.
  • Apply backpressure to telemetry and realtime publishers.
  • Broadcast semantic deltas rather than complete state documents.
  • Isolate high-volume WebSocket workloads if persistent connections begin to compete with API capacity.
  • Do not introduce WebRTC peer meshes for general state synchronization; they become inefficient and difficult to govern as group size grows.

Application and content security

The OWASP API Security Top 10 highlights risks directly relevant to this product, including broken object-level authorization, broken authentication, unrestricted resource consumption, broken function-level authorization, server-side request forgery, and unsafe consumption of APIs. Every scenario, run, event stream, metric, and export therefore needs object-level checks rather than route-level authentication alone.

Core controls should include:

Control areaRequired implementation
IdentityOIDC or another established organizational identity mechanism; phishing-resistant MFA for authors and administrators where available
Browser sessionSecure, HttpOnly, SameSite cookies when using cookie authentication; CSRF defense for state-changing requests; short-lived realtime tickets
AuthorizationRun membership plus role and resource checks on every API call, WebSocket subscription, event recovery request, metric query, and asset manifest
Input validationVersioned JSON Schema or equivalent server validation; reject unknown command types, excessive nesting, unbounded arrays, arbitrary URLs, markup, and executable strings
Output safetyContextual output encoding; sanitized learner text; no direct innerHTML; no interpretation of scenario fields as code
Content Security PolicyRestrict scripts, workers, connections, images, audio, and models to approved origins; avoid unsafe-eval; use nonces or hashes where appropriate
Asset safetyQuarantine uploads; validate file type, size, dimensions, mesh counts, texture budgets, and supported glTF extensions; transcode assets before publication
Realtime securityValidate Origin; authenticate upgrades; authorize channels; limit connection count, message rate, and frame size; terminate idle or malformed clients
Rate limitingSeparate quotas for login, run creation, commands, event recovery, telemetry, exports, and asset uploads
AuditabilityImmutable records for publication, role changes, exports, facilitator overrides, and administrative access
Dependency securityComposer and npm lockfiles, automated advisory checks, SBOM generation, signed deployment artifacts, prompt patching
SecretsManaged secret storage; no credentials in JavaScript bundles, scenarios, 3D files, or container images
PrivacyCollect only metrics tied to explicit learning or operational questions; aggregate or discard high-frequency pose information client-side

Telemetry privacy

Do not persist raw headset pose, controller pose, hand-joint, gaze, microphone, or room-mapping data by default. Derive limited measures such as:

time spent at stage
number of evidence objects inspected
decision latency
incorrect interventions
help requests
navigation discomfort report
frame-time percentile
disconnect and recovery count

Use pseudonymous participant identifiers in analytics, keep account mapping in a more restricted system, and set a deletion date when data is written. Cohort dashboards should suppress small groups and avoid ranking individuals where the educational purpose does not require it.

Testing and evaluation

A rigorous validation plan needs four complementary levels.

Software and domain testing. Unit-test transition rules, scoring, visibility, ATT&CK-reference resolution, command allowlists, and privacy filters. Use property-based tests to generate unexpected event sequences and verify invariants such as monotonic sequence numbers, no transition after completion, and no learner access to facilitator-only evidence.

Integration and system testing. Test database transactions, outbox delivery, duplicated commands, reconnection, delayed messages, schema upgrades, snapshot rebuilding, browser refresh, and headset session interruption. Use contract tests for OpenAPI, GraphQL, event schemas, and realtime messages.

Rendering and device testing. Maintain a matrix of representative standalone headsets, desktop browsers, controllers, hand tracking where supported, and non-XR fallback. Test low-memory conditions, context loss, slow asset delivery, WebSocket interruption, controller disconnect, repeated XR entry/exit, seated mode, text legibility, and motion comfort. Official WebXR samples are useful as minimal capability references and device-diagnostic baselines.

Security testing. Include static analysis, dependency scanning, secret scanning, dynamic API tests, authorization matrix tests, WebSocket fuzzing, upload validation tests, CSP verification, SSRF probes, rate-limit tests, and a review of scenario content for operational misuse. A penetration test should explicitly attempt cross-run access, facilitator impersonation, event forgery, sequence replay, malicious glTF uploads, telemetry exfiltration, and denial of service.

Learning evaluation should use both immediate and delayed measures:

DimensionExample measure
Factual knowledgeCorrect identification of stages, tactics, indicators, and controls
Causal understandingExplanation of how one event enabled the next and where intervention was possible
TransferPerformance on a structurally similar scenario with different surface details
Decision qualityCorrect intervention, timing, prioritization, and confidence calibration
RetentionRepeated assessment after an appropriate delay
UsabilitySystem Usability Scale or another established instrument
WorkloadNASA-TLX or a suitable workload instrument
Presence and agencyValidated presence or embodiment scales relevant to the implementation
ComfortSimulator-sickness symptoms, early exit, locomotion changes, and help requests
System qualityFrame-time percentiles, dropped frames, long tasks, event lag, reconnects, memory, and load time

The preferred study is a randomized or counterbalanced comparison of VR and desktop versions using identical learning content. Use a pretest, immediate post-test, delayed test, scenario-transfer task, usability/workload measures, and qualitative interviews. Define primary outcomes before analysis and use power analysis rather than choosing sample size solely from available participants. Because instructional method interacts with immersive media, include reflection or self-explanation prompts as a tested design factor rather than evaluating headset use alone.

Roadmap, minimal viable prototype, and reference implementations

The estimates below are planning assumptions for a team already competent in PHP and modern JavaScript but not necessarily in WebXR. One person-week means one full-time engineer-week. “Low” is up to one person-week, “Medium” is approximately two to three, and “High” is four or more. Custom art production and institutional procurement are excluded.

Implementation roadmap

Milestone and taskEffortIndicative effortExit criterion
Governance and ethical-use policyMedium1–2 person-weeks across legal/security/SME rolesWritten content boundary, authorization policy, telemetry inventory, scenario-review process
Canonical model and learning objectivesMedium2 person-weeksApproved Lockheed/ATT&CK crosswalk, assessment rubric, first synthetic scenario outline
Domain schema and API contractsMedium2–3 person-weeksVersioned relational schema, JSON event schemas, OpenAPI contract, authorization matrix
PHP foundationMedium2–3 person-weeksAuthentication, scenario retrieval, run creation, command endpoint, event store, migrations
Desktop 3D sceneMedium3–4 person-weeksSeven-stage scene, asset loading, evidence interactions, state reducer, desktop navigation
Single-user WebXRHigh3–5 person-weeksHeadset entry, controller selection, teleport/snap turn, seated mode, acceptable device performance
Guided scenario and debriefMedium2–3 person-weeksOne end-to-end scenario, interventions, feedback, rewind, ATT&CK debrief
Realtime synchronizationHigh3–5 person-weeksWebSocket or SSE delivery, sequence recovery, snapshots, reconnect behavior
Security and privacy hardeningHigh3–5 person-weeksContent validation, object authorization tests, CSP, rate limits, telemetry minimization, audit trail
Automated and device testingHigh4–6 person-weeksCI test suite, browser/headset matrix, load tests, recovery tests, security test report
Instructor dashboardMedium2–3 person-weeksStart/pause/reset run, participant status, event timeline, approved metrics
Multiuser and presenceHigh4–7 person-weeksRole-specific clients, authoritative shared state, bounded pose updates, facilitator controls
Formal pilot evaluationHigh4–8 person-weeksApproved study protocol, pilot dataset, qualitative findings, prioritized revisions
Production operationsHigh4–8 person-weeksInfrastructure as code, monitoring, backup/recovery, retention automation, deployment runbooks

Activities overlap. A tightly scoped MVP does not require the full sum of the table; a production pilot does.

Minimal viable prototype

A defensible MVP should include:

AreaMVP scope
ScenarioOne fictional phishing-to-impact storyline; seven narrative stages; approximately 12–20 visible entities
ModelsLockheed stage labels plus selected ATT&CK tactics and techniques pinned to a specific ATT&CK release
ModesGuided tour and constrained branching exercise
PlatformsDesktop browser plus one primary WebXR headset family; desktop remains functionally complete
InteractionsInspect evidence, answer a prompt, apply one of several predefined defensive controls, advance after feedback
StateServer-authoritative run, append-only events, sequence recovery, deterministic replay
TransportREST plus SSE or a basic WebSocket channel
PHPAuthentication, scenario API, run API, command validation, event persistence, telemetry batching
JavaScript3D stage view, WebXR controller selection, teleport/snap turn, event reducer, simple debrief
MetricsCompletion, decision accuracy, decision latency, evidence inspected, help use, performance diagnostics
SecurityNo uploads, no custom scripts, no external URLs, synthetic indicators only, object-level authorization, rate limits
ExclusionsMultiuser avatars, WebRTC voice, AI-generated scenarios, real SIEM integration, cyber-range execution, gaze recording, comprehensive authoring

Suggested acceptance criteria are:

  • The same scenario can be completed in desktop and immersive modes without losing learning-critical functionality.
  • Refreshing or reconnecting reconstructs the exact run state.
  • Replaying the same event stream yields the same scene and score.
  • No scenario field can cause code execution, arbitrary network access, or loading from an unapproved origin.
  • A learner cannot access another run, facilitator-only evidence, or cohort telemetry.
  • The application maintains the selected headset’s required frame cadence under the defined scene budget.
  • At least one formative pilot demonstrates that learners can explain the causal chain, not merely recall stage names.
  • A privacy review confirms that no raw pose, gaze, voice, or room data is retained by default.

The MVP is approximately 12–16 person-weeks. A production classroom pilot with instructor tooling, hardened realtime synchronization, broader device testing, formal content review, and evaluation is more plausibly 30–45 person-weeks, excluding bespoke 3D art and enterprise procurement.

Primary references and open-source examples

Reference or projectTypeWhat to reuseImportant limitation
Hutchins, Cloppert, and Amin, Intelligence-Driven Computer Network Defense…Original industry paperSeven-phase narrative, campaign analysis, disruption-oriented teachingLinear abstraction should not be presented as a complete model of modern adversary behavior.
MITRE ATT&CK Design and PhilosophyPrimary methodology paperTactic/technique semantics, empirical grounding, coverage cautions, defensive and emulation use casesThe paper is a methodology source; current object content must come from the versioned ATT&CK data.
ATT&CK STIX/TAXII dataPrimary machine-readable sourceAutomated imports, identifiers, descriptions, relationships, version pinningTransform into a curated educational subset; do not expose the entire corpus to learners.
ATT&CK NavigatorOpen-source visualizationLayer documents, filtering, highlighting, matrix interaction, mapping displaysIt is a two-dimensional matrix tool, not a simulation runtime.
ATT&CK WorkbenchOpen-source content toolingEditing workflows, ATT&CK object management, local knowledge-base patternsIts data-authoring model still needs instructional and spatial extensions.
MITRE CALDERAOpen-source adversary-emulation platformTerminology, operation timelines, adversary-profile concepts, plugin architecture ideasDo not embed executable abilities in a public educational simulator; integration requires a separately authorized range.
W3C WebXR Device API and Immersive Web samplesPrimary standard and reference demosSession lifecycle, input, reference spaces, capability checks, minimal diagnostic examplesSamples are deliberately small and do not supply application architecture, accessibility, or security policy.
three.js examples and loadersOpen-source rendering examplesWebXR setup, controller interaction, glTF, KTX2, Draco, instancing, pickingExamples require production error handling, disposal, accessibility, and state architecture.
Khronos glTF and KTX specificationsPrimary format standardsRuntime asset format, texture packaging, compression pipelineAsset safety, extension allowlists, and complexity budgets remain application responsibilities.
OASIS STIX 2.1Primary CTI standardInterchange for indicators, threat actors, attack patterns, relationships, and bundlesNot a substitute for run events, spatial entities, learning objectives, or learner telemetry.
Makransky and Petersen’s CAMILOriginal academic modelDesign hypotheses concerning presence, agency, cognitive load, reflection, and learningIt motivates evaluation; it does not guarantee that an immersive implementation will outperform desktop instruction.
Rehman et al., immersive VR cybersecurity education studyAcademic empirical studyEvaluation dimensions, desktop/immersive comparison, engagement, retention, usability, presenceResults are study- and implementation-specific and should be replicated for the proposed kill-chain curriculum.

The central design decision is to make semantic events—not visual effects—the core product. A carefully versioned scenario graph and authoritative event stream can support desktop, VR, replay, assessment, instructor dashboards, analytics, and future engines. A scene built first without that domain model is likely to become an attractive but brittle demonstration. Conversely, a secure event model with strong instructional design can begin as a modest desktop/VR prototype and evolve into a validated simulation platform without crossing the boundary into operational offensive tooling.