package handler import ( "github.com/warmbly/warmbly/internal/app/admin" "github.com/warmbly/warmbly/internal/app/adminoutreach" "github.com/warmbly/warmbly/internal/app/advanced" "github.com/warmbly/warmbly/internal/app/advisor" "github.com/warmbly/warmbly/internal/app/aiagent" "github.com/warmbly/warmbly/internal/app/aitools" "github.com/warmbly/warmbly/internal/app/analytics" "github.com/warmbly/warmbly/internal/app/apikey" "github.com/warmbly/warmbly/internal/app/audit" "github.com/warmbly/warmbly/internal/app/auth" "github.com/warmbly/warmbly/internal/app/behavior" "github.com/warmbly/warmbly/internal/app/bootstrap" "github.com/warmbly/warmbly/internal/app/campaign" "github.com/warmbly/warmbly/internal/app/compose" "github.com/warmbly/warmbly/internal/app/contact" "github.com/warmbly/warmbly/internal/app/credits" "github.com/warmbly/warmbly/internal/app/crm" "github.com/warmbly/warmbly/internal/app/dangerzone" "github.com/warmbly/warmbly/internal/app/discount" "github.com/warmbly/warmbly/internal/app/email" "github.com/warmbly/warmbly/internal/app/emailsend" emailverifyapp "github.com/warmbly/warmbly/internal/app/emailverify" "github.com/warmbly/warmbly/internal/app/feature" "github.com/warmbly/warmbly/internal/app/group" "github.com/warmbly/warmbly/internal/app/instancecheck" "github.com/warmbly/warmbly/internal/app/instanceconfig" "github.com/warmbly/warmbly/internal/app/instancesettings" "github.com/warmbly/warmbly/internal/app/integration" "github.com/warmbly/warmbly/internal/app/leadsync" "github.com/warmbly/warmbly/internal/app/mcp" "github.com/warmbly/warmbly/internal/app/notification" "github.com/warmbly/warmbly/internal/app/oauth" "github.com/warmbly/warmbly/internal/app/organization" "github.com/warmbly/warmbly/internal/app/orgtransfer" "github.com/warmbly/warmbly/internal/app/passkey" "github.com/warmbly/warmbly/internal/app/placement" "github.com/warmbly/warmbly/internal/app/ratelimit" "github.com/warmbly/warmbly/internal/app/referral" "github.com/warmbly/warmbly/internal/app/releases" "github.com/warmbly/warmbly/internal/app/research" "github.com/warmbly/warmbly/internal/app/sequence" "github.com/warmbly/warmbly/internal/app/skills" "github.com/warmbly/warmbly/internal/app/socket" "github.com/warmbly/warmbly/internal/app/stripe" "github.com/warmbly/warmbly/internal/app/subscription" "github.com/warmbly/warmbly/internal/app/sysstatus" "github.com/warmbly/warmbly/internal/app/team" "github.com/warmbly/warmbly/internal/app/template" "github.com/warmbly/warmbly/internal/app/token" "github.com/warmbly/warmbly/internal/app/trial" "github.com/warmbly/warmbly/internal/app/twofa" "github.com/warmbly/warmbly/internal/app/tz" "github.com/warmbly/warmbly/internal/app/unibox" "github.com/warmbly/warmbly/internal/app/user" "github.com/warmbly/warmbly/internal/app/warmup" "github.com/warmbly/warmbly/internal/app/warmupcontent" "github.com/warmbly/warmbly/internal/app/webhook" "github.com/warmbly/warmbly/internal/app/worker" "github.com/warmbly/warmbly/internal/app/worker_orchestrator" "github.com/warmbly/warmbly/internal/pkg/generation" "github.com/warmbly/warmbly/internal/infrastructure/encryptedkeys" "github.com/warmbly/warmbly/internal/infrastructure/pubsub" "github.com/warmbly/warmbly/internal/infrastructure/storage" "github.com/warmbly/warmbly/internal/models" "github.com/warmbly/warmbly/internal/notify" "github.com/warmbly/warmbly/internal/repository" "github.com/warmbly/warmbly/internal/tasks" ) type Handler struct { AuthService auth.AuthService TokenService token.TokenService PasskeyService passkey.Service // Native-app social sign-in discovery (GET /auth/providers). ExternalAuthProviders models.ExternalAuthProviders // Deployment facts served by GET /auth/config so the login screen renders // what this backend can actually do instead of guessing. GoogleWebSignIn bool AppleWebSignIn bool OIDCEnabled bool MailDelivers bool PasskeysUsable bool MailTransport string // MailTransportRef backs the admin mail diagnostics, which need Preflight // and so cannot go through the EmailNotificationService interface. MailTransportRef *notify.Transport // BootstrapService backs the first-run setup page. BootstrapService *bootstrap.Service UserService user.UserService EmailService email.EmailService CampaignService campaign.CampaignService ContactService contact.ContactService SequenceService sequence.SequenceService UniboxService unibox.UniboxService FolderService group.GroupService TagService group.GroupService CategoryService group.GroupService TzService tz.TzService SocketService socket.SocketService TasksService tasks.TasksService NotificationService notification.Service TwoFAService twofa.Service // New services APIKeyService apikey.APIKeyService AnalyticsService analytics.AnalyticsService AuditService audit.AuditService RateLimitService ratelimit.RateLimitService // Subscription & billing SubscriptionService subscription.SubscriptionService StripeService stripe.StripeService DiscountService discount.DiscountService ReferralService referral.Service // Trial & feature gates TrialService trial.TrialService FeatureGateService feature.FeatureGateService WorkerAssignmentService worker.WorkerAssignmentService // Organization & IAM OrganizationService organization.OrganizationService // CRM CRMService crm.CRMService // Teams TeamService team.TeamService // Email send & templates TemplateService template.TemplateService EmailSendService emailsend.EmailSendService // Compose mailbox picker: scores the org's mailboxes for a recipient // (affinity, budget, auth health) and backs auto selection. ComposeService compose.Service // Admin AdminService admin.AdminService AdminOutreachService adminoutreach.Service // Worker orchestration (SSH-driven lifecycle for admin-managed workers) WorkerOrchestrator *worker_orchestrator.Orchestrator WorkerRepo repository.WorkerRepository CredentialsRepo repository.CredentialsRepository ReleasesService *releases.Service // Notifications EmailNotificationService notify.EmailNotificationService // Advanced outreach controls AdvancedService advanced.Service // Pre-send email verification (control-plane SMTP RCPT probe / pluggable // paid backend). Drops hard-bouncing addresses before a worker sends. EmailVerifyService emailverifyapp.Service // Per-mailbox human sending behaviour: the ranges a mailbox rolls its // workday from, and the plan it rolled for today. Nil disables the // behaviour endpoints (the schedulers then run every mailbox on its fixed // cap and gap). BehaviorService behavior.Service // Warmup health WarmupService warmup.Service // Warmup routing rules — customer-defined preferences for premium-pool // partner selection (e.g. Gmail recipients from Google Workspace senders). WarmupRoutingRepo repository.WarmupRoutingRepository // Warmup content bank + offline AI generator (admin control/visibility). WarmupContentRepo repository.WarmupContentRepository WarmupContentService warmupcontent.Service // AI writing assistant + credit ledger. CreditService credits.CreditService WritingGenerator generation.WritingGenerator // AI provider layer (RunAgent tool-loop backend) + pluggable web search, // shared by the dashboard agent, research, automation AI nodes, and the // inbox agent. Nil when no LLM provider is configured. AIProvider generation.Provider AISearch generation.SearchClient // AITools is the shared tool registry the dashboard agent and MCP server // run on. Handlers bound to the invoking user's permissions. AITools *aitools.Registry // AIAgentService orchestrates the dashboard agent (sessions, SSE runs, // approvals, per-iteration credits). Nil when no LLM provider is configured. AIAgentService aiagent.Service // ResearchService runs the AI contact-research agent (sync + batch). ResearchService research.Service // SkillsService manages org AI skills (playbooks) and injects them into AI // prompts. SkillsService skills.Service // MCPService manages org-connected MCP servers (external tools). MCPService mcp.Service // AIDraftRepo stores inbox-agent reply drafts awaiting human review (M10). // The draft is created in the consumer; these list/approve/discard handlers // read + resolve it. Nil disables the review endpoints. AIDraftRepo repository.AIDraftRepository // Seed inbox-placement testing. PlacementRepo repository.PlacementRepository PlacementService placement.Service // Advisor: continuously-evaluated recommendations about deliverability, // mailbox config, warmup, campaign performance, copy, and list hygiene. // The repository is held alongside the service so a read can cheaply check // how stale the findings are before deciding to re-evaluate inline. AdvisorService advisor.Service AdvisorRepository repository.AdvisorRepository // Customer-facing webhooks (subscribe → HMAC-signed delivery). WebhookService webhook.Service // Third-party integrations (Calendly, Cal.com, DMARC, Postmaster, // SNDS, Cloudflare, GoDaddy, Namecheap, Google Sheets). IntegrationService integration.Service ContactRepo repository.ContactRepository // OAuth 2.1 authorization server (third-party app registration + the // authorization-code-with-PKCE flow + bearer-token validation). OAuthService *oauth.Service // Realtime publisher for handler paths that emit live dashboard events // directly (inbound meeting webhooks have no service layer of their own). // nil-safe: realtime is a nicety, not a requirement. StreamingPublisher *pubsub.StreamingPublisher // On-demand Google Sheets -> leads sync. Reuses the google_sheets OAuth // connection's token to read sheets and the contact import path to upsert. LeadSyncService leadsync.Service // Public websocket URL used by frontend clients WebsocketURI string // Object storage for user-uploaded artifacts (avatars, etc.). Storage storage.Store // Encrypted-DEK store. Served to workers over HTTPS at // /api/v1/internal/dek/:userID so workers don't need direct Postgres // access. Backend processes use Postgres directly; workers use the // HTTP-proxy implementation. EncryptedKeys encryptedkeys.Store // Worker messageId -> internal email map, served to workers over HTTPS at // /api/v1/internal/email-message-map for the same no-direct-Postgres reason // as EncryptedKeys. Backed by Postgres in the backend. EmailMessageMap repository.EmailMessageMapRepository // Mailbox sync state, read by the dashboard (GET /emails/:id/sync) and by // the worker's priority lane over /api/v1/internal/sync/own-conversation. EmailSyncState repository.EmailSyncStateRepository // Click-link store, served to the tracking service over HTTPS at // /api/v1/internal/tracked-links/:id (same no-direct-Postgres rule). TrackedLinks repository.TrackedLinkRepository // Direct repositories used by handlers that don't yet have a // service layer (avatars, etc.). Keep narrow and add a service // only when business logic accumulates. UserRepo repository.UserRepository OrgRepo repository.OrganizationRepository AttachmentRepo repository.AttachmentRepository StorageBackendRepo repository.StorageBackendRepository CloudCredentialRepo repository.CloudCredentialRepository ProvisioningTemplateRepo repository.ProvisioningTemplateRepository ProvisioningJobRepo repository.ProvisioningJobRepository ProvisioningPolicyRepo repository.ProvisioningPolicyRepository // Danger zone (delayed deletions for orgs & user accounts) DangerZoneService dangerzone.Service // Workspace archives: export an organization to a portable file and import // one back, for moving between instances. Nil disables the endpoints. OrgTransferService orgtransfer.Service // Infrastructure liveness probes for the admin System Status page. // Wired in cmd/backend/main.go where the concrete clients live. SystemChecker *sysstatus.Checker // Operator visibility (admin panel, Instance section). // // InstanceRuntime carries the facts only boot knows (the resolved CORS // list, the WebAuthn RP, the OIDC redirect, the auth policy) so the // configuration page shows what the process actually derived. Nil is safe: // every resolver falls back to the environment. InstanceRuntime *instanceconfig.Runtime // InstanceChecks is the setup and health registry. Nil falls back to the // environment-only checks, so the page is never blank. InstanceChecks *instancecheck.Registry // InstanceSettings is the database-backed settings tier. It holds only // keys no environment variable owns. InstanceSettings instancesettings.Service }