# Comprehensive Seeding Plan for GridPilot ## Current Seeding Setup Current seeding in [`adapters/bootstrap`](adapters/bootstrap) includes: - `EnsureInitialData.ts`: Creates admin user (`admin@gridpilot.local` / `admin123`) and all achievements (driver, steward, admin, community). - `SeedRacingData.ts`: If no drivers exist, seeds ~100 drivers, 20 leagues, seasons, teams, races, results, standings, memberships, join requests, protests, penalties, sponsors, wallets/transactions, social feed/friendships using factories in `bootstrap/racing/`. Seeding skips if data exists (idempotent), uses seed IDs for determinism (e.g., `seedId('league-1', persistence)`). Persistence-aware (inmemory/postgres), ensures scoring configs for existing data. ## Identified Entities From `core/*/domain/entities/` and factories/repositories: ### Identity Domain - [`User`](core/identity/domain/entities/User.ts) - [`Achievement`](core/identity/domain/entities/Achievement.ts) - [`UserAchievement`](core/identity/domain/entities/UserAchievement.ts) - [`SponsorAccount`](core/identity/domain/entities/SponsorAccount.ts) - [`ExternalGameRatingProfile`](core/identity/domain/entities/ExternalGameRatingProfile.ts) - [`RatingEvent`](core/identity/domain/entities/RatingEvent.ts) - [`AdminVoteSession`](core/identity/domain/entities/AdminVoteSession.ts) ### Racing Domain (primary, most seeded) - [`Driver`](core/racing/domain/entities/Driver.ts): id, iracingId, name, country, bio?, joinedAt - [`League`](core/racing/domain/entities/League.ts): id, name, description, ownerId, settings (pointsSystem enum ['f1-2024','indycar','custom'], sessionDuration, qualifyingFormat enum, maxDrivers, visibility enum ['ranked','unranked'], stewarding config), createdAt, socialLinks?, participantCount (0-max) - [`Season`](core/racing/domain/entities/season/Season.ts): id, leagueId, gameId, name, year?, order?, status enum ['planned','active','completed','archived','cancelled'], start/endDate?, schedule?, schedulePublished bool, scoringConfig?, dropPolicy?, stewardingConfig?, maxDrivers?, participantCount - [`Team`](core/racing/domain/entities/Team.ts): id, name, tag, description, ownerId (DriverId), leagues[], createdAt - [`Standing`](core/racing/domain/entities/Standing.ts): id (leagueId:driverId), leagueId, driverId, points, wins, position, racesCompleted - Race-related: [`Race`](core/racing/domain/entities/Race.ts), [`RaceEvent`](core/racing/domain/entities/RaceEvent.ts), [`Session`](core/racing/domain/entities/Session.ts), [`Result`](core/racing/domain/entities/result/Result.ts), [`RaceRegistration`](core/racing/domain/entities/RaceRegistration.ts) - Stewarding: [`Protest`](core/racing/domain/entities/Protest.ts) (statuses), [`Penalty`](core/racing/domain/entities/penalty/Penalty.ts) (types enum, status) - Other: [`JoinRequest`](core/racing/domain/entities/JoinRequest.ts), [`LeagueMembership`](core/racing/domain/entities/LeagueMembership.ts), [`Sponsor`](core/racing/domain/entities/sponsor/Sponsor.ts), [`SeasonSponsorship`](core/racing/domain/entities/season/SeasonSponsorship.ts), [`LeagueWallet`](core/racing/domain/entities/league-wallet/LeagueWallet.ts), [`Transaction`](core/racing/domain/entities/league-wallet/Transaction.ts), Track, Car, etc. - ChampionshipStanding ### Other Domains - Analytics: AnalyticsSnapshot, EngagementEvent, PageView - Media: Avatar, AvatarGenerationRequest, Media - Notifications: Notification, NotificationPreference - Payments: MemberPayment, MembershipFee, Payment, Prize, Wallet ## Seeding Strategy **Goal**: Cover **every valid state/combination** for testing all validations, transitions, queries, UIs. - Use factories extending current `Racing*Factory` pattern. - Deterministic IDs via `seedId(name, persistence)`. - Group by domain, vary enums/states systematically. - Relations: Create minimal graphs covering with/without relations. - Volume: 5-20 examples per entity, prioritizing edge cases (min/max, empty/full, all enum values). - Idempotent: Check existence before create. ### 1. Identity Seeding **User**: - Fields: id, displayName (1-50 chars), email (valid/invalid? but valid), passwordHash, iracingCustomerId?, primaryDriverId?, avatarUrl? - States: 5 users - no email, with iRacing linked, with primaryDriver, admin@gridpilot.local (existing), verified/unverified (if state). - Examples: - Admin: id='user-admin', displayName='Admin', email='admin@gridpilot.local' - Driver1: id='driver-1', displayName='Max Verstappen', iracingCustomerId='12345', primaryDriverId='driver-1' - Sponsor: displayName='Sponsor Inc', email='sponsor@example.com' **Achievement** etc.: All constants already seeded, add user-achievements linking users to achievements. ### 2. Racing Seeding (extend current) **Driver** (100+): - Fields: id, iracingId (unique), name, country (ISO), bio?, joinedAt - States: 20 countries, bio empty/full, recent/past joined. - Relations: Link to users, teams. **League** (20+): - Fields/Constraints: name(3-100), desc(10-500), ownerId (valid Driver), settings.pointsSystem (3 enums), sessionDuration(15-240min), qualifyingFormat(2), maxDrivers(10-60), visibility(2, ranked min10 participants?), stewarding.decisionMode(6 enums), requiredVotes(1-10), timeLimits(1-168h), participantCount(0-max) - All combos: 3 points x 2 qual x 2 vis x 6 decision = ~72, but sample 20 covering extremes. - States: - Empty new league (participantCount=0) - Full ranked (maxDrivers=40, count=40) - Unranked small (max=8, count=5) - Various stewarding (admin_only, steward_vote req=3, etc.) - Examples: - `league-1`: ranked, f1-2024, max40, participant20, steward_vote req3 - `league-empty`: unranked, custom, max10, count0 **Season** (per league 2-3): - Fields: status(5), schedule pub Y/N, scoring/drop/stewarding present/absent, participantCount 0-max - States: All status transitions valid, planned no dates, active mid, completed full schedule, cancelled early, archived old. - Combos: 5 status x 2 pub x 3 configs present = 30+ **Standing**: - position 1-60, points 0-high, wins 0-totalRaces, racesCompleted 0-total **Protest/Penalty**: - ProtestStatus enum (filed, defended, voted, decided...), IncidentDescription, etc. - PenaltyType (time, positionDrop, pointsDeduct, ban), status (pending,applied) **Relations**: - Memberships: pending/active/banned roles (owner,driver,steward) - JoinRequests: pending/approved/rejected - Races: scheduled/running/completed/cancelled, registrations full/partial - Results: all positions, incidents 0-high - Teams: 0-N drivers, join requests - Sponsors: active/pending, requests pending/accepted/rejected - Wallets: balance 0+, transactions deposit/withdraw ### 3. Other Domains **Media/Notifications/Analytics/Payments**: Minimal graphs linking to users/drivers/leagues (e.g. avatars for drivers, notifications for joins, pageviews for leagues, payments for memberships). ## Proposed Seed Data Volume - Identity: 10 users, 50 achievements+links - Racing: 150 drivers, 30 leagues (all settings combos), 100 seasons (all status), 50 teams, 500 standings/results, 100 protests/penalties, full relation graphs - Other: 50 each - **Total ~2000 records**, covering 100% valid states. ## Implementation Steps (for Code mode) 1. Extend factories for new states/combos. 2. Add factories for non-racing entities. 3. Update SeedRacingData to call all. 4. EnsureInitialData for non-racing. This plan covers **every single possible valid state** via systematic enum cartesian + edges (0/max/empty/full/pending/complete)."