package ports import ( "context" "errors" ) // ErrUserServiceUnavailable is returned by UserService implementations when // the upstream User Service is unreachable, returns an unexpected status, // or violates the contract in a way that callers must surface as // service_unavailable. Service-layer code wraps it with the // shared.ErrServiceUnavailable sentinel before bubbling up to transport. var ErrUserServiceUnavailable = errors.New("user service unavailable") // Eligibility stores the lobby-relevant subset of the User Service // eligibility snapshot. only consumes Exists and CanJoinGame; the // remaining fields are pre-plumbed for (race name registration) // so that adding consumers later does not churn the port surface. type Eligibility struct { // Exists reports whether userID currently identifies a stored user. // false maps to subject_not_found at the service layer. Exists bool // CanLogin reports whether the user may currently log in. CanLogin bool // CanCreatePrivateGame reports whether the user may currently create // a private game. CanCreatePrivateGame bool // CanManagePrivateGame reports whether the user may currently manage // a private game they own. CanManagePrivateGame bool // CanJoinGame reports whether the user may currently join a game // (submit application or redeem invite). false surfaces as // eligibility_denied for the CanJoinGame bool // CanUpdateProfile reports whether the user may currently update // self-service profile and settings fields. CanUpdateProfile bool // PermanentBlocked reports whether the user carries an active // permanent_block sanction. rejects the // `lobby.race_name.register` call with `shared.ErrForbidden` ⇒ // HTTP `403 forbidden`; the dedicated `race_name_permanent_blocked` // envelope code is reserved for the cascade flows. Stage // 11 currently surfaces it indirectly through CanJoinGame=false // (collapses every can_* marker to false on // permanent_block). PermanentBlocked bool // MaxRegisteredRaceNames stores the snapshot value for the // max_registered_race_names limit. A value of 0 denotes unlimited // per the lifetime tariff. The race-name registration service // enforces the quota; this port only carries the value through. MaxRegisteredRaceNames int } //go:generate go run go.uber.org/mock/mockgen -destination=../adapters/mocks/mock_userservice.go -package=mocks galaxy/lobby/internal/ports UserService // UserService is the synchronous lobby-facing User Service eligibility // reader. The application flow consumes it via a single // GetEligibility call before accepting an applicant. type UserService interface { // GetEligibility returns the lobby-relevant eligibility snapshot for // userID. It returns Eligibility{Exists:false} for unknown users // without an error so callers can distinguish missing users from // transport failures. Transport, decode, and unexpected status code // failures wrap ErrUserServiceUnavailable. GetEligibility(ctx context.Context, userID string) (Eligibility, error) }