diff --git a/docs/plans/2026-03-04-gateway-unification-design.md b/docs/plans/2026-03-04-gateway-unification-design.md new file mode 100644 index 000000000..282765a02 --- /dev/null +++ b/docs/plans/2026-03-04-gateway-unification-design.md @@ -0,0 +1,116 @@ +# Gateway Unification: api_gateway + web-gateway → api + +## Decision + +Unify `services/api_gateway/` and `crates/web-gateway/` into a single `services/api/` service. gRPC-only (no REST), with `tonic-web` for browser access. Full 6-layer auth preserved. + +## Context + +Two gateways exist with overlapping functionality: + +- **api_gateway** (12.8K LOC, 357 tests): gRPC proxy to 9 backend services, 100+ endpoints, 6-layer auth (mTLS, JWT, Redis revocation, RBAC, rate limiting, audit), optional MFA +- **web-gateway** (3K LOC, 104 tests): REST+WebSocket for React dashboard, JWT+rate limiting, 24 endpoints, 8 WS topics + +Both do JWT auth, rate limiting (identical 3-tier), and proxy to trading/backtesting/ML services. + +## Architecture + +### Single Binary: `api` + +``` +services/api/ +├── Cargo.toml # name = "api", binary = "api" +├── build.rs +└── src/ + ├── main.rs # gRPC + tonic-web server + ├── lib.rs + ├── auth/ # 6-layer auth (mTLS, JWT, revocation, RBAC, rate limit, audit) + │ ├── interceptor.rs + │ ├── jwt/ # JWT service, revocation, login endpoints + │ ├── mfa/ # Optional TOTP (feature-gated) + │ └── mtls/ # TLS 1.3, certificate validation, OCSP/CRL + ├── grpc/ # 15 proxy implementations (all 9 backend services) + ├── routing/ # Rate limiter (DashMap token bucket) + ├── config/ # RBAC config, hot-reload + ├── metrics/ # Prometheus exporter + └── health.rs # K8s probes +``` + +### Ports + +| Port | Protocol | Purpose | +|------|----------|---------| +| 50051 | gRPC (HTTP/2) + grpc-web (HTTP/1.1) | All API traffic | +| 9091 | HTTP | Prometheus metrics + health probes | + +### tonic-web Integration + +```rust +Server::builder() + .accept_http1(true) + .layer(cors_layer) // CORS for browser origins + .layer(GrpcWebLayer::new()) // grpc-web ↔ gRPC translation + .add_service(auth_interceptor.layer(trading_svc)) + .add_service(auth_interceptor.layer(backtesting_svc)) + // ... all services + .serve(addr) +``` + +Port 50051 serves both native gRPC (HTTP/2) and grpc-web (HTTP/1.1) — no proxy needed. + +### What's Deleted + +- `services/api_gateway/` — code moves to `services/api/` +- `crates/web-gateway/` — entirely deleted (REST+WS layer no longer needed) +- `infra/k8s/services/web-gateway.yaml` +- `infra/k8s/network-policies/web-gateway.yaml` +- `handlers/` directory (4 ML REST endpoints dropped) +- Axum dependency removed from api service + +### What's Preserved + +- All 15 gRPC proxy implementations (100+ endpoints, 37+ streaming) +- Full 6-layer auth stack +- Optional MFA (TOTP, feature-gated) +- Circuit breakers, health monitoring +- Prometheus metrics, observability + +### What's Added + +- `tonic-web` crate dependency +- `tower-http` CORS layer for grpc-web browser access +- `CORS_ORIGINS` env var (from web-gateway) + +## Blast Radius + +~25 files need updating: + +| Category | Count | Change | +|----------|-------|--------| +| Workspace Cargo.toml | 1 | Remove old members, add `services/api` | +| trading_service/Cargo.toml | 1 | Update path dep `api-gateway` → `api` | +| K8s manifests | 4 | Rename api-gateway, delete web-gateway | +| CI (.gitlab-ci.yml) | 1 | Binary name `api-gateway` → `api` | +| Docker compose | 2 | Rename service, update ports | +| Prometheus config | 3 | Rename scrape targets | +| Scripts | 4 | Update binary/service references | +| FXT TUI | 3 | Update service name in pod/status fetching | +| Test crates | 5 | Update imports, fixture configs | +| Load test crate | 1 | Rename `testing/api-gateway-load/` → `testing/api-load/` | + +## Dashboard Migration (Separate Task) + +The React dashboard (`web-dashboard/`) currently calls web-gateway REST endpoints. After unification: + +1. Replace `fetch()` calls with `@connectrpc/connect-web` or `grpc-web` client +2. Server-streaming RPCs replace the 8 WebSocket topics +3. JWT goes in gRPC metadata instead of `Authorization` header + +This is a separate task — the dashboard will be temporarily broken until migrated. + +## Testing Strategy + +- Port all api_gateway tests (357) with updated imports +- Delete web-gateway tests (104) — they test REST handlers that no longer exist +- Add integration tests for tonic-web/grpc-web access +- Rename `testing/api-gateway-load/` → `testing/api-load/`, update load test targets