generated from Labyricorn/labyricorn-project-template
344 lines
12 KiB
Markdown
344 lines
12 KiB
Markdown
# CyberSim Scenario Format v1.0 — Specification & Author Guide
|
||
|
||
## 1. Overview
|
||
|
||
The **CyberSim Scenario Format v1.0** is a declarative, portable, JSON-based format for authoring simulation scenarios in CyberSim OS. It enables scenario designers to construct complete cybersecurity training experiences without writing or modifying CyberSim OS code.
|
||
|
||
A scenario package defines:
|
||
- **Simulation identity & metadata** (title, description, duration, learner profile, target score)
|
||
- **Workplace context** (people, organizations, domains, department hierarchies)
|
||
- **Simulated objects** (emails, web pages, intranet sites, forms, documents, spreadsheets, files)
|
||
- **Scheduled & reactive events** (timed triggers, action-driven consequences, delays, repetitions)
|
||
- **Behavior vocabulary & actions** (app launches, notifications, alert generation, inbox deliveries)
|
||
- **Multi-axis behavioral evaluation** (scoring rules, pedagogical findings, after-action feedback)
|
||
|
||
---
|
||
|
||
## 2. Package Structure
|
||
|
||
A scenario is stored within a self-contained directory:
|
||
|
||
```
|
||
scenarios/my-scenario/
|
||
├── scenario.json # Main manifest & scenario definition (required)
|
||
├── assets/ # Local attachments & assets (optional)
|
||
└── README.md # Scenario author notes & changelog (optional)
|
||
```
|
||
|
||
For large scenarios, sub-collections can optionally be split across multiple files using `$ref:` references:
|
||
|
||
```json
|
||
{
|
||
"formatVersion": "1.0",
|
||
"id": "enterprise-phish-triage",
|
||
"people": "$ref:people.json",
|
||
"messages": "$ref:messages.json"
|
||
}
|
||
```
|
||
|
||
*Note: All referenced files must reside within the scenario directory tree. Paths with `..`, absolute paths, and external URL schemes are rejected by the loader.*
|
||
|
||
---
|
||
|
||
## 3. Top-Level Manifest Reference
|
||
|
||
| Property | Type | Required | Description |
|
||
|---|---|---|---|
|
||
| `formatVersion` | `string` | **Yes** | Must be `"1.0"`. |
|
||
| `id` | `string` | **Yes** | Unique identifier (lowercase alphanumeric and hyphens). |
|
||
| `version` | `string` | **Yes** | Semantic version of the scenario (e.g. `"1.0.0"`). |
|
||
| `title` | `string` | **Yes** | Human-readable title displayed in the launcher and AAR. |
|
||
| `description` | `string` | **Yes** | Overview of the simulation setting and primary challenges. |
|
||
| `durationSeconds`| `number` | **Yes** | Expected run time in seconds (e.g. `900`). |
|
||
| `mode` | `string` | **Yes** | Instruction mode: `"guided"`, `"practice"`, or `"assessment"`. |
|
||
| `entryEvent` | `string` | **Yes** | ID of the event executed at scenario start. |
|
||
| `passingScore` | `number` | **Yes** | Minimum score required to pass and earn a certificate (0–100). |
|
||
| `supportedLocales` | `array` | No | List of supported language codes (e.g. `["en", "es"]`). |
|
||
| `login` | `object` | No | Network login metadata: `{ networkName, networkDescription, networkIcon }`. |
|
||
| `engine` | `object` | No | Minimum engine version requirements (`{ "minimumVersion": "0.2.0" }`). |
|
||
| `learner` | `object` | No | Initial persona: `{ name, role, email, department }`. |
|
||
| `organizations` | `array` | No | List of simulated organizations & trusted domain lists. |
|
||
| `people` | `array` | No | Simulated personas and contact directory. |
|
||
| `objectives` | `array` | No | Visible shift objectives shown in Start Menu and UI. |
|
||
| `messages` | `array` | No | Simulated email messages (Inlook). |
|
||
| `pages` | `array` | No | Simulated web pages and browser targets (Navigator). |
|
||
| `files` | `array` | No | Virtual filesystem items (Documents, Downloads, Shared). |
|
||
| `notifications`| `array` | No | Pre-configured desktop toast notification templates. |
|
||
| `alerts` | `array` | No | Security Center alert definitions. |
|
||
| `events` | `array` | **Yes** | Declarative triggers and action lists. |
|
||
| `scoring` | `object` | **Yes** | Category declarations and rule definitions. |
|
||
| `findings` | `array` | No | Predefined pedagogical findings and deductions. |
|
||
| `feedback` | `array` | No | Performance-conditional after-action remarks. |
|
||
| `completion` | `object` | No | Finalization criteria and certificate issuance rules. |
|
||
|
||
---
|
||
|
||
## 4. Object Types
|
||
|
||
### 4.1 Organizations (`organizations[]`)
|
||
Defines trusted enterprise domains and third-party corporate entities.
|
||
|
||
```json
|
||
{
|
||
"id": "nexacore",
|
||
"name": "NexaCore Technologies",
|
||
"domains": ["nexacore.internal"],
|
||
"departments": ["Finance", "Information Security", "IT Helpdesk"],
|
||
"securityContacts": ["[email protected]"]
|
||
}
|
||
```
|
||
|
||
### 4.2 People (`people[]`)
|
||
Defines characters and email identities.
|
||
|
||
```json
|
||
{
|
||
"id": "alex-rivera",
|
||
"name": "Alex Rivera",
|
||
"role": "Chief Information Security Officer",
|
||
"email": "[email protected]",
|
||
"organization": "nexacore",
|
||
"department": "Information Security"
|
||
}
|
||
```
|
||
|
||
### 4.3 Messages (`messages[]`)
|
||
Defines email communications in Inlook.
|
||
|
||
```json
|
||
{
|
||
"id": "email_phish_pwreset",
|
||
"sender": "NexaCore IT Helpdesk",
|
||
"rfcSender": "[email protected]",
|
||
"recipient": "[email protected]",
|
||
"subject": "URGENT: Password Verification Required",
|
||
"date": "09:05 AM",
|
||
"folder": "pending",
|
||
"unread": true,
|
||
"body": "Please confirm credentials at: <a class=\"inlook-msg-link\" data-url=\"http://login-nexac0re-portal.com/auth/login\" data-display=\"https://intranet.nexacore.internal/sso\">https://intranet.nexacore.internal/sso</a>",
|
||
"links": [
|
||
{
|
||
"displayText": "https://intranet.nexacore.internal/sso",
|
||
"actualUrl": "http://login-nexac0re-portal.com/auth/login"
|
||
}
|
||
],
|
||
"attachments": []
|
||
}
|
||
```
|
||
|
||
### 4.4 Pages (`pages[]`)
|
||
Defines intranet and external web destinations in Navigator. Form submissions are bound declaratively by ID.
|
||
|
||
```json
|
||
{
|
||
"url": "http://login-nexac0re-portal.com/auth/login",
|
||
"title": "NexaCore Identity SSO",
|
||
"isSecure": false,
|
||
"isPhishing": true,
|
||
"content": "<div class=\"phish-card\"><form id=\"phish-login-form\">...</form></div>",
|
||
"forms": [
|
||
{
|
||
"id": "phish-login-form",
|
||
"onSubmit": {
|
||
"emitEvent": "NAV_FORM_SUBMITTED",
|
||
"target": "phish_login_form",
|
||
"response": {
|
||
"type": "pageContent",
|
||
"content": "<div>Account Verification Complete</div>"
|
||
}
|
||
}
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 4.5 Files (`files[]`)
|
||
Virtual files accessible in the Files app and DocViewer.
|
||
|
||
```json
|
||
{
|
||
"id": "file_budget",
|
||
"name": "Q3_Budget_Forecast.xlsx",
|
||
"type": "spreadsheet",
|
||
"folder": "Documents",
|
||
"size": "48 KB",
|
||
"date": "2026-08-20",
|
||
"content": {
|
||
"title": "Q3 Budget Forecast",
|
||
"headers": ["Category", "Q1", "Q2", "Q3"],
|
||
"rows": [["Infrastructure", "$142k", "$155k", "$168k"]]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 5. Event System & Behavior Vocabulary
|
||
|
||
Events are evaluated deterministically on each engine cycle.
|
||
|
||
```json
|
||
{
|
||
"id": "deliver-phish-email",
|
||
"when": { "elapsedSeconds": 30 },
|
||
"actions": [
|
||
{ "type": "mail.deliver", "message": "email_phish_pwreset" },
|
||
{ "type": "desktop.notify", "title": "Inlook Mail", "body": "New message received.", "type": "info" }
|
||
]
|
||
}
|
||
```
|
||
|
||
### 5.1 Condition Triggers (`when`)
|
||
- `{ "scenarioStart": true }` — Triggers on the initial simulation tick.
|
||
- `{ "elapsedSeconds": 45 }` — Triggers when `simSeconds >= 45`.
|
||
- `{ "actionOccurred": { "type": "EMAIL_OPENED", "target": "email_phish" } }` — Triggers on user action.
|
||
- `{ "stateEquals": { "object": "inlook", "key": "selected", "value": "email_1" } }` — Triggers on state match.
|
||
- `{ "all": [ condition1, condition2 ] }` — Logical AND.
|
||
- `{ "any": [ condition1, condition2 ] }` — Logical OR.
|
||
- `{ "not": condition }` — Logical NOT.
|
||
|
||
### 5.2 Behavior Vocabulary (Action Whitelist)
|
||
|
||
#### Desktop Actions
|
||
- `desktop.notify` — Toast alert (`{ title, body, type, timeout, icon }` or `{ notification: "notif_id" }`).
|
||
- `desktop.openApp` — Launch app (`{ app: "inlook" | "navigator" | "files" | "security_center" | "docviewer" }`).
|
||
- `desktop.focusApp` — Bring window to focus.
|
||
- `desktop.setBadge` — Update taskbar/tab badge counter.
|
||
- `desktop.endScenario` — Complete the session and launch AAR.
|
||
|
||
#### Mail Actions
|
||
- `mail.deliver` — Deliver message to Inlook inbox (`{ message: "msg_id" }`).
|
||
- `mail.updateMessage` — Update message attributes.
|
||
|
||
#### Navigator Actions
|
||
- `navigator.open` — Open browser to specified URL (`{ url: "http://..." }`).
|
||
- `navigator.redirect` — Redirect current browser tab.
|
||
|
||
#### Files Actions
|
||
- `files.create` — Dynamically inject file into virtual filesystem.
|
||
- `files.open` — Open document in DocViewer (`{ fileId: "file_id" }`).
|
||
|
||
#### Security Center Actions
|
||
- `security.addAlert` — Add security notification item (`{ alert: "alert_id" }` or inline object).
|
||
- `security.updateStatus` — Change dashboard threat state.
|
||
|
||
#### Evaluation Actions
|
||
- `evaluation.addFinding` — Record a pedagogical finding (`{ finding: "finding_id" }`).
|
||
- `evaluation.setState` — Set custom runtime state variable.
|
||
- `evaluation.completeObjective` — Mark a shift task completed (`{ objective: "obj_id" }`).
|
||
- `evaluation.awardPoints` — Adjust category points (`{ category: "cat_id", points: 10 }`).
|
||
|
||
---
|
||
|
||
## 6. Scoring & Findings Pipeline
|
||
|
||
Scoring is computed at the end of the shift or on-demand:
|
||
|
||
```json
|
||
{
|
||
"scoring": {
|
||
"categories": [
|
||
{ "id": "threat-detection", "label": "Threat Detection", "maxPoints": 20, "startingPoints": 0 },
|
||
{ "id": "safe-handling", "label": "Safe Handling", "maxPoints": 15, "startingPoints": 15 }
|
||
],
|
||
"rules": [
|
||
{
|
||
"id": "opened-phish-email",
|
||
"condition": { "actionOccurred": { "type": "EMAIL_OPENED", "target": "email_phish_pwreset" } },
|
||
"award": { "category": "threat-detection", "points": 10 },
|
||
"timeline": { "type": "positive", "text": "Identified and reviewed the password reset notice." }
|
||
},
|
||
{
|
||
"id": "submitted-phish-credentials",
|
||
"condition": { "actionOccurred": { "type": "NAV_FORM_SUBMITTED", "target": "phish_login_form" } },
|
||
"award": { "category": "safe-handling", "points": -10 },
|
||
"timeline": { "type": "critical", "text": "Entered password on untrusted external portal." },
|
||
"feedback": "CRITICAL: Never enter credentials into untrusted external sites."
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Cryptographic Fingerprinting & Certificates
|
||
|
||
When a scenario is loaded, the engine computes a canonical SHA-256 hash across all evaluation-relevant elements (messages, pages, files, events, scoring rules, findings).
|
||
|
||
Upon completion with a passing score (`totalScore >= passingScore`), the learner may claim an exportable `*.cybercert` JSON record. The certificate embeds the scenario fingerprint and an integrity hash that can be verified offline via `verify.html`.
|
||
|
||
---
|
||
|
||
## 8. Authoring Diagnostics & Development Mode
|
||
|
||
To inspect and test scenarios during development, add `?dev=true` to the URL:
|
||
|
||
```
|
||
http://127.0.0.1:8080?scenario=scenarios/my-scenario/scenario.json&dev=true
|
||
```
|
||
|
||
The diagnostics overlay provides:
|
||
- Live structural & semantic validation errors
|
||
- Event trigger states and scheduled timers
|
||
- Current category score breakdowns and recorded findings
|
||
- Scenario SHA-256 fingerprint calculations
|
||
|
||
---
|
||
|
||
## 9. Scenario Localization & Personalization
|
||
|
||
### 9.1 Declaring Supported Locales & Login Presentation
|
||
|
||
Scenarios declare their supported language codes in `scenario.json`:
|
||
|
||
```json
|
||
{
|
||
"formatVersion": "1.0",
|
||
"id": "my-scenario",
|
||
"supportedLocales": ["en", "es"],
|
||
"login": {
|
||
"networkName": "ACME Corporate Network",
|
||
"networkDescription": "Simulated Corporate Workplace",
|
||
"networkIcon": "corporate"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 9.2 Providing Scenario Translations (`locales/<lang>.json`)
|
||
|
||
Translations for scenario-specific content are stored within the scenario package under `locales/`:
|
||
|
||
```
|
||
scenarios/my-scenario/
|
||
├── scenario.json
|
||
└── locales/
|
||
├── en.json
|
||
└── es.json
|
||
```
|
||
|
||
The translation catalog can override text properties across messages, pages, files, notifications, alerts, findings, and feedback:
|
||
|
||
```json
|
||
{
|
||
"title": "Turno Operativo y Concientización",
|
||
"messages": {
|
||
"email_welcome": {
|
||
"sender": "Morgan Chen (Vicepresidente)",
|
||
"subject": "Bienvenido al equipo",
|
||
"body": "Hola {{learner.firstName}},\n\n¡Bienvenido!"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 9.3 Learner Personalization Variables
|
||
|
||
The following template variables are available for dynamic interpolation across messages, documents, web pages, notifications, and feedback:
|
||
|
||
- `{{learner.firstName}}`: Learner's validated first name entered at login (HTML-escaped).
|
||
- `{{learner.name}}`: Learner's full name.
|
||
- `{{learner.email}}`: Learner's assigned workplace email address.
|
||
- `{{learner.role}}`: Learner's assigned workplace job title.
|
||
- `{{company.name}}`: Primary enterprise organization name.
|