docs: add design for fxt broker check CLI command

Two-layer IBKR connectivity validation: direct ibapi handshake +
broker-gateway gRPC health check. Pure-client architecture using
ibapi as optional dep on fxt (not trading_engine).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-03-02 13:26:17 +01:00
parent 0c1ac34fd9
commit 50d1aff97c

View File

@@ -0,0 +1,127 @@
# Design: `fxt broker check` — IBKR Connectivity Validation
## Problem
No CLI command exists to validate IBKR TWS/Gateway connectivity. The only option is running `#[ignore]` integration tests manually with `cargo test`. Operators need a quick, production-friendly way to verify the broker connection chain.
## Solution
Add `fxt broker check` — a two-layer connectivity validation command:
1. **Direct IB Gateway check**: TCP connect → ibapi handshake → account summary → disconnect
2. **Broker Gateway gRPC check**: `HealthCheck` + `GetSessionStatus` RPCs via `broker_gateway_service`
## Command Interface
```
fxt broker check [OPTIONS]
Options:
--host <HOST> IB Gateway host (env: IBKR_HOST, config: broker.ibkr.host, default: 127.0.0.1)
--port <PORT> IB Gateway port (env: IBKR_PORT, config: broker.ibkr.port, default: 4002)
--client-id <ID> TWS client ID (env: IBKR_CLIENT_ID, default: 99)
--gateway-url <URL> Broker Gateway gRPC URL (env: BROKER_GATEWAY_URL, config: broker.gateway_url, default: http://localhost:50060)
--skip-gateway Skip broker-gateway gRPC check
--skip-ibkr Skip direct IB Gateway check
```
Config precedence: CLI flags > env vars > `~/.foxhunt/config.toml` > defaults.
## Output
Success:
```
Broker Connectivity Check
═══════════════════════════════════════
IB Gateway (direct)
TCP connect .............. ✓ 127.0.0.1:4002 (12ms)
ibapi handshake .......... ✓ client_id=99, server v10.19
Account summary .......... ✓ DU9600528 (paper)
Broker Gateway (gRPC)
Health check ............. ✓ broker-gateway:50060 (8ms)
Session status ........... ✓ ACTIVE (seq: 1042/1041, RTT: 2.3ms)
Result: All checks passed ✓
```
Failure:
```
IB Gateway (direct)
TCP connect .............. ✗ Connection refused (127.0.0.1:4002)
Broker Gateway (gRPC)
Health check ............. ✗ Unavailable (connection timeout)
Result: 2/2 checks failed ✗
```
## Architecture
### Pure-client constraint
fxt is a pure gRPC client — it must NOT depend on `trading_engine`. The direct IB check uses `ibapi` as an optional dependency on fxt itself, behind a `broker-check` feature flag. When compiled without the feature, `fxt broker check` still works for the gRPC layer but skips the direct ibapi check.
### Files to create/modify
| File | Action | Purpose |
|------|--------|---------|
| `bin/fxt/src/commands/broker.rs` | Create | `BrokerCommand::Check` implementation |
| `bin/fxt/src/commands/mod.rs` | Modify | Add `pub mod broker` + re-export |
| `bin/fxt/src/main.rs` | Modify | Add `Broker` variant to `Commands` enum |
| `bin/fxt/src/config.rs` | Modify | Add `BrokerConfig` section to `TliConfig` |
| `bin/fxt/Cargo.toml` | Modify | Add `ibapi` optional dep, `broker-check` feature |
| `bin/fxt/build.rs` | Modify | Compile `broker_gateway.proto` |
| `bin/fxt/proto/broker_gateway.proto` | Create | Copy/symlink from `services/broker_gateway_service/proto/` |
### Proto strategy
The `broker_gateway.proto` lives in `services/broker_gateway_service/proto/`. fxt needs to compile it for client stubs. Options:
- **Copy the proto** into `bin/fxt/proto/` (matches existing pattern — fxt has its own proto dir)
- Symlink (fragile across platforms)
Recommend: copy the proto file. fxt already has its own proto directory with 6 protos. This is consistent.
### Config file addition
```toml
# ~/.foxhunt/config.toml
[broker]
gateway_url = "http://localhost:50060"
[broker.ibkr]
host = "127.0.0.1"
port = 4002
client_id = 99
```
### ibapi usage in fxt
The `ibapi` crate's `Client::connect()` is synchronous/blocking. Wrap in `tokio::task::spawn_blocking` (same pattern as `trading_engine`). The check sequence:
1. TCP probe via `tokio::net::TcpStream::connect()` with timeout (fail-fast)
2. `ibapi::Client::connect(host, port, client_id)` on blocking thread
3. Request account summary (proves authenticated session)
4. Disconnect
### Feature flag
```toml
[features]
default = ["broker-check"]
broker-check = ["dep:ibapi"]
```
Default-enabled so `fxt broker check` works out of the box. Can be disabled for minimal builds.
## Exit codes
- `0` — all checks passed
- `1` — one or more checks failed
- `2` — configuration error (bad host/port/URL)
## Testing
- Unit tests: config parsing, output formatting
- Integration test (`#[ignore]`): requires running IB Gateway, tests full flow
- CLI test: `assert_cmd` for arg parsing and `--skip-*` flags