Status: Accepted Date: 2026-04-13
Context: Cloud mode needs a management API for projects, sessions, images, and profiles. gRPC is excellent for terminal I/O streaming but awkward for CRUD operations (REST clients are more widely available, OpenAPI tooling is richer, browser-based UIs can call REST directly).
Decision: Run an axum HTTP server on a separate port (rest_port, default 8080) alongside the tonic gRPC server (port 50051). The REST API handles all management operations; gRPC handles terminal I/O streaming.
Alternatives considered:
- gRPC for everything — possible but loses REST tooling benefits. gRPC-web requires a proxy for browser clients. OpenAPI/Swagger is the standard for management APIs.
- axum only (no gRPC) — would require WebSocket or chunked HTTP for terminal streaming, losing the typed protobuf messages and bidirectional flow control.
- tonic-web (gRPC-web in the same server) — avoids a second port but still requires gRPC clients. Doesn't solve the "management API should be REST" requirement.
- Single port with path routing — technically possible but complicates the middleware stack (gRPC requires HTTP/2, REST works on HTTP/1.1).
Consequences:
- Two ports: 50051 (gRPC) and 8080 (REST)
- OpenAPI 3.x spec auto-generated via
utoipaat/api/v1/openapi.json - Auth middleware reuses the same
AuthInterceptorandRateLimiterfrom the gRPC layer - SSE events on
GET /api/v1/events— natural fit for HTTP, impossible in pure gRPC tower-httpprovides tracing and CORS middleware- Trade-off: two server processes to manage, two ports to expose. Justified by the clear separation of concerns.