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:
@@ -531,6 +531,15 @@ This section describes the secure exchange model between client and
|
||||
gateway. It applies at the public boundary and does not rely on backend
|
||||
behaviour for any of its guarantees.
|
||||
|
||||
The authenticated edge listener is built on `connectrpc.com/connect` and
|
||||
natively serves the Connect, gRPC, and gRPC-Web protocols on a single
|
||||
HTTP/2 cleartext (`h2c`) port. Browser clients use Connect via
|
||||
`@connectrpc/connect-web`; native iOS / Android / desktop clients can
|
||||
use either Connect or raw gRPC framing against the same listener.
|
||||
Envelope, signature, freshness, and anti-replay rules below are
|
||||
protocol-agnostic — they apply identically to every supported wire
|
||||
framing.
|
||||
|
||||
### Principles
|
||||
|
||||
- No browser cookies.
|
||||
|
||||
+10
-8
@@ -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.
|
||||
|
||||
+12
-10
@@ -138,9 +138,10 @@ Throttle-переиспользование на стороне send означ
|
||||
### 1.4 Поиск сессии для каждого запроса
|
||||
|
||||
Когда у клиента есть идентификатор устройства-сессии и приватный ключ,
|
||||
каждый аутентифицированный вызов — это подписанный gRPC-запрос к
|
||||
gateway. Gateway — единственный компонент, который видит подпись
|
||||
запроса; backend доверяет вердикту gateway.
|
||||
каждый аутентифицированный вызов — это подписанный запрос к gateway
|
||||
по аутентифицированному edge-листенеру (Connect / gRPC / gRPC-Web на
|
||||
одном HTTP/h2c-порту). Gateway — единственный компонент, который видит
|
||||
подпись запроса; backend доверяет вердикту gateway.
|
||||
|
||||
Gateway нужен публичный ключ сессии для проверки подписи, поэтому
|
||||
каждый аутентифицированный запрос разрешает устройство-сессию через
|
||||
@@ -618,10 +619,10 @@ Wire-формат команд, приказов и отчётов — собс
|
||||
|
||||
### 6.2 Роль backend: pass-through с авторизацией
|
||||
|
||||
Signed-gRPC-конвейер для in-game-трафика использует три message
|
||||
types на аутентифицированной поверхности — `user.games.command`,
|
||||
`user.games.order`, `user.games.report` — у каждого типизированный
|
||||
FlatBuffers-payload. Gateway транскодирует FB-запрос в JSON-форму,
|
||||
Подписанный конвейер аутентифицированного edge для in-game-трафика
|
||||
использует три message types на аутентифицированной поверхности —
|
||||
`user.games.command`, `user.games.order`, `user.games.report` —
|
||||
у каждого типизированный FlatBuffers-payload. Gateway транскодирует FB-запрос в JSON-форму,
|
||||
которую ждёт backend, форвардит её REST'ом в соответствующий
|
||||
`/api/v1/user/games/{game_id}/*` endpoint, после чего транскодирует
|
||||
JSON-ответ обратно в FB перед подписью.
|
||||
@@ -697,9 +698,10 @@ notification-каталог явно их опускает
|
||||
|
||||
### 7.1 Состав
|
||||
|
||||
В составе: gRPC-стрим, который клиент открывает к gateway,
|
||||
bootstrap-событие, фрейминг форварднутых событий, control-канал
|
||||
backend → gateway, который производит эти события.
|
||||
В составе: server-streaming-подписка, которую клиент открывает к
|
||||
gateway (Connect / gRPC / gRPC-Web фреймы все маршрутизируются на
|
||||
одну точку), bootstrap-событие, фрейминг форварднутых событий,
|
||||
control-канал backend → gateway, который производит эти события.
|
||||
|
||||
Вне состава: каталог видов событий — см.
|
||||
[Раздел 8](#8-уведомления-и-почта) для notification-стороны и
|
||||
|
||||
Reference in New Issue
Block a user