Helm
Under the hood EULA Terms Back to site

Under the hood

For engineers evaluating Helm. Updated July 3, 2026.

Helm is a multi-app desktop + cloud system: a player-facing launcher kiosk, an operator console, an agent on every station, and a shared cloud receiver. Below is the actual shape of what ships, the gates that protect it, and the gaps we have not closed yet. We would rather show this page than have you find the gaps on your own.

Component map

Four runtime components, one event spine, one brand pipeline.

┌─ Launcher (kiosk per station)
│   WPF · .NET 8 self-contained
│   Tile grid, game detail, ranks + challenges, leaderboard,
│   membership checkout, recovery UI
│   Pulls its game catalog from the cloud at start (offline cache)
│   Emits: GameLaunchAttempt / GameLaunched / GameLaunchFailed /
│          AbandonedLaunch / MemberIdle / PerformanceSample / ...
│
├─ FrontDesk operator console (one per venue)
│   WPF · .NET 8 · 5 pillars (Time / Members / Licenses
│   / Software / Payment) + Overview
│   Drill-down drawers, smart segments, settlement view,
│   inline confirm strip for destructive ops
│
├─ Floor View + Crew Tools (wall display / crew screens)
│   Live station board with morning-check self-heal summary;
│   per-player profiles with real match history + crew notes.
│   Both label sample data as sample data - never a faked floor.
│
├─ Agent (per station, runs as SYSTEM)
│   PowerShell + scheduled tasks
│   Cleanup, reconcile, telemetry sync, autologin guard,
│   HMAC-signed job surface with replay protection
│
└─ Cloud (multi-tenant)
    ASP.NET Minimal API · SQLite (Postgres path planned)
    /events ingest · /matches · game catalog + venue packs
    Ranks, challenges + seasons, licensing pool, members,
    billing, venue pricing

Event spine

Every meaningful action emits a typed event. The launcher writes to a local SQLite event store; a background uploader batches to the cloud's POST /events. The cloud serves the operator console (live activity feed) and downstream dashboards off the same store.

Event types in flight today:

  • Launch lifecycle: GameLaunchAttempt → GameLaunched | GameLaunchFailed → GameSessionEnded. All four share an AttemptId join key so the cloud can compute per-attempt success rate without inferring from timing.
  • Silent-crash detector: AbandonedLaunch fires when an attempt produced no process within 90 s - catches the gap a typed failure can't see.
  • Member presence: MemberCheckedIn, MemberCheckedOut, MemberIdle, MemberReturned.
  • UI interaction: TileClicked, AppLaunched, ForegroundAppChanged.
  • Platform health: PerformanceSample (CPU, memory, every 60 s), ControllerConnected/Disconnected/BatteryLow (XInput-driven, 5-min cadence, edge-debounced), NetworkSample, LauncherStarted/ShuttingDown.
  • Day-rollups (cloud-side): a background runner scans the event stream into event_projections_daily under three projection kinds today - event_counts_daily (per-station per-type counters), station_utilization (sessions + minutes played + members seated), and game_popularity (per-game launches + minutes + abandoned). The Insights tab in the operator console renders all three.
  • Crew signal: CoachAttentionRequested - raised when a player clicks "Tell the crew" on the launcher's recovery overlay, with GameId + Source. The operator console surfaces these in the Needs-Attention rail.
  • Match results: per-game adapters (replay-file watcher, official game APIs, on-screen reading) publish typed match summaries through one relay. Every adapter feeds the same sink: local matches-*.jsonl journal, then POST /matches to the cloud, where results move ranks, challenges, and the venue leaderboard. No manual score entry anywhere in the pipeline.

Brand pipeline (the white-label seam)

Every WPF app reads VALHALLAN_BRAND at startup and merges a brand-specific ResourceDictionary before the window constructs. Palette, wordmark, logo, even motion accents come from there. The same binary runs Valhallan or Helm; nothing in the apps hardcodes a venue color or copy string. One source file (Shared.Design/DesignLanguage.cs) is link-compiled into every WPF project so motion durations, easing curves, and depth shadows stay identical across the suite.

Verify gates

Hard gates run before every release, as scripts anyone on the team can run:

  • Verify-Demo.ps1 - invariants on a cold-start demo cloud (members seeded, licenses queued, refund flow, tenant isolation).
  • Verify-Operator-Console.ps1 - static checks on the operator console's surface area (every drawer wired, every handler present, no MessageBox, cmd-K palette + dispatch, stats card, all five pillar tabs, build clean).
  • Verify-Launcher-Catalog.ps1 - catalog gates on the seeded pack (every tile resolves to a runnable adapter, every platform launcher configured, override modes valid).
  • Verify-Telemetry.ps1 - hard + soft gates on the live event pipeline (every expected event type fired today, per-PC freshness, cloud ingestion latency).

Unit tests

1,887 tests green across five .NET projects (run fresh for this update, July 3, 2026):

  • Valhallan.Cloud.Tests - 593. Game licensing state machine, billing, refunds, tenant isolation, game catalog + venue packs, match ingest, ranks + challenge progress, seasons, fleet power scheduling, pricing rules, projection runner.
  • Valhallan.Launcher.Tests - 750. Launch service (typed outcomes, dedupe, process probe), game-session tracker, match-telemetry relay + per-game adapters, ranks and leaderboard VMs, membership checkout, idle presence watcher, abandoned-launch watcher, settings VM.
  • Valhallan.Shared.Tests - 313. Event wire-shape round-trips, match summary shapes, challenge models, request-signing + nonce (replay) protection.
  • Valhallan.FrontDesk.Tests - 141. Pillar tabs, command palette, settlement + licensing flows.
  • Valhallan.Agent.Tests - 90. Heartbeat, status reporting, job surface auth + replay protection.

What we have not built yet

We would rather you know now than discover later:

  • Strict auth is an ops flip, not yet flipped. Every client signs requests (HMAC) and every signer mints nonces; the agent's job surface rejects replays. What remains is operational: provision per-tenant secrets on every box, deploy one build, then enforce. Until that flip, the cloud accepts unsigned requests inside the venue LAN.
  • Payments are live for membership, simulated for the rest. Membership checkout at the seat tokenizes the card straight to Stripe (the card number never touches our cloud) and has run a real charge end to end. Time top-ups and franchise revenue share are built and audited against a simulated gateway while connected-account onboarding lands.
  • HQ rollup is not built. The cloud is multi-tenant - every request carries a tenant, isolation is enforced in the data layer and tested - and one cloud serves a venue today. The cross-venue dashboard that aggregates a whole franchise is designed but not shipped.
  • Database is SQLite. Schema migrations run on cloud startup. A Postgres provider path is wired but not switched on - switching is one DI rebind.
  • No CI pipeline yet. Verify gates and the 1,887 tests exist as scripts anyone can run; they have not been wired into a hosted CI yet.
  • Phone view of Floor. Wall display and front desk are shipped; a phone-sized floor view is on the roadmap.
  • Console curation of the game catalog. The catalog lives in the cloud and every station pulls it, but adding or toggling games is an API call today; the operator console screen for it is in progress.

If you want to run it

The portable demo bundles the full suite into a single self-extracting helm-demo.exe (~469 MB). It runs a self-contained cloud + console + launcher with seeded data on a clean Windows path. Email founders@runhelm.app for a build and the walkthrough script.

This page is honest. If anything looks off, write back and we will fix the page or the product, whichever is wrong.

© 2026 Helm · Made on Long Island