diff --git a/docs/plans/2026-03-02-fxt-broker-check-design.md b/docs/plans/2026-03-02-fxt-broker-check-design.md new file mode 100644 index 000000000..68d3a6fee --- /dev/null +++ b/docs/plans/2026-03-02-fxt-broker-check-design.md @@ -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 IB Gateway host (env: IBKR_HOST, config: broker.ibkr.host, default: 127.0.0.1) + --port IB Gateway port (env: IBKR_PORT, config: broker.ibkr.port, default: 4002) + --client-id TWS client ID (env: IBKR_CLIENT_ID, default: 99) + --gateway-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