feat(deploy): single-origin path-based deployment + project site
Build · Site / build (push) Successful in 8s
Tests · Go / test (push) Successful in 2m22s
Tests · UI / test (push) Failing after 2m42s

Serve the whole stack behind one host: site at /, game UI at /game/,
gateway REST at /api + /healthz, Connect at /rpc (prefix stripped by the
edge Caddy). The built artifact is domain-agnostic — the UI talks to the
gateway same-origin via relative URLs, so the same bundle runs under any
host with no rebuild and with CORS disabled.

- Rename the Connect proto service galaxy.gateway.v1.EdgeGateway ->
  edge.v1.Gateway; regenerate Go + TS; public path /rpc/edge.v1.Gateway.
- Move the game UI under base path /game (env BASE_PATH); make the
  manifest, service-worker scope, WASM loader, and all navigation
  base-aware via a withBase helper.
- Relative API + /rpc Connect prefix; Vite dev proxy mirrors the strip.
- Rewrite the edge Caddy (dev + prod) for path-based routing; empty CORS
  allow-lists (same-origin); single host.
- New VitePress project site (site/): i18n en/ru with switcher, LaTeX
  math, minimal monospace theme; built and served at /.
- dev-deploy compose/Makefile + CI (dev-deploy, prod-build, new
  site-build) build and seed the site; probes hit /, /game/, /healthz.
- Sync docs (ARCHITECTURE, gateway README/openapi, dev-deploy &
  local-dev READMEs, CLAUDE.md, ui/PLAN).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-23 18:19:07 +02:00
parent fa0df5183a
commit 8565942392
104 changed files with 2967 additions and 787 deletions
+20 -5
View File
@@ -94,8 +94,20 @@ The authenticated edge listener is built on
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.
listener. TLS termination happens upstream of the gateway at the edge
Caddy, which fronts both transports under one host.
Both transports are served same-origin under one host. The edge routes
public REST and the health probe at `/api/*` and `/healthz` to the
public listener, and the authenticated Connect/gRPC-Web surface at
`/rpc/*` to the authenticated listener (the `/rpc` prefix is stripped
before the gateway). Because the game UI is served from the same origin,
the gateway runs with CORS disabled by default: both
`GATEWAY_PUBLIC_HTTP_CORS_ALLOWED_ORIGINS` and
`GATEWAY_AUTHENTICATED_GRPC_CORS_ALLOWED_ORIGINS` are empty, an empty
allow-list turns the CORS middleware off, and responses carry no
`Access-Control-*` headers. Those knobs would only be repopulated if a
deployment ever fronted the gateway on a different host than the UI.
### Public REST Surface
@@ -225,10 +237,13 @@ It binds the stream to `user_id` and `device_session_id` and starts by sending
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`.
`proto/edge/v1/edge_gateway.proto` under package `edge.v1` and service
`Gateway`. Browser and native clients address its methods at
`/rpc/edge.v1.Gateway/<Method>`; the edge Caddy strips the `/rpc`
prefix so the gateway listener sees the proto-derived
`/edge.v1.Gateway/<Method>` path.
Generated Go bindings are committed under
`proto/galaxy/gateway/v1/` (gRPC stubs and `gatewayv1connect/` Connect
`proto/edge/v1/` (gRPC stubs and `edgev1connect/` Connect
handlers) and are regenerated with:
```bash
+8 -8
View File
@@ -11,7 +11,7 @@ import (
"galaxy/gateway/authn"
"galaxy/gateway/internal/clock"
"galaxy/gateway/internal/downstream"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
@@ -21,9 +21,9 @@ import (
// commandRoutingService translates the verified authenticated request context
// into an internal downstream command and signs successful unary responses.
type commandRoutingService struct {
gatewayv1.UnimplementedEdgeGatewayServer
edgev1.UnimplementedGatewayServer
subscribeDelegate gatewayv1.EdgeGatewayServer
subscribeDelegate edgev1.GatewayServer
router downstream.Router
responseSigner authn.ResponseSigner
clock clock.Clock
@@ -32,7 +32,7 @@ type commandRoutingService struct {
// ExecuteCommand builds a verified downstream command, routes it by exact
// message_type, executes it, and signs the resulting unary response.
func (s commandRoutingService) ExecuteCommand(ctx context.Context, _ *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
func (s commandRoutingService) ExecuteCommand(ctx context.Context, _ *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
command, err := authenticatedCommandFromContext(ctx)
if err != nil {
return nil, err
@@ -80,7 +80,7 @@ func (s commandRoutingService) ExecuteCommand(ctx context.Context, _ *gatewayv1.
return nil, status.Error(codes.Unavailable, "response signer is unavailable")
}
return &gatewayv1.ExecuteCommandResponse{
return &edgev1.ExecuteCommandResponse{
ProtocolVersion: command.ProtocolVersion,
RequestId: command.RequestID,
TimestampMs: responseTimestampMS,
@@ -93,13 +93,13 @@ func (s commandRoutingService) ExecuteCommand(ctx context.Context, _ *gatewayv1.
// SubscribeEvents delegates to the authenticated streaming service
// implementation selected during server construction.
func (s commandRoutingService) SubscribeEvents(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
func (s commandRoutingService) SubscribeEvents(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
return s.subscribeDelegate.SubscribeEvents(req, stream)
}
// newCommandRoutingService constructs the final authenticated service that
// owns verified unary routing while preserving the delegated streaming path.
func newCommandRoutingService(subscribeDelegate gatewayv1.EdgeGatewayServer, router downstream.Router, responseSigner authn.ResponseSigner, clk clock.Clock, downstreamTimeout time.Duration) gatewayv1.EdgeGatewayServer {
func newCommandRoutingService(subscribeDelegate edgev1.GatewayServer, router downstream.Router, responseSigner authn.ResponseSigner, clk clock.Clock, downstreamTimeout time.Duration) edgev1.GatewayServer {
return commandRoutingService{
subscribeDelegate: subscribeDelegate,
router: router,
@@ -142,4 +142,4 @@ func (unavailableResponseSigner) SignEvent(authn.EventSigningFields) ([]byte, er
return nil, errors.New("response signer is unavailable")
}
var _ gatewayv1.EdgeGatewayServer = commandRoutingService{}
var _ edgev1.GatewayServer = commandRoutingService{}
+11 -11
View File
@@ -5,8 +5,8 @@ import (
"errors"
"fmt"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
"galaxy/gateway/proto/galaxy/gateway/v1/gatewayv1connect"
edgev1 "galaxy/gateway/proto/edge/v1"
"galaxy/gateway/proto/edge/v1/edgev1connect"
"connectrpc.com/connect"
"google.golang.org/grpc/codes"
@@ -17,15 +17,15 @@ import (
// connectEdgeAdapter exposes the existing gRPC-shaped authenticated edge
// service decorator stack (envelope → session → payload-hash → signature →
// freshness/replay → rate-limit → routing/push) through the
// gatewayv1connect.EdgeGatewayHandler interface. It owns no logic of its
// edgev1connect.GatewayHandler interface. It owns no logic of its
// own; the underlying decorator stack carries the full ingress contract
// unchanged.
type connectEdgeAdapter struct {
impl gatewayv1.EdgeGatewayServer
impl edgev1.GatewayServer
}
// newConnectEdgeAdapter wraps impl as a Connect handler.
func newConnectEdgeAdapter(impl gatewayv1.EdgeGatewayServer) gatewayv1connect.EdgeGatewayHandler {
func newConnectEdgeAdapter(impl edgev1.GatewayServer) edgev1connect.GatewayHandler {
return &connectEdgeAdapter{impl: impl}
}
@@ -33,7 +33,7 @@ func newConnectEdgeAdapter(impl gatewayv1.EdgeGatewayServer) gatewayv1connect.Ed
// service, and wraps the typed response. gRPC `status.Error` values
// returned by the decorator stack are translated to *connect.Error so
// the Connect client receives the matching code and message.
func (a *connectEdgeAdapter) ExecuteCommand(ctx context.Context, req *connect.Request[gatewayv1.ExecuteCommandRequest]) (*connect.Response[gatewayv1.ExecuteCommandResponse], error) {
func (a *connectEdgeAdapter) ExecuteCommand(ctx context.Context, req *connect.Request[edgev1.ExecuteCommandRequest]) (*connect.Response[edgev1.ExecuteCommandResponse], error) {
resp, err := a.impl.ExecuteCommand(ctx, req.Msg)
if err != nil {
return nil, translateGRPCStatusError(err)
@@ -48,7 +48,7 @@ func (a *connectEdgeAdapter) ExecuteCommand(ctx context.Context, req *connect.Re
// stream; the remaining grpc.ServerStream surface is satisfied by no-op
// shims so the interface contract is met without panicking. Errors
// returned by the decorator stack are translated to *connect.Error.
func (a *connectEdgeAdapter) SubscribeEvents(ctx context.Context, req *connect.Request[gatewayv1.SubscribeEventsRequest], stream *connect.ServerStream[gatewayv1.GatewayEvent]) error {
func (a *connectEdgeAdapter) SubscribeEvents(ctx context.Context, req *connect.Request[edgev1.SubscribeEventsRequest], stream *connect.ServerStream[edgev1.GatewayEvent]) error {
wrapped := &connectEdgeStream{ctx: ctx, stream: stream}
if err := a.impl.SubscribeEvents(req.Msg, wrapped); err != nil {
return translateGRPCStatusError(err)
@@ -83,19 +83,19 @@ func translateGRPCStatusError(err error) error {
return connect.NewError(connect.Code(grpcStatus.Code()), errors.New(grpcStatus.Message()))
}
// connectEdgeStream satisfies grpc.ServerStreamingServer[gatewayv1.GatewayEvent]
// connectEdgeStream satisfies grpc.ServerStreamingServer[edgev1.GatewayEvent]
// on top of *connect.ServerStream. The decorator stack reads the request
// context and pushes outbound events through Send; the rest of the
// grpc.ServerStream surface is not exercised in the gateway, so the no-op
// implementations preserve the type contract without surprising behaviour.
type connectEdgeStream struct {
ctx context.Context
stream *connect.ServerStream[gatewayv1.GatewayEvent]
stream *connect.ServerStream[edgev1.GatewayEvent]
}
// Send forwards a typed gateway event through the underlying Connect server
// stream.
func (s *connectEdgeStream) Send(event *gatewayv1.GatewayEvent) error {
func (s *connectEdgeStream) Send(event *edgev1.GatewayEvent) error {
return s.stream.Send(event)
}
@@ -127,7 +127,7 @@ func (s *connectEdgeStream) SetTrailer(metadata.MD) {}
// SendMsg directly; if a future caller does, the typed Send path is used
// when the message is a GatewayEvent.
func (s *connectEdgeStream) SendMsg(m any) error {
event, ok := m.(*gatewayv1.GatewayEvent)
event, ok := m.(*edgev1.GatewayEvent)
if !ok {
return fmt.Errorf("connectEdgeStream.SendMsg: unsupported message type %T", m)
}
+12 -12
View File
@@ -4,7 +4,7 @@ import (
"bytes"
"context"
"fmt"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"buf.build/go/protovalidate"
"google.golang.org/grpc"
@@ -47,14 +47,14 @@ func parsedEnvelopeFromContext(ctx context.Context) (parsedEnvelope, bool) {
// envelopeValidatingService applies envelope parsing and the protocol gate
// before delegating to the configured service implementation.
type envelopeValidatingService struct {
gatewayv1.UnimplementedEdgeGatewayServer
edgev1.UnimplementedGatewayServer
delegate gatewayv1.EdgeGatewayServer
delegate edgev1.GatewayServer
}
// ExecuteCommand validates req and only then forwards it to the configured
// delegate with the parsed envelope attached to ctx.
func (s envelopeValidatingService) ExecuteCommand(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
func (s envelopeValidatingService) ExecuteCommand(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
envelope, err := parseExecuteCommandRequest(req)
if err != nil {
return nil, err
@@ -65,7 +65,7 @@ func (s envelopeValidatingService) ExecuteCommand(ctx context.Context, req *gate
// SubscribeEvents validates req and only then forwards it to the configured
// delegate with the parsed envelope attached to the stream context.
func (s envelopeValidatingService) SubscribeEvents(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
func (s envelopeValidatingService) SubscribeEvents(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
envelope, err := parseSubscribeEventsRequest(req)
if err != nil {
return err
@@ -79,7 +79,7 @@ func (s envelopeValidatingService) SubscribeEvents(req *gatewayv1.SubscribeEvent
// parseExecuteCommandRequest validates req according to the request-envelope
// rules and returns a cloned parsed envelope suitable for later auth steps.
func parseExecuteCommandRequest(req *gatewayv1.ExecuteCommandRequest) (parsedEnvelope, error) {
func parseExecuteCommandRequest(req *edgev1.ExecuteCommandRequest) (parsedEnvelope, error) {
if req == nil {
return parsedEnvelope{}, newMalformedEnvelopeError("request envelope must not be nil")
}
@@ -105,7 +105,7 @@ func parseExecuteCommandRequest(req *gatewayv1.ExecuteCommandRequest) (parsedEnv
// parseSubscribeEventsRequest validates req according to the request-envelope
// rules and returns a cloned parsed envelope suitable for later auth steps.
func parseSubscribeEventsRequest(req *gatewayv1.SubscribeEventsRequest) (parsedEnvelope, error) {
func parseSubscribeEventsRequest(req *edgev1.SubscribeEventsRequest) (parsedEnvelope, error) {
if req == nil {
return parsedEnvelope{}, newMalformedEnvelopeError("request envelope must not be nil")
}
@@ -131,13 +131,13 @@ func parseSubscribeEventsRequest(req *gatewayv1.SubscribeEventsRequest) (parsedE
// newEnvelopeValidatingService wraps delegate with the envelope-validation
// gate.
func newEnvelopeValidatingService(delegate gatewayv1.EdgeGatewayServer) gatewayv1.EdgeGatewayServer {
func newEnvelopeValidatingService(delegate edgev1.GatewayServer) edgev1.GatewayServer {
return envelopeValidatingService{delegate: delegate}
}
// canonicalExecuteCommandValidationError maps any ExecuteCommand validation
// failure into the stable canonical error chosen by field order.
func canonicalExecuteCommandValidationError(req *gatewayv1.ExecuteCommandRequest) error {
func canonicalExecuteCommandValidationError(req *edgev1.ExecuteCommandRequest) error {
switch {
case req.GetProtocolVersion() == "":
return newMalformedEnvelopeError("protocol_version must not be empty")
@@ -162,7 +162,7 @@ func canonicalExecuteCommandValidationError(req *gatewayv1.ExecuteCommandRequest
// canonicalSubscribeEventsValidationError maps any SubscribeEvents validation
// failure into the stable canonical error chosen by field order.
func canonicalSubscribeEventsValidationError(req *gatewayv1.SubscribeEventsRequest) error {
func canonicalSubscribeEventsValidationError(req *edgev1.SubscribeEventsRequest) error {
switch {
case req.GetProtocolVersion() == "":
return newMalformedEnvelopeError("protocol_version must not be empty")
@@ -198,7 +198,7 @@ func newUnsupportedProtocolVersionError(version string) error {
type parsedEnvelopeContextKey struct{}
type envelopeContextStream struct {
grpc.ServerStreamingServer[gatewayv1.GatewayEvent]
grpc.ServerStreamingServer[edgev1.GatewayEvent]
ctx context.Context
}
@@ -210,4 +210,4 @@ func (s envelopeContextStream) Context() context.Context {
return s.ctx
}
var _ gatewayv1.EdgeGatewayServer = envelopeValidatingService{}
var _ edgev1.GatewayServer = envelopeValidatingService{}
+43 -43
View File
@@ -4,7 +4,7 @@ import (
"context"
"testing"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -19,10 +19,10 @@ func TestParseExecuteCommandRequest(t *testing.T) {
tests := []struct {
name string
mutate func(*gatewayv1.ExecuteCommandRequest)
mutate func(*edgev1.ExecuteCommandRequest)
wantCode codes.Code
wantMessage string
assertValid func(*testing.T, *gatewayv1.ExecuteCommandRequest, parsedEnvelope)
assertValid func(*testing.T, *edgev1.ExecuteCommandRequest, parsedEnvelope)
}{
{
name: "nil request",
@@ -31,7 +31,7 @@ func TestParseExecuteCommandRequest(t *testing.T) {
},
{
name: "empty protocol version",
mutate: func(req *gatewayv1.ExecuteCommandRequest) {
mutate: func(req *edgev1.ExecuteCommandRequest) {
req.ProtocolVersion = ""
},
wantCode: codes.InvalidArgument,
@@ -39,7 +39,7 @@ func TestParseExecuteCommandRequest(t *testing.T) {
},
{
name: "empty device session id",
mutate: func(req *gatewayv1.ExecuteCommandRequest) {
mutate: func(req *edgev1.ExecuteCommandRequest) {
req.DeviceSessionId = ""
},
wantCode: codes.InvalidArgument,
@@ -47,7 +47,7 @@ func TestParseExecuteCommandRequest(t *testing.T) {
},
{
name: "empty message type",
mutate: func(req *gatewayv1.ExecuteCommandRequest) {
mutate: func(req *edgev1.ExecuteCommandRequest) {
req.MessageType = ""
},
wantCode: codes.InvalidArgument,
@@ -55,7 +55,7 @@ func TestParseExecuteCommandRequest(t *testing.T) {
},
{
name: "zero timestamp",
mutate: func(req *gatewayv1.ExecuteCommandRequest) {
mutate: func(req *edgev1.ExecuteCommandRequest) {
req.TimestampMs = 0
},
wantCode: codes.InvalidArgument,
@@ -63,7 +63,7 @@ func TestParseExecuteCommandRequest(t *testing.T) {
},
{
name: "empty request id",
mutate: func(req *gatewayv1.ExecuteCommandRequest) {
mutate: func(req *edgev1.ExecuteCommandRequest) {
req.RequestId = ""
},
wantCode: codes.InvalidArgument,
@@ -71,7 +71,7 @@ func TestParseExecuteCommandRequest(t *testing.T) {
},
{
name: "empty payload bytes",
mutate: func(req *gatewayv1.ExecuteCommandRequest) {
mutate: func(req *edgev1.ExecuteCommandRequest) {
req.PayloadBytes = nil
},
wantCode: codes.InvalidArgument,
@@ -79,7 +79,7 @@ func TestParseExecuteCommandRequest(t *testing.T) {
},
{
name: "empty payload hash",
mutate: func(req *gatewayv1.ExecuteCommandRequest) {
mutate: func(req *edgev1.ExecuteCommandRequest) {
req.PayloadHash = nil
},
wantCode: codes.InvalidArgument,
@@ -87,7 +87,7 @@ func TestParseExecuteCommandRequest(t *testing.T) {
},
{
name: "empty signature",
mutate: func(req *gatewayv1.ExecuteCommandRequest) {
mutate: func(req *edgev1.ExecuteCommandRequest) {
req.Signature = nil
},
wantCode: codes.InvalidArgument,
@@ -95,7 +95,7 @@ func TestParseExecuteCommandRequest(t *testing.T) {
},
{
name: "unsupported protocol version",
mutate: func(req *gatewayv1.ExecuteCommandRequest) {
mutate: func(req *edgev1.ExecuteCommandRequest) {
req.ProtocolVersion = "v2"
},
wantCode: codes.FailedPrecondition,
@@ -104,7 +104,7 @@ func TestParseExecuteCommandRequest(t *testing.T) {
{
name: "valid request",
wantCode: codes.OK,
assertValid: func(t *testing.T, req *gatewayv1.ExecuteCommandRequest, envelope parsedEnvelope) {
assertValid: func(t *testing.T, req *edgev1.ExecuteCommandRequest, envelope parsedEnvelope) {
t.Helper()
assert.Equal(t, supportedProtocolVersion, envelope.ProtocolVersion)
@@ -138,7 +138,7 @@ func TestParseExecuteCommandRequest(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
var req *gatewayv1.ExecuteCommandRequest
var req *edgev1.ExecuteCommandRequest
if tt.name != "nil request" {
req = newValidExecuteCommandRequest()
if tt.mutate != nil {
@@ -166,10 +166,10 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
tests := []struct {
name string
mutate func(*gatewayv1.SubscribeEventsRequest)
mutate func(*edgev1.SubscribeEventsRequest)
wantCode codes.Code
wantMessage string
assertValid func(*testing.T, *gatewayv1.SubscribeEventsRequest, parsedEnvelope)
assertValid func(*testing.T, *edgev1.SubscribeEventsRequest, parsedEnvelope)
}{
{
name: "nil request",
@@ -178,7 +178,7 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
},
{
name: "empty protocol version",
mutate: func(req *gatewayv1.SubscribeEventsRequest) {
mutate: func(req *edgev1.SubscribeEventsRequest) {
req.ProtocolVersion = ""
},
wantCode: codes.InvalidArgument,
@@ -186,7 +186,7 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
},
{
name: "empty device session id",
mutate: func(req *gatewayv1.SubscribeEventsRequest) {
mutate: func(req *edgev1.SubscribeEventsRequest) {
req.DeviceSessionId = ""
},
wantCode: codes.InvalidArgument,
@@ -194,7 +194,7 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
},
{
name: "empty message type",
mutate: func(req *gatewayv1.SubscribeEventsRequest) {
mutate: func(req *edgev1.SubscribeEventsRequest) {
req.MessageType = ""
},
wantCode: codes.InvalidArgument,
@@ -202,7 +202,7 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
},
{
name: "zero timestamp",
mutate: func(req *gatewayv1.SubscribeEventsRequest) {
mutate: func(req *edgev1.SubscribeEventsRequest) {
req.TimestampMs = 0
},
wantCode: codes.InvalidArgument,
@@ -210,7 +210,7 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
},
{
name: "empty request id",
mutate: func(req *gatewayv1.SubscribeEventsRequest) {
mutate: func(req *edgev1.SubscribeEventsRequest) {
req.RequestId = ""
},
wantCode: codes.InvalidArgument,
@@ -218,7 +218,7 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
},
{
name: "empty payload hash",
mutate: func(req *gatewayv1.SubscribeEventsRequest) {
mutate: func(req *edgev1.SubscribeEventsRequest) {
req.PayloadHash = nil
},
wantCode: codes.InvalidArgument,
@@ -226,7 +226,7 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
},
{
name: "empty signature",
mutate: func(req *gatewayv1.SubscribeEventsRequest) {
mutate: func(req *edgev1.SubscribeEventsRequest) {
req.Signature = nil
},
wantCode: codes.InvalidArgument,
@@ -234,7 +234,7 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
},
{
name: "unsupported protocol version",
mutate: func(req *gatewayv1.SubscribeEventsRequest) {
mutate: func(req *edgev1.SubscribeEventsRequest) {
req.ProtocolVersion = "v2"
},
wantCode: codes.FailedPrecondition,
@@ -243,7 +243,7 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
{
name: "valid request with empty payload bytes",
wantCode: codes.OK,
assertValid: func(t *testing.T, req *gatewayv1.SubscribeEventsRequest, envelope parsedEnvelope) {
assertValid: func(t *testing.T, req *edgev1.SubscribeEventsRequest, envelope parsedEnvelope) {
t.Helper()
assert.Empty(t, req.GetPayloadBytes())
@@ -260,7 +260,7 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
var req *gatewayv1.SubscribeEventsRequest
var req *edgev1.SubscribeEventsRequest
if tt.name != "nil request" {
req = newValidSubscribeEventsRequest()
if tt.mutate != nil {
@@ -286,10 +286,10 @@ func TestParseSubscribeEventsRequest(t *testing.T) {
func TestEnvelopeValidatingServiceExecuteCommandRejectsInvalidRequestBeforeDelegate(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
service := newEnvelopeValidatingService(delegate)
_, err := service.ExecuteCommand(context.Background(), &gatewayv1.ExecuteCommandRequest{})
_, err := service.ExecuteCommand(context.Background(), &edgev1.ExecuteCommandRequest{})
require.Error(t, err)
assert.Equal(t, codes.InvalidArgument, status.Code(err))
@@ -299,10 +299,10 @@ func TestEnvelopeValidatingServiceExecuteCommandRejectsInvalidRequestBeforeDeleg
func TestEnvelopeValidatingServiceSubscribeEventsRejectsInvalidRequestBeforeDelegate(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
service := newEnvelopeValidatingService(delegate)
err := service.SubscribeEvents(&gatewayv1.SubscribeEventsRequest{}, stubGatewayEventStream{})
err := service.SubscribeEvents(&edgev1.SubscribeEventsRequest{}, stubGatewayEventStream{})
require.Error(t, err)
assert.Equal(t, codes.InvalidArgument, status.Code(err))
@@ -313,15 +313,15 @@ func TestEnvelopeValidatingServiceExecuteCommandAttachesParsedEnvelope(t *testin
t.Parallel()
want := newValidExecuteCommandRequest()
delegate := &recordingEdgeGatewayService{
executeCommandFunc: func(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
delegate := &recordingGatewayService{
executeCommandFunc: func(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
envelope, ok := parsedEnvelopeFromContext(ctx)
require.True(t, ok)
assert.Equal(t, want.GetRequestId(), envelope.RequestID)
assert.Equal(t, want.GetDeviceSessionId(), envelope.DeviceSessionID)
assert.Equal(t, want.GetMessageType(), envelope.MessageType)
assert.Equal(t, want.GetPayloadBytes(), envelope.PayloadBytes)
return &gatewayv1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
return &edgev1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
},
}
service := newEnvelopeValidatingService(delegate)
@@ -337,8 +337,8 @@ func TestEnvelopeValidatingServiceSubscribeEventsAttachesParsedEnvelope(t *testi
t.Parallel()
want := newValidSubscribeEventsRequest()
delegate := &recordingEdgeGatewayService{
subscribeEventsFunc: func(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
delegate := &recordingGatewayService{
subscribeEventsFunc: func(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
envelope, ok := parsedEnvelopeFromContext(stream.Context())
require.True(t, ok)
assert.Equal(t, want.GetRequestId(), envelope.RequestID)
@@ -357,25 +357,25 @@ func TestEnvelopeValidatingServiceSubscribeEventsAttachesParsedEnvelope(t *testi
assert.Equal(t, 1, delegate.subscribeCalls)
}
type recordingEdgeGatewayService struct {
gatewayv1.UnimplementedEdgeGatewayServer
type recordingGatewayService struct {
edgev1.UnimplementedGatewayServer
executeCalls int
subscribeCalls int
executeCommandFunc func(context.Context, *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error)
subscribeEventsFunc func(*gatewayv1.SubscribeEventsRequest, grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error
executeCommandFunc func(context.Context, *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error)
subscribeEventsFunc func(*edgev1.SubscribeEventsRequest, grpc.ServerStreamingServer[edgev1.GatewayEvent]) error
}
func (s *recordingEdgeGatewayService) ExecuteCommand(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
func (s *recordingGatewayService) ExecuteCommand(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
s.executeCalls++
if s.executeCommandFunc != nil {
return s.executeCommandFunc(ctx, req)
}
return &gatewayv1.ExecuteCommandResponse{}, nil
return &edgev1.ExecuteCommandResponse{}, nil
}
func (s *recordingEdgeGatewayService) SubscribeEvents(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
func (s *recordingGatewayService) SubscribeEvents(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
s.subscribeCalls++
if s.subscribeEventsFunc != nil {
return s.subscribeEventsFunc(req, stream)
@@ -389,7 +389,7 @@ type stubGatewayEventStream struct {
ctx context.Context
}
func (s stubGatewayEventStream) Send(*gatewayv1.GatewayEvent) error {
func (s stubGatewayEventStream) Send(*edgev1.GatewayEvent) error {
return nil
}
+7 -7
View File
@@ -7,7 +7,7 @@ import (
"galaxy/gateway/internal/clock"
"galaxy/gateway/internal/replay"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
@@ -19,9 +19,9 @@ const minimumReplayReservationTTL = time.Millisecond
// freshnessAndReplayService applies freshness and anti-replay checks after
// client-signature verification and before later policy or routing steps run.
type freshnessAndReplayService struct {
gatewayv1.UnimplementedEdgeGatewayServer
edgev1.UnimplementedGatewayServer
delegate gatewayv1.EdgeGatewayServer
delegate edgev1.GatewayServer
clock clock.Clock
replayStore replay.Store
freshnessWindow time.Duration
@@ -29,7 +29,7 @@ type freshnessAndReplayService struct {
// ExecuteCommand verifies request freshness and replay protection before
// delegating to the configured service implementation.
func (s freshnessAndReplayService) ExecuteCommand(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
func (s freshnessAndReplayService) ExecuteCommand(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
if err := s.verifyFreshnessAndReplay(ctx); err != nil {
return nil, err
}
@@ -39,7 +39,7 @@ func (s freshnessAndReplayService) ExecuteCommand(ctx context.Context, req *gate
// SubscribeEvents verifies request freshness and replay protection before
// delegating to the configured service implementation.
func (s freshnessAndReplayService) SubscribeEvents(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
func (s freshnessAndReplayService) SubscribeEvents(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
if err := s.verifyFreshnessAndReplay(stream.Context()); err != nil {
return err
}
@@ -49,7 +49,7 @@ func (s freshnessAndReplayService) SubscribeEvents(req *gatewayv1.SubscribeEvent
// newFreshnessAndReplayService wraps delegate with the freshness and replay
// gate.
func newFreshnessAndReplayService(delegate gatewayv1.EdgeGatewayServer, clk clock.Clock, replayStore replay.Store, freshnessWindow time.Duration) gatewayv1.EdgeGatewayServer {
func newFreshnessAndReplayService(delegate edgev1.GatewayServer, clk clock.Clock, replayStore replay.Store, freshnessWindow time.Duration) edgev1.GatewayServer {
return freshnessAndReplayService{
delegate: delegate,
clock: clk,
@@ -92,4 +92,4 @@ func (unavailableReplayStore) Reserve(context.Context, string, string, time.Dura
return errors.New("replay store is unavailable")
}
var _ gatewayv1.EdgeGatewayServer = freshnessAndReplayService{}
var _ edgev1.GatewayServer = freshnessAndReplayService{}
@@ -9,7 +9,7 @@ import (
"galaxy/gateway/internal/replay"
"galaxy/gateway/internal/session"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"connectrpc.com/connect"
"github.com/stretchr/testify/assert"
@@ -40,7 +40,7 @@ func TestExecuteCommandRejectsStaleTimestamp(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
@@ -82,7 +82,7 @@ func TestSubscribeEventsRejectsStaleTimestamp(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
@@ -104,7 +104,7 @@ func TestSubscribeEventsRejectsStaleTimestamp(t *testing.T) {
func TestExecuteCommandRejectsReplay(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
@@ -131,7 +131,7 @@ func TestExecuteCommandRejectsReplay(t *testing.T) {
func TestSubscribeEventsRejectsReplay(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
@@ -162,9 +162,9 @@ func TestSubscribeEventsRejectsReplay(t *testing.T) {
func TestExecuteCommandAllowsSameRequestIDAcrossDistinctSessions(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{
executeCommandFunc: func(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
return &gatewayv1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
delegate := &recordingGatewayService{
executeCommandFunc: func(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
return &edgev1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
},
}
@@ -196,8 +196,8 @@ func TestExecuteCommandAllowsSameRequestIDAcrossDistinctSessions(t *testing.T) {
func TestSubscribeEventsAllowsSameRequestIDAcrossDistinctSessions(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{
subscribeEventsFunc: func(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
delegate := &recordingGatewayService{
subscribeEventsFunc: func(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
return nil
},
}
@@ -238,7 +238,7 @@ func TestSubscribeEventsAllowsSameRequestIDAcrossDistinctSessions(t *testing.T)
func TestExecuteCommandRejectsReplayStoreUnavailable(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
@@ -262,7 +262,7 @@ func TestExecuteCommandRejectsReplayStoreUnavailable(t *testing.T) {
func TestSubscribeEventsRejectsReplayStoreUnavailable(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
@@ -286,9 +286,9 @@ func TestSubscribeEventsRejectsReplayStoreUnavailable(t *testing.T) {
func TestExecuteCommandFreshRequestReachesDelegateAndUsesDynamicReplayTTL(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{
executeCommandFunc: func(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
return &gatewayv1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
delegate := &recordingGatewayService{
executeCommandFunc: func(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
return &edgev1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
},
}
@@ -324,8 +324,8 @@ func TestExecuteCommandFreshRequestReachesDelegateAndUsesDynamicReplayTTL(t *tes
func TestSubscribeEventsFreshRequestReachesDelegateAndUsesDynamicReplayTTL(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{
subscribeEventsFunc: func(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
delegate := &recordingGatewayService{
subscribeEventsFunc: func(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
return nil
},
}
@@ -361,9 +361,9 @@ func TestSubscribeEventsFreshRequestReachesDelegateAndUsesDynamicReplayTTL(t *te
func TestExecuteCommandFutureSkewUsesExtendedReplayTTL(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{
executeCommandFunc: func(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
return &gatewayv1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
delegate := &recordingGatewayService{
executeCommandFunc: func(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
return &edgev1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
},
}
@@ -395,9 +395,9 @@ func TestExecuteCommandFutureSkewUsesExtendedReplayTTL(t *testing.T) {
func TestExecuteCommandBoundaryFreshnessUsesMinimumReplayTTL(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{
executeCommandFunc: func(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
return &gatewayv1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
delegate := &recordingGatewayService{
executeCommandFunc: func(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
return &edgev1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
},
}
+4 -4
View File
@@ -8,7 +8,7 @@ import (
"galaxy/gateway/internal/logging"
"galaxy/gateway/internal/telemetry"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"go.opentelemetry.io/otel/attribute"
"go.uber.org/zap"
@@ -78,9 +78,9 @@ func recordEdgeRequest(logger *zap.Logger, metrics *telemetry.Runtime, ctx conte
func envelopeFieldsFromRequest(req any) (messageType string, requestID string, traceID string) {
switch typed := req.(type) {
case *gatewayv1.ExecuteCommandRequest:
case *edgev1.ExecuteCommandRequest:
return typed.GetMessageType(), typed.GetRequestId(), typed.GetTraceId()
case *gatewayv1.SubscribeEventsRequest:
case *edgev1.SubscribeEventsRequest:
return typed.GetMessageType(), typed.GetRequestId(), typed.GetTraceId()
default:
return "", "", ""
@@ -88,7 +88,7 @@ func envelopeFieldsFromRequest(req any) (messageType string, requestID string, t
}
func resultCodeFromResponse(resp any) string {
typed, ok := resp.(*gatewayv1.ExecuteCommandResponse)
typed, ok := resp.(*edgev1.ExecuteCommandResponse)
if !ok {
return ""
}
+7 -7
View File
@@ -5,7 +5,7 @@ import (
"errors"
"galaxy/gateway/authn"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
@@ -15,14 +15,14 @@ import (
// payloadHashVerifyingService applies payload-hash verification after session
// lookup and before any later auth or routing step runs.
type payloadHashVerifyingService struct {
gatewayv1.UnimplementedEdgeGatewayServer
edgev1.UnimplementedGatewayServer
delegate gatewayv1.EdgeGatewayServer
delegate edgev1.GatewayServer
}
// ExecuteCommand verifies req payload integrity before delegating to the
// configured service implementation.
func (s payloadHashVerifyingService) ExecuteCommand(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
func (s payloadHashVerifyingService) ExecuteCommand(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
if err := verifyPayloadHash(ctx); err != nil {
return nil, err
}
@@ -32,7 +32,7 @@ func (s payloadHashVerifyingService) ExecuteCommand(ctx context.Context, req *ga
// SubscribeEvents verifies req payload integrity before delegating to the
// configured service implementation.
func (s payloadHashVerifyingService) SubscribeEvents(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
func (s payloadHashVerifyingService) SubscribeEvents(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
if err := verifyPayloadHash(stream.Context()); err != nil {
return err
}
@@ -42,7 +42,7 @@ func (s payloadHashVerifyingService) SubscribeEvents(req *gatewayv1.SubscribeEve
// newPayloadHashVerifyingService wraps delegate with the payload-hash
// verification gate.
func newPayloadHashVerifyingService(delegate gatewayv1.EdgeGatewayServer) gatewayv1.EdgeGatewayServer {
func newPayloadHashVerifyingService(delegate edgev1.GatewayServer) edgev1.GatewayServer {
return payloadHashVerifyingService{delegate: delegate}
}
@@ -63,4 +63,4 @@ func verifyPayloadHash(ctx context.Context) error {
}
}
var _ gatewayv1.EdgeGatewayServer = payloadHashVerifyingService{}
var _ edgev1.GatewayServer = payloadHashVerifyingService{}
@@ -15,7 +15,7 @@ import (
func TestExecuteCommandRejectsPayloadHashWithInvalidLength(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
@@ -38,7 +38,7 @@ func TestExecuteCommandRejectsPayloadHashWithInvalidLength(t *testing.T) {
func TestExecuteCommandRejectsPayloadHashMismatch(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
@@ -62,7 +62,7 @@ func TestExecuteCommandRejectsPayloadHashMismatch(t *testing.T) {
func TestSubscribeEventsRejectsPayloadHashWithInvalidLength(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
@@ -85,7 +85,7 @@ func TestSubscribeEventsRejectsPayloadHashWithInvalidLength(t *testing.T) {
func TestSubscribeEventsRejectsPayloadHashMismatch(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
+7 -7
View File
@@ -11,7 +11,7 @@ import (
"galaxy/gateway/internal/logging"
"galaxy/gateway/internal/push"
"galaxy/gateway/internal/telemetry"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"go.uber.org/zap"
"google.golang.org/grpc"
@@ -22,7 +22,7 @@ import (
// NewFanOutPushStreamService constructs the authenticated SubscribeEvents tail
// service that registers active streams in hub and forwards client-facing
// events after the bootstrap event has been sent.
func NewFanOutPushStreamService(hub *push.Hub, responseSigner authn.ResponseSigner, clk clock.Clock, logger *zap.Logger) gatewayv1.EdgeGatewayServer {
func NewFanOutPushStreamService(hub *push.Hub, responseSigner authn.ResponseSigner, clk clock.Clock, logger *zap.Logger) edgev1.GatewayServer {
if responseSigner == nil {
responseSigner = unavailableResponseSigner{}
}
@@ -44,7 +44,7 @@ func NewFanOutPushStreamService(hub *push.Hub, responseSigner authn.ResponseSign
// fanOutPushStreamService owns the post-bootstrap authenticated push-stream
// lifecycle backed by the in-memory push hub.
type fanOutPushStreamService struct {
gatewayv1.UnimplementedEdgeGatewayServer
edgev1.UnimplementedGatewayServer
hub *push.Hub
responseSigner authn.ResponseSigner
@@ -54,7 +54,7 @@ type fanOutPushStreamService struct {
// SubscribeEvents registers the verified stream in the push hub and forwards
// matching client-facing events until the stream ends.
func (s fanOutPushStreamService) SubscribeEvents(_ *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
func (s fanOutPushStreamService) SubscribeEvents(_ *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
binding, ok := authenticatedStreamBindingFromContext(stream.Context())
if !ok {
return status.Error(codes.Internal, "authenticated request context is incomplete")
@@ -109,7 +109,7 @@ func (s fanOutPushStreamService) SubscribeEvents(_ *gatewayv1.SubscribeEventsReq
}
}
func (s fanOutPushStreamService) buildGatewayEvent(event push.Event) (*gatewayv1.GatewayEvent, error) {
func (s fanOutPushStreamService) buildGatewayEvent(event push.Event) (*edgev1.GatewayEvent, error) {
timestampMS := s.clock.Now().UTC().UnixMilli()
payloadHash := sha256.Sum256(event.PayloadBytes)
@@ -125,7 +125,7 @@ func (s fanOutPushStreamService) buildGatewayEvent(event push.Event) (*gatewayv1
return nil, status.Error(codes.Unavailable, "response signer is unavailable")
}
return &gatewayv1.GatewayEvent{
return &edgev1.GatewayEvent{
EventType: event.EventType,
EventId: event.EventID,
TimestampMs: timestampMS,
@@ -169,4 +169,4 @@ func mapSubscriptionOutcome(err error) telemetry.EdgeOutcome {
}
}
var _ gatewayv1.EdgeGatewayServer = fanOutPushStreamService{}
var _ edgev1.GatewayServer = fanOutPushStreamService{}
+6 -6
View File
@@ -6,7 +6,7 @@ import (
"time"
"galaxy/gateway/internal/telemetry"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"go.opentelemetry.io/otel/attribute"
"google.golang.org/grpc"
@@ -26,7 +26,7 @@ import (
// 15-second default a fully-idle stream costs ~840 KB/day per client;
// see `docs/ARCHITECTURE.md` for the per-scale projection.
type heartbeatingStream struct {
grpc.ServerStreamingServer[gatewayv1.GatewayEvent]
grpc.ServerStreamingServer[edgev1.GatewayEvent]
interval time.Duration
metrics *telemetry.Runtime
@@ -43,7 +43,7 @@ type heartbeatingStream struct {
// the wrapping entirely; non-nil returns must have `Stop()` called once
// the stream lifecycle ends.
func newHeartbeatingStream(
inner grpc.ServerStreamingServer[gatewayv1.GatewayEvent],
inner grpc.ServerStreamingServer[edgev1.GatewayEvent],
interval time.Duration,
metrics *telemetry.Runtime,
) *heartbeatingStream {
@@ -64,7 +64,7 @@ func newHeartbeatingStream(
// so the heartbeat goroutine waits a fresh interval before firing
// again. A Send that succeeds means the transport just delivered real
// bytes; the silence window restarts from "now".
func (s *heartbeatingStream) Send(event *gatewayv1.GatewayEvent) error {
func (s *heartbeatingStream) Send(event *edgev1.GatewayEvent) error {
s.sendMu.Lock()
defer s.sendMu.Unlock()
if err := s.ServerStreamingServer.Send(event); err != nil {
@@ -158,6 +158,6 @@ func (s *heartbeatingStream) resetTimerLocked() {
// EventType is left at its proto3 default so the wire frame stays as
// small as Connect framing allows. See `gatewayHeartbeatEventType` for
// the security rationale of leaving the event unsigned.
func buildHeartbeatEvent() *gatewayv1.GatewayEvent {
return &gatewayv1.GatewayEvent{EventType: gatewayHeartbeatEventType}
func buildHeartbeatEvent() *edgev1.GatewayEvent {
return &edgev1.GatewayEvent{EventType: gatewayHeartbeatEventType}
}
@@ -7,7 +7,7 @@ import (
"testing"
"time"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -66,7 +66,7 @@ func TestHeartbeatingStreamRealSendResetsSilenceTimer(t *testing.T) {
defer ticker.Stop()
for range 6 {
<-ticker.C
if err := hb.Send(&gatewayv1.GatewayEvent{EventType: "real.event"}); err != nil {
if err := hb.Send(&edgev1.GatewayEvent{EventType: "real.event"}); err != nil {
t.Errorf("real Send failed: %v", err)
return
}
@@ -134,16 +134,16 @@ func TestHeartbeatingStreamSendErrorPropagates(t *testing.T) {
require.NotNil(t, hb)
defer hb.Stop()
err := hb.Send(&gatewayv1.GatewayEvent{EventType: "real.event"})
err := hb.Send(&edgev1.GatewayEvent{EventType: "real.event"})
require.ErrorIs(t, err, wantErr)
}
// capturingStream is a minimal grpc.ServerStreamingServer that pushes
// every Send into a channel so tests can assert on the wire frame.
type capturingStream struct {
grpc.ServerStreamingServer[gatewayv1.GatewayEvent]
grpc.ServerStreamingServer[edgev1.GatewayEvent]
events chan *gatewayv1.GatewayEvent
events chan *edgev1.GatewayEvent
sendErr atomic.Pointer[errorBox]
}
@@ -152,10 +152,10 @@ type errorBox struct{ err error }
func newCapturingStream(t *testing.T) *capturingStream {
t.Helper()
return &capturingStream{events: make(chan *gatewayv1.GatewayEvent, 16)}
return &capturingStream{events: make(chan *edgev1.GatewayEvent, 16)}
}
func (s *capturingStream) Send(event *gatewayv1.GatewayEvent) error {
func (s *capturingStream) Send(event *edgev1.GatewayEvent) error {
if box := s.sendErr.Load(); box != nil {
return box.err
}
@@ -172,7 +172,7 @@ func (s *capturingStream) SetTrailer(metadata.MD) {}
func (s *capturingStream) SendMsg(any) error { return errors.New("capturingStream.SendMsg: unused") }
func (s *capturingStream) RecvMsg(any) error { return errors.New("capturingStream.RecvMsg: unused") }
func (s *capturingStream) recv(t *testing.T, timeout time.Duration) *gatewayv1.GatewayEvent {
func (s *capturingStream) recv(t *testing.T, timeout time.Duration) *edgev1.GatewayEvent {
t.Helper()
select {
+12 -12
View File
@@ -9,7 +9,7 @@ import (
"galaxy/gateway/authn"
"galaxy/gateway/internal/clock"
"galaxy/gateway/internal/telemetry"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
gatewayfbs "galaxy/schema/fbs/gateway"
flatbuffers "github.com/google/flatbuffers/go"
@@ -81,9 +81,9 @@ func authenticatedStreamBindingFromContext(ctx context.Context) (authenticatedSt
// the tail performs and only emits a heartbeat when the silence window
// elapses; tails remain heartbeat-unaware.
type authenticatedPushStreamService struct {
gatewayv1.UnimplementedEdgeGatewayServer
edgev1.UnimplementedGatewayServer
tailDelegate gatewayv1.EdgeGatewayServer
tailDelegate edgev1.GatewayServer
responseSigner authn.ResponseSigner
clock clock.Clock
heartbeatInterval time.Duration
@@ -92,7 +92,7 @@ type authenticatedPushStreamService struct {
// SubscribeEvents binds the verified stream identity, sends the initial signed
// server-time event, and then delegates the remaining lifecycle.
func (s authenticatedPushStreamService) SubscribeEvents(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
func (s authenticatedPushStreamService) SubscribeEvents(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
envelope, ok := parsedEnvelopeFromContext(stream.Context())
if !ok {
return status.Error(codes.Internal, "authenticated request context is incomplete")
@@ -134,7 +134,7 @@ func (s authenticatedPushStreamService) SubscribeEvents(req *gatewayv1.Subscribe
return status.Error(codes.Unavailable, "response signer is unavailable")
}
if err := boundStream.Send(&gatewayv1.GatewayEvent{
if err := boundStream.Send(&edgev1.GatewayEvent{
EventType: serverTimeEventType,
EventId: envelope.RequestID,
TimestampMs: serverTimeMS,
@@ -147,7 +147,7 @@ func (s authenticatedPushStreamService) SubscribeEvents(req *gatewayv1.Subscribe
return err
}
var streamForTail grpc.ServerStreamingServer[gatewayv1.GatewayEvent] = boundStream
var streamForTail grpc.ServerStreamingServer[edgev1.GatewayEvent] = boundStream
if hbStream := newHeartbeatingStream(boundStream, s.heartbeatInterval, s.metrics); hbStream != nil {
defer hbStream.Stop()
go func() {
@@ -165,12 +165,12 @@ func (s authenticatedPushStreamService) SubscribeEvents(req *gatewayv1.Subscribe
}
func newAuthenticatedPushStreamService(
tailDelegate gatewayv1.EdgeGatewayServer,
tailDelegate edgev1.GatewayServer,
responseSigner authn.ResponseSigner,
clk clock.Clock,
heartbeatInterval time.Duration,
metrics *telemetry.Runtime,
) gatewayv1.EdgeGatewayServer {
) edgev1.GatewayServer {
if tailDelegate == nil {
tailDelegate = holdOpenSubscribeEventsService{}
}
@@ -197,7 +197,7 @@ func buildServerTimeEventPayload(serverTimeMS int64) []byte {
type authenticatedStreamBindingContextKey struct{}
type authenticatedStreamContextStream struct {
grpc.ServerStreamingServer[gatewayv1.GatewayEvent]
grpc.ServerStreamingServer[edgev1.GatewayEvent]
ctx context.Context
}
@@ -210,12 +210,12 @@ func (s authenticatedStreamContextStream) Context() context.Context {
}
type holdOpenSubscribeEventsService struct {
gatewayv1.UnimplementedEdgeGatewayServer
edgev1.UnimplementedGatewayServer
}
func (holdOpenSubscribeEventsService) SubscribeEvents(_ *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
func (holdOpenSubscribeEventsService) SubscribeEvents(_ *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
<-stream.Context().Done()
return stream.Context().Err()
}
var _ gatewayv1.EdgeGatewayServer = authenticatedPushStreamService{}
var _ edgev1.GatewayServer = authenticatedPushStreamService{}
+7 -7
View File
@@ -7,7 +7,7 @@ import (
"galaxy/gateway/internal/config"
"galaxy/gateway/internal/ratelimit"
"galaxy/gateway/internal/session"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
@@ -102,9 +102,9 @@ type AuthenticatedRequestPolicy interface {
}
type authenticatedRateLimitService struct {
gatewayv1.UnimplementedEdgeGatewayServer
edgev1.UnimplementedGatewayServer
delegate gatewayv1.EdgeGatewayServer
delegate edgev1.GatewayServer
limiter AuthenticatedRequestLimiter
policy AuthenticatedRequestPolicy
cfg config.AuthenticatedGRPCAntiAbuseConfig
@@ -112,7 +112,7 @@ type authenticatedRateLimitService struct {
// ExecuteCommand applies authenticated rate limits and edge policy before
// delegating to the configured service implementation.
func (s authenticatedRateLimitService) ExecuteCommand(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
func (s authenticatedRateLimitService) ExecuteCommand(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
if err := s.applyRateLimitsAndPolicy(ctx, authenticatedRPCExecuteCommand); err != nil {
return nil, err
}
@@ -122,7 +122,7 @@ func (s authenticatedRateLimitService) ExecuteCommand(ctx context.Context, req *
// SubscribeEvents applies authenticated rate limits and edge policy before
// delegating to the configured service implementation.
func (s authenticatedRateLimitService) SubscribeEvents(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
func (s authenticatedRateLimitService) SubscribeEvents(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
if err := s.applyRateLimitsAndPolicy(stream.Context(), authenticatedRPCSubscribeEvents); err != nil {
return err
}
@@ -132,7 +132,7 @@ func (s authenticatedRateLimitService) SubscribeEvents(req *gatewayv1.SubscribeE
// newAuthenticatedRateLimitService wraps delegate with the authenticated
// rate-limit and edge-policy gate.
func newAuthenticatedRateLimitService(delegate gatewayv1.EdgeGatewayServer, limiter AuthenticatedRequestLimiter, policy AuthenticatedRequestPolicy, cfg config.AuthenticatedGRPCAntiAbuseConfig) gatewayv1.EdgeGatewayServer {
func newAuthenticatedRateLimitService(delegate edgev1.GatewayServer, limiter AuthenticatedRequestLimiter, policy AuthenticatedRequestPolicy, cfg config.AuthenticatedGRPCAntiAbuseConfig) edgev1.GatewayServer {
return authenticatedRateLimitService{
delegate: delegate,
limiter: limiter,
@@ -279,4 +279,4 @@ func (noopAuthenticatedRequestPolicy) Evaluate(context.Context, AuthenticatedReq
return nil
}
var _ gatewayv1.EdgeGatewayServer = authenticatedRateLimitService{}
var _ edgev1.GatewayServer = authenticatedRateLimitService{}
@@ -14,7 +14,7 @@ import (
"galaxy/gateway/internal/ratelimit"
"galaxy/gateway/internal/restapi"
"galaxy/gateway/internal/session"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"connectrpc.com/connect"
"github.com/stretchr/testify/assert"
@@ -24,7 +24,7 @@ import (
func TestExecuteCommandRateLimitsByIP(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGatewayWithGRPCConfig(t, newAuthenticatedGRPCConfigForTest(func(cfg *config.AuthenticatedGRPCConfig) {
cfg.AntiAbuse.IP = config.AuthenticatedRateLimitConfig{
Requests: 1,
@@ -54,7 +54,7 @@ func TestExecuteCommandRateLimitsByIP(t *testing.T) {
func TestExecuteCommandRateLimitsBySession(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGatewayWithGRPCConfig(t, newAuthenticatedGRPCConfigForTest(func(cfg *config.AuthenticatedGRPCConfig) {
cfg.AntiAbuse.Session = config.AuthenticatedRateLimitConfig{
Requests: 1,
@@ -87,7 +87,7 @@ func TestExecuteCommandRateLimitsBySession(t *testing.T) {
func TestExecuteCommandRateLimitsByUser(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGatewayWithGRPCConfig(t, newAuthenticatedGRPCConfigForTest(func(cfg *config.AuthenticatedGRPCConfig) {
cfg.AntiAbuse.User = config.AuthenticatedRateLimitConfig{
Requests: 1,
@@ -124,7 +124,7 @@ func TestExecuteCommandRateLimitsByUser(t *testing.T) {
func TestExecuteCommandRateLimitsByMessageClass(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGatewayWithGRPCConfig(t, newAuthenticatedGRPCConfigForTest(func(cfg *config.AuthenticatedGRPCConfig) {
cfg.AntiAbuse.MessageClass = config.AuthenticatedRateLimitConfig{
Requests: 1,
@@ -161,7 +161,7 @@ func TestAuthenticatedPolicyHookReceivesVerifiedRequest(t *testing.T) {
t.Parallel()
policy := &recordingAuthenticatedRequestPolicy{}
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: userMappedSessionCache(map[string]string{"device-session-123": "user-123"}),
@@ -189,7 +189,7 @@ func TestAuthenticatedPolicyHookReceivesVerifiedRequest(t *testing.T) {
func TestExecuteCommandPolicyRejectMapsToPermissionDenied(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: userMappedSessionCache(map[string]string{"device-session-123": "user-123"}),
@@ -212,7 +212,7 @@ func TestExecuteCommandPolicyRejectMapsToPermissionDenied(t *testing.T) {
func TestSubscribeEventsRateLimitRejectsStream(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGatewayWithGRPCConfig(t, newAuthenticatedGRPCConfigForTest(func(cfg *config.AuthenticatedGRPCConfig) {
cfg.AntiAbuse.IP = config.AuthenticatedRateLimitConfig{
Requests: 1,
@@ -274,7 +274,7 @@ func TestAuthenticatedRateLimitsStayIsolatedFromPublicREST(t *testing.T) {
AuthService: staticAuthServiceClient{},
Limiter: publicLimiterAdapter{limiter: sharedLimiter},
})
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
grpcServer := NewServer(grpcCfg, ServerDependencies{
Service: delegate,
Router: executeCommandAdapterRouter{service: delegate},
@@ -342,7 +342,7 @@ func newAuthenticatedGRPCConfigForTest(mutate func(*config.AuthenticatedGRPCConf
return cfg
}
func newValidExecuteCommandRequestWithMessageType(deviceSessionID string, requestID string, messageType string) *gatewayv1.ExecuteCommandRequest {
func newValidExecuteCommandRequestWithMessageType(deviceSessionID string, requestID string, messageType string) *edgev1.ExecuteCommandRequest {
req := newValidExecuteCommandRequestWithSessionAndRequestID(deviceSessionID, requestID)
req.MessageType = messageType
req.Signature = signRequest(
+5 -5
View File
@@ -24,8 +24,8 @@ import (
"galaxy/gateway/internal/replay"
"galaxy/gateway/internal/session"
"galaxy/gateway/internal/telemetry"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
"galaxy/gateway/proto/galaxy/gateway/v1/gatewayv1connect"
edgev1 "galaxy/gateway/proto/edge/v1"
"galaxy/gateway/proto/edge/v1/edgev1connect"
"connectrpc.com/connect"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
@@ -42,7 +42,7 @@ type ServerDependencies struct {
// after the initial authenticated service event has been sent. When nil, the
// gateway keeps authenticated SubscribeEvents streams open until the client
// cancels them, the server shuts down, or a later stream send fails.
Service gatewayv1.EdgeGatewayServer
Service edgev1.GatewayServer
// Router resolves the exact downstream unary client for the verified
// message_type value. When nil, the authenticated unary surface uses an
@@ -93,7 +93,7 @@ type ServerDependencies struct {
// single net/http listener.
type Server struct {
cfg config.AuthenticatedGRPCConfig
service gatewayv1.EdgeGatewayServer
service edgev1.GatewayServer
logger *zap.Logger
pushHub *push.Hub
metrics *telemetry.Runtime
@@ -169,7 +169,7 @@ func (s *Server) Run(ctx context.Context) error {
mux := http.NewServeMux()
connectHandler := newConnectEdgeAdapter(s.service)
path, handler := gatewayv1connect.NewEdgeGatewayHandler(
path, handler := edgev1connect.NewGatewayHandler(
connectHandler,
connect.WithInterceptors(observabilityConnectInterceptor(s.logger, s.metrics)),
)
+7 -7
View File
@@ -12,8 +12,8 @@ import (
"galaxy/gateway/internal/app"
"galaxy/gateway/internal/config"
"galaxy/gateway/internal/session"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
"galaxy/gateway/proto/galaxy/gateway/v1/gatewayv1connect"
edgev1 "galaxy/gateway/proto/edge/v1"
"galaxy/gateway/proto/edge/v1/edgev1connect"
"connectrpc.com/connect"
"github.com/stretchr/testify/assert"
@@ -30,7 +30,7 @@ func TestExecuteCommandRejectsMalformedEnvelope(t *testing.T) {
addr := waitForListenAddr(t, server)
client := newEdgeClient(t, addr)
_, err := client.ExecuteCommand(context.Background(), connect.NewRequest(&gatewayv1.ExecuteCommandRequest{}))
_, err := client.ExecuteCommand(context.Background(), connect.NewRequest(&edgev1.ExecuteCommandRequest{}))
require.Error(t, err)
assert.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
}
@@ -44,7 +44,7 @@ func TestSubscribeEventsRejectsMalformedEnvelope(t *testing.T) {
addr := waitForListenAddr(t, server)
client := newEdgeClient(t, addr)
err := subscribeEventsError(t, context.Background(), client, &gatewayv1.SubscribeEventsRequest{})
err := subscribeEventsError(t, context.Background(), client, &edgev1.SubscribeEventsRequest{})
require.Error(t, err)
assert.Equal(t, connect.CodeInvalidArgument, connect.CodeOf(err))
}
@@ -58,7 +58,7 @@ func TestExecuteCommandRejectsUnsupportedProtocolVersion(t *testing.T) {
addr := waitForListenAddr(t, server)
client := newEdgeClient(t, addr)
_, err := client.ExecuteCommand(context.Background(), connect.NewRequest(&gatewayv1.ExecuteCommandRequest{
_, err := client.ExecuteCommand(context.Background(), connect.NewRequest(&edgev1.ExecuteCommandRequest{
ProtocolVersion: "v2",
DeviceSessionId: "device-session-123",
MessageType: "fleet.move",
@@ -418,7 +418,7 @@ func waitForListenAddr(t *testing.T, server *Server) string {
// authenticated edge listener. AllowHTTP forces the client to issue plain
// HTTP/2 requests (h2c) instead of attempting TLS, which the gateway's
// in-process test bootstrap does not configure.
func newEdgeClient(t *testing.T, addr string) gatewayv1connect.EdgeGatewayClient {
func newEdgeClient(t *testing.T, addr string) edgev1connect.GatewayClient {
t.Helper()
httpClient := &http.Client{
@@ -429,7 +429,7 @@ func newEdgeClient(t *testing.T, addr string) gatewayv1connect.EdgeGatewayClient
},
},
}
return gatewayv1connect.NewEdgeGatewayClient(httpClient, "http://"+addr)
return edgev1connect.NewGatewayClient(httpClient, "http://"+addr)
}
// connectErrorMessage extracts the *connect.Error message from err. It
+8 -8
View File
@@ -5,7 +5,7 @@ import (
"errors"
"galaxy/gateway/internal/session"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
@@ -30,15 +30,15 @@ func resolvedSessionFromContext(ctx context.Context) (session.Record, bool) {
// sessionLookupService resolves the authenticated session from SessionCache
// after envelope parsing succeeds and before later auth steps run.
type sessionLookupService struct {
gatewayv1.UnimplementedEdgeGatewayServer
edgev1.UnimplementedGatewayServer
delegate gatewayv1.EdgeGatewayServer
delegate edgev1.GatewayServer
cache session.Cache
}
// ExecuteCommand resolves the cached session for req and only then forwards it
// to the configured delegate with the resolved session attached to ctx.
func (s sessionLookupService) ExecuteCommand(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
func (s sessionLookupService) ExecuteCommand(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
record, err := s.lookupSession(ctx)
if err != nil {
return nil, err
@@ -50,7 +50,7 @@ func (s sessionLookupService) ExecuteCommand(ctx context.Context, req *gatewayv1
// SubscribeEvents resolves the cached session for req and only then forwards it
// to the configured delegate with the resolved session attached to the stream
// context.
func (s sessionLookupService) SubscribeEvents(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
func (s sessionLookupService) SubscribeEvents(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
record, err := s.lookupSession(stream.Context())
if err != nil {
return err
@@ -63,7 +63,7 @@ func (s sessionLookupService) SubscribeEvents(req *gatewayv1.SubscribeEventsRequ
}
// newSessionLookupService wraps delegate with the session-cache lookup gate.
func newSessionLookupService(delegate gatewayv1.EdgeGatewayServer, cache session.Cache) gatewayv1.EdgeGatewayServer {
func newSessionLookupService(delegate edgev1.GatewayServer, cache session.Cache) edgev1.GatewayServer {
return sessionLookupService{
delegate: delegate,
cache: cache,
@@ -105,7 +105,7 @@ func cloneSessionRecord(record session.Record) session.Record {
type resolvedSessionContextKey struct{}
type resolvedSessionContextStream struct {
grpc.ServerStreamingServer[gatewayv1.GatewayEvent]
grpc.ServerStreamingServer[edgev1.GatewayEvent]
ctx context.Context
}
@@ -126,4 +126,4 @@ func (unavailableSessionCache) Lookup(context.Context, string) (session.Record,
func (unavailableSessionCache) MarkRevoked(string) {}
func (unavailableSessionCache) MarkAllRevokedForUser(string) {}
var _ gatewayv1.EdgeGatewayServer = sessionLookupService{}
var _ edgev1.GatewayServer = sessionLookupService{}
@@ -6,7 +6,7 @@ import (
"testing"
"galaxy/gateway/internal/session"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"connectrpc.com/connect"
"github.com/stretchr/testify/assert"
@@ -17,7 +17,7 @@ import (
func TestExecuteCommandRejectsUnknownSession(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{
@@ -40,7 +40,7 @@ func TestExecuteCommandRejectsUnknownSession(t *testing.T) {
func TestSubscribeEventsRejectsUnknownSession(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{
@@ -63,7 +63,7 @@ func TestSubscribeEventsRejectsUnknownSession(t *testing.T) {
func TestExecuteCommandRejectsRevokedSession(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newRevokedSessionRecord(), nil }},
@@ -82,7 +82,7 @@ func TestExecuteCommandRejectsRevokedSession(t *testing.T) {
func TestSubscribeEventsRejectsRevokedSession(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newRevokedSessionRecord(), nil }},
@@ -101,7 +101,7 @@ func TestSubscribeEventsRejectsRevokedSession(t *testing.T) {
func TestExecuteCommandRejectsSessionCacheUnavailable(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{
@@ -124,7 +124,7 @@ func TestExecuteCommandRejectsSessionCacheUnavailable(t *testing.T) {
func TestSubscribeEventsRejectsSessionCacheUnavailable(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{
@@ -147,12 +147,12 @@ func TestSubscribeEventsRejectsSessionCacheUnavailable(t *testing.T) {
func TestExecuteCommandAttachesResolvedSession(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{
executeCommandFunc: func(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
delegate := &recordingGatewayService{
executeCommandFunc: func(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
record, ok := resolvedSessionFromContext(ctx)
require.True(t, ok)
assert.Equal(t, newActiveSessionRecord(), record)
return &gatewayv1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
return &edgev1.ExecuteCommandResponse{RequestId: req.GetRequestId()}, nil
},
}
@@ -173,8 +173,8 @@ func TestExecuteCommandAttachesResolvedSession(t *testing.T) {
func TestSubscribeEventsAttachesResolvedSession(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{
subscribeEventsFunc: func(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
delegate := &recordingGatewayService{
subscribeEventsFunc: func(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
record, ok := resolvedSessionFromContext(stream.Context())
require.True(t, ok)
assert.Equal(t, newActiveSessionRecord(), record)
@@ -204,8 +204,8 @@ func TestSubscribeEventsAttachesResolvedSession(t *testing.T) {
func TestSubscribeEventsAttachesAuthenticatedStreamBinding(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{
subscribeEventsFunc: func(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
delegate := &recordingGatewayService{
subscribeEventsFunc: func(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
binding, ok := authenticatedStreamBindingFromContext(stream.Context())
require.True(t, ok)
assert.Equal(t, authenticatedStreamBinding{
+7 -7
View File
@@ -5,7 +5,7 @@ import (
"errors"
"galaxy/gateway/authn"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
edgev1 "galaxy/gateway/proto/edge/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
@@ -15,14 +15,14 @@ import (
// signatureVerifyingService applies client-signature verification after
// payload integrity checks and before later auth or routing steps run.
type signatureVerifyingService struct {
gatewayv1.UnimplementedEdgeGatewayServer
edgev1.UnimplementedGatewayServer
delegate gatewayv1.EdgeGatewayServer
delegate edgev1.GatewayServer
}
// ExecuteCommand verifies req client signature before delegating to the
// configured service implementation.
func (s signatureVerifyingService) ExecuteCommand(ctx context.Context, req *gatewayv1.ExecuteCommandRequest) (*gatewayv1.ExecuteCommandResponse, error) {
func (s signatureVerifyingService) ExecuteCommand(ctx context.Context, req *edgev1.ExecuteCommandRequest) (*edgev1.ExecuteCommandResponse, error) {
if err := verifyRequestSignature(ctx); err != nil {
return nil, err
}
@@ -32,7 +32,7 @@ func (s signatureVerifyingService) ExecuteCommand(ctx context.Context, req *gate
// SubscribeEvents verifies req client signature before delegating to the
// configured service implementation.
func (s signatureVerifyingService) SubscribeEvents(req *gatewayv1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[gatewayv1.GatewayEvent]) error {
func (s signatureVerifyingService) SubscribeEvents(req *edgev1.SubscribeEventsRequest, stream grpc.ServerStreamingServer[edgev1.GatewayEvent]) error {
if err := verifyRequestSignature(stream.Context()); err != nil {
return err
}
@@ -42,7 +42,7 @@ func (s signatureVerifyingService) SubscribeEvents(req *gatewayv1.SubscribeEvent
// newSignatureVerifyingService wraps delegate with the client-signature
// verification gate.
func newSignatureVerifyingService(delegate gatewayv1.EdgeGatewayServer) gatewayv1.EdgeGatewayServer {
func newSignatureVerifyingService(delegate edgev1.GatewayServer) edgev1.GatewayServer {
return signatureVerifyingService{delegate: delegate}
}
@@ -77,4 +77,4 @@ func verifyRequestSignature(ctx context.Context) error {
}
}
var _ gatewayv1.EdgeGatewayServer = signatureVerifyingService{}
var _ edgev1.GatewayServer = signatureVerifyingService{}
@@ -14,7 +14,7 @@ import (
func TestExecuteCommandRejectsInvalidSignature(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
@@ -37,7 +37,7 @@ func TestExecuteCommandRejectsInvalidSignature(t *testing.T) {
func TestExecuteCommandRejectsWrongKey(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{
@@ -62,7 +62,7 @@ func TestExecuteCommandRejectsWrongKey(t *testing.T) {
func TestExecuteCommandRejectsInvalidCachedPublicKey(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{
@@ -87,7 +87,7 @@ func TestExecuteCommandRejectsInvalidCachedPublicKey(t *testing.T) {
func TestSubscribeEventsRejectsInvalidSignature(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{lookupFunc: func(context.Context, string) (session.Record, error) { return newActiveSessionRecord(), nil }},
@@ -110,7 +110,7 @@ func TestSubscribeEventsRejectsInvalidSignature(t *testing.T) {
func TestSubscribeEventsRejectsWrongKey(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{
@@ -135,7 +135,7 @@ func TestSubscribeEventsRejectsWrongKey(t *testing.T) {
func TestSubscribeEventsRejectsInvalidCachedPublicKey(t *testing.T) {
t.Parallel()
delegate := &recordingEdgeGatewayService{}
delegate := &recordingGatewayService{}
server, runGateway := newTestGateway(t, ServerDependencies{
Service: delegate,
SessionCache: staticSessionCache{
+16 -16
View File
@@ -13,8 +13,8 @@ import (
"galaxy/gateway/authn"
"galaxy/gateway/internal/downstream"
"galaxy/gateway/internal/session"
gatewayv1 "galaxy/gateway/proto/galaxy/gateway/v1"
"galaxy/gateway/proto/galaxy/gateway/v1/gatewayv1connect"
edgev1 "galaxy/gateway/proto/edge/v1"
"galaxy/gateway/proto/edge/v1/edgev1connect"
gatewayfbs "galaxy/schema/fbs/gateway"
@@ -29,19 +29,19 @@ var (
testFreshnessWindow = 5 * time.Minute
)
func newValidExecuteCommandRequest() *gatewayv1.ExecuteCommandRequest {
func newValidExecuteCommandRequest() *edgev1.ExecuteCommandRequest {
return newValidExecuteCommandRequestWithSessionAndRequestID("device-session-123", "request-123")
}
func newValidExecuteCommandRequestWithSessionAndRequestID(deviceSessionID string, requestID string) *gatewayv1.ExecuteCommandRequest {
func newValidExecuteCommandRequestWithSessionAndRequestID(deviceSessionID string, requestID string) *edgev1.ExecuteCommandRequest {
return newValidExecuteCommandRequestWithTimestamp(deviceSessionID, requestID, testCurrentTime.UnixMilli())
}
func newValidExecuteCommandRequestWithTimestamp(deviceSessionID string, requestID string, timestampMS int64) *gatewayv1.ExecuteCommandRequest {
func newValidExecuteCommandRequestWithTimestamp(deviceSessionID string, requestID string, timestampMS int64) *edgev1.ExecuteCommandRequest {
payloadBytes := []byte("payload")
payloadHash := sha256.Sum256(payloadBytes)
req := &gatewayv1.ExecuteCommandRequest{
req := &edgev1.ExecuteCommandRequest{
ProtocolVersion: supportedProtocolVersion,
DeviceSessionId: deviceSessionID,
MessageType: "fleet.move",
@@ -56,18 +56,18 @@ func newValidExecuteCommandRequestWithTimestamp(deviceSessionID string, requestI
return req
}
func newValidSubscribeEventsRequest() *gatewayv1.SubscribeEventsRequest {
func newValidSubscribeEventsRequest() *edgev1.SubscribeEventsRequest {
return newValidSubscribeEventsRequestWithSessionAndRequestID("device-session-123", "request-123")
}
func newValidSubscribeEventsRequestWithSessionAndRequestID(deviceSessionID string, requestID string) *gatewayv1.SubscribeEventsRequest {
func newValidSubscribeEventsRequestWithSessionAndRequestID(deviceSessionID string, requestID string) *edgev1.SubscribeEventsRequest {
return newValidSubscribeEventsRequestWithTimestamp(deviceSessionID, requestID, testCurrentTime.UnixMilli())
}
func newValidSubscribeEventsRequestWithTimestamp(deviceSessionID string, requestID string, timestampMS int64) *gatewayv1.SubscribeEventsRequest {
func newValidSubscribeEventsRequestWithTimestamp(deviceSessionID string, requestID string, timestampMS int64) *edgev1.SubscribeEventsRequest {
payloadHash := sha256.Sum256(nil)
req := &gatewayv1.SubscribeEventsRequest{
req := &edgev1.SubscribeEventsRequest{
ProtocolVersion: supportedProtocolVersion,
DeviceSessionId: deviceSessionID,
MessageType: "gateway.subscribe",
@@ -172,7 +172,7 @@ func (c fixedClock) Now() time.Time {
func recvBootstrapEvent(t interface {
require.TestingT
Helper()
}, stream *connect.ServerStreamForClient[gatewayv1.GatewayEvent]) *gatewayv1.GatewayEvent {
}, stream *connect.ServerStreamForClient[edgev1.GatewayEvent]) *edgev1.GatewayEvent {
t.Helper()
if !stream.Receive() {
@@ -189,7 +189,7 @@ func recvBootstrapEvent(t interface {
func subscribeEventsError(t interface {
require.TestingT
Helper()
}, ctx context.Context, client gatewayv1connect.EdgeGatewayClient, req *gatewayv1.SubscribeEventsRequest) error {
}, ctx context.Context, client edgev1connect.GatewayClient, req *edgev1.SubscribeEventsRequest) error {
t.Helper()
stream, err := client.SubscribeEvents(ctx, connect.NewRequest(req))
@@ -208,7 +208,7 @@ func subscribeEventsError(t interface {
func assertServerTimeBootstrapEvent(t interface {
require.TestingT
Helper()
}, event *gatewayv1.GatewayEvent, publicKey ed25519.PublicKey, wantRequestID string, wantTraceID string, wantTimestampMS int64) {
}, event *edgev1.GatewayEvent, publicKey ed25519.PublicKey, wantRequestID string, wantTraceID string, wantTimestampMS int64) {
t.Helper()
require.NotNil(t, event)
@@ -244,7 +244,7 @@ func (s staticReplayStore) Reserve(ctx context.Context, deviceSessionID string,
}
type executeCommandAdapterRouter struct {
service gatewayv1.EdgeGatewayServer
service edgev1.GatewayServer
}
func (r executeCommandAdapterRouter) Route(string) (downstream.Client, error) {
@@ -252,11 +252,11 @@ func (r executeCommandAdapterRouter) Route(string) (downstream.Client, error) {
}
type executeCommandAdapterClient struct {
service gatewayv1.EdgeGatewayServer
service edgev1.GatewayServer
}
func (c executeCommandAdapterClient) ExecuteCommand(ctx context.Context, command downstream.AuthenticatedCommand) (downstream.UnaryResult, error) {
response, err := c.service.ExecuteCommand(ctx, &gatewayv1.ExecuteCommandRequest{
response, err := c.service.ExecuteCommand(ctx, &edgev1.ExecuteCommandRequest{
ProtocolVersion: command.ProtocolVersion,
DeviceSessionId: command.DeviceSessionID,
MessageType: command.MessageType,
+8
View File
@@ -6,6 +6,14 @@ info:
This specification documents the implemented `galaxy/gateway` v1 public
REST surface.
At the edge this surface is served same-origin under one host: the edge
Caddy routes `/api/*` and `/healthz` to the public REST listener, so those
paths are reached at `https://<host>/healthz` and
`https://<host>/api/v1/public/auth/*`. The authenticated Connect/gRPC-Web
surface lives behind the same host at `/rpc/*` and is not part of this
REST contract. `/readyz` is an in-process readiness probe served on the
listener itself and is not exposed through the edge.
Implemented endpoints:
- `GET /healthz`
- `GET /readyz`
@@ -2,9 +2,9 @@
// versions:
// protoc-gen-go v1.36.11
// protoc (unknown)
// source: galaxy/gateway/v1/edge_gateway.proto
// source: edge/v1/edge_gateway.proto
package gatewayv1
package edgev1
import (
_ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate"
@@ -42,7 +42,7 @@ type ExecuteCommandRequest struct {
func (x *ExecuteCommandRequest) Reset() {
*x = ExecuteCommandRequest{}
mi := &file_galaxy_gateway_v1_edge_gateway_proto_msgTypes[0]
mi := &file_edge_v1_edge_gateway_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -54,7 +54,7 @@ func (x *ExecuteCommandRequest) String() string {
func (*ExecuteCommandRequest) ProtoMessage() {}
func (x *ExecuteCommandRequest) ProtoReflect() protoreflect.Message {
mi := &file_galaxy_gateway_v1_edge_gateway_proto_msgTypes[0]
mi := &file_edge_v1_edge_gateway_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -67,7 +67,7 @@ func (x *ExecuteCommandRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ExecuteCommandRequest.ProtoReflect.Descriptor instead.
func (*ExecuteCommandRequest) Descriptor() ([]byte, []int) {
return file_galaxy_gateway_v1_edge_gateway_proto_rawDescGZIP(), []int{0}
return file_edge_v1_edge_gateway_proto_rawDescGZIP(), []int{0}
}
func (x *ExecuteCommandRequest) GetProtocolVersion() string {
@@ -148,7 +148,7 @@ type ExecuteCommandResponse struct {
func (x *ExecuteCommandResponse) Reset() {
*x = ExecuteCommandResponse{}
mi := &file_galaxy_gateway_v1_edge_gateway_proto_msgTypes[1]
mi := &file_edge_v1_edge_gateway_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -160,7 +160,7 @@ func (x *ExecuteCommandResponse) String() string {
func (*ExecuteCommandResponse) ProtoMessage() {}
func (x *ExecuteCommandResponse) ProtoReflect() protoreflect.Message {
mi := &file_galaxy_gateway_v1_edge_gateway_proto_msgTypes[1]
mi := &file_edge_v1_edge_gateway_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -173,7 +173,7 @@ func (x *ExecuteCommandResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use ExecuteCommandResponse.ProtoReflect.Descriptor instead.
func (*ExecuteCommandResponse) Descriptor() ([]byte, []int) {
return file_galaxy_gateway_v1_edge_gateway_proto_rawDescGZIP(), []int{1}
return file_edge_v1_edge_gateway_proto_rawDescGZIP(), []int{1}
}
func (x *ExecuteCommandResponse) GetProtocolVersion() string {
@@ -246,7 +246,7 @@ type SubscribeEventsRequest struct {
func (x *SubscribeEventsRequest) Reset() {
*x = SubscribeEventsRequest{}
mi := &file_galaxy_gateway_v1_edge_gateway_proto_msgTypes[2]
mi := &file_edge_v1_edge_gateway_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -258,7 +258,7 @@ func (x *SubscribeEventsRequest) String() string {
func (*SubscribeEventsRequest) ProtoMessage() {}
func (x *SubscribeEventsRequest) ProtoReflect() protoreflect.Message {
mi := &file_galaxy_gateway_v1_edge_gateway_proto_msgTypes[2]
mi := &file_edge_v1_edge_gateway_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -271,7 +271,7 @@ func (x *SubscribeEventsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use SubscribeEventsRequest.ProtoReflect.Descriptor instead.
func (*SubscribeEventsRequest) Descriptor() ([]byte, []int) {
return file_galaxy_gateway_v1_edge_gateway_proto_rawDescGZIP(), []int{2}
return file_edge_v1_edge_gateway_proto_rawDescGZIP(), []int{2}
}
func (x *SubscribeEventsRequest) GetProtocolVersion() string {
@@ -353,7 +353,7 @@ type GatewayEvent struct {
func (x *GatewayEvent) Reset() {
*x = GatewayEvent{}
mi := &file_galaxy_gateway_v1_edge_gateway_proto_msgTypes[3]
mi := &file_edge_v1_edge_gateway_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -365,7 +365,7 @@ func (x *GatewayEvent) String() string {
func (*GatewayEvent) ProtoMessage() {}
func (x *GatewayEvent) ProtoReflect() protoreflect.Message {
mi := &file_galaxy_gateway_v1_edge_gateway_proto_msgTypes[3]
mi := &file_edge_v1_edge_gateway_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -378,7 +378,7 @@ func (x *GatewayEvent) ProtoReflect() protoreflect.Message {
// Deprecated: Use GatewayEvent.ProtoReflect.Descriptor instead.
func (*GatewayEvent) Descriptor() ([]byte, []int) {
return file_galaxy_gateway_v1_edge_gateway_proto_rawDescGZIP(), []int{3}
return file_edge_v1_edge_gateway_proto_rawDescGZIP(), []int{3}
}
func (x *GatewayEvent) GetEventType() string {
@@ -437,11 +437,11 @@ func (x *GatewayEvent) GetTraceId() string {
return ""
}
var File_galaxy_gateway_v1_edge_gateway_proto protoreflect.FileDescriptor
var File_edge_v1_edge_gateway_proto protoreflect.FileDescriptor
const file_galaxy_gateway_v1_edge_gateway_proto_rawDesc = "" +
const file_edge_v1_edge_gateway_proto_rawDesc = "" +
"\n" +
"$galaxy/gateway/v1/edge_gateway.proto\x12\x11galaxy.gateway.v1\x1a\x1bbuf/validate/validate.proto\"\x9c\x03\n" +
"\x1aedge/v1/edge_gateway.proto\x12\aedge.v1\x1a\x1bbuf/validate/validate.proto\"\x9c\x03\n" +
"\x15ExecuteCommandRequest\x122\n" +
"\x10protocol_version\x18\x01 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\x0fprotocolVersion\x123\n" +
"\x11device_session_id\x18\x02 \x01(\tB\a\xbaH\x04r\x02\x10\x01R\x0fdeviceSessionId\x12*\n" +
@@ -484,35 +484,35 @@ const file_galaxy_gateway_v1_edge_gateway_proto_rawDesc = "" +
"\tsignature\x18\x06 \x01(\fR\tsignature\x12\x1d\n" +
"\n" +
"request_id\x18\a \x01(\tR\trequestId\x12\x19\n" +
"\btrace_id\x18\b \x01(\tR\atraceId2\xd5\x01\n" +
"\vEdgeGateway\x12e\n" +
"\x0eExecuteCommand\x12(.galaxy.gateway.v1.ExecuteCommandRequest\x1a).galaxy.gateway.v1.ExecuteCommandResponse\x12_\n" +
"\x0fSubscribeEvents\x12).galaxy.gateway.v1.SubscribeEventsRequest\x1a\x1f.galaxy.gateway.v1.GatewayEvent0\x01B2Z0galaxy/gateway/proto/galaxy/gateway/v1;gatewayv1b\x06proto3"
"\btrace_id\x18\b \x01(\tR\atraceId2\xa9\x01\n" +
"\aGateway\x12Q\n" +
"\x0eExecuteCommand\x12\x1e.edge.v1.ExecuteCommandRequest\x1a\x1f.edge.v1.ExecuteCommandResponse\x12K\n" +
"\x0fSubscribeEvents\x12\x1f.edge.v1.SubscribeEventsRequest\x1a\x15.edge.v1.GatewayEvent0\x01B%Z#galaxy/gateway/proto/edge/v1;edgev1b\x06proto3"
var (
file_galaxy_gateway_v1_edge_gateway_proto_rawDescOnce sync.Once
file_galaxy_gateway_v1_edge_gateway_proto_rawDescData []byte
file_edge_v1_edge_gateway_proto_rawDescOnce sync.Once
file_edge_v1_edge_gateway_proto_rawDescData []byte
)
func file_galaxy_gateway_v1_edge_gateway_proto_rawDescGZIP() []byte {
file_galaxy_gateway_v1_edge_gateway_proto_rawDescOnce.Do(func() {
file_galaxy_gateway_v1_edge_gateway_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_galaxy_gateway_v1_edge_gateway_proto_rawDesc), len(file_galaxy_gateway_v1_edge_gateway_proto_rawDesc)))
func file_edge_v1_edge_gateway_proto_rawDescGZIP() []byte {
file_edge_v1_edge_gateway_proto_rawDescOnce.Do(func() {
file_edge_v1_edge_gateway_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_edge_v1_edge_gateway_proto_rawDesc), len(file_edge_v1_edge_gateway_proto_rawDesc)))
})
return file_galaxy_gateway_v1_edge_gateway_proto_rawDescData
return file_edge_v1_edge_gateway_proto_rawDescData
}
var file_galaxy_gateway_v1_edge_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_galaxy_gateway_v1_edge_gateway_proto_goTypes = []any{
(*ExecuteCommandRequest)(nil), // 0: galaxy.gateway.v1.ExecuteCommandRequest
(*ExecuteCommandResponse)(nil), // 1: galaxy.gateway.v1.ExecuteCommandResponse
(*SubscribeEventsRequest)(nil), // 2: galaxy.gateway.v1.SubscribeEventsRequest
(*GatewayEvent)(nil), // 3: galaxy.gateway.v1.GatewayEvent
var file_edge_v1_edge_gateway_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_edge_v1_edge_gateway_proto_goTypes = []any{
(*ExecuteCommandRequest)(nil), // 0: edge.v1.ExecuteCommandRequest
(*ExecuteCommandResponse)(nil), // 1: edge.v1.ExecuteCommandResponse
(*SubscribeEventsRequest)(nil), // 2: edge.v1.SubscribeEventsRequest
(*GatewayEvent)(nil), // 3: edge.v1.GatewayEvent
}
var file_galaxy_gateway_v1_edge_gateway_proto_depIdxs = []int32{
0, // 0: galaxy.gateway.v1.EdgeGateway.ExecuteCommand:input_type -> galaxy.gateway.v1.ExecuteCommandRequest
2, // 1: galaxy.gateway.v1.EdgeGateway.SubscribeEvents:input_type -> galaxy.gateway.v1.SubscribeEventsRequest
1, // 2: galaxy.gateway.v1.EdgeGateway.ExecuteCommand:output_type -> galaxy.gateway.v1.ExecuteCommandResponse
3, // 3: galaxy.gateway.v1.EdgeGateway.SubscribeEvents:output_type -> galaxy.gateway.v1.GatewayEvent
var file_edge_v1_edge_gateway_proto_depIdxs = []int32{
0, // 0: edge.v1.Gateway.ExecuteCommand:input_type -> edge.v1.ExecuteCommandRequest
2, // 1: edge.v1.Gateway.SubscribeEvents:input_type -> edge.v1.SubscribeEventsRequest
1, // 2: edge.v1.Gateway.ExecuteCommand:output_type -> edge.v1.ExecuteCommandResponse
3, // 3: edge.v1.Gateway.SubscribeEvents:output_type -> edge.v1.GatewayEvent
2, // [2:4] is the sub-list for method output_type
0, // [0:2] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
@@ -520,26 +520,26 @@ var file_galaxy_gateway_v1_edge_gateway_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for field type_name
}
func init() { file_galaxy_gateway_v1_edge_gateway_proto_init() }
func file_galaxy_gateway_v1_edge_gateway_proto_init() {
if File_galaxy_gateway_v1_edge_gateway_proto != nil {
func init() { file_edge_v1_edge_gateway_proto_init() }
func file_edge_v1_edge_gateway_proto_init() {
if File_edge_v1_edge_gateway_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_galaxy_gateway_v1_edge_gateway_proto_rawDesc), len(file_galaxy_gateway_v1_edge_gateway_proto_rawDesc)),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_edge_v1_edge_gateway_proto_rawDesc), len(file_edge_v1_edge_gateway_proto_rawDesc)),
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_galaxy_gateway_v1_edge_gateway_proto_goTypes,
DependencyIndexes: file_galaxy_gateway_v1_edge_gateway_proto_depIdxs,
MessageInfos: file_galaxy_gateway_v1_edge_gateway_proto_msgTypes,
GoTypes: file_edge_v1_edge_gateway_proto_goTypes,
DependencyIndexes: file_edge_v1_edge_gateway_proto_depIdxs,
MessageInfos: file_edge_v1_edge_gateway_proto_msgTypes,
}.Build()
File_galaxy_gateway_v1_edge_gateway_proto = out.File
file_galaxy_gateway_v1_edge_gateway_proto_goTypes = nil
file_galaxy_gateway_v1_edge_gateway_proto_depIdxs = nil
File_edge_v1_edge_gateway_proto = out.File
file_edge_v1_edge_gateway_proto_goTypes = nil
file_edge_v1_edge_gateway_proto_depIdxs = nil
}
@@ -1,12 +1,12 @@
syntax = "proto3";
package galaxy.gateway.v1;
package edge.v1;
option go_package = "galaxy/gateway/proto/galaxy/gateway/v1;gatewayv1";
option go_package = "galaxy/gateway/proto/edge/v1;edgev1";
import "buf/validate/validate.proto";
service EdgeGateway {
service Gateway {
rpc ExecuteCommand(ExecuteCommandRequest) returns (ExecuteCommandResponse);
rpc SubscribeEvents(SubscribeEventsRequest) returns (stream GatewayEvent);
}
@@ -2,9 +2,9 @@
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc (unknown)
// source: galaxy/gateway/v1/edge_gateway.proto
// source: edge/v1/edge_gateway.proto
package gatewayv1
package edgev1
import (
context "context"
@@ -19,39 +19,39 @@ import (
const _ = grpc.SupportPackageIsVersion9
const (
EdgeGateway_ExecuteCommand_FullMethodName = "/galaxy.gateway.v1.EdgeGateway/ExecuteCommand"
EdgeGateway_SubscribeEvents_FullMethodName = "/galaxy.gateway.v1.EdgeGateway/SubscribeEvents"
Gateway_ExecuteCommand_FullMethodName = "/edge.v1.Gateway/ExecuteCommand"
Gateway_SubscribeEvents_FullMethodName = "/edge.v1.Gateway/SubscribeEvents"
)
// EdgeGatewayClient is the client API for EdgeGateway service.
// GatewayClient is the client API for Gateway service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type EdgeGatewayClient interface {
type GatewayClient interface {
ExecuteCommand(ctx context.Context, in *ExecuteCommandRequest, opts ...grpc.CallOption) (*ExecuteCommandResponse, error)
SubscribeEvents(ctx context.Context, in *SubscribeEventsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GatewayEvent], error)
}
type edgeGatewayClient struct {
type gatewayClient struct {
cc grpc.ClientConnInterface
}
func NewEdgeGatewayClient(cc grpc.ClientConnInterface) EdgeGatewayClient {
return &edgeGatewayClient{cc}
func NewGatewayClient(cc grpc.ClientConnInterface) GatewayClient {
return &gatewayClient{cc}
}
func (c *edgeGatewayClient) ExecuteCommand(ctx context.Context, in *ExecuteCommandRequest, opts ...grpc.CallOption) (*ExecuteCommandResponse, error) {
func (c *gatewayClient) ExecuteCommand(ctx context.Context, in *ExecuteCommandRequest, opts ...grpc.CallOption) (*ExecuteCommandResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ExecuteCommandResponse)
err := c.cc.Invoke(ctx, EdgeGateway_ExecuteCommand_FullMethodName, in, out, cOpts...)
err := c.cc.Invoke(ctx, Gateway_ExecuteCommand_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *edgeGatewayClient) SubscribeEvents(ctx context.Context, in *SubscribeEventsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GatewayEvent], error) {
func (c *gatewayClient) SubscribeEvents(ctx context.Context, in *SubscribeEventsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GatewayEvent], error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
stream, err := c.cc.NewStream(ctx, &EdgeGateway_ServiceDesc.Streams[0], EdgeGateway_SubscribeEvents_FullMethodName, cOpts...)
stream, err := c.cc.NewStream(ctx, &Gateway_ServiceDesc.Streams[0], Gateway_SubscribeEvents_FullMethodName, cOpts...)
if err != nil {
return nil, err
}
@@ -66,98 +66,98 @@ func (c *edgeGatewayClient) SubscribeEvents(ctx context.Context, in *SubscribeEv
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type EdgeGateway_SubscribeEventsClient = grpc.ServerStreamingClient[GatewayEvent]
type Gateway_SubscribeEventsClient = grpc.ServerStreamingClient[GatewayEvent]
// EdgeGatewayServer is the server API for EdgeGateway service.
// All implementations must embed UnimplementedEdgeGatewayServer
// GatewayServer is the server API for Gateway service.
// All implementations must embed UnimplementedGatewayServer
// for forward compatibility.
type EdgeGatewayServer interface {
type GatewayServer interface {
ExecuteCommand(context.Context, *ExecuteCommandRequest) (*ExecuteCommandResponse, error)
SubscribeEvents(*SubscribeEventsRequest, grpc.ServerStreamingServer[GatewayEvent]) error
mustEmbedUnimplementedEdgeGatewayServer()
mustEmbedUnimplementedGatewayServer()
}
// UnimplementedEdgeGatewayServer must be embedded to have
// UnimplementedGatewayServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedEdgeGatewayServer struct{}
type UnimplementedGatewayServer struct{}
func (UnimplementedEdgeGatewayServer) ExecuteCommand(context.Context, *ExecuteCommandRequest) (*ExecuteCommandResponse, error) {
func (UnimplementedGatewayServer) ExecuteCommand(context.Context, *ExecuteCommandRequest) (*ExecuteCommandResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ExecuteCommand not implemented")
}
func (UnimplementedEdgeGatewayServer) SubscribeEvents(*SubscribeEventsRequest, grpc.ServerStreamingServer[GatewayEvent]) error {
func (UnimplementedGatewayServer) SubscribeEvents(*SubscribeEventsRequest, grpc.ServerStreamingServer[GatewayEvent]) error {
return status.Error(codes.Unimplemented, "method SubscribeEvents not implemented")
}
func (UnimplementedEdgeGatewayServer) mustEmbedUnimplementedEdgeGatewayServer() {}
func (UnimplementedEdgeGatewayServer) testEmbeddedByValue() {}
func (UnimplementedGatewayServer) mustEmbedUnimplementedGatewayServer() {}
func (UnimplementedGatewayServer) testEmbeddedByValue() {}
// UnsafeEdgeGatewayServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to EdgeGatewayServer will
// UnsafeGatewayServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to GatewayServer will
// result in compilation errors.
type UnsafeEdgeGatewayServer interface {
mustEmbedUnimplementedEdgeGatewayServer()
type UnsafeGatewayServer interface {
mustEmbedUnimplementedGatewayServer()
}
func RegisterEdgeGatewayServer(s grpc.ServiceRegistrar, srv EdgeGatewayServer) {
// If the following call panics, it indicates UnimplementedEdgeGatewayServer was
func RegisterGatewayServer(s grpc.ServiceRegistrar, srv GatewayServer) {
// If the following call panics, it indicates UnimplementedGatewayServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&EdgeGateway_ServiceDesc, srv)
s.RegisterService(&Gateway_ServiceDesc, srv)
}
func _EdgeGateway_ExecuteCommand_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
func _Gateway_ExecuteCommand_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ExecuteCommandRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(EdgeGatewayServer).ExecuteCommand(ctx, in)
return srv.(GatewayServer).ExecuteCommand(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: EdgeGateway_ExecuteCommand_FullMethodName,
FullMethod: Gateway_ExecuteCommand_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EdgeGatewayServer).ExecuteCommand(ctx, req.(*ExecuteCommandRequest))
return srv.(GatewayServer).ExecuteCommand(ctx, req.(*ExecuteCommandRequest))
}
return interceptor(ctx, in, info, handler)
}
func _EdgeGateway_SubscribeEvents_Handler(srv interface{}, stream grpc.ServerStream) error {
func _Gateway_SubscribeEvents_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(SubscribeEventsRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(EdgeGatewayServer).SubscribeEvents(m, &grpc.GenericServerStream[SubscribeEventsRequest, GatewayEvent]{ServerStream: stream})
return srv.(GatewayServer).SubscribeEvents(m, &grpc.GenericServerStream[SubscribeEventsRequest, GatewayEvent]{ServerStream: stream})
}
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
type EdgeGateway_SubscribeEventsServer = grpc.ServerStreamingServer[GatewayEvent]
type Gateway_SubscribeEventsServer = grpc.ServerStreamingServer[GatewayEvent]
// EdgeGateway_ServiceDesc is the grpc.ServiceDesc for EdgeGateway service.
// Gateway_ServiceDesc is the grpc.ServiceDesc for Gateway service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var EdgeGateway_ServiceDesc = grpc.ServiceDesc{
ServiceName: "galaxy.gateway.v1.EdgeGateway",
HandlerType: (*EdgeGatewayServer)(nil),
var Gateway_ServiceDesc = grpc.ServiceDesc{
ServiceName: "edge.v1.Gateway",
HandlerType: (*GatewayServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ExecuteCommand",
Handler: _EdgeGateway_ExecuteCommand_Handler,
Handler: _Gateway_ExecuteCommand_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "SubscribeEvents",
Handler: _EdgeGateway_SubscribeEvents_Handler,
Handler: _Gateway_SubscribeEvents_Handler,
ServerStreams: true,
},
},
Metadata: "galaxy/gateway/v1/edge_gateway.proto",
Metadata: "edge/v1/edge_gateway.proto",
}
@@ -0,0 +1,136 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: edge/v1/edge_gateway.proto
package edgev1connect
import (
connect "connectrpc.com/connect"
context "context"
errors "errors"
v1 "galaxy/gateway/proto/edge/v1"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect.IsAtLeastVersion1_13_0
const (
// GatewayName is the fully-qualified name of the Gateway service.
GatewayName = "edge.v1.Gateway"
)
// These constants are the fully-qualified names of the RPCs defined in this package. They're
// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route.
//
// Note that these are different from the fully-qualified method names used by
// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to
// reflection-formatted method names, remove the leading slash and convert the remaining slash to a
// period.
const (
// GatewayExecuteCommandProcedure is the fully-qualified name of the Gateway's ExecuteCommand RPC.
GatewayExecuteCommandProcedure = "/edge.v1.Gateway/ExecuteCommand"
// GatewaySubscribeEventsProcedure is the fully-qualified name of the Gateway's SubscribeEvents RPC.
GatewaySubscribeEventsProcedure = "/edge.v1.Gateway/SubscribeEvents"
)
// GatewayClient is a client for the edge.v1.Gateway service.
type GatewayClient interface {
ExecuteCommand(context.Context, *connect.Request[v1.ExecuteCommandRequest]) (*connect.Response[v1.ExecuteCommandResponse], error)
SubscribeEvents(context.Context, *connect.Request[v1.SubscribeEventsRequest]) (*connect.ServerStreamForClient[v1.GatewayEvent], error)
}
// NewGatewayClient constructs a client for the edge.v1.Gateway service. By default, it uses the
// Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends
// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or
// connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewGatewayClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) GatewayClient {
baseURL = strings.TrimRight(baseURL, "/")
gatewayMethods := v1.File_edge_v1_edge_gateway_proto.Services().ByName("Gateway").Methods()
return &gatewayClient{
executeCommand: connect.NewClient[v1.ExecuteCommandRequest, v1.ExecuteCommandResponse](
httpClient,
baseURL+GatewayExecuteCommandProcedure,
connect.WithSchema(gatewayMethods.ByName("ExecuteCommand")),
connect.WithClientOptions(opts...),
),
subscribeEvents: connect.NewClient[v1.SubscribeEventsRequest, v1.GatewayEvent](
httpClient,
baseURL+GatewaySubscribeEventsProcedure,
connect.WithSchema(gatewayMethods.ByName("SubscribeEvents")),
connect.WithClientOptions(opts...),
),
}
}
// gatewayClient implements GatewayClient.
type gatewayClient struct {
executeCommand *connect.Client[v1.ExecuteCommandRequest, v1.ExecuteCommandResponse]
subscribeEvents *connect.Client[v1.SubscribeEventsRequest, v1.GatewayEvent]
}
// ExecuteCommand calls edge.v1.Gateway.ExecuteCommand.
func (c *gatewayClient) ExecuteCommand(ctx context.Context, req *connect.Request[v1.ExecuteCommandRequest]) (*connect.Response[v1.ExecuteCommandResponse], error) {
return c.executeCommand.CallUnary(ctx, req)
}
// SubscribeEvents calls edge.v1.Gateway.SubscribeEvents.
func (c *gatewayClient) SubscribeEvents(ctx context.Context, req *connect.Request[v1.SubscribeEventsRequest]) (*connect.ServerStreamForClient[v1.GatewayEvent], error) {
return c.subscribeEvents.CallServerStream(ctx, req)
}
// GatewayHandler is an implementation of the edge.v1.Gateway service.
type GatewayHandler interface {
ExecuteCommand(context.Context, *connect.Request[v1.ExecuteCommandRequest]) (*connect.Response[v1.ExecuteCommandResponse], error)
SubscribeEvents(context.Context, *connect.Request[v1.SubscribeEventsRequest], *connect.ServerStream[v1.GatewayEvent]) error
}
// NewGatewayHandler builds an HTTP handler from the service implementation. It returns the path on
// which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewGatewayHandler(svc GatewayHandler, opts ...connect.HandlerOption) (string, http.Handler) {
gatewayMethods := v1.File_edge_v1_edge_gateway_proto.Services().ByName("Gateway").Methods()
gatewayExecuteCommandHandler := connect.NewUnaryHandler(
GatewayExecuteCommandProcedure,
svc.ExecuteCommand,
connect.WithSchema(gatewayMethods.ByName("ExecuteCommand")),
connect.WithHandlerOptions(opts...),
)
gatewaySubscribeEventsHandler := connect.NewServerStreamHandler(
GatewaySubscribeEventsProcedure,
svc.SubscribeEvents,
connect.WithSchema(gatewayMethods.ByName("SubscribeEvents")),
connect.WithHandlerOptions(opts...),
)
return "/edge.v1.Gateway/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case GatewayExecuteCommandProcedure:
gatewayExecuteCommandHandler.ServeHTTP(w, r)
case GatewaySubscribeEventsProcedure:
gatewaySubscribeEventsHandler.ServeHTTP(w, r)
default:
http.NotFound(w, r)
}
})
}
// UnimplementedGatewayHandler returns CodeUnimplemented from all methods.
type UnimplementedGatewayHandler struct{}
func (UnimplementedGatewayHandler) ExecuteCommand(context.Context, *connect.Request[v1.ExecuteCommandRequest]) (*connect.Response[v1.ExecuteCommandResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("edge.v1.Gateway.ExecuteCommand is not implemented"))
}
func (UnimplementedGatewayHandler) SubscribeEvents(context.Context, *connect.Request[v1.SubscribeEventsRequest], *connect.ServerStream[v1.GatewayEvent]) error {
return connect.NewError(connect.CodeUnimplemented, errors.New("edge.v1.Gateway.SubscribeEvents is not implemented"))
}
@@ -1,138 +0,0 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: galaxy/gateway/v1/edge_gateway.proto
package gatewayv1connect
import (
connect "connectrpc.com/connect"
context "context"
errors "errors"
v1 "galaxy/gateway/proto/galaxy/gateway/v1"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect.IsAtLeastVersion1_13_0
const (
// EdgeGatewayName is the fully-qualified name of the EdgeGateway service.
EdgeGatewayName = "galaxy.gateway.v1.EdgeGateway"
)
// These constants are the fully-qualified names of the RPCs defined in this package. They're
// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route.
//
// Note that these are different from the fully-qualified method names used by
// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to
// reflection-formatted method names, remove the leading slash and convert the remaining slash to a
// period.
const (
// EdgeGatewayExecuteCommandProcedure is the fully-qualified name of the EdgeGateway's
// ExecuteCommand RPC.
EdgeGatewayExecuteCommandProcedure = "/galaxy.gateway.v1.EdgeGateway/ExecuteCommand"
// EdgeGatewaySubscribeEventsProcedure is the fully-qualified name of the EdgeGateway's
// SubscribeEvents RPC.
EdgeGatewaySubscribeEventsProcedure = "/galaxy.gateway.v1.EdgeGateway/SubscribeEvents"
)
// EdgeGatewayClient is a client for the galaxy.gateway.v1.EdgeGateway service.
type EdgeGatewayClient interface {
ExecuteCommand(context.Context, *connect.Request[v1.ExecuteCommandRequest]) (*connect.Response[v1.ExecuteCommandResponse], error)
SubscribeEvents(context.Context, *connect.Request[v1.SubscribeEventsRequest]) (*connect.ServerStreamForClient[v1.GatewayEvent], error)
}
// NewEdgeGatewayClient constructs a client for the galaxy.gateway.v1.EdgeGateway service. By
// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses,
// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the
// connect.WithGRPC() or connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewEdgeGatewayClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) EdgeGatewayClient {
baseURL = strings.TrimRight(baseURL, "/")
edgeGatewayMethods := v1.File_galaxy_gateway_v1_edge_gateway_proto.Services().ByName("EdgeGateway").Methods()
return &edgeGatewayClient{
executeCommand: connect.NewClient[v1.ExecuteCommandRequest, v1.ExecuteCommandResponse](
httpClient,
baseURL+EdgeGatewayExecuteCommandProcedure,
connect.WithSchema(edgeGatewayMethods.ByName("ExecuteCommand")),
connect.WithClientOptions(opts...),
),
subscribeEvents: connect.NewClient[v1.SubscribeEventsRequest, v1.GatewayEvent](
httpClient,
baseURL+EdgeGatewaySubscribeEventsProcedure,
connect.WithSchema(edgeGatewayMethods.ByName("SubscribeEvents")),
connect.WithClientOptions(opts...),
),
}
}
// edgeGatewayClient implements EdgeGatewayClient.
type edgeGatewayClient struct {
executeCommand *connect.Client[v1.ExecuteCommandRequest, v1.ExecuteCommandResponse]
subscribeEvents *connect.Client[v1.SubscribeEventsRequest, v1.GatewayEvent]
}
// ExecuteCommand calls galaxy.gateway.v1.EdgeGateway.ExecuteCommand.
func (c *edgeGatewayClient) ExecuteCommand(ctx context.Context, req *connect.Request[v1.ExecuteCommandRequest]) (*connect.Response[v1.ExecuteCommandResponse], error) {
return c.executeCommand.CallUnary(ctx, req)
}
// SubscribeEvents calls galaxy.gateway.v1.EdgeGateway.SubscribeEvents.
func (c *edgeGatewayClient) SubscribeEvents(ctx context.Context, req *connect.Request[v1.SubscribeEventsRequest]) (*connect.ServerStreamForClient[v1.GatewayEvent], error) {
return c.subscribeEvents.CallServerStream(ctx, req)
}
// EdgeGatewayHandler is an implementation of the galaxy.gateway.v1.EdgeGateway service.
type EdgeGatewayHandler interface {
ExecuteCommand(context.Context, *connect.Request[v1.ExecuteCommandRequest]) (*connect.Response[v1.ExecuteCommandResponse], error)
SubscribeEvents(context.Context, *connect.Request[v1.SubscribeEventsRequest], *connect.ServerStream[v1.GatewayEvent]) error
}
// NewEdgeGatewayHandler builds an HTTP handler from the service implementation. It returns the path
// on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewEdgeGatewayHandler(svc EdgeGatewayHandler, opts ...connect.HandlerOption) (string, http.Handler) {
edgeGatewayMethods := v1.File_galaxy_gateway_v1_edge_gateway_proto.Services().ByName("EdgeGateway").Methods()
edgeGatewayExecuteCommandHandler := connect.NewUnaryHandler(
EdgeGatewayExecuteCommandProcedure,
svc.ExecuteCommand,
connect.WithSchema(edgeGatewayMethods.ByName("ExecuteCommand")),
connect.WithHandlerOptions(opts...),
)
edgeGatewaySubscribeEventsHandler := connect.NewServerStreamHandler(
EdgeGatewaySubscribeEventsProcedure,
svc.SubscribeEvents,
connect.WithSchema(edgeGatewayMethods.ByName("SubscribeEvents")),
connect.WithHandlerOptions(opts...),
)
return "/galaxy.gateway.v1.EdgeGateway/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case EdgeGatewayExecuteCommandProcedure:
edgeGatewayExecuteCommandHandler.ServeHTTP(w, r)
case EdgeGatewaySubscribeEventsProcedure:
edgeGatewaySubscribeEventsHandler.ServeHTTP(w, r)
default:
http.NotFound(w, r)
}
})
}
// UnimplementedEdgeGatewayHandler returns CodeUnimplemented from all methods.
type UnimplementedEdgeGatewayHandler struct{}
func (UnimplementedEdgeGatewayHandler) ExecuteCommand(context.Context, *connect.Request[v1.ExecuteCommandRequest]) (*connect.Response[v1.ExecuteCommandResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("galaxy.gateway.v1.EdgeGateway.ExecuteCommand is not implemented"))
}
func (UnimplementedEdgeGatewayHandler) SubscribeEvents(context.Context, *connect.Request[v1.SubscribeEventsRequest], *connect.ServerStream[v1.GatewayEvent]) error {
return connect.NewError(connect.CodeUnimplemented, errors.New("galaxy.gateway.v1.EdgeGateway.SubscribeEvents is not implemented"))
}