syntax = "proto3"; package galaxy.backend.push.v1; option go_package = "galaxy/backend/proto/push/v1;pushv1"; // Push is the unidirectional control channel from backend to gateway. // // Gateway opens SubscribePush once at startup and keeps the stream open. // Backend pushes two classes of events: ClientEvent (opaque payload that // gateway signs and forwards to active client subscriptions) and // SessionInvalidation (instructs gateway to close subscriptions and // reject in-flight requests for the affected sessions). // // See backend/README.md §7 for the runtime contract. service Push { rpc SubscribePush(GatewaySubscribeRequest) returns (stream PushEvent); } // GatewaySubscribeRequest opens a push subscription. gateway_client_id // uniquely identifies the gateway instance; backend tracks one // subscription per id and replaces an existing one on reconnect. cursor // is the last consumed PushEvent.cursor; backend resumes from the next // event when the cursor is still inside the freshness-window ring, or // from a fresh point otherwise. message GatewaySubscribeRequest { string gateway_client_id = 1; string cursor = 2; } // PushEvent is one server-pushed frame. Exactly one of the kind oneof // fields is set. cursor is a monotonically increasing string assigned by // backend at publish time; gateway persists the last cursor it processed // so it can resume after reconnect. message PushEvent { oneof kind { ClientEvent client_event = 1; SessionInvalidation session_invalidation = 2; } string cursor = 3; } // ClientEvent carries an opaque payload destined for one user_id and // optionally one device_session_id (empty means fan-out to every active // session of user_id). kind is the notification catalog kind from // README §10. payload is the JSON encoding of the producer's payload // map; gateway forwards the bytes inside the signed envelope without // re-interpreting them. // // event_id, request_id and trace_id are correlation identifiers that // gateway carries verbatim into the signed client envelope. event_id is // stable per logical client-facing event (typically the route id of the // notification route that produced the event). request_id and trace_id // are optional and may be empty when the producer has no upstream // correlation to attach. message ClientEvent { string user_id = 1; string device_session_id = 2; string kind = 3; bytes payload = 4; string event_id = 5; string request_id = 6; string trace_id = 7; } // SessionInvalidation tells gateway to drop active subscriptions and // reject in-flight authenticated requests bound to the affected // sessions. user_id is always set; device_session_id narrows the // invalidation to a single session, empty means revoke every session of // user_id. reason is a free-form code logged by both sides. message SessionInvalidation { string device_session_id = 1; string user_id = 2; string reason = 3; }