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:
Ilia Denisov
2026-05-07 11:49:28 +02:00
parent 39b7b2ef29
commit 118f7c17a2
30 changed files with 1009 additions and 772 deletions
+10 -8
View File
@@ -139,9 +139,10 @@ consumed exactly once.
### 1.4 Per-request session lookup
Once the client holds a device session id and a private key, every
authenticated call is a signed gRPC request to gateway. Gateway is the
only component that ever sees the request signature; backend trusts
gateway's verdict.
authenticated call is a signed request to gateway over the
authenticated edge listener (Connect / gRPC / gRPC-Web on a single
HTTP/h2c port). Gateway is the only component that ever sees the
request signature; backend trusts gateway's verdict.
Gateway needs the session's public key to verify the signature, so each
authenticated request resolves the device session through an in-memory
@@ -602,8 +603,8 @@ not duplicated here.
### 6.2 Backend's role: pass-through with authorisation
The signed-gRPC pipeline for in-game traffic uses three message types
on the authenticated surface — `user.games.command`,
The signed authenticated-edge pipeline for in-game traffic uses three
message types on the authenticated surface — `user.games.command`,
`user.games.order`, `user.games.report` — each with a typed
FlatBuffers payload. Gateway transcodes the FB request into the JSON
shape backend expects, forwards over plain REST to the corresponding
@@ -680,9 +681,10 @@ session invalidations).
### 7.1 Scope
In scope: the gRPC stream a client opens against gateway, the
bootstrap event, the framing of forwarded events, and the
backend → gateway control channel that produces those events.
In scope: the server-streaming subscription a client opens against
gateway (Connect / gRPC / gRPC-Web framing all map to the same
endpoint), the bootstrap event, the framing of forwarded events, and
the backend → gateway control channel that produces those events.
Out of scope: the catalog of event kinds — see [Section 8](#8-notifications-and-mail) for the
notification side and [`backend/README.md` §10](../backend/README.md#10-notification-catalog) for the closed list.