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:
127
docs/plans/2026-03-02-fxt-broker-check-design.md
Normal file
127
docs/plans/2026-03-02-fxt-broker-check-design.md
Normal 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
|
||||
Reference in New Issue
Block a user