Edge Gateway
Purpose
Edge Gateway is the only public ingress for Galaxy Plus clients.
It terminates the external transport and security boundary, enforces edge
policies, and routes verified requests to internal services.
The gateway does not implement domain-specific business logic. Business validation, authorization, ownership checks, and state transitions remain inside downstream services.
Trust Boundary
The gateway sits between untrusted external clients and trusted internal services.
The gateway is responsible for:
- parsing external transport requests;
- classifying public REST traffic;
- authenticating protected gRPC traffic;
- loading session state from cache;
- verifying request freshness and anti-replay constraints;
- applying edge rate limits and anti-abuse policy;
- building an authenticated internal command context;
- routing verified commands to internal services;
- maintaining authenticated push delivery connections.
The gateway is not responsible for:
- deciding whether a user is allowed to execute a business action;
- validating domain invariants;
- storing the source-of-truth session record;
- implementing business idempotency.
Transport Matrix
The gateway exposes two external transport classes.
| Transport | Audience | Authentication | Payload format | Primary use |
|---|---|---|---|---|
| REST/JSON | Public, unauthenticated traffic | No device session auth | JSON | Public auth commands, health checks, browser/bootstrap traffic |
| gRPC over HTTP/2 | Authenticated clients only | Required | FlatBuffers payload inside protobuf control envelope | Verified commands and push delivery |
Public REST Surface
The public REST surface is used for commands that must work before a device session exists and for browser-originated traffic that may share the same edge.
Stable public endpoints:
POST /api/v1/public/auth/send-email-codePOST /api/v1/public/auth/confirm-email-codeGET /healthzGET /readyz
In addition to the fixed endpoints above, the gateway may front browser bootstrap or asset traffic through a pluggable public handler or proxy. That traffic belongs to dedicated public route classes and must not share rate limit buckets or abuse counters with the public auth API.
Authenticated gRPC Surface
All authenticated client requests use HTTP/2 and gRPC.
The public gRPC service exposes two methods:
ExecuteCommand(ExecuteCommandRequest) returns (ExecuteCommandResponse)SubscribeEvents(SubscribeEventsRequest) returns (stream GatewayEvent)
ExecuteCommand is a generic unary RPC.
The gateway routes the request downstream by message_type after transport
verification succeeds.
SubscribeEvents is an authenticated server-streaming RPC.
It binds the stream to user_id and device_session_id and starts by sending
a service event that includes the current server time in milliseconds.
Envelope and Payload Model
The authenticated transport uses a split contract:
- gRPC control messages are protobuf-based;
- business payload bytes are FlatBuffers;
- signatures are computed over canonical envelope fields and a hash of raw FlatBuffers bytes.
The gateway treats payload_bytes as opaque business data.
It verifies integrity and forwards verified bytes downstream without rewriting
them.
ExecuteCommandRequest
Required fields:
protocol_versiondevice_session_idmessage_typetimestamp_msrequest_idpayload_bytespayload_hashsignature
Optional fields:
trace_id
ExecuteCommandResponse
Required fields:
protocol_versionrequest_idtimestamp_msresult_codepayload_bytespayload_hashsignature
SubscribeEventsRequest
The stream open request reuses the authenticated request model. It contains the same authentication fields as the unary request and either an empty payload or a minimal connect payload.
Required fields:
protocol_versiondevice_session_idmessage_typetimestamp_msrequest_idpayload_hashsignature
Optional fields:
payload_bytestrace_id
GatewayEvent
Every stream event is a client-facing signed server message.
Required fields:
event_typeevent_idtimestamp_mspayload_bytespayload_hashsignature
Optional fields:
request_idtrace_id
Verification and Routing Pipeline
The gateway applies the same strict verification order for authenticated gRPC ingress.
- Parse the control envelope and validate required fields.
- Check whether
protocol_versionis supported. - Resolve
device_session_idthroughSessionCache. - Reject unknown or revoked sessions.
- Verify that
payload_hashmatches rawpayload_bytes. - Verify the client signature using the public key from session cache.
- Verify that
timestamp_msis inside the accepted freshness window. - Verify anti-replay by checking
device_session_id + request_id. - Apply authenticated rate limit and edge policy checks.
- Build the authenticated internal command context.
- Route the command downstream by
message_type.
No downstream business service should receive a request that has not passed this full verification pipeline.
Internal Authenticated Contract
Downstream services should receive an internal authenticated command rather than raw external gRPC transport data.
The minimum authenticated context is:
user_iddevice_session_idmessage_type- verified
payload_bytes request_id- optional
trace_id - optional client metadata needed for logs and tracing
Downstream services may trust that the gateway has already performed transport authentication, freshness verification, and anti-replay checks. They must still perform business authorization and domain validation.
Session Model
The Auth / Session Service is the source of truth for device session state. The gateway is designed to authenticate the hot path from cache.
Expected session fields available to the gateway:
device_session_iduser_id- client public key
- session status
- revoke metadata
- optional client metadata
Session Cache
SessionCache provides the fast path for:
- session existence checks;
device_session_id -> user_id;- access to the client public key used for signature verification;
- revoked versus active status checks.
Cache updates are event-driven. TTL is allowed only as a safety net and must not replace invalidation events.
Revocation Behavior
When a device session is revoked:
- the Auth / Session Service updates the source of truth;
- it publishes a session update or revoke event;
- the gateway invalidates or updates
SessionCache; - new unary gRPC requests for that session are rejected;
- active
SubscribeEventsstreams for that session are closed.
Public Anti-Abuse Model
The public REST layer must distinguish between public auth operations and browser-originated traffic that may burst during a normal first page load.
The gateway uses these public route classes:
public_authbrowser_bootstrapbrowser_assetpublic_misc
Public Auth
public_auth includes send-email-code and confirm-email-code.
This class uses stricter limits and abuse scoring because it directly touches
account and session creation flows.
Controls include:
- per-IP and per-identity rate limits;
- request body size limits;
- method allow-lists;
- malformed request counters;
- elevated logging and security telemetry for repeated failures.
Browser Bootstrap and Asset Traffic
browser_bootstrap and browser_asset use separate coarse-grained budgets.
They may exhibit bursty behavior during the first load and therefore must not
be treated as hostile based on burst pattern alone.
This traffic is still constrained by:
- dedicated rate limits;
- method allow-lists;
- body size limits where request bodies are expected;
- protocol and path validation;
- independent abuse telemetry.
The gateway must not merge these buckets or counters with public_auth.
Push Delivery Model
The v1 push channel is a gRPC server stream. Long-polling is intentionally out of scope for the first version.
Expected stream behavior:
- the client opens
SubscribeEvents; - the gateway applies the full authenticated ingress verification pipeline;
- the stream is bound to
user_idanddevice_session_id; - the first service event includes
server_time_ms; - client-facing events from internal pub/sub are fanned out to matching active streams;
- revoke events close affected streams.
Recommended Package Layout
The initial package layout should keep transport, policy, and downstream adapters separate:
cmd/gatewayinternal/appinternal/configinternal/restapiinternal/grpcapiinternal/authninternal/sessioninternal/replayinternal/ratelimitinternal/downstreaminternal/pushinternal/eventsinternal/clock
Key Interfaces
The gateway should be built around explicit consumer-side interfaces.
SessionCache
Provides cached session lookup by device_session_id.
Returns enough data to verify signatures and identify the authenticated user.
ReplayStore
Tracks recently seen request_id values per device session and rejects replayed
requests inside the accepted freshness window.
RateLimiter
Applies independent policies for:
- public REST route classes;
- authenticated gRPC requests by IP;
- authenticated gRPC requests by session;
- authenticated gRPC requests by user;
- authenticated gRPC requests by message class.
PublicTrafficClassifier
Maps incoming public REST requests to one of the public route classes so that limits and anti-abuse counters remain isolated.
AuthServiceClient
Handles public auth commands and session-related updates exchanged with the Auth / Session Service.
DownstreamRouter
Resolves the target downstream service or adapter by message_type.
DownstreamClient
Executes a verified authenticated command against a downstream internal service and returns response payload bytes plus a stable result code.
EventSubscriber
Subscribes to internal pub/sub topics used for:
- session cache updates;
- revocations;
- client-facing event delivery.
PushHub
Tracks active SubscribeEvents streams, binds them to authenticated identities,
and delivers events to the correct connections.
ResponseSigner
Signs unary responses and stream events so clients can verify server-originated messages.
Clock
Provides current server time and supports consistent freshness-window checks.
Error Model and Observability
The gateway should expose stable edge-level error classes instead of leaking internal implementation details.
Minimum error categories:
- malformed request;
- unsupported protocol;
- unknown session;
- revoked session;
- invalid signature;
- stale request;
- replay detected;
- rate limited;
- downstream unavailable;
- internal error.
Observability requirements:
- stable correlation identifiers, including
request_idand optionaltrace_id; - structured logs;
- security audit events for rejects and abuse signals;
- metrics keyed by route class, message type, result code, and reject reason;
- no logging of secrets, raw private material, or raw signatures.
Non-Goals
The gateway is not a business authorization layer and must not grow into a domain coordinator.
The gateway must not:
- implement business ownership checks;
- validate domain state transitions;
- replace the Auth / Session Service as the session source of truth;
- degrade into a synchronous pass-through that reloads session state for every authenticated request.