// Package lobby defines the public typed command and response payloads // exposed at the authenticated Gateway -> Game Lobby boundary. package lobby import "time" const ( // MessageTypeMyGamesList is the authenticated gateway message type // used to read the calling user's own games. MessageTypeMyGamesList = "lobby.my.games.list" // MessageTypePublicGamesList is the authenticated gateway message // type used to read the paginated list of joinable public games. MessageTypePublicGamesList = "lobby.public.games.list" // MessageTypeMyApplicationsList is the authenticated gateway message // type used to read the caller's pending and decided applications to // public games. MessageTypeMyApplicationsList = "lobby.my.applications.list" // MessageTypeMyInvitesList is the authenticated gateway message type // used to read the caller's pending invites to private games. MessageTypeMyInvitesList = "lobby.my.invites.list" // MessageTypeOpenEnrollment is the authenticated gateway message // type used by the game owner to transition a draft game to // `enrollment_open`. MessageTypeOpenEnrollment = "lobby.game.open-enrollment" // MessageTypeGameCreate is the authenticated gateway message type // used to create a private game owned by the caller. Public games // are created exclusively through the admin surface; the gateway // rejects any attempt to set visibility to `public`. MessageTypeGameCreate = "lobby.game.create" // MessageTypeApplicationSubmit is the authenticated gateway message // type used by a user to submit an application to a public game in // `enrollment_open`. MessageTypeApplicationSubmit = "lobby.application.submit" // MessageTypeInviteRedeem is the authenticated gateway message type // used to accept an outstanding invite and create the corresponding // membership. MessageTypeInviteRedeem = "lobby.invite.redeem" // MessageTypeInviteDecline is the authenticated gateway message type // used to terminally decline an outstanding invite. No membership is // created. MessageTypeInviteDecline = "lobby.invite.decline" ) // MyGamesListRequest stores the authenticated read request for the // caller's games. The request body is intentionally empty; gateway // derives the calling user identity from the verified session. type MyGamesListRequest struct{} // MyGamesListResponse stores the list of games the caller participates // in, ordered as Lobby returns them. type MyGamesListResponse struct { Items []GameSummary `json:"items"` } // GameSummary stores one game record returned by the various lobby // list endpoints. `OwnerUserID` is empty for public games (no human // owner). `CurrentTurn` carries the runtime's most recently observed // turn number; the value is zero before the engine produces its first // snapshot. The user surface uses it to fetch the corresponding // `user.games.report` without an extra round-trip. type GameSummary struct { GameID string `json:"game_id"` GameName string `json:"game_name"` GameType string `json:"game_type"` Status string `json:"status"` OwnerUserID string `json:"owner_user_id"` MinPlayers int `json:"min_players"` MaxPlayers int `json:"max_players"` EnrollmentEndsAt time.Time `json:"enrollment_ends_at"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` CurrentTurn int32 `json:"current_turn"` } // PublicGamesListRequest stores the paginated read request for joinable // public games. Page numbers start at 1; page sizes are capped by the // backend. type PublicGamesListRequest struct { Page int `json:"page"` PageSize int `json:"page_size"` } // PublicGamesListResponse stores one page of public games together with // the pagination metadata returned by the backend. type PublicGamesListResponse struct { Items []GameSummary `json:"items"` Page int `json:"page"` PageSize int `json:"page_size"` Total int `json:"total"` } // MyApplicationsListRequest stores the authenticated read request for // the caller's applications. Empty body — gateway derives identity from // the authenticated session. type MyApplicationsListRequest struct{} // MyApplicationsListResponse stores the caller's application list, // ordered as Lobby returns it. type MyApplicationsListResponse struct { Items []ApplicationSummary `json:"items"` } // ApplicationSummary stores a single application record returned by // `lobby.my.applications.list` and `lobby.application.submit`. // `DecidedAt` is nil while the application is pending. type ApplicationSummary struct { ApplicationID string `json:"application_id"` GameID string `json:"game_id"` ApplicantUserID string `json:"applicant_user_id"` RaceName string `json:"race_name"` Status string `json:"status"` CreatedAt time.Time `json:"created_at"` DecidedAt *time.Time `json:"decided_at,omitempty"` } // MyInvitesListRequest stores the authenticated read request for the // caller's invites. Empty body. type MyInvitesListRequest struct{} // MyInvitesListResponse stores the caller's invite list. type MyInvitesListResponse struct { Items []InviteSummary `json:"items"` } // InviteSummary stores one invite record returned by // `lobby.my.invites.list`, `lobby.invite.redeem`, and // `lobby.invite.decline`. `InvitedUserID` is empty for code-based // invites; `Code` is empty for user-bound invites; `DecidedAt` is nil // while the invite is still pending. type InviteSummary struct { InviteID string `json:"invite_id"` GameID string `json:"game_id"` InviterUserID string `json:"inviter_user_id"` InvitedUserID string `json:"invited_user_id,omitempty"` Code string `json:"code,omitempty"` RaceName string `json:"race_name"` Status string `json:"status"` CreatedAt time.Time `json:"created_at"` ExpiresAt time.Time `json:"expires_at"` DecidedAt *time.Time `json:"decided_at,omitempty"` } // OpenEnrollmentRequest stores the owner-only command that transitions // a game from `draft` to `enrollment_open`. type OpenEnrollmentRequest struct { // GameID identifies the game whose enrollment the caller wants to // open. The owner check is enforced by Lobby. GameID string `json:"game_id"` } // OpenEnrollmentResponse stores the resulting game record after a // successful open-enrollment transition. type OpenEnrollmentResponse struct { GameID string `json:"game_id"` Status string `json:"status"` } // GameCreateRequest stores the create-game command issued by the user // surface. Visibility is always `private` here; the gateway rejects any // other value before forwarding to backend, mirroring the FUNCTIONAL // §3.3 invariant. type GameCreateRequest struct { GameName string `json:"game_name"` Description string `json:"description"` MinPlayers int `json:"min_players"` MaxPlayers int `json:"max_players"` StartGapHours int `json:"start_gap_hours"` StartGapPlayers int `json:"start_gap_players"` EnrollmentEndsAt time.Time `json:"enrollment_ends_at"` TurnSchedule string `json:"turn_schedule"` TargetEngineVersion string `json:"target_engine_version"` } // GameCreateResponse stores the freshly created game projected onto the // shared GameSummary shape — the gateway does not expose runtime fields // at create time because the game is always in `draft` until the owner // transitions it. type GameCreateResponse struct { Game GameSummary `json:"game"` } // ApplicationSubmitRequest stores the submit-application command. The // game must be public and in `enrollment_open`; backend rejects all // other states. type ApplicationSubmitRequest struct { GameID string `json:"game_id"` RaceName string `json:"race_name"` } // ApplicationSubmitResponse wraps the application created by a // successful submit-application call. type ApplicationSubmitResponse struct { Application ApplicationSummary `json:"application"` } // InviteRedeemRequest accepts a pending invite and creates the // corresponding membership at the backend. type InviteRedeemRequest struct { GameID string `json:"game_id"` InviteID string `json:"invite_id"` } // InviteRedeemResponse wraps the invite record updated by a successful // redeem (status transitions to `accepted`). type InviteRedeemResponse struct { Invite InviteSummary `json:"invite"` } // InviteDeclineRequest terminally declines a pending invite. No // membership is created. type InviteDeclineRequest struct { GameID string `json:"game_id"` InviteID string `json:"invite_id"` } // InviteDeclineResponse wraps the invite record updated by a successful // decline (status transitions to `declined`). type InviteDeclineResponse struct { Invite InviteSummary `json:"invite"` } // ErrorBody stores the canonical Lobby error envelope code/message // pair. type ErrorBody struct { Code string `json:"code"` Message string `json:"message"` } // ErrorResponse wraps ErrorBody for the FlatBuffers payload boundary. type ErrorResponse struct { Error ErrorBody `json:"error"` }