Skip to content

feat(orchestrator): wire C2 command dispatch through the WS server#49

Merged
martinjms merged 1 commit intomainfrom
feat/c2-ws-server-wiring
May 2, 2026
Merged

feat(orchestrator): wire C2 command dispatch through the WS server#49
martinjms merged 1 commit intomainfrom
feat/c2-ws-server-wiring

Conversation

@martinjms
Copy link
Copy Markdown
Collaborator

Completes the wire layer that PR #43 (in-process dispatcher) deliberately deferred. A real driver can now register, receive server-pushed `Command` envelopes, and ack them — and the dispatcher's `submit()` resolves end-to-end against a real WebSocket.

This is the orchestrator-side counterpart to #27 (driver-side `--orchestrator-url` extension); together they form the full C2 wire path.

Protocol additions (backward-compatible)

  • `DriverMessage::CommandAck(CommandAck)` — driver→orchestrator ack frame
  • `OrchestratorResponse::Command(CommandEnvelope { seq, command })` — server-pushed command frame
  • `DriverChannel::send` now takes a `seq` parameter so the dispatcher's monotonic sequence number flows through to the wire envelope and back via the matching ack

Server changes

  • `DriverServer::with_dispatcher` constructor wires an `Arc` through to `handle_connection`. Old `new()` (no dispatcher) preserved for call sites that don't need command dispatch.
  • `handle_connection` refactored into a reader/writer pair. The writer multiplexes command envelopes + handshake responses onto the WS sink; the reader handles register/heartbeat/deregister/ack messages and routes acks to per-seq `oneshot`s.
  • `WsDriverChannel` (new module): production `DriverChannel` impl backed by a per-connection mpsc + oneshot pair; populated on Register, dropped on Deregister or disconnect.

Tests

Two new e2e tests in `tests/ws_command_e2e.rs` drive a real WS round-trip:

  • `dispatcher_round_trips_command_to_real_driver_via_ws` — submit returns acks routed back through the wire
  • `dispatcher_drops_channel_when_driver_deregisters` — the dispatcher's channel is dropped when a driver deregisters

Test plan

  • `cargo test -p arcane-swarm-orchestrator` — 58 passed, 0 failed (2 new e2e + 56 prior)
  • `cargo clippy -p arcane-swarm-orchestrator --all-targets -- -D warnings` clean
  • `cargo fmt --all -- --check` clean

🤖 Generated with Claude Code

Completes the wire layer that PR #43 (in-process dispatcher) deliberately
deferred. A real driver can now register, receive server-pushed Command
envelopes, and ack them — and the dispatcher's submit() resolves
end-to-end against a real WebSocket.

Protocol additions (backward-compatible):
- DriverMessage::CommandAck(CommandAck): driver→orchestrator ack frame
- OrchestratorResponse::Command(CommandEnvelope { seq, command }):
  server-pushed command frame
- DriverChannel::send takes a `seq` parameter so the dispatcher's
  monotonic sequence number flows through to the wire envelope and
  back via the matching ack.

Server changes (server.rs):
- DriverServer::with_dispatcher constructor wires an Arc<CommandDispatcher>
  through to handle_connection. Old `new()` (no dispatcher) preserved for
  call sites that don't need command dispatch.
- handle_connection refactored into a reader/writer pair. The writer
  multiplexes command envelopes + handshake responses onto the WS sink;
  the reader handles register/heartbeat/deregister/ack messages and
  routes acks to per-seq oneshots.
- WsDriverChannel: production DriverChannel impl backed by a per-
  connection mpsc + oneshot pair; populated on Register, dropped on
  Deregister or disconnect.

Tests:
- Two new e2e tests (tests/ws_command_e2e.rs) drive a real WS round-trip:
  one asserts the dispatcher's submit returns acks routed back through
  the wire; the other asserts the dispatcher's channel is dropped when
  a driver deregisters.

This is the orchestrator-side counterpart to issue #27 (driver-side
extension); together they form the full C2 wire path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@martinjms martinjms merged commit f10740f into main May 2, 2026
1 check passed
@martinjms martinjms deleted the feat/c2-ws-server-wiring branch May 2, 2026 18:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant