# 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
