package bootstrap import ( "baron-sso-backend/internal/domain" "fmt" "log/slog" "gorm.io/gorm" ) // Run executes the application bootstrap logic (migrations, seeding, etc.) func Run(db *gorm.DB) error { slog.Info("[Bootstrap] Starting application bootstrap...") // 1. Auto Migration if err := migrateSchemas(db); err != nil { return fmt.Errorf("migration failed: %w", err) } // 2. Seed Tenants if err := SeedTenants(db); err != nil { return fmt.Errorf("tenant seeding failed: %w", err) } // 3. Normalize staging seed/read-model data if err := SanitizeLegacyUserMetadata(db); err != nil { return fmt.Errorf("legacy user metadata sanitize failed: %w", err) } slog.Info("[Bootstrap] User seed skipped (Kratos is SoT)") slog.Info("[Bootstrap] Bootstrap completed successfully.") return nil } func migrateSchemas(db *gorm.DB) error { slog.Info("[Bootstrap] Migrating database schemas...") if err := dropLegacyTenantDomainUniqueIndex(db); err != nil { return err } // Add all domain models here return db.AutoMigrate( &domain.Tenant{}, &domain.TenantDomain{}, &domain.User{}, &domain.UserLoginID{}, &domain.UserProjectionState{}, &domain.UserGroup{}, &domain.ApiKey{}, &domain.IdentityProviderConfig{}, &domain.ClientSecret{}, &domain.ClientConsent{}, &domain.KetoOutbox{}, &domain.RPUsageEvent{}, &domain.WorksmobileOutbox{}, &domain.WorksmobileResourceMapping{}, &domain.SharedLink{}, &domain.DeveloperRequest{}, &domain.RPUserMetadata{}, // &domain.RelyingParty{}, // Removed: SSOT is Hydra + Keto ) } func dropLegacyTenantDomainUniqueIndex(db *gorm.DB) error { if !db.Migrator().HasTable(&domain.TenantDomain{}) { return nil } if !db.Migrator().HasIndex(&domain.TenantDomain{}, "idx_tenant_domains_domain") { return nil } if err := db.Migrator().DropIndex(&domain.TenantDomain{}, "idx_tenant_domains_domain"); err != nil { return fmt.Errorf("failed to drop legacy tenant domain unique index: %w", err) } return nil }