phase 4: connectrpc on the gateway authenticated edge
Replace the native-gRPC server bootstrap with a single `connectrpc.com/connect` HTTP/h2c listener. Connect-Go natively serves Connect, gRPC, and gRPC-Web on the same port, so browsers can now reach the authenticated surface without giving up the gRPC framing native and desktop clients may use later. The decorator stack (envelope → session → payload-hash → signature → freshness/replay → rate-limit → routing/push) is reused unchanged behind a small Connect → gRPC adapter and a `grpc.ServerStream` shim around `*connect.ServerStream`. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+33
-16
@@ -87,7 +87,15 @@ The gateway exposes two external transport classes.
|
||||
| Transport | Audience | Authentication | Payload format | Primary use |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| REST/JSON | Public, unauthenticated traffic | No device session auth | JSON | Health checks, public auth commands, and browser/bootstrap traffic |
|
||||
| gRPC over HTTP/2 | Authenticated clients only | Required | FlatBuffers payload inside protobuf control envelope | Verified commands and push delivery |
|
||||
| Connect / gRPC / gRPC-Web over HTTP/2 (h2c) | Authenticated clients only | Required | FlatBuffers payload inside protobuf control envelope | Verified commands and push delivery |
|
||||
|
||||
The authenticated edge listener is built on
|
||||
[`connectrpc.com/connect`](https://connectrpc.com/) and natively serves
|
||||
the Connect, gRPC, and gRPC-Web protocols on a single HTTP/2 cleartext
|
||||
(`h2c`) port. Browser clients use `@connectrpc/connect-web`; native
|
||||
clients can use either Connect or raw gRPC framing against the same
|
||||
listener. Production TLS termination happens upstream of the gateway,
|
||||
matching the previous gRPC-only deployment posture.
|
||||
|
||||
### Public REST Surface
|
||||
|
||||
@@ -181,16 +189,21 @@ The endpoint exposes metrics in the Prometheus text exposition format described
|
||||
in the official Prometheus documentation:
|
||||
<https://prometheus.io/docs/instrumenting/exposition_formats/>.
|
||||
|
||||
### Authenticated gRPC Surface
|
||||
### Authenticated Edge Surface
|
||||
|
||||
All authenticated client requests use HTTP/2 and gRPC.
|
||||
The listener address is configured by `GATEWAY_AUTHENTICATED_GRPC_ADDR`.
|
||||
Inbound authenticated gRPC connection setup is bounded by
|
||||
All authenticated client requests use HTTP/2 cleartext (`h2c`) and are
|
||||
served through `connectrpc.com/connect`, which natively accepts the
|
||||
Connect, gRPC, and gRPC-Web protocols on the same listener.
|
||||
The listener address is configured by `GATEWAY_AUTHENTICATED_GRPC_ADDR`
|
||||
(the env-var name retains the historical `GRPC` infix for operational
|
||||
stability — it labels the authenticated edge tier, not the wire
|
||||
protocol).
|
||||
Inbound authenticated edge connection setup is bounded by
|
||||
`GATEWAY_AUTHENTICATED_GRPC_CONNECTION_TIMEOUT`, which defaults to `5s`.
|
||||
The accepted client timestamp skew is configured by
|
||||
`GATEWAY_AUTHENTICATED_GRPC_FRESHNESS_WINDOW` and defaults to `5m`.
|
||||
|
||||
The public gRPC service exposes two methods:
|
||||
The public service exposes two methods:
|
||||
|
||||
- `ExecuteCommand(ExecuteCommandRequest) returns (ExecuteCommandResponse)`
|
||||
- `SubscribeEvents(SubscribeEventsRequest) returns (stream GatewayEvent)`
|
||||
@@ -200,9 +213,12 @@ The gateway routes the request downstream by `message_type` after transport
|
||||
verification succeeds.
|
||||
Downstream unary execution is bounded by
|
||||
`GATEWAY_AUTHENTICATED_DOWNSTREAM_TIMEOUT`, which defaults to `5s`.
|
||||
When that timeout expires, the gateway preserves the authenticated gRPC
|
||||
contract and returns gRPC `UNAVAILABLE` with message
|
||||
`downstream service is unavailable`.
|
||||
When that timeout expires, the gateway preserves the authenticated edge
|
||||
contract and returns `UNAVAILABLE` with message
|
||||
`downstream service is unavailable`. Reject codes are documented using
|
||||
their gRPC names (`INVALID_ARGUMENT`, `UNAUTHENTICATED`, …); the same
|
||||
codes flow back to Connect clients as the corresponding `connect.Code*`
|
||||
values.
|
||||
|
||||
`SubscribeEvents` is an authenticated server-streaming RPC.
|
||||
It binds the stream to `user_id` and `device_session_id` and starts by sending
|
||||
@@ -211,8 +227,9 @@ a signed service event that includes the current server time in milliseconds.
|
||||
The v1 protobuf contract lives in
|
||||
`proto/galaxy/gateway/v1/edge_gateway.proto` under package
|
||||
`galaxy.gateway.v1` and service `EdgeGateway`.
|
||||
Generated Go bindings are committed under `proto/galaxy/gateway/v1/` and are
|
||||
regenerated with:
|
||||
Generated Go bindings are committed under
|
||||
`proto/galaxy/gateway/v1/` (gRPC stubs and `gatewayv1connect/` Connect
|
||||
handlers) and are regenerated with:
|
||||
|
||||
```bash
|
||||
buf generate
|
||||
@@ -286,8 +303,8 @@ affected stream is closed with gRPC `RESOURCE_EXHAUSTED` and message
|
||||
same `device_session_id` was revoked, every active `SubscribeEvents` stream
|
||||
bound to that exact session is closed with gRPC `FAILED_PRECONDITION` and
|
||||
message `device session is revoked`. During gateway shutdown, the in-memory
|
||||
push hub is closed before gRPC graceful stop, and every active
|
||||
`SubscribeEvents` stream is terminated with gRPC `UNAVAILABLE` and message
|
||||
push hub is closed before HTTP graceful stop, and every active
|
||||
`SubscribeEvents` stream is terminated with `UNAVAILABLE` and message
|
||||
`gateway is shutting down`.
|
||||
Authenticated anti-abuse budgets are configured by the
|
||||
`GATEWAY_AUTHENTICATED_GRPC_ANTI_ABUSE_*` environment variables.
|
||||
@@ -851,9 +868,9 @@ subscribers, and telemetry runtime.
|
||||
|
||||
`GATEWAY_SHUTDOWN_TIMEOUT` configures the per-component graceful shutdown
|
||||
budget and defaults to `5s`.
|
||||
During authenticated gRPC shutdown, the in-memory `PushHub` closes active
|
||||
streams before gRPC graceful stop, so active `SubscribeEvents` calls terminate
|
||||
with gRPC `UNAVAILABLE` and message `gateway is shutting down`.
|
||||
During authenticated edge shutdown, the in-memory `PushHub` closes active
|
||||
streams before HTTP graceful stop, so active `SubscribeEvents` calls terminate
|
||||
with `UNAVAILABLE` and message `gateway is shutting down`.
|
||||
|
||||
## Recommended Package Layout
|
||||
|
||||
|
||||
Reference in New Issue
Block a user