Documentation

Builder tutorial

Step-by-step guide for Create, Library, engines, workflows, and play URLs. Source file: app/admin/TUTORIAL.md

Simulator Builder — Admin Tutorial

This is the operator guide for the Cyfotok config-driven Simulator Builder. Use it to author labs without writing TypeScript packages. Students play your configs through the shared runtime lab slug config-simulator.

Builder (short URL)`/create-simulator`
Builder (admin)`/admin/create-simulator`
Library`/admin/simulators`
In-app docs`/admin/tutorial`
Play slugconfig-simulator
Play URL shape/lab/config-simulator?configId=<id>&token=<jwt>
StorageBrowser localStorage + JSON import/export
TemplatesBundled under simulator-configs/templates/
Important: The builder is ungated (no lab JWT). Playing a published config still requires a normal lab token for slug config-simulator.

How to use this tutorial

  1. Keep this doc open beside the builder.
  2. Complete Part A once (orient + first publish).
  3. Use Part B for the engine you are authoring.
  4. Use Part C for sharing, play tokens, and troubleshooting.

Checkpoint style:

  • Do: action you take
  • See: what the UI should show
  • Why: why it matters
  • Next: where to go

Table of contents

Part A — Orient & first lab

  1. What the builder is
  2. Open the builder and library
  3. Wizard steps overview
  4. Pick a template
  5. Meta & intro
  6. Seed data vs content
  7. Live preview
  8. Validate, save, publish, export
  9. Play your lab with a JWT

Part B — Engines

  1. Engine cheat sheet
  2. Step quiz labs
  3. EDR labs
  4. SIEM labs
  5. Web pentest labs
  6. Linux shell labs (workflows)

Part C — Operations

  1. Library: templates, edit, export, delete
  2. Import / export JSON
  3. Query parameters & deep links
  4. Flag design guidelines
  5. Troubleshooting
  6. Appendix: field reference

Part A — Orient & first lab

1. What the builder is

Why

Historically each lab lived as a TypeScript package under labs/<slug>/. The Simulator Builder lets you author config JSON that the single runtime lab config-simulator interprets.

Engines

EngineWhat students get
stepGuided info + quiz steps
edrReduced live EDR console + scenario objectives
siemReduced live SIEM console + scenario objectives
web-pentestChallenge range (XSS, SQLi, upload, auth, …)
linux-shellFake bash terminal with authored commands & workflow

What is *not* codegen

Publishing does not create a new labs/<slug>/ folder. It saves a definition (localStorage and/or JSON file) that config-simulator loads by configId.


2. Open the builder and library

Do

  • From the vuln home page, click Simulator builder, or open /create-simulator.
  • Or open /admin/create-simulator / /admin/simulators.

See

  • Sticky admin nav: Create · Library · Docs · Home
  • Soft grid + emerald glow background
  • Create page: hero, 5-step progress, template cards, live preview pane

Why

Create is the authoring wizard. Library lists browser-saved drafts/published configs and one-click clones of bundled templates.

Next

Stay on Create for your first lab.


3. Wizard steps overview

StepNamePurpose
1TemplateChoose starter, blank, or import JSON
2Meta & introTitle, difficulty, tags, final flag, briefing
3Seed dataInventory / shell settings / static seeds (engine-specific)
4ContentScenarios, steps, challenges, or command workflow
5ReviewValidate, save draft, publish, export, raw JSON

You can click completed step pills to jump back. Steps after Template stay disabled until a definition exists.

The right column is a live preview of the student experience (reset anytime).


4. Pick a template

Do

  1. On step Template, choose a starter card (recommended first time), or a blank shell for the same engine.
  2. Or paste exported JSON → Import & continue.
  3. Or open Library / use ?template=<id>.

See

  • Message like “Loaded linux-shell-starter”
  • Wizard advances to Meta & intro
  • Preview shows the lab intro

Starter IDs

Catalog idBundled play id
edr-startertpl-edr-starter
siem-startertpl-siem-starter
step-startertpl-step-starter
web-pentest-startertpl-web-pentest-starter
linux-shell-startertpl-linux-shell-starter

Deep link example:

/create-simulator?template=linux-shell-starter

Why

Starters ship with working scenarios so you learn by editing, not inventing every field.

Next

Edit Meta & intro.


5. Meta & intro

Do

Fill:

FieldNotes
TitleStudent-facing lab name
DescriptionShort catalog blurb (max ~500 chars)
Difficultybeginner · intermediate · advanced
TagsComma-separated topics
Final flagAwarded when the lab’s win condition is met
Intro title / body / bulletsBriefing screen before play

See

Preview intro updates as you type (refresh preview if needed).

Why

finalFlag is the primary completion reward for every engine. Engine-specific “unlock” flags (if any) are optional extras — see Flag design.

Next

Open Seed data, then Content.


6. Seed data vs content

Mental model:

LayerMeaningExamples
SeedWorld / environment that exists before the scenario runsEndpoints, hosts, fake FS, env vars, blocked patterns
ContentWhat the student must doScenarios + objectives, quiz steps, web challenges, shell commands

Linux shell: Seed = shell chrome + FS + policy; Content = Terminal workflow (commands).


7. Live preview

Do

  • Interact with the preview like a student.
  • Click Reset / Refresh preview after large edits.

See

Intro → play surface → completion overlay when win conditions are met.

Why

Catch match-rule mistakes (especially shell/web) before publish.


8. Validate, save, publish, export

Do (Review step)

  1. Confirm the green Definition is valid banner (or fix listed Zod errors).
  2. Save draft — keep iterating in this browser.
  3. Publish — marks status: "published" in localStorage.
  4. Export JSON — download a portable file for git, sharing, or another machine.
  5. Optional: Edit raw JSON → Apply JSON (advanced).

See

Toast/message with saved id, e.g. cfg-linux-….

Why

  • Draft vs published is metadata for you; both can be played if you know the id.
  • Export is the durable backup — localStorage is per-browser and can be cleared.

Next

Play with a JWT.


9. Play your lab with a JWT

Do

  1. Issue a lab token whose claim lab is exactly config-simulator (see root `HOW_TO_WORK.md` / npm run sign-token).
  2. Open:
/lab/config-simulator?configId=<your-id>&token=<jwt>

For bundled starters without saving:

/lab/config-simulator?configId=tpl-linux-shell-starter&token=<jwt>

See

Same experience as the builder preview, under normal lab chrome and token middleware.

Why

Builder preview skips lab auth. Production play must use the RS256 gate like every other lab.

Resolution order

  1. Saved config in this browser’s localStorage matching configId
  2. Else bundled template id (tpl-… or catalog alias)

Part B — Engines

10. Engine cheat sheet

EngineWin condition (final flag)Author focus
stepComplete all steps correctlyStep kinds + answers
edrComplete all scenario objectivesEndpoints, beats, objectives
siemComplete all scenario objectivesSources, rules, beats, objectives
web-pentestComplete required challengesChallenge kinds + success patterns
linux-shellSucceed every required commandWorkflow gates + outputs

11. Step quiz labs

When to use

Short lessons, concept checks, ordering exercises — no live console.

Content: step kinds

KindStudent task
infoRead content, continue
single_choicePick one correct option
multi_choicePick all correct options
order_listPut items in correct order

Do

  1. Template → Step Quiz Starter (or blank step).
  2. Meta → set finalFlag.
  3. Content → add/edit steps; set correct option ids carefully.
  4. Preview: walk the quiz; finish → Final Success.

Tips

  • Option / item ids must match correctOptionId / correctOptionIds / correctOrderIds.
  • Keep info steps short; put depth in the intro briefing.

12. EDR labs

When to use

Endpoint detection & response training: investigate hosts, alerts, IOCs, containment-style objectives.

Seed

Typical seeds:

  • Endpoints — hostname, user, IP, OS, risk, health
  • Alerts / IOCs / MITRE — static catalog entries

Content: scenarios

Each scenario has:

  • Title / description
  • Timed beats (spawn process, network, alert, …) that mutate the console over simulation time
  • Objectives — typed actions the student must perform (isolate_endpoint, kill_process_name, open_alert, …)

Do

  1. Start from EDR Starter.
  2. Adjust endpoints so objective targets match real ids/names.
  3. Edit objectives’ target fields to match seed data (hostname, hash, process name).
  4. Preview → launch scenario → complete objectives → flag.

Tips

  • Objective target mismatches are the #1 “I did the action but it didn’t count” bug.
  • Keep beat timelines short for training labs.

13. SIEM labs

When to use

Log/search/incident workflow training.

Seed

Sources, hosts, users, detection rules, seed alerts/IOCs/MITRE.

Content: scenarios

Beats inject logs/alerts/incidents; objectives include run_search, open_incident, assign_incident, enable_rule, etc.

Do

  1. Start from SIEM Starter.
  2. Align objective targets with rule names, alert ids, or search strings your UI expects.
  3. Preview the investigation path end-to-end.

Tips

Same as EDR: targets must match seed identifiers exactly.


14. Web pentest labs

When to use

Browser-based vuln challenges in a sandboxed player (XSS stays in iframes).

Challenge kinds (overview)

KindIdea
reflected_inputReflect payload; optional WAF blockedPatterns
stored_formMulti-field stored XSS-style render
file_upload_simFilename/content inspection (simulated)
sqli_formFake SQL string + tautology / pattern success
auth_formWeak password / hidden field / alg=none style modes
open_redirectDangerous redirect parameter
path_traversalFake FS read via ../
idorObject id access control
cmd_injection_simSimulated command injection
ssrf_simSimulated SSRF allow/deny
csrf_token_bypassToken missing/wrong handling
cookie_tamperClient cookie privilege change
infoReading / interstitial

Success is driven by successPatterns (includes / equals / regex).

Do

  1. Start from Web Pentest Starter.
  2. For each challenge: set prompt, hints, patterns, and sample payloads.
  3. Preview each challenge; confirm completion marks.

Tips

  • Prefer includes patterns for teaching labs; use regex when you need precision.
  • WAF patterns run before success checks on reflected challenges.

15. Linux shell labs (workflows)

This engine is built for multi-command missions with a single final flag.

Core ideas

  1. Add many commands — each with its own match rules and outputs.
  2. Mark only mission-critical ones as Required for final flag.
  3. Optional commands never block completion.
  4. Use prerequisites to lock tools until earlier steps succeed.
  5. Award `meta.finalFlag` only after every required command succeeds.
  6. Leave per-command intermediate unlock flags empty unless you want bonus breadcrumbs.

Seed (shell settings)

AreaPurpose
User / hostname / cwd / home / promptPrompt chrome
Welcome linesBanner on start
Env (KEY=value)Available to templates / env builtin
Fake FS`path\
Blocked patternsLab policy (e.g. block rm -rf)
Builtins / tab / clearQuality-of-life toggles

Stdout templates support: {{user}}, {{hostname}}, {{cwd}}, {{home}}, {{pwd}}.

Content: Terminal workflow

#### Workflow settings

  • Mission title / description — shown in the player sidebar
  • Final flag — same as Meta (editable here for convenience)
  • Show numbered mission progress — required steps checklist

#### Per command

ControlPurpose
Required for final flagCounts toward completion
Match mode / patternexact, prefix, or regex selects the command
Default success outputStdout on success
+ Output variantAlternate stdout when a secondary pattern matches
+ Error ruleWrong usage / wrong target → stderr (does not complete)
+ AliasExtra patterns that select this same command
PrerequisitesCheckbox gates (must complete those ids first)
Hint + reveal after N failsTeaching aid
Intermediate unlock flagOptional; usually leave blank

#### Authoring a chain (recommended)

Do

  1. Template → Linux Shell Starter (or blank Linux shell).
  2. Content → review the workflow preview (whoami → ping → nmap).
  3. + Required step to append another gated step (auto-chains to previous required).
  4. + Optional command for practice tools that should not block the flag.
  5. For each tool, add error rules (wrong host) and success variants (e.g. ping -c 4 …).
  6. Preview: try locked tools early → see “Permission denied…”; complete required set → Final Success with only the final flag.

See

  • Sidebar: numbered mission progress + catalog (required / optional / locked)
  • After all required succeed → completion overlay with finalFlag

Why

Students practice a realistic path; you control pacing with gates; you do not spam flags on every command.

Match evaluation order (simplified)

  1. Blocked line patterns (lab policy)
  2. Builtins (clear, help, …)
  3. Authored commands (primary match or alias)
  4. Inside a command: missing prereqs → error; else error rules; else success variants; else default success
  5. FS builtins (cd, ls, cat, …) if enabled
  6. Unknown command template

Part C — Operations

16. Library: templates, edit, export, delete

Do

Open `/admin/simulators`.

Bundled templates

  • Use in builder/admin/create-simulator?template=<id> (fresh clone, new id)
  • Short link/create-simulator?template=<id>

Saved configs

ActionEffect
Edit?edit=<id> loads that localStorage config
ExportDownload JSON
DeleteRemove from this browser only

17. Import / export JSON

Export

Review → Export JSON, or Library → Export.

Import

Template step → paste → Import & continue, or Review → Edit raw JSON → Apply.

Why

Move labs between machines, commit JSON under simulator-configs/, or hand off to another author.

Tip

After hand-editing JSON, always hit Review validation before publish.


URLMeaning
/create-simulatorAlias → admin create
/admin/create-simulatorNew / continue wizard
?template=linux-shell-starterClone bundled starter
?edit=<configId>Open saved config
/admin/simulatorsLibrary
/admin/tutorialThis tutorial (in-app)
/lab/config-simulator?configId=…Play (needs JWT)

19. Flag design guidelines

PatternUse when
Single final flagDefault. Set meta.finalFlag; mark required steps/objectives only.
Intermediate `unlockFlag` (shell)Rare. Prints FLAG: … on that command’s success — does not replace the final flag.
No required commands (shell)Lab never auto-completes — always mark ≥1 required.

Suggested naming:

cyfotok{short_lab_goal_complete}

20. Troubleshooting

SymptomLikely causeFix
Validation errors on ReviewMissing fields / bad enumsRead path + message; fix in UI or JSON
Preview blankNo template chosenPick starter or import
Shell never completesZero required commandsMark required steps
Shell tool always deniedPrerequisites not done / wrong idsCheck prerequisite checkboxes
Wrong stdoutVariant/error matched firstReorder rules; tighten patterns
EDR/SIEM objective stucktarget ≠ seed id/nameAlign targets
Play 401 / unauthorizedJWT missing or labconfig-simulatorRe-issue token
Play loads wrong labBad configIdConfirm id in Library / export
Lost draftCleared site dataRestore from exported JSON

21. Appendix: field reference

Shared (meta / intro)

  • meta.title, meta.description, meta.difficulty, meta.tags[], meta.finalFlag
  • intro.title, intro.body, intro.bullets[]
  • status: draft \| published
  • engine: one of the five kinds
  • version: 1

Linux workflow

  • title, description, showMissionProgress

Linux commands[]

  • id, name, synopsis, hint
  • match / aliases[]{ mode, pattern, flags? }
  • success{ stdout, exitCode, delayMs }
  • successVariants[]{ id, when, stdout, exitCode }
  • errors[]{ id, when, stderr, exitCode }
  • requiresCommandIds[], required, unlockFlag?, showInCatalog, revealHintAfterFails

Schema source of truth

TypeScript Zod schemas live in `lib/simulator-builder/schema.ts`. When the UI and this doc disagree, trust the schema + live preview.


Quick start (10 minutes)

  1. Open `/create-simulator?template=linux-shell-starter`.
  2. Skim Meta; keep the starter final flag or rename it.
  3. Open Content → note required chain and optional curl / id.
  4. Preview: whoamiping cyfotok.comnmap cyfotok.com → flag.
  5. Publish → copy play path from Review.
  6. Sign a config-simulator token and open /lab/config-simulator?configId=<id>&token=….

You are ready to author your own workflow.

Also available in the repo as Create · Library