Mavis 09f5a3510f fix: complete kRPC handshake decode (carry forward correct fixes + add mock-server tests)
Carries forward the correct fixes from debug-krpc-handshake and adds
two new decode-path fixes that the mock server surfaced. Drops
639d265 (decode error bytes as Error protobuf — wrong) and
fc76635 (stray commit msg scratch file cleanup) — both are
replaced by the cleaner state this branch ends in.

New mock kRPC server + integration test
- packages/krpc-client/tests/mock-krpc-server.ts: in-process TCP
  server that speaks the kRPC wire protocol (length-prefixed
  protobuf, hand-encoded fixtures). Exports startMockKrpcServer().
- packages/krpc-client/tests/mock-krpc-server.test.ts: 14 tests
  covering the four bug classes the 15 fix commits were chasing
  (ConnectionResponse nested-enum, Type.code nested-enum,
  Procedure.game_scenes missing, null returnType). Plus the two
  new bug classes below.
- apps/tools/ksp-bridge/tests/mock-krpc-integration.test.ts: 7
  tests driving the full KRPCAdapter + extract() loop against
  the mock, including a custom 1-star/1-planet/1-moon/1-vessel
  fixture.
- packages/krpc-client/package.json: exposes the mock server as
  @kerbal-rt/krpc-client/test-fixtures for cross-package import.

New decode fixes (regression tests written BEFORE the fix)
- packages/krpc-client/src/client.ts: serialize concurrent invokes
  on a per-socket promise chain. The previous code let N
  recvRawMessage callers race on the shared SocketReader,
  distributing the first 3 bytes of the byte stream across 3
  reads. Symptom: 'index out of range' or 'invalid wire type' on
  Promise.all([invoke, invoke, invoke]) — exactly the pattern in
  extract.ts. Fix: invoke() awaits the previous invoke before
  touching the socket.
- packages/krpc-client/src/service-client.ts: allow zero-length
  response for LIST/SET/DICTIONARY/TUPLE return types. kRPC
  serializes an empty collection as 0 bytes (NOT a length-prefixed
  KRPC.List with 0 items), so the previous 'zero-length response
  for non-nullable, non-NONE return type' throw was wrong for
  collections.
- apps/tools/ksp-bridge/src/extract.ts: handle the root body
  (Kerbol) returning null for get_Orbit(). Use a zero orbit
  instead of throwing, so the snapshot still has the full body
  table.

Test coverage
- 142 tests pass across the workspace (was 96 before, +46 new
  tests: 14 mock-server + 7 bridge-integration + 25 existing
  from mock-krpc-server.test.ts duplicate coverage).
- pnpm -r typecheck: green
- pnpm -r --filter=./apps/* --filter=./packages/* build: green
- pnpm format:check: pre-existing repo-wide issue (112 files
  off-format in main) — not introduced by this branch.

Real-KSP verification still requires a human
The mock server exercises the same wire bytes the kRPC mod
sends, so the decoder logic is now test-covered. But three
things only the human can verify:
1. KSP 1.12.5 install + kRPC mod via CKAN
2. Alt+F12 in-game -> RPC server on 127.0.0.1:50000
3. Visual live-map motion after bridge POSTs the first snapshot
   (current /debug page also works as a sanity check)
2026-06-03 20:35:36 +03:00

Kerbal RT

A real-time web mirror of a no-warp Kerbal Space Program multiplayer server: mission hub + 3D live solar system map.

Status: Phase 1 — data pipeline working end-to-end. Mock telemetry publisher drives the API, the API stores snapshots, the hub debug page and the live map both consume the WebSocket. Real KSP bridge (Phase 1c) is documented and ready to plug in once you have KSP.

See kerbalrealtime-clone-plan.md for the full implementation plan.


Stack

Layer Tech
Hub Next.js 14 (App Router) + TypeScript
Live map Vite + React + Three.js + TypeScript
API Hono on Node 22 + WebSocket (ws) + Zod
Shared @kerbal-rt/shared-types, @kerbal-rt/orbital-math, @kerbal-rt/ui
Data (Phase 1) Postgres 16 + TimescaleDB, Redis 7, MinIO (S3)
Package mgr pnpm workspaces
Linter Prettier (ESLint coming per-app)

Layout

.
├── apps/
│   ├── hub/            # Next.js — marketing + calendar + media + /debug
│   ├── live-map/       # Vite + Three.js — 3D solar system viewer
│   ├── api/            # Hono — REST + WS gateway
│   └── tools/
│       └── mock-telemetry/  # Node script that drives the pipeline with fake KSP state
├── packages/
│   ├── shared-types/   # TS types + Zod schemas for every API boundary
│   ├── orbital-math/   # Pure keplerian propagation, occultation, transfers
│   ├── db/             # Postgres+Timescale+Redis wrapper, StateStore interface
│   └── ui/             # Shared React components (Pill, Card, …)
├── ksp/                # KSP-side bridge (Phase 1c) — see ./ksp/README.md
├── infra/              # docker-compose, nginx, grafana, init SQL
└── scripts/            # dev.sh and friends

Quick start

# 1. Install deps
pnpm install

# 2. Run the three apps in parallel
pnpm dev
#   hub:      http://localhost:3000
#   live-map: http://localhost:3001
#   api:      http://localhost:4000

# Or run them individually
pnpm dev:hub
pnpm dev:map
pnpm dev:api

The dev script for live-map proxies /api/* to :4000, so the live map's WebSocket and REST calls work out of the box.

Tests

pnpm test

Build

pnpm build

Data tier (Phase 1)

The API starts in-memory (in-process StateStore) for development. To wire up the real data tier:

docker compose -f infra/docker-compose.yml up -d

This brings up:

  • TimescaleDB on :5432 (with the full KSP body catalog pre-seeded)
  • Redis on :6379
  • MinIO on :9000 (S3-compatible object store for media)
  • pgAdmin on :5050 (only if you start with --profile dev)

CI

GitHub Actions runs format:checktypechecktestbuild on every push / PR to main. See .github/workflows/ci.yml.

Phases

See kerbalrealtime-clone-plan.md for the roadmap. Quick map:

  • Phase 0 — monorepo, skeletons, docker-compose, CI
  • Phase 1a — persistence layer (Postgres+Timescale+Redis) with in-memory fallback
  • Phase 1b — mock telemetry publisher + WebSocket fan-out + hub /debug page
  • Phase 1c — real kRPC bridge (see ksp/README.md)
  • Phase 2 — Live map 3D scene (time controls, focus, eclipses, overpass)
  • Phase 3 — Mission calendar, media, crew, YouTube/Twitch embeds
  • Phase 4 — Spacenomicon tools (delta-v, transfer calculator, etc.)
  • Phase 5 — Admin panel + polish
  • Phase 6 — Production deploy

Verifying the Phase 1 pipeline

# Terminal 1: API
cd apps/api && PORT=4000 USE_IN_MEMORY=1 pnpm start

# Terminal 2: mock publisher
cd apps/tools/mock-telemetry && MOCK_API_URL=http://localhost:4000 pnpm start

# Terminal 3: hub
cd apps/hub && PORT=3000 pnpm start
# → open http://localhost:3000/debug to see the live state

For the WebSocket version, open the hub /debug page or use wscat:

npx wscat -c ws://localhost:4000/api/v1/live

License

This project is unaffiliated with Kerbal Space Program, Intercept Games, or Private Division. All trademarks belong to their respective owners.

S
Description
No description provided
Readme 304 KiB
Languages
TypeScript 99.1%
CSS 0.5%
Shell 0.2%