Home

M5 – Interlocking, radio & takeover

Implementation plan — Interlocking view, radio & takeover (M5)

This plan implements the detailed specification spread across:

Starting point

Confirmed design decisions

  1. Takeover — 15 s reject window; auto-grant → 5-minute self-lease; driver evicted from throttle; signalman drives in a closable overlay (speed 0 gate).
  2. Radio — Redis-only, 4 h TTL; required context (vehicle XOR train) and target (user XOR interlocking).
  3. Single-target stopsystem.estopTarget, „Zatrzymaj skład".
  4. dcc-bus is lease-agnosticloco-server folds driving rights into controllerUserIds and republishes allowed_vehicles.
  5. Interlocking command-station picker — cog button, same as throttle.
  6. Radio Stop in interlocking view — icon + „Radio stop" label above panels; signalman role alone may trigger (even idle).

Implementation stages

Four functional stages. Each stage is independently shippable and ends with verifiable acceptance criteria. Stages are sequential — later stages build on earlier ones.

Stage 1 ──► Stage 2 ──► Stage 3 ──► Stage 4
 shell &      radio       takeover    estop &
 roster       comms                   polish
Stage Focus Delivers
1 Interlocking shell & roster Staffed box with cog picker, Radio Stop bar, searchable roster with in-motion indicator; controllerUserIds lease folding
2 Radio (walkie-talkie) End-to-end radio: Redis store, WS/REST, interlocking chat panel, driver throttle radio + chat overlays, sounds
3 Takeover control 15 s state machine, 5-min self-lease, roster „Przejęcie" action, throttle overlay, driver eviction
4 Per-target stop & polish system.estopTarget + „Zatrzymaj skład" button, remaining i18n/assets, full acceptance walkthrough

Stage 1 — Interlocking shell & roster panel

Goal: Replace the radio placeholder with the interlocking work-area layout and a live vehicle/train roster. No radio or takeover yet — action buttons in the roster may be disabled or hidden until their stage lands.

Backend

Frontend

Stage 1 acceptance


Stage 2 — Radio (walkie-talkie)

Goal: Full walkie-talkie channel — signalman group chat, driver send/receive, Redis persistence, sounds.

Backend

Frontend

Stage 2 acceptance

Stage 2 tests


Stage 3 — Takeover control

Goal: Signalman can request takeover from the roster; after the 15 s window the driver is evicted and the signalman drives in an overlay.

Depends on stage 1 (controllerUserIds folding, roster panel, cog picker).

Backend

Frontend

Stage 3 acceptance

Stage 3 tests


Stage 4 — Per-target stop & polish

Goal: „Zatrzymaj skład" action on the roster; final i18n/assets; full acceptance-criteria walkthrough.

Depends on stages 1 (roster panel) and 3 (takeover overlay uses cog picker for command-station context).

Backend

Frontend

Stage 4 acceptance

Stage 4 tests


Cross-cutting risks

Reference — file inventory

Quick lookup of new/changed files across all stages:

Area Files
Domain server/domain/radio.go, server/domain/takeover.go
Repo server/repo/takeover_requests.go, migrations
Service server/service/radio.go, radio_store.go, takeover.go
Security server/security/radio.go, takeover.go, estop_target.go, radio_stop.go
Contract contract/radio.go, radio_events.go, takeover_events.go
HTTP server/http/radio.go (replay endpoints)
WS server/ws/hub.go (radio + takeover + estopTarget handlers)
Frontend — interlocking InterlockingChatPanel, InterlockingRosterPanel, RadioPhrasePickerDialog, TakeoverThrottleOverlay
Frontend — throttle ThrottleRadioButton/Overlay, ThrottleChatButton/Overlay, useRadioSounds
Frontend — shared RadioStopButton (variant refactor), api/radio.ts, api/takeover.ts
i18n radio.json, extensions to interlocking.json + throttle.json
Assets web/public/sounds/interlockings/*.ogg