New: tools/SiteConfigMerge (net48 console app) - dump: decode any .siteconfig (squads, pods, IPs, MACs, host types) - merge: combine <siteName>.siteconfig inputs into master.siteconfig, renaming squads "<siteName>-<original squad name>" - Pod records pass through byte-for-byte; only squad records (the rename) are re-serialized, under the TeslaConsole assembly identity captured from the input. Stand-in types + SerializationBinder, so no build dependency on TeslaSuite. - Warns on duplicate pod GUID/MAC and cross-site IP overlap. - Verified end-to-end: the real TeslaConsole.exe 4.11.4.1 loaded the merged master via its own Site.LoadFromFile (reflection harness). Doc updates from operator decisions: - Operating model settled: sites voluntarily hand console authority to the central console for the duration of a SiteLink event, by contributing their siteconfig. Federation ruled out at current scale. - Siteconfig "secrets" framing corrected: pod keys have no practical value outside the air-gapped bay; files are exchanged per event and never stored in this repo (tools only). - Fleet scale recorded: 6 active pod bays, <120 cockpits in existence; bay sizes range console+2 cockpits up to the full 20-node complement. Open question 9 answered. - Hub hosting direction: neutral Firestorm host at the WireGuard hub; the FS server usually IS the Live Cam, so stream its output to all sites and optionally to the public internet. Mission Review instance runs at the hub too - one authoritative debrief streamed everywhere. - Virtual PDF scoresheet printer at the hub: event debriefings print centrally, retrievable from any site on the link. - Voice (Mumble) backburnered - revisit only on event interest. - .gitignore: build outputs; siteconfig exclusion rationale reworded. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
18 KiB
SiteLink — design brainstorm
Working record, started 2026-07-10. Companion to PODBAY-ECOSYSTEM.md, which holds the verified facts this brainstorm builds on.
0. Goals (proposed — confirm/edit)
- Cross-site play: cockpits at site A and site B in the same match (Firestorm first; BT411/RP as they mature).
- Preserve the air gap: the linked fleet is one private network. No bay machine ever gets a route to the general internet.
- Fleet visibility/command: an operator (eventually a master console) can see — and where appropriate command — pods at every site.
- Shared front-of-house: cross-site events share a queue, callsigns, scores. (Voice: backburnered — see §6.)
- Zero changes to cockpit hardware, minimal changes to bay-local operation: a bay must keep working stand-alone when the link is down.
Non-goals (for now): public matchmaking, spectating from home, per-player home clients.
1. The seed proposal
Each site gets its own
10.0.y.xsubnet (we get10.0.1.x, you get10.0.2.x, …), VPN them all together into a single /16, collect every site's.siteconfig, concatenate them, and give the result to a master console that commands the fleet.
Verdict: sound skeleton. The three pieces (site-numbered subnets, VPN mesh into
10.0.0.0/16, merged fleet config) survive contact with the code. The refinements below
are about how, not whether.
2. Addressing plan
10.0.<siteID>.0/24per site, keeping each bay's existing last-octet conventions (pods.1–.8,.11–.18, camera.9, …) so per-site configs become a template stamped with a site ID. Legacy200.0.0.xbays get renumbered on joining — that space is public internet space and must not exist inside the linked fleet.- Reserve
10.0.0.0/24for shared infrastructure: VPN hub, master console, central PQS, Mumble, NTP, a neutral dedicated game host. Nothing site-specific lives there. - Site ID registry lives in this repo (
sites/— one small file per site: ID, name, operator, subnet, contact). First allocation:10.0.1.0/24= Fallout Shelter Arcade;10.0.2.0/24= next site. Scale reality (2026): 6 active pod bays, fewer than 120 cockpits in existence — 254 site IDs is beyond generous, and every topology choice below can assume single-digit sites. - Netmask choice is the real design fork (see §3): hosts configured
/24+ gateway = routed model; hosts configured/16= requires a bridged L2 overlay. - Renumbering mechanics: TeslaConsole already owns pod IP config (provisioning writes
mIPAddress/mGateway/mDns/mSubnet), and the CTCL[teslas]inis are trivially regenerated from a template. So renumbering is a console-driven afternoon, not a reimage.
3. Topology: routed L3 vs bridged L2
Option A — Routed L3 (recommended default)
Each site keeps its /24; a per-site VPN gateway (its only new hardware) routes
between sites over WireGuard tunnels.
- ✅ Works because Firestorm's join path is directed by IP (
TryToJoinASpecificGame, see ecosystem doc) and every console→pod protocol (53290 RPC, Munga 1501, BT egg push) is directed TCP. Nothing in the match-play path needs broadcast. - ✅ Clean failure isolation, no cross-WAN broadcast chatter from era Windows boxes, easy per-flow firewalling at each gateway.
- ✅ Hub-and-spoke (hub on shared infra, e.g. alongside mysticmachines.com) or full mesh — WireGuard does either; start hub-and-spoke, it's simpler and the hub is also where shared services live.
- ⚠️ Breaks broadcast-dependent conveniences: DirectPlay "browse LAN games" listing and SecureConfig first-boot beacons don't cross sites. Both are acceptable: game joins are console-directed anyway, and provisioning is an on-site act by design.
Option B — Bridged L2 overlay (fallback / experiment)
One virtual Ethernet across all sites (ZeroTier, VXLAN/EoIP between gateways, tinc
switch mode); hosts could then even use a flat /16.
- ✅ Everything behaves like one big LAN — broadcast discovery, any undiscovered broadcast assumption in 1996–2009 era code, zero renumbering logic beyond uniqueness.
- ❌ One broadcast domain of ancient unpatched Windows across the WAN (NetBIOS chatter, broadcast storms), MTU headaches, harder to reason about, and failure at one site can be noisy everywhere.
- Position: keep in the back pocket. If Phase-0 testing (vPOD + two subnets) turns up a flow that genuinely requires broadcast, bridge only that (e.g. a targeted UDP broadcast relay) before going full L2.
VPN tech choice
WireGuard first (kernel-fast, tiny config, UDP hole-punch friendly, runs on a $50 box or
the site router). Tailscale/NetBird/ZeroTier are managed alternates if key/peer
management becomes a burden — but note ZeroTier is the L2 option, Tailscale/NetBird are
L3. The bay machines themselves never run VPN software; only the per-site gateway does.
Bay boxes keep no default route — gateways carry routes for 10.0.0.0/16 only.
4. Fleet configuration: master console vs federation
The seed proposal: merge all .siteconfig files → one master console commands the fleet.
The merge tool exists: tools/SiteConfigMerge
decodes <siteName>.siteconfig files and emits one master.siteconfig, renaming every
squad <siteName>-<original squad name> ("FSA-bay1", "Pharaoh-bay1", …) — one
squad group per site, which TeslaConsole's UI already organizes naturally. Pod records
pass through byte-for-byte; verified against the real TeslaConsole 4.11.4.1 loader.
The operating model (settled 2026-07-10): event-scoped authority handover. When a
SiteLink event runs, every participating site willingly hands console authority to
the central console for the duration of the event — concretely, by contributing its
<siteName>.siteconfig to the merged master. Outside events, each site console is
authoritative over its own bay. Notes that keep this clean:
- The pod keys inside a siteconfig have no practical value outside the bay's air-gapped network (anyone with bay access has the file anyway) — handing the file over is the handover ceremony, not a security event.
- Siteconfigs change over time, so they are exchanged fresh per event and are not stored in this repo (tools only).
- Nothing enforces the handover — TeslaLauncher has no arbitration if a site console and the central console command the same pod concurrently. Convention: site consoles stand down for the event window. A soft "event mode" lock in TeslaConsole is a nice-to-have if the convention ever gets violated in practice.
- Remaining technical to-do for the central console: WAN-tolerant RPC timeouts, and
it should live on shared infra (
10.0.0.0/24) with a decent uplink.
Federation (a coordinator service so raw keys never leave a site) is off the table at current scale — 6 bays run by trusted operators doesn't need it. Recorded here only in case the fleet's trust model ever changes.
5. Linking the games themselves
Firestorm (first target)
- Session model: one DirectPlay host; everyone joins directed-by-IP. Options for
host placement:
- a) Host at one site's console (simplest; other site eats the WAN RTT; O(n²) load on that console's uplink);
- b) Neutral host at the WireGuard hub (preferred direction, 2026-07-10).
Symmetric latency for every site, best uplink — and it exploits an operational
fact: the Firestorm server is almost always the Live Cam for that game. A
hub-hosted host running the camera-ship role turns the neutral server into the
event's broadcast point: capture its output and stream the show to every
participating site (Live Cam screens everywhere show the same feed), and
optionally stream it publicly to the internet as the fleet's shop window.
Considerations: the camera ship renders, so the hub box needs a real GPU
(physical box at the hub location or a GPU cloud instance — not a bare VPS);
mw4dedicatedui(headless) remains the fallback if hub rendering is impractical, with a camera-ship client joining from a site instead. Streaming transport is one-way and latency-tolerant: OBS capture → SRT/RTMP internally, Twitch/YouTube for the public leg. Needs validation either way (dedicated UI is unexercised in the modern tree; camera-ship-as-DirectPlay-host in the CTCL flow should be confirmed againstctcl-game.ini's*1/cameraship entry and the PQScamerashipflag). - The Mission Review instance lives at the hub too, for the same reasons: one
authoritative post-match review (
ctcl-mrrole / MSRSpectator) running next to the host that recorded the match, its output streamed to every site's Mission Review screen — every bay debriefs from the same show.
- Player counts: the golden first milestone is 8v8 across two sites (8 cockpits
each) — inside the stock 16-player cap, zero engine changes. Full 16v16 site-vs-site
needs the already-drafted 16→32 plan in
firestorm\CLAUDE.md(compiled defaults + drop-zone authoring per map + lobby UI polish). - Latency budget: the netcode shipped for dial-up (150–300 ms era). Inter-city internet (20–80 ms) + WireGuard (~1 ms) should be comfortable. Measure, don't assume: put netem delay/jitter/loss on a test gateway and find the cliff (see Phase 0).
- Port hygiene: set the
DirectPlayPortregistry value at every site so game traffic is a single known port for the gateways' firewalls, instead of DirectPlay's default 47624 + 2300–2400 spread. - Fixed-port + MTU checks: DirectPlay UDP datagrams over a 1420-byte WireGuard MTU — verify no fragmentation weirdness (era stacks are fragile here).
BT411 (classic BattleTech)
- The console already launches multi-pod games by address list (
btconsole.py MP.EGG 10.0.1.11:1501 10.0.2.11:1501is a cross-site launch). Two unknowns to resolve:- Does the pod↔pod mesh derived from the egg
[pilots]list carry literal IPs (routes fine) or assume same-subnet? - The 1996 sim's latency tolerance — lockstep-ish engines of that era can be unforgiving. netem test early.
- Does the pod↔pod mesh derived from the egg
- Console-must-stay-connected quirk means the WAN link drop kills the match — argues for running the BT console at the site with the most pods, or fixing the engine bug.
Red Planet (RP411 reconstruction)
- Same console-directed model (Munga TCP 1501). Park until BT411 learnings land — shared engine lineage means most answers transfer.
Original Tesla 4.10 games under emulation (TeslaRel410)
- When the DOSBox-X/VPX emulator matures, the original BT/RP binaries land on current pod hardware speaking their original network stack: WATTCP (real TCP/IP) via NetNub, surfaced through NE2000-emulation bridged onto the bay LAN via pcap. Because it's plain IP with the emulated pod holding a real bay address, the routed-VPN model extends to them in principle unchanged.
- Unknowns to test (cheap — emulator instances run on any PC, no cockpit needed): NetNub discovery/mesh addressing across subnets, and the latency tolerance of a 30 Hz 1996 lockstep-era sim. Fold into the Phase 0 netem lab once the emulator reaches its networking phase (PLAN.md Phase 6).
- Strategic note: BT411/RP411 (native, netcode we can patch) and TeslaRel410 (faithful, netcode frozen in 1996) are complementary. If the original protocol proves WAN-hostile, the answer may be "emulated originals for local play, native reconstructions for cross-site" — SiteLink shouldn't promise WAN play for the emulated path until measured.
6. Shared services (the 10.0.0.0/24 rack)
| Service | Notes |
|---|---|
| WireGuard hub | The rendezvous point; a VPS (could sit near the existing mysticmachines.com infra) or a box at the best-connected site |
| Virtual scoresheet printer | A virtual printer at the hub that "prints" event debriefings/scoresheets to PDF (Firestorm's print path: printdebriefing / mw4print). PDFs land in one place and are retrievable from any site on the link — a simple web share on the hub over the VPN. Sites can still print paper locally from the PDFs |
| Voice (backburnered) | The FS507D release integrated Mumble, but only one operator ever ran it. Technically easy to stand up on the shared network — revisit only if event interest warrants |
| Queue/roster coordination (future) | Cross-site events will want one queue/roster. PQS — the operator-built event traffic-flow tool — is the natural seed, but for now it stays support tooling. If promoted: (a) one central instance all consoles poll — simplest, DB schema grows a site column; (b) per-site instances + sync — only if WAN-down resilience of the local queue matters during events. Callsign uniqueness would become fleet-wide |
| Neutral game host + event broadcast | Firestorm host for site-vs-site matches, co-located with the WireGuard hub. Doubles as the Live Cam (the FS server usually is the Live Cam): stream its output to all sites' Live Cam screens, optionally to the public internet. The Mission Review instance runs at the hub too — one authoritative debrief streamed to every site's MR screen. Needs GPU at the hub |
| NTP | One clock for scores, logs, and replay/debrief alignment |
| Fleet monitoring | VncThumbnailViewer pointed across the VPN; later, master-console status board |
Local-only forever: printer and RIO/cockpit I/O. For cross-site events the Live Cam and Mission Review instances run at the hub (above); each site's LC/MR screens become display endpoints for the hub streams, serving the local audience. Bay-local games keep running their own LC/MR stations exactly as today. Cross-site scoresheets go to the hub's virtual PDF printer (table above) — retrievable from any site, with local paper printing off the PDFs where wanted.
7. Security posture
- The fleet stays air-gapped as a whole. Only gateways touch the internet, only to
carry WireGuard to known peers. Bay machines: no default route, no DNS egress, static
10.0.0.0/16routes via the gateway. - Gateway firewall = allowlist by flow, per the port map in the ecosystem doc.
Suggested split:
- Game plane (DirectPlay fixed port, Munga 1501, Mumble): site↔site and site↔shared.
- Management plane (TCP 53290 launcher RPC, VNC 5900): only site-console↔own-pods and master-console↔pods — other sites' consoles have no business on your 53290.
- Repo hygiene: WireGuard private keys never enter this repo. Siteconfigs aren't stored here either — not because the pod keys matter off-site (they don't; the bays are air-gapped and anyone with bay access has the file), but because they're living operational data exchanged fresh per event. Repo holds tools, templates, and public site registry data (subnets, endpoint hostnames, WireGuard public keys).
- Era-Windows reality: assume every bay box is compromised-if-reachable. The allowlist above is the actual security boundary; the VPN is transport, not trust.
8. Open questions
- FS end-to-end join over routed subnets — directed-join API confirmed in source; prove the whole ConLobby/CTCL flow passes the host IP (vPOD + two subnets, or two VMs). Any broadcast dependency hiding in the lobby flow?
DirectPlayPortin practice — is it set at existing sites, and does a fixed port carry all session traffic (or only enumeration) under DirectPlay Protocol?- BT411
[pilots]mesh — IPs or subnet assumptions? (ReadL4NET.CPPStartConnecting path.) - Latency cliffs per title — netem sweep: at what RTT/jitter/loss does each engine degrade (rubber-banding, desync, disconnect)?
- Dedicated Firestorm host — does
mw4dedicateduibuild & run in the modern tree, and can camera/MR spectators join it cleanly? - PQS promotion — if/when the event queue tool becomes cross-site coordination: site column vs event database; global callsign policy.
- Console arbitration — policy settled 2026-07-10: sites voluntarily hand authority to the central console for the event window. Residual: nothing enforces it (TeslaLauncher has no arbitration); an optional soft "event mode" lock in TeslaConsole only if the convention ever fails in practice.
- Who hosts shared infra — VPS vs best-connected site; bandwidth math for a 32-player O(n²) host (~upstream estimate needed from real packet captures).
Site count ambitions— answered 2026-07-10: 6 active bays, fewer than 120 cockpits in existence. Hub-and-spoke is trivially sufficient; federation is permanently unnecessary barring a trust-model change.- WAN-drop behavior — for each linked flow, what breaks when the tunnel drops mid-match, and does the bay cleanly fall back to stand-alone?
- NetNub over routed subnets (TeslaRel410) — how do the original 4.10 games
discover/address each other (read
CODE\*\MUNGA_L4\NETNUB\+L4NETlineage)? Broadcast-dependent or console-directed like their descendants? And what RTT does the 30 Hz 1996 sim tolerate?
9. Phased roadmap (strawman)
- Phase 0 — Lab proof (no hardware, no travel). Two "bays" as VMs/vPOD instances on two subnets with a WireGuard/netem gateway between them. Prove: console→remote-pod RPC (53290), a 2-client Firestorm match across subnets, latency sweep, BT411 cross-subnet egg push. Everything above that's marked "verify" gets verified here.
- Phase 1 — First real link. Two sites, gateways, tunnel, renumber to
10.0.1.x/10.0.2.x. Fleet VNC + remote Mission-Review spectating. First cross-site Firestorm match at ≤16 total players (8v8) on the stock exe. - Phase 2 — Fleet operations.
siteconfig merge tool✅ built (tools/SiteConfigMerge, verified against the real console loader) → run an event under the authority-handover model (§4): collect<siteName>.siteconfigs, merge, central console commands the fleet. Optional PQS event mode with shared queue/callsigns; debrief/scoresheet distribution to both printers. - Phase 3 — Full site-vs-site. Execute the firestorm 16→32 plan (code defaults + drop zones), neutral dedicated host, 16v16 events.
- Phase 4 — More titles, more sites. BT411/RP cross-site as those engines mature; 3rd+ site onboarding kit (gateway image + site-ID allocation + config templates); revisit federation and the GUN/GameSpy-style fleet game browser.