feat(lobby): F8-04b hierarchical sidebar + paid-tier gate for create-game
Reshape the lobby UI from a single Overview into a two-level sidebar (games · profile · DEV synthetic-reports) with four games sub-panels (active-past · recruitment · invitations · private-games). Move the `create new game` button into the private-games panel, merge the applications section into recruitment cards as status chips, and add DEV-only synthetic-report loader as a top-level screen. Add a paid-tier gate at backend `lobby.game.create`: free callers get `403 forbidden` before the lobby service is invoked. The UI hides the private-games sub-panel + create button on free tier (DEV affordances flag overrides). Update every integration test that creates a game to use a new `testenv.PromoteToPaid` helper; add a new `TestLobbyFlow_FreeUserCreateGameForbidden`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
package lobby
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
@@ -28,6 +29,7 @@ import (
|
||||
|
||||
"galaxy/backend/internal/config"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
@@ -207,6 +209,17 @@ func (s *Service) Config() config.LobbyConfig {
|
||||
return s.deps.Config
|
||||
}
|
||||
|
||||
// IsPaid reports whether userID currently sits on a paid tier. Thin
|
||||
// pass-through over EntitlementProvider used by the HTTP handler that
|
||||
// fronts user-driven private-game creation; admin-driven public-game
|
||||
// creation does not consult this gate.
|
||||
func (s *Service) IsPaid(ctx context.Context, userID uuid.UUID) (bool, error) {
|
||||
if s == nil || s.deps.Entitlement == nil {
|
||||
return false, fmt.Errorf("lobby: entitlement provider not configured")
|
||||
}
|
||||
return s.deps.Entitlement.IsPaid(ctx, userID)
|
||||
}
|
||||
|
||||
// generateInviteCode produces an `inviteCodeBytes`-byte hex code used
|
||||
// for code-based invites. The function uses `crypto/rand`; a failure to
|
||||
// read entropy is propagated to the caller.
|
||||
|
||||
Reference in New Issue
Block a user