docs: add gateway unification design (api_gateway + web-gateway → api)
Unify both gateways into a single gRPC-only `services/api/` with tonic-web for browser access. Drop REST+WebSocket, keep full 6-layer auth. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
116
docs/plans/2026-03-04-gateway-unification-design.md
Normal file
116
docs/plans/2026-03-04-gateway-unification-design.md
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user