services

package
v0.0.0-...-7f6939c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 6, 2026 License: MIT Imports: 35 Imported by: 0

Documentation

Overview

File: backend/internal/services/campaign_worker_service.go

File: backend/internal/services/db_monitor.go

Package services provides business logic for campaign phase orchestration.

File: backend/internal/services/interfaces.go

Package services provides phase state machine for campaign orchestration. This module defines valid phase state transitions and enforces them. See docs/PHASE_STATE_CONTRACT.md for the authoritative contract.

backend/internal/services/phase_status_derivation.go

File: backend/internal/services/rule_loader_service.go

File: backend/internal/services/sse_service.go

Index

Constants

View Source
const DefaultIdempotencyTTL = 5 * time.Minute

DefaultIdempotencyTTL is the default time-to-live for idempotency keys.

Variables

View Source
var (
	ErrSessionSecurityViolation = fmt.Errorf("session security violation")
	ErrSessionLimitExceeded     = fmt.Errorf("session limit exceeded")
	ErrSessionNotFound          = fmt.Errorf("session not found")
	ErrSessionExpired           = fmt.Errorf("session expired")
)

Session service errors

Functions

func CanPause

func CanPause(status models.PhaseStatusEnum) bool

CanPause returns true if the phase can be paused from its current state.

func CanRerun

func CanRerun(status models.PhaseStatusEnum) bool

CanRerun returns true if the phase can be rerun from its current state.

func CanResume

func CanResume(status models.PhaseStatusEnum) bool

CanResume returns true if the phase can be resumed from its current state.

func CanRetry

func CanRetry(status models.PhaseStatusEnum) bool

CanRetry returns true if the phase can be retried from its current state.

func CanStart

func CanStart(status models.PhaseStatusEnum) bool

CanStart returns true if the phase can be started from its current state.

func CanTransition

func CanTransition(from, to models.PhaseStatusEnum) bool

CanTransition returns true if the transition is valid.

func DefaultSessionConfig

func DefaultSessionConfig() *config.SessionConfig

DefaultSessionConfig returns VERY RELAXED session configuration

func GenerateCampaignIdentifier

func GenerateCampaignIdentifier(campaignID string) string

GenerateCampaignIdentifier creates a campaign-specific identifier for optimization decisions

func GenerateSessionIdentifier

func GenerateSessionIdentifier(sessionID string) string

GenerateSessionIdentifier creates a session-specific identifier for optimization decisions

func GenerateUserIdentifier

func GenerateUserIdentifier(userID, sessionID, campaignID string) string

GenerateUserIdentifier creates a consistent identifier for feature flag decisions This can be based on user ID, session ID, campaign ID, or other contextual data

func HashIdentifier

func HashIdentifier(identifier string) string

HashIdentifier creates a consistent hash for any identifier

func IsActiveState

func IsActiveState(status models.PhaseStatusEnum) bool

IsActiveState returns true if the phase is actively executing.

func IsPausedState

func IsPausedState(status models.PhaseStatusEnum) bool

IsPausedState returns true if the phase is paused.

func IsTerminalState

func IsTerminalState(status models.PhaseStatusEnum) bool

IsTerminalState returns true if the phase is in a terminal state (completed, failed, skipped).

func RegisterServiceContracts

func RegisterServiceContracts(registry *architecture.ServiceRegistry) error

RegisterServiceContracts registers basic contracts for core services.

func ResolveControlPhase

func ResolveControlPhase(phases []PhaseWithStatus) *models.PhaseTypeEnum

ResolveControlPhase determines the controlPhase from a list of phase statuses. Per contract: controlPhase = pausedPhase ?? inProgressPhase ?? null

Resolution order: 1. If any phase is paused → that phase is controlPhase 2. Else if any phase is in_progress → that phase is controlPhase 3. Else → nil (no active work)

func ShouldExtendSession

func ShouldExtendSession(expiresAt time.Time) bool

ShouldExtendSession checks if a session should be extended (within 6 hours of expiry)

func SignSessionCookie

func SignSessionCookie(sessionID string) string

SignSessionCookie creates a signed session cookie value. Format: {sessionID}.{base64(hmac-sha256(sessionID, secret))}

func ValidTransitionsFrom

func ValidTransitionsFrom(from models.PhaseStatusEnum) []models.PhaseStatusEnum

ValidTransitionsFrom returns all valid target states from a given state.

func ValidateTransition

func ValidateTransition(from, to models.PhaseStatusEnum, phase models.PhaseTypeEnum) error

ValidateTransition checks if a state transition is valid according to the state machine. Returns nil if valid, or a PhaseTransitionError if invalid.

func VerifySessionCookie

func VerifySessionCookie(cookieValue string) (string, bool)

VerifySessionCookie verifies a signed session cookie and returns the session ID. Returns the sessionID and true if valid, or empty string and false if invalid.

Types

type APIKey

type APIKey struct {
	ID         uuid.UUID
	UserID     string
	KeyName    string
	Key        string // The actual API key (only available on creation)
	KeyHash    string // SHA256 hash of the key for validation
	KeyHint    string // Last 4 characters for identification
	ExpiresAt  *time.Time
	LastUsedAt *time.Time
	CreatedAt  time.Time
	UpdatedAt  time.Time
}

APIKey represents an API key with metadata

type APIKeyRotationPolicy

type APIKeyRotationPolicy struct {
	MaxAge             time.Duration // Maximum age before rotation
	MaxUsageCount      int64         // Maximum number of uses before rotation
	RotateOnCompromise bool          // Force rotation if key is compromised
}

APIKeyRotationPolicy defines when keys should be rotated

type APIKeyService

type APIKeyService struct {
	// contains filtered or unexported fields
}

APIKeyService handles API key generation, validation, and rotation

func NewAPIKeyService

func NewAPIKeyService(encryptionService *EncryptionService) *APIKeyService

NewAPIKeyService creates a new API key service

func (*APIKeyService) CreateAPIKey

func (s *APIKeyService) CreateAPIKey(userID, keyName string, expiresIn *time.Duration) (*APIKey, error)

CreateAPIKey creates a new API key for a user

func (*APIKeyService) GenerateAPIKey

func (s *APIKeyService) GenerateAPIKey() (string, error)

GenerateAPIKey creates a new API key

func (*APIKeyService) HashAPIKey

func (s *APIKeyService) HashAPIKey(key string) string

HashAPIKey creates a SHA256 hash of the API key

func (*APIKeyService) IsExpired

func (s *APIKeyService) IsExpired(apiKey *APIKey) bool

IsExpired checks if an API key has expired

func (*APIKeyService) RotateAPIKey

func (s *APIKeyService) RotateAPIKey(oldKey *APIKey) (*APIKey, error)

RotateAPIKey creates a new API key to replace an existing one

func (*APIKeyService) ShouldRotate

func (s *APIKeyService) ShouldRotate(apiKey *APIKey, policy APIKeyRotationPolicy, usageCount int64) bool

ShouldRotate checks if an API key should be rotated based on policy

func (*APIKeyService) ValidateAPIKey

func (s *APIKeyService) ValidateAPIKey(key string, storedHash string) bool

ValidateAPIKey checks if an API key is valid

type AnalysisPhaseConfig

type AnalysisPhaseConfig struct {
	MinLeadScore   float64  `json:"minLeadScore,omitempty"`
	RequiredFields []string `json:"requiredFields,omitempty"`
	AnalysisRules  []string `json:"analysisRules,omitempty"`
}

AnalysisPhaseConfig contains analysis phase parameters

type AnalysisService

type AnalysisService interface {
	// ProcessAnalysisCampaignBatch performs content analysis on HTTP results and stores analysis results
	ProcessAnalysisCampaignBatch(ctx context.Context, campaignID uuid.UUID, batchSize int) (done bool, processedCount int64, err error)
	// ScoreDomains recomputes scores (idempotent) for a campaign
	ScoreDomains(ctx context.Context, campaignID uuid.UUID) error
	// RescoreCampaign recalculates scores after profile change
	RescoreCampaign(ctx context.Context, campaignID uuid.UUID) error
}

AnalysisService defines the interface for content analysis and lead extraction from HTTP results.

type BulkDeleteResult

type BulkDeleteResult struct {
	SuccessfullyDeleted int         `json:"successfully_deleted"`
	FailedDeletions     int         `json:"failed_deletions"`
	DeletedCampaignIDs  []uuid.UUID `json:"deleted_campaign_ids"`
	FailedCampaignIDs   []uuid.UUID `json:"failed_campaign_ids,omitempty"`
	Errors              []string    `json:"errors,omitempty"`
}

BulkDeleteResult represents the result of a bulk delete operation

type CachedSessionConfig

type CachedSessionConfig struct {
	// How long to cache valid sessions in Redis (default: 5 minutes)
	CacheTTL time.Duration
	// How long to cache "session not found" results to prevent DB spam (default: 30 seconds)
	NegativeCacheTTL time.Duration
	// Cache key prefix
	KeyPrefix string
	// Enable/disable distributed caching
	Enabled bool
}

CachedSessionConfig defines caching behavior for sessions

func DefaultCachedSessionConfig

func DefaultCachedSessionConfig() *CachedSessionConfig

DefaultCachedSessionConfig returns optimized cache configuration

type CachedSessionData

type CachedSessionData struct {
	*SessionData
	CachedAt time.Time `json:"cached_at"`
	IsValid  bool      `json:"is_valid"`
}

CachedSessionData represents session data optimized for caching

type CachedSessionService

type CachedSessionService struct {
	*SessionService
	// contains filtered or unexported fields
}

CachedSessionService wraps SessionService with Redis distributed caching

func NewCachedSessionService

func NewCachedSessionService(
	db *sqlx.DB,
	sessionConfig *config.SessionConfig,
	auditLogStore store.AuditLogStore,
	redisCache *cache.DistributedCacheManager,
	cacheConfig *CachedSessionConfig,
) (*CachedSessionService, error)

NewCachedSessionService creates a new cached session service

func (*CachedSessionService) GetCacheMetrics

func (s *CachedSessionService) GetCacheMetrics() map[string]interface{}

GetCacheMetrics returns enhanced metrics including Redis cache performance

func (*CachedSessionService) HealthCheck

func (s *CachedSessionService) HealthCheck() map[string]interface{}

Health check method for monitoring

func (*CachedSessionService) InvalidateAllUserSessions

func (s *CachedSessionService) InvalidateAllUserSessions(userID uuid.UUID) error

InvalidateAllUserSessions removes all user sessions from caches and database

func (*CachedSessionService) InvalidateSession

func (s *CachedSessionService) InvalidateSession(sessionID string) error

InvalidateSession removes from all caches and database

func (*CachedSessionService) ValidateSession

func (s *CachedSessionService) ValidateSession(sessionID, clientIP string) (*SessionData, error)

ValidateSession with distributed Redis caching

type CampaignDependencyInfo

type CampaignDependencyInfo struct {
	Campaign           models.LeadGenerationCampaign   `json:"campaign"`
	DependentCampaigns []models.LeadGenerationCampaign `json:"dependentCampaigns"`
	HasDependencies    bool                            `json:"hasDependencies"`
	CanDelete          bool                            `json:"canDelete"`
}

CampaignDependencyInfo provides information about campaign dependencies

type CampaignStateMachine

type CampaignStateMachine struct {
	// contains filtered or unexported fields
}

DEPRECATED: Legacy CampaignStateMachine for backward compatibility Use state.CampaignStateMachine for new implementations

func NewCampaignStateMachine

func NewCampaignStateMachine() *CampaignStateMachine

DEPRECATED: Use state.NewCampaignStateMachine() instead

func (*CampaignStateMachine) CanTransition

func (sm *CampaignStateMachine) CanTransition(current, target models.PhaseStatusEnum) bool

DEPRECATED: Use state.CampaignStateMachine.CanTransition() instead

func (*CampaignStateMachine) GetValidTransitions

func (sm *CampaignStateMachine) GetValidTransitions(current models.PhaseStatusEnum) []models.PhaseStatusEnum

DEPRECATED: Use state.CampaignStateMachine.GetValidTransitions() instead

func (*CampaignStateMachine) IsTerminalState

func (sm *CampaignStateMachine) IsTerminalState(status models.PhaseStatusEnum) bool

DEPRECATED: Use state.CampaignStateMachine.IsTerminalState() instead

func (*CampaignStateMachine) ValidateTransition

func (sm *CampaignStateMachine) ValidateTransition(current, target models.PhaseStatusEnum) error

DEPRECATED: Use state.CampaignStateMachine.ValidateTransition() instead

type CampaignTransactionOptions

type CampaignTransactionOptions struct {
	IsolationLevel sql.IsolationLevel
	ReadOnly       bool
	Operation      string
	CampaignID     string
	Timeout        time.Duration
	MaxRetries     int
	RetryDelay     time.Duration
}

CampaignTransactionOptions defines transaction options for campaign operations

type CampaignWorkerService

type CampaignWorkerService interface {
	StartWorkers(ctx context.Context, numWorkers int)
}

CampaignWorkerService manages the pool of background workers that process campaign jobs.

func NewCampaignWorkerService

func NewCampaignWorkerService(
	js store.CampaignJobStore,
	phaseService WorkerCompatibleService,
	serverInstanceID string,
	appCfg *config.AppConfig,
	db *sqlx.DB,
) CampaignWorkerService

NewCampaignWorkerService creates a new CampaignWorkerService.

type ConfigManagerInterface

type ConfigManagerInterface interface {
	GetDomainGenerationPhaseConfig(ctx context.Context, configHash string) (*models.DomainGenerationPhaseConfigState, error)
	UpdateDomainGenerationPhaseConfig(ctx context.Context, configHash string, updateFn func(currentState *models.DomainGenerationPhaseConfigState) (*models.DomainGenerationPhaseConfigState, error)) (*models.DomainGenerationPhaseConfigState, error)
}

ConfigManagerInterface defines the interface for configuration management

type ConsistencyReport

type ConsistencyReport struct {
	KeywordSetID          uuid.UUID   `json:"keywordSetId"`
	JSONBRuleCount        int         `json:"jsonbRuleCount"`
	RelationalRuleCount   int         `json:"relationalRuleCount"`
	IsConsistent          bool        `json:"isConsistent"`
	MissingFromJSONB      []uuid.UUID `json:"missingFromJsonb,omitempty"`
	MissingFromRelational []uuid.UUID `json:"missingFromRelational,omitempty"`
}

ConsistencyReport provides details about hybrid storage consistency

type CreateCampaignRequest

type CreateCampaignRequest struct {
	Name           string    `json:"name" validate:"required"`
	Description    string    `json:"description,omitempty"`
	UserID         uuid.UUID `json:"userId,omitempty"`
	LaunchSequence bool      `json:"launchSequence,omitempty"` // Whether to automatically progress through phases when each phase completes

	// Full sequence mode support - when enabled, stores all phase configurations at creation
	FullSequenceMode    bool                          `json:"fullSequenceMode,omitempty"`    // UI toggle for showing all phase configurations
	DNSValidationParams *DNSValidationRequest         `json:"dnsValidationParams,omitempty"` // DNS validation configuration for full sequence mode
	HTTPKeywordParams   *HTTPKeywordValidationRequest `json:"httpKeywordParams,omitempty"`   // HTTP validation configuration for full sequence mode

	// Phases-based architecture - all campaigns start in setup phase with domain generation
	DomainGenerationParams *DomainGenerationParams `json:"domainGenerationParams,omitempty"`
}

type CreateDomainGenerationCampaignRequest

type CreateDomainGenerationCampaignRequest struct {
	Name                 string                     `json:"name" validate:"required,min=1,max=100"`
	PatternType          string                     `json:"patternType" validate:"required,oneof=prefix suffix both"`
	Keywords             []string                   `json:"keywords" validate:"required,min=1,dive,min=1,max=50"`
	TLDs                 []string                   `json:"tlds" validate:"required,min=1,dive,min=2,max=10"`
	MaxResults           int                        `json:"maxResults" validate:"required,min=1,max=100000"`
	EnableDNSValidation  bool                       `json:"enableDnsValidation"`
	EnableHTTPValidation bool                       `json:"enableHttpValidation"`
	DNSValidationConfig  *DNSValidationPhaseConfig  `json:"dnsValidationConfig,omitempty"`
	HTTPValidationConfig *HTTPValidationPhaseConfig `json:"httpValidationConfig,omitempty"`

	// Domain generation fields
	VariableLength       int                  `json:"variableLength" validate:"required,gte=0,max=50"`
	CharacterSet         string               `json:"characterSet" validate:"required,min=1"`
	ConstantString       string               `json:"constantString,omitempty"`
	TLD                  string               `json:"tld" validate:"required,min=3,max=10"`
	NumDomainsToGenerate int                  `json:"numDomainsToGenerate" validate:"required,min=1"`
	UserID               uuid.UUID            `json:"userId,omitempty"`
	LaunchSequence       *bool                `json:"launchSequence,omitempty"`
	DNSValidationParams  *DNSValidationParams `json:"dnsValidationParams,omitempty"`
	HTTPKeywordParams    *HTTPKeywordParams   `json:"httpKeywordParams,omitempty"`
}

CreateDomainGenerationCampaignRequest defines request for creating domain generation campaigns

type CreateLeadGenerationCampaignRequest

type CreateLeadGenerationCampaignRequest struct {
	Name        string    `json:"name" validate:"required"`
	Description string    `json:"description,omitempty"`
	UserID      uuid.UUID `json:"userId,omitempty"`
	// Domain generation config for Phase 1 initialization
	DomainConfig DomainGenerationPhaseConfig `json:"domainConfig" validate:"required"`
}

type DNSValidationParams

type DNSValidationParams struct {
	PersonaIDs               []uuid.UUID `json:"personaIds" validate:"required,min=1"`
	RotationIntervalSeconds  *int        `json:"rotationIntervalSeconds,omitempty"`
	ProcessingSpeedPerMinute *int        `json:"processingSpeedPerMinute,omitempty"`
	BatchSize                *int        `json:"batchSize,omitempty"`
	RetryAttempts            *int        `json:"retryAttempts,omitempty"`
}

DNSValidationParams defines DNS validation parameters

type DNSValidationPhaseConfig

type DNSValidationPhaseConfig struct {
	PersonaIDs []string `json:"personaIds" validate:"required,min=1"`
}

DNSValidationPhaseConfig contains DNS validation phase parameters All timing/batch/retry settings come from the DNS persona's configDetails.

type DNSValidationRequest

type DNSValidationRequest struct {
	PersonaIDs               []uuid.UUID `json:"personaIds" validate:"omitempty,min=1,dive,uuid"`
	RotationIntervalSeconds  *int        `json:"rotationIntervalSeconds,omitempty" validate:"omitempty,gte=0"`
	ProcessingSpeedPerMinute *int        `json:"processingSpeedPerMinute,omitempty" validate:"omitempty,gte=0"`
	BatchSize                *int        `json:"batchSize,omitempty" validate:"omitempty,gt=0"`
	RetryAttempts            *int        `json:"retryAttempts,omitempty" validate:"omitempty,gte=0"`
}

DNSValidationRequest represents the request for phased DNS validation

type DNSValidationResultsResponse

type DNSValidationResultsResponse struct {
	Data       []models.DNSValidationResult `json:"data"`
	NextCursor string                       `json:"nextCursor,omitempty"` // Represents the last domain_name for the next query
	TotalCount int64                        `json:"totalCount"`
}

type DatabaseMonitor

type DatabaseMonitor struct {
	// contains filtered or unexported fields
}

DatabaseMonitor monitors database connection pool performance and health

func NewDatabaseMonitor

func NewDatabaseMonitor(db *sqlx.DB, campaignStore store.CampaignStore) *DatabaseMonitor

NewDatabaseMonitor creates a new database monitor instance

func (*DatabaseMonitor) GetCurrentStats

func (dm *DatabaseMonitor) GetCurrentStats() sql.DBStats

GetCurrentStats returns current database connection statistics

func (*DatabaseMonitor) GetHealthStatus

func (dm *DatabaseMonitor) GetHealthStatus() map[string]interface{}

GetHealthStatus returns the health status of the database connection pool

func (*DatabaseMonitor) OptimizeConnectionPool

func (dm *DatabaseMonitor) OptimizeConnectionPool() error

OptimizeConnectionPool automatically optimizes connection pool settings based on usage patterns

func (*DatabaseMonitor) RunHealthCheck

func (dm *DatabaseMonitor) RunHealthCheck(ctx context.Context) error

RunHealthCheck performs a comprehensive health check of the database

func (*DatabaseMonitor) Start

func (dm *DatabaseMonitor) Start(interval time.Duration)

Start begins monitoring database performance

func (*DatabaseMonitor) Stop

func (dm *DatabaseMonitor) Stop()

Stop stops the database monitoring

type DnsValidationParams

type DnsValidationParams struct {
	SourceCampaignID         *uuid.UUID  `json:"sourceCampaignId,omitempty"` // For standalone validation from past campaigns
	PersonaIDs               []uuid.UUID `json:"personaIds" validate:"required,min=1,dive,uuid"`
	RotationIntervalSeconds  int         `json:"rotationIntervalSeconds,omitempty" validate:"gte=0"`
	ProcessingSpeedPerMinute int         `json:"processingSpeedPerMinute,omitempty" validate:"gte=0"`
	BatchSize                int         `json:"batchSize,omitempty" validate:"gt=0"`
	RetryAttempts            int         `json:"retryAttempts,omitempty" validate:"gte=0"`
}

type DomainGenerationParams

type DomainGenerationParams struct {
	PatternType          string `json:"patternType" validate:"required,oneof=prefix suffix both"`
	VariableLength       int    `json:"variableLength" validate:"required,gte=0"`
	CharacterSet         string `json:"characterSet" validate:"required"`
	ConstantString       string `json:"constantString" validate:"required"`
	TLD                  string `json:"tld" validate:"required"`
	NumDomainsToGenerate int64  `json:"numDomainsToGenerate,omitempty" validate:"omitempty,gte=0"`
}

type DomainGenerationPhaseConfig

type DomainGenerationPhaseConfig struct {
	PatternType          string   `` /* 129-byte string literal not displayed */
	VariableLength       int      `json:"variableLength" validate:"required,gte=0" example:"5" description:"Length of variable part (0 for constant-only)"`
	CharacterSet         string   `json:"characterSet" validate:"required" example:"abcdefghijklmnopqrstuvwxyz" description:"Character set for generation"`
	ConstantString       string   `json:"constantString" validate:"required" example:"test" description:"Constant string part"`
	TLDs                 []string `json:"tlds" validate:"required,min=1" example:"[\".com\"]" description:"Array of top-level domains"`
	NumDomainsToGenerate int      `json:"numDomainsToGenerate,omitempty" validate:"omitempty,gte=0" example:"1000" description:"Number of domains to generate"`
	BatchSize            int      `json:"batchSize,omitempty" validate:"omitempty,gt=0" example:"100" description:"Batch size for generation"`
}

DomainGenerationPhaseConfig contains domain generation phase parameters

type DomainGenerationProgress

type DomainGenerationProgress struct {
	CampaignID         uuid.UUID `json:"campaignId"`
	Status             string    `json:"status"`
	DomainsGenerated   int       `json:"domainsGenerated"`
	TotalDomains       int       `json:"totalDomains"`
	Progress           float64   `json:"progress"`
	StartedAt          time.Time `json:"startedAt"`
	EstimatedEnd       time.Time `json:"estimatedEnd"`
	ProcessedCount     int       `json:"processedCount"`
	SuccessfulCount    int       `json:"successfulCount"`
	FailedCount        int       `json:"failedCount"`
	ProgressPercentage float64   `json:"progressPercentage"`
}

DomainGenerationProgress tracks domain generation progress

type DomainGenerationService

type DomainGenerationService interface {
	ProcessGenerationCampaignBatch(ctx context.Context, campaignID uuid.UUID, batchSize int) (batchDone bool, processedCount int, err error)
}

DomainGenerationService defines interface for domain generation operations

type DomainGenerationStats

type DomainGenerationStats struct {
	CampaignID         uuid.UUID `json:"campaignId"`
	TotalCombinations  int64     `json:"totalCombinations"`
	CurrentOffset      int64     `json:"currentOffset"`
	DomainsGenerated   int       `json:"domainsGenerated"`
	GenerationRate     float64   `json:"generationRate"`
	MemoryUsage        int64     `json:"memoryUsage"`
	ConfigHash         string    `json:"configHash"`
	EstimatedTimeLeft  int64     `json:"estimatedTimeLeft"`
	TotalGenerated     int64     `json:"totalGenerated"`
	UniqueDomainsCount int64     `json:"uniqueDomainsCount"`
	DuplicatesSkipped  int64     `json:"duplicatesSkipped"`
	ErrorCount         int64     `json:"errorCount"`
}

DomainGenerationStats tracks domain generation statistics

type EncryptionService

type EncryptionService struct {
	// contains filtered or unexported fields
}

EncryptionService provides field-level encryption for sensitive data

func NewEncryptionService

func NewEncryptionService(key []byte) (*EncryptionService, error)

NewEncryptionService creates a new encryption service with the provided key

func (*EncryptionService) DecryptBytes

func (e *EncryptionService) DecryptBytes(ciphertext []byte) ([]byte, error)

DecryptBytes decrypts raw bytes that were encrypted with EncryptBytes

func (*EncryptionService) DecryptField

func (e *EncryptionService) DecryptField(ciphertext string) (string, error)

DecryptField decrypts a ciphertext string that was encrypted with EncryptField

func (*EncryptionService) EncryptBytes

func (e *EncryptionService) EncryptBytes(plaintext []byte) ([]byte, error)

EncryptBytes encrypts raw bytes using AES-GCM

func (*EncryptionService) EncryptField

func (e *EncryptionService) EncryptField(plaintext string) (string, error)

EncryptField encrypts a plaintext string using AES-GCM

type FeatureFlagService

type FeatureFlagService struct {
	// contains filtered or unexported fields
}

FeatureFlagService handles gradual rollout and feature flag logic

func NewFeatureFlagService

func NewFeatureFlagService(config config.FeatureFlagConfig) *FeatureFlagService

NewFeatureFlagService creates a new feature flag service

func (*FeatureFlagService) GetConfig

GetConfig returns the current feature flag configuration

func (*FeatureFlagService) GetOptimizationLevel

func (f *FeatureFlagService) GetOptimizationLevel(identifier string) OptimizationLevel

GetOptimizationLevel returns a structured view of which optimizations are enabled

func (*FeatureFlagService) GetRolloutPercentage

func (f *FeatureFlagService) GetRolloutPercentage() int

GetRolloutPercentage returns the current rollout percentage

func (*FeatureFlagService) IsDebugLoggingEnabled

func (f *FeatureFlagService) IsDebugLoggingEnabled() bool

IsDebugLoggingEnabled checks if debug logging is enabled for feature flags

func (*FeatureFlagService) IsOptimizationEnabled

func (f *FeatureFlagService) IsOptimizationEnabled() bool

IsOptimizationEnabled checks if any optimization features are enabled globally

func (*FeatureFlagService) ShouldFallbackOnError

func (f *FeatureFlagService) ShouldFallbackOnError() bool

ShouldFallbackOnError checks if the system should fallback to non-optimized behavior on errors

func (*FeatureFlagService) ShouldUseBatchQueries

func (f *FeatureFlagService) ShouldUseBatchQueries(identifier string) bool

ShouldUseBatchQueries checks if batch query optimization should be used

func (*FeatureFlagService) ShouldUseCaching

func (f *FeatureFlagService) ShouldUseCaching(identifier string) bool

ShouldUseCaching checks if caching optimization should be used

func (*FeatureFlagService) ShouldUseExternalValidation

func (f *FeatureFlagService) ShouldUseExternalValidation(identifier string) bool

ShouldUseExternalValidation checks if external validation optimization should be used

func (*FeatureFlagService) ShouldUseOptimization

func (f *FeatureFlagService) ShouldUseOptimization(identifier string) bool

ShouldUseOptimization determines if optimization features should be used for a given identifier

func (*FeatureFlagService) ShouldUseServiceOptimization

func (f *FeatureFlagService) ShouldUseServiceOptimization(identifier string) bool

ShouldUseServiceOptimization checks if service-level optimization should be used

func (*FeatureFlagService) UpdateConfig

func (f *FeatureFlagService) UpdateConfig(newConfig config.FeatureFlagConfig)

UpdateConfig updates the feature flag configuration

type GenerateDomainsRequest

type GenerateDomainsRequest struct {
	CampaignID      uuid.UUID                    `json:"campaignId" validate:"required"`
	BatchSize       int                          `json:"batchSize" validate:"required,min=1,max=10000"`
	StartFromOffset int64                        `json:"startFromOffset"`
	Config          *DomainGenerationPhaseConfig `json:"config" validate:"required"`
}

GenerateDomainsRequest defines request for domain generation

type GeneratedDomainsResponse

type GeneratedDomainsResponse struct {
	Data       []models.GeneratedDomain `json:"data"`
	NextCursor int64                    `json:"nextCursor,omitempty"` // Represents the last offset_index for the next query
	TotalCount int64                    `json:"totalCount"`
}

type HTTPKeywordParams

type HTTPKeywordParams struct {
	PersonaIDs []uuid.UUID `json:"personaIds" validate:"required,min=1"`
	Keywords   []string    `json:"keywords,omitempty"`
}

HTTPKeywordParams defines HTTP keyword validation parameters

type HTTPKeywordResultsResponse

type HTTPKeywordResultsResponse struct {
	Data       []models.HTTPKeywordResult `json:"data"`
	NextCursor string                     `json:"nextCursor,omitempty"` // Represents the last domain_name for the next query
	TotalCount int64                      `json:"totalCount"`
}

type HTTPKeywordValidationPhaseConfig

type HTTPKeywordValidationPhaseConfig struct {
	PersonaIDs []string `json:"personaIds" validate:"required,min=1"`
	Keywords   []string `json:"keywords,omitempty"`
}

HTTPKeywordValidationPhaseConfig contains HTTP keyword validation phase parameters All timing/batch/retry settings come from the HTTP persona's configDetails.

type HTTPKeywordValidationRequest

type HTTPKeywordValidationRequest struct {
	PersonaIDs []uuid.UUID `json:"personaIds" validate:"omitempty,min=1,dive,uuid"`
	Keywords   []string    `json:"keywords,omitempty" validate:"omitempty,min=1,dive,required"`
}

HTTPKeywordValidationRequest represents the request for phased HTTP keyword validation

type HTTPValidationPhaseConfig

type HTTPValidationPhaseConfig struct {
	PersonaIDs []uuid.UUID `json:"personaIds" validate:"required,min=1"`
	Keywords   []string    `json:"keywords,omitempty"`
}

HTTPValidationPhaseConfig defines HTTP validation phase configuration All timing/batch/retry settings come from the HTTP persona's configDetails.

type HttpKeywordParams

type HttpKeywordParams struct {
	SourceCampaignID uuid.UUID   `json:"sourceCampaignId" validate:"required"`
	KeywordSetIDs    []uuid.UUID `json:"keywordSetIds,omitempty" validate:"omitempty,dive,uuid"`
	PersonaIDs       []uuid.UUID `json:"personaIds" validate:"required,min=1,dive,uuid"`
	ProxyPoolID      *uuid.UUID  `json:"proxyPoolId,omitempty"`
}

type IdempotencyCache

type IdempotencyCache struct {
	// contains filtered or unexported fields
}

IdempotencyCache provides in-memory caching for idempotent control operations. Keys expire after DefaultTTL and are cleaned up periodically.

MULTI-INSTANCE CONSIDERATION (P3.4): This implementation uses in-memory storage which works for single-instance deployments. For multi-instance deployments (e.g., Kubernetes with multiple pods), consider:

  1. Redis-backed implementation: - Use SETNX with TTL for atomic check-and-set - Example: `SETNX <key> <result> EX 300` (5 min TTL) - Read with `GET <key>`, returns nil if expired

  2. Interface extraction: - Extract IdempotencyStore interface: Get(key) (*Entry, error), Set(key, result, err, ttl) error - Create InMemoryIdempotencyStore (current impl) - Create RedisIdempotencyStore for distributed deployments

  3. Configuration: - Add config option: `idempotency_store: "memory" | "redis"` - For Redis: `redis_url`, `redis_password`, `redis_db`

The current in-memory implementation is sufficient for: - Single-instance deployments - Development/testing environments - Deployments behind sticky sessions (same user → same instance)

func NewIdempotencyCache

func NewIdempotencyCache(ttl time.Duration) *IdempotencyCache

NewIdempotencyCache creates a new idempotency cache with the given TTL. Pass 0 for ttl to use DefaultIdempotencyTTL.

func (*IdempotencyCache) Delete

func (c *IdempotencyCache) Delete(key string)

Delete removes an entry by key.

func (*IdempotencyCache) Get

Get retrieves an entry by key. Returns nil if not found or expired.

func (*IdempotencyCache) Set

func (c *IdempotencyCache) Set(key string, result interface{}, err error)

Set stores an entry with the configured TTL.

func (*IdempotencyCache) Size

func (c *IdempotencyCache) Size() int

Size returns the current number of entries.

func (*IdempotencyCache) Stop

func (c *IdempotencyCache) Stop()

Stop halts the background cleanup goroutine.

type IdempotencyEntry

type IdempotencyEntry struct {
	Key       string      `json:"key"`
	Result    interface{} `json:"result"`
	Error     error       `json:"-"`
	CreatedAt time.Time   `json:"created_at"`
	ExpiresAt time.Time   `json:"expires_at"`
}

IdempotencyEntry stores the result of an idempotent operation.

type InMemorySessionStore

type InMemorySessionStore struct {
	// contains filtered or unexported fields
}

InMemorySessionStore provides fast in-memory session storage

type KeywordSetService

type KeywordSetService struct {
	// contains filtered or unexported fields
}

KeywordSetService provides unified access to keyword sets from both config and database

func NewKeywordSetService

func NewKeywordSetService(db *sqlx.DB, keywordStore store.KeywordStore, appConfig *config.AppConfig) *KeywordSetService

NewKeywordSetService creates a new keyword set service

func (*KeywordSetService) CreateKeywordSet

func (s *KeywordSetService) CreateKeywordSet(ctx context.Context, keywordSet *models.KeywordSet) error

CreateKeywordSet creates a new keyword set in the database

func (*KeywordSetService) DeleteKeywordSet

func (s *KeywordSetService) DeleteKeywordSet(ctx context.Context, id uuid.UUID) error

DeleteKeywordSet deletes a keyword set from the database

func (*KeywordSetService) GetKeywordRulesBySetID

func (s *KeywordSetService) GetKeywordRulesBySetID(ctx context.Context, setID uuid.UUID) ([]models.KeywordRule, error)

GetKeywordRulesBySetID retrieves keyword rules for a given set ID

func (*KeywordSetService) GetKeywordSetByID

func (s *KeywordSetService) GetKeywordSetByID(ctx context.Context, id uuid.UUID) (*models.KeywordSet, error)

GetKeywordSetByID retrieves a keyword set by ID, checking both database and config

func (*KeywordSetService) GetKeywordSetByName

func (s *KeywordSetService) GetKeywordSetByName(ctx context.Context, name string) (*models.KeywordSet, error)

GetKeywordSetByName retrieves a keyword set by name, checking both database and config

func (*KeywordSetService) ListKeywordSets

func (s *KeywordSetService) ListKeywordSets(ctx context.Context, filter store.ListKeywordSetsFilter) ([]*models.KeywordSet, error)

ListKeywordSets returns keyword sets from both database and config

func (*KeywordSetService) SyncConfigToDatabase

func (s *KeywordSetService) SyncConfigToDatabase(ctx context.Context) error

SyncConfigToDatabase synchronizes config-based keyword sets to database This is useful for making config sets persistent and searchable

func (*KeywordSetService) UpdateKeywordSet

func (s *KeywordSetService) UpdateKeywordSet(ctx context.Context, keywordSet *models.KeywordSet) error

UpdateKeywordSet updates an existing keyword set in the database

type LeadGenerationProgress

type LeadGenerationProgress struct {
	CampaignID      uuid.UUID                `json:"campaign_id"`
	CurrentPhase    models.PhaseTypeEnum     `json:"current_phase"`
	PhaseProgress   map[string]PhaseProgress `json:"phase_progress"`
	OverallProgress float64                  `json:"overall_progress"`
}

type LifecycleTransition

type LifecycleTransition struct {
	CampaignID uuid.UUID              `json:"campaign_id"`
	Phase      models.PhaseTypeEnum   `json:"phase"`
	FromState  models.PhaseStatusEnum `json:"from_state"`
	ToState    models.PhaseStatusEnum `json:"to_state"`
	Trigger    TransitionTrigger      `json:"trigger"`
	Sequence   int64                  `json:"sequence"`
	Timestamp  time.Time              `json:"timestamp"`
}

LifecycleTransition captures a state transition with sequence for SSE emission. Sequence is generated in the orchestrator at the moment the transition is persisted.

func NewLifecycleTransition

func NewLifecycleTransition(
	campaignID uuid.UUID,
	phase models.PhaseTypeEnum,
	from, to models.PhaseStatusEnum,
	sequence int64,
) *LifecycleTransition

NewLifecycleTransition creates a transition record. The sequence should be assigned by the orchestrator when persisting.

type MFAChallenge

type MFAChallenge struct {
	ChallengeID string    `json:"challengeId"`
	UserID      string    `json:"userId"`
	Method      MFAMethod `json:"method"`
	CreatedAt   time.Time `json:"createdAt"`
	ExpiresAt   time.Time `json:"expiresAt"`
	Attempts    int       `json:"attempts"`
	MaxAttempts int       `json:"maxAttempts"`
}

MFAChallenge represents an MFA challenge

type MFAEnrollment

type MFAEnrollment struct {
	UserID          string    `json:"userId"`
	TOTPEnabled     bool      `json:"totpEnabled"`
	TOTPSecret      string    `json:"-"` // Never expose
	BackupCodesUsed []string  `json:"-"` // Never expose
	PreferredMethod MFAMethod `json:"preferredMethod"`
	EnrolledAt      time.Time `json:"enrolledAt"`
	LastUsedAt      time.Time `json:"lastUsedAt"`
}

MFAEnrollment represents a user's MFA enrollment status

type MFAMethod

type MFAMethod string

MFAMethod represents different MFA methods

const (
	MFAMethodTOTP   MFAMethod = "totp"
	MFAMethodSMS    MFAMethod = "sms"
	MFAMethodEmail  MFAMethod = "email"
	MFAMethodBackup MFAMethod = "backup"
)

type MFAService

type MFAService struct {
	// contains filtered or unexported fields
}

MFAService handles multi-factor authentication

func NewMFAService

func NewMFAService(issuer string) *MFAService

NewMFAService creates a new MFA service

func (*MFAService) CreateMFAChallenge

func (s *MFAService) CreateMFAChallenge(userID string, method MFAMethod) (*MFAChallenge, error)

CreateMFAChallenge creates a new MFA challenge

func (*MFAService) EnrollTOTP

func (s *MFAService) EnrollTOTP(userID string, secret string) (*MFAEnrollment, error)

EnrollTOTP enrolls a user in TOTP MFA

func (*MFAService) GenerateTOTPSecret

func (s *MFAService) GenerateTOTPSecret(userID, userEmail string) (*TOTPSecret, error)

GenerateTOTPSecret generates a new TOTP secret for a user

func (*MFAService) GetRecoveryOptions

func (s *MFAService) GetRecoveryOptions(enrollment *MFAEnrollment) *RecoveryOptions

GetRecoveryOptions returns available recovery options for a user

func (*MFAService) HashBackupCode

func (s *MFAService) HashBackupCode(code string) string

HashBackupCode hashes a backup code for storage

func (*MFAService) ValidateChallenge

func (s *MFAService) ValidateChallenge(challenge *MFAChallenge) error

ValidateChallenge checks if a challenge is still valid

func (*MFAService) VerifyTOTP

func (s *MFAService) VerifyTOTP(secret, token string) (bool, error)

VerifyTOTP verifies a TOTP token

func (*MFAService) VerifyTOTPWithWindow

func (s *MFAService) VerifyTOTPWithWindow(secret, token string, window int) (bool, error)

VerifyTOTPWithWindow verifies a TOTP token with a time window

type OptimizationLevel

type OptimizationLevel struct {
	BatchQueries        bool   `json:"batchQueries"`
	ServiceOptimization bool   `json:"serviceOptimization"`
	ExternalValidation  bool   `json:"externalValidation"`
	Caching             bool   `json:"caching"`
	Identifier          string `json:"identifier"`
}

OptimizationLevel represents which optimization features are enabled for a specific context

type PhaseConfig

type PhaseConfig struct {
	PhaseType models.PhaseTypeEnum `json:"phaseType"`

	// Domain Generation Phase Config
	DomainGeneration *DomainGenerationPhaseConfig `json:"domainGeneration,omitempty"`

	// DNS Validation Phase Config
	DNSValidation *DNSValidationPhaseConfig `json:"dnsValidation,omitempty"`

	// HTTP Keyword Validation Phase Config
	HTTPKeywordValidation *HTTPKeywordValidationPhaseConfig `json:"httpKeywordValidation,omitempty"`

	// Analysis Phase Config
	Analysis *AnalysisPhaseConfig `json:"analysis,omitempty"`
}

PhaseConfig contains configuration for any phase type in a lead generation campaign

type PhaseProgress

type PhaseProgress struct {
	CampaignID      uuid.UUID              `json:"campaignId"`
	PhaseType       models.PhaseTypeEnum   `json:"phaseType"`
	Status          models.PhaseStatusEnum `json:"status"`
	ItemsTotal      int64                  `json:"itemsTotal"`
	ItemsProcessed  int64                  `json:"itemsProcessed"`
	ItemsSuccessful int64                  `json:"itemsSuccessful"`
	ItemsFailed     int64                  `json:"itemsFailed"`
	Progress        float64                `json:"progress"`
	StartedAt       *time.Time             `json:"startedAt,omitempty"`
	EstimatedEnd    *time.Time             `json:"estimatedEnd,omitempty"`
	ErrorMessage    *string                `json:"errorMessage,omitempty"`
}

PhaseProgress represents the current progress of any phase in a lead generation campaign

type PhaseStats

type PhaseStats struct {
	CampaignID     uuid.UUID            `json:"campaignId"`
	PhaseType      models.PhaseTypeEnum `json:"phaseType"`
	ProcessingRate float64              `json:"processingRate"`
	MemoryUsage    int64                `json:"memoryUsage"`
	Duration       time.Duration        `json:"duration"`
	TotalResults   int64                `json:"totalResults"`
	SuccessRate    float64              `json:"successRate"`
	ErrorCounts    map[string]int64     `json:"errorCounts,omitempty"`
}

PhaseStats provides statistics about any phase execution

type PhaseStatusDerivationService

type PhaseStatusDerivationService struct {
	// contains filtered or unexported fields
}

PhaseStatusDerivationService handles deriving campaign-level status from individual phases

func NewPhaseStatusDerivationService

func NewPhaseStatusDerivationService(campaignStore store.CampaignStore, db store.Querier) *PhaseStatusDerivationService

NewPhaseStatusDerivationService creates a new derivation service

func (*PhaseStatusDerivationService) DeriveCurrentPhaseFromPhases

func (s *PhaseStatusDerivationService) DeriveCurrentPhaseFromPhases(ctx context.Context, campaignID uuid.UUID) (*models.PhaseTypeEnum, *models.PhaseStatusEnum, error)

DeriveCurrentPhaseFromPhases determines current phase and status from campaign_phases table

func (*PhaseStatusDerivationService) GetCompletedPhasesCount

func (s *PhaseStatusDerivationService) GetCompletedPhasesCount(ctx context.Context, campaignID uuid.UUID) (int, error)

GetCompletedPhasesCount returns the number of completed phases

func (*PhaseStatusDerivationService) SyncCampaignStatusFromPhases

func (s *PhaseStatusDerivationService) SyncCampaignStatusFromPhases(ctx context.Context, campaignID uuid.UUID) error

SyncCampaignStatusFromPhases updates campaign-level status to match phases

type PhaseTransitionError

type PhaseTransitionError struct {
	From   models.PhaseStatusEnum
	To     models.PhaseStatusEnum
	Phase  models.PhaseTypeEnum
	Reason string
}

PhaseTransitionError is returned when an invalid state transition is attempted.

func (*PhaseTransitionError) Error

func (e *PhaseTransitionError) Error() string

func (*PhaseTransitionError) To409Error

func (e *PhaseTransitionError) To409Error(attemptedAction string) *TransitionError409

To409Error converts to the contract-compliant 409 envelope.

type PhaseWithStatus

type PhaseWithStatus struct {
	Phase  models.PhaseTypeEnum
	Status models.PhaseStatusEnum
}

PhaseWithStatus represents a phase and its current status for controlPhase resolution.

type RecoveryOptions

type RecoveryOptions struct {
	BackupCodesRemaining int         `json:"backupCodesRemaining"`
	AlternativeMethods   []MFAMethod `json:"alternativeMethods"`
	RecoveryEmail        string      `json:"recoveryEmail,omitempty"`
	RecoveryPhone        string      `json:"recoveryPhone,omitempty"`
}

RecoveryOptions represents MFA recovery options

type ResourceLockManager

type ResourceLockManager struct {
	// contains filtered or unexported fields
}

ResourceLockManager manages resource locking for worker coordination

func NewResourceLockManager

func NewResourceLockManager(db *sqlx.DB) *ResourceLockManager

NewResourceLockManager creates a new ResourceLockManager

func (*ResourceLockManager) AcquireResourceLock

func (rlm *ResourceLockManager) AcquireResourceLock(ctx context.Context, resourceID string, operation string, workerID string, timeout time.Duration) (string, error)

AcquireResourceLock acquires a resource lock

func (*ResourceLockManager) ReleaseResourceLock

func (rlm *ResourceLockManager) ReleaseResourceLock(ctx context.Context, lockID string, resourceID string, workerID string) error

ReleaseResourceLock releases a resource lock

type RuleLoaderService

type RuleLoaderService struct {
	// contains filtered or unexported fields
}

RuleLoaderService provides high-performance rule loading for Phase 3 HTTP scanning and traditional rule management operations using the hybrid storage approach.

func NewRuleLoaderService

func NewRuleLoaderService(db *sqlx.DB) *RuleLoaderService

NewRuleLoaderService creates a new rule loader service

func (*RuleLoaderService) GetRuleStatistics

func (s *RuleLoaderService) GetRuleStatistics(ctx context.Context) (*RuleStatistics, error)

GetRuleStatistics provides statistics about rule usage across keyword sets.

func (*RuleLoaderService) LoadEnabledKeywordSetsForScanning

func (s *RuleLoaderService) LoadEnabledKeywordSetsForScanning(ctx context.Context) ([]models.KeywordSet, error)

LoadEnabledKeywordSetsForScanning loads all enabled keyword sets with their rules using JSONB. Optimized for bulk Phase 3 HTTP scanning operations.

func (*RuleLoaderService) LoadRulesForManagement

func (s *RuleLoaderService) LoadRulesForManagement(ctx context.Context, keywordSetID uuid.UUID) ([]models.KeywordRule, error)

LoadRulesForManagement loads keyword rules using the relational table for management operations. This method uses the keyword_rules table for complex queries and rule administration.

func (*RuleLoaderService) LoadRulesForScanning

func (s *RuleLoaderService) LoadRulesForScanning(ctx context.Context, keywordSetID uuid.UUID) ([]models.KeywordRule, error)

LoadRulesForScanning loads keyword rules using JSONB for high-performance Phase 3 HTTP scanning. This method leverages the hybrid storage: JSONB for atomic fast loading.

func (*RuleLoaderService) QueryRulesWithFilters

func (s *RuleLoaderService) QueryRulesWithFilters(ctx context.Context, filter RuleQueryFilter) ([]models.KeywordRule, error)

QueryRulesWithFilters performs advanced rule queries using the relational table. Supports complex filtering for rule management interfaces.

func (*RuleLoaderService) ValidateHybridStorageConsistency

func (s *RuleLoaderService) ValidateHybridStorageConsistency(ctx context.Context, keywordSetID uuid.UUID) (*ConsistencyReport, error)

ValidateHybridStorageConsistency checks if JSONB and relational data are in sync

type RuleQueryFilter

type RuleQueryFilter struct {
	KeywordSetID    *uuid.UUID                  `json:"keywordSetId,omitempty"`
	RuleType        *models.KeywordRuleTypeEnum `json:"ruleType,omitempty"`
	Category        *string                     `json:"category,omitempty"`
	IsCaseSensitive *bool                       `json:"isCaseSensitive,omitempty"`
	PatternSearch   *string                     `json:"patternSearch,omitempty"`
	Limit           int                         `json:"limit,omitempty"`
	Offset          int                         `json:"offset,omitempty"`
}

RuleQueryFilter defines filters for advanced rule querying

type RuleStatistics

type RuleStatistics struct {
	TotalKeywordSets   int `db:"total_keyword_sets" json:"totalKeywordSets"`
	EnabledKeywordSets int `db:"enabled_keyword_sets" json:"enabledKeywordSets"`
	TotalRules         int `db:"total_rules" json:"totalRules"`
	StringRules        int `db:"string_rules" json:"stringRules"`
	RegexRules         int `db:"regex_rules" json:"regexRules"`
	CaseSensitiveRules int `db:"case_sensitive_rules" json:"caseSensitiveRules"`
	DistinctCategories int `db:"distinct_categories" json:"distinctCategories"`
}

RuleStatistics provides aggregated statistics about keyword rules

type SSEClient

type SSEClient struct {
	ID             string
	UserID         uuid.UUID
	CampaignID     *uuid.UUID // Optional: filter events for specific campaign
	ResponseWriter http.ResponseWriter
	Flusher        http.Flusher
	Context        context.Context
	Cancel         context.CancelFunc
	LastSeen       time.Time
	// contains filtered or unexported fields
}

SSEClient represents a connected SSE client

type SSEConfig

type SSEConfig struct {
	KeepAliveInterval time.Duration
	StaleClientTTL    time.Duration
	CleanupInterval   time.Duration
}

type SSEEvent

type SSEEvent struct {
	ID         string                 `json:"id,omitempty"`
	Event      SSEEventType           `json:"event"`
	Data       map[string]interface{} `json:"data"`
	Timestamp  time.Time              `json:"timestamp"`
	CampaignID *uuid.UUID             `json:"campaign_id,omitempty"`
	UserID     *uuid.UUID             `json:"user_id,omitempty"`
}

SSEEvent represents a server-sent event

func CreateCampaignCompletedEvent

func CreateCampaignCompletedEvent(campaignID uuid.UUID, userID uuid.UUID, meta map[string]interface{}) SSEEvent

CreateCampaignCompletedEvent creates a campaign completed SSE event

func CreateCampaignProgressEvent

func CreateCampaignProgressEvent(campaignID uuid.UUID, userID uuid.UUID, progress map[string]interface{}) SSEEvent

CreateCampaignProgressEvent creates a campaign progress SSE event

func CreateModeChangedEvent

func CreateModeChangedEvent(campaignID uuid.UUID, userID uuid.UUID, mode string) SSEEvent

CreateModeChangedEvent emits when campaign execution mode changes

func CreatePhaseAutoStartedEvent

func CreatePhaseAutoStartedEvent(campaignID uuid.UUID, userID uuid.UUID, phase models.PhaseTypeEnum) SSEEvent

CreatePhaseAutoStartedEvent emits when a phase is started automatically (chained) in full_sequence mode

func CreatePhaseCompletedEvent

func CreatePhaseCompletedEvent(campaignID uuid.UUID, userID uuid.UUID, phase models.PhaseTypeEnum, results map[string]interface{}) SSEEvent

CreatePhaseCompletedEvent creates a phase completed SSE event

func CreatePhaseCompletedEventWithSequence

func CreatePhaseCompletedEventWithSequence(campaignID uuid.UUID, userID uuid.UUID, phase models.PhaseTypeEnum, sequence int64, results map[string]interface{}) SSEEvent

CreatePhaseCompletedEventWithSequence creates a phase completed SSE event with lifecycle sequence.

func CreatePhaseFailedEvent

func CreatePhaseFailedEvent(campaignID uuid.UUID, userID uuid.UUID, phase models.PhaseTypeEnum, error string) SSEEvent

CreatePhaseFailedEvent creates a phase failed SSE event

func CreatePhaseFailedEventWithSequence

func CreatePhaseFailedEventWithSequence(campaignID uuid.UUID, userID uuid.UUID, phase models.PhaseTypeEnum, sequence int64, errorMsg string) SSEEvent

CreatePhaseFailedEventWithSequence creates a phase failed SSE event with lifecycle sequence.

func CreatePhasePausedEvent

func CreatePhasePausedEvent(campaignID uuid.UUID, userID uuid.UUID, phase models.PhaseTypeEnum) SSEEvent

CreatePhasePausedEvent creates a phase paused SSE event

func CreatePhasePausedEventWithSequence

func CreatePhasePausedEventWithSequence(campaignID uuid.UUID, userID uuid.UUID, phase models.PhaseTypeEnum, sequence int64) SSEEvent

CreatePhasePausedEventWithSequence creates a phase paused SSE event with lifecycle sequence.

func CreatePhaseResumedEvent

func CreatePhaseResumedEvent(campaignID uuid.UUID, userID uuid.UUID, phase models.PhaseTypeEnum) SSEEvent

CreatePhaseResumedEvent creates a phase resumed SSE event

func CreatePhaseResumedEventWithSequence

func CreatePhaseResumedEventWithSequence(campaignID uuid.UUID, userID uuid.UUID, phase models.PhaseTypeEnum, sequence int64) SSEEvent

CreatePhaseResumedEventWithSequence creates a phase resumed SSE event with lifecycle sequence.

func CreatePhaseStartedEvent

func CreatePhaseStartedEvent(campaignID uuid.UUID, userID uuid.UUID, phase models.PhaseTypeEnum) SSEEvent

CreatePhaseStartedEvent creates a phase started SSE event

func CreatePhaseStartedEventWithSequence

func CreatePhaseStartedEventWithSequence(campaignID uuid.UUID, userID uuid.UUID, phase models.PhaseTypeEnum, sequence int64) SSEEvent

CreatePhaseStartedEventWithSequence creates a phase started SSE event with lifecycle sequence. Per contract: sequence is monotonically increasing per campaign, generated at persist time.

type SSEEventType

type SSEEventType string

SSEEventType represents the different types of SSE events

const (
	SSEEventCampaignProgress   SSEEventType = "campaign_progress"
	SSEEventCampaignCompleted  SSEEventType = "campaign_completed"
	SSEEventPhaseStarted       SSEEventType = "phase_started"
	SSEEventPhasePaused        SSEEventType = "phase_paused"
	SSEEventPhaseResumed       SSEEventType = "phase_resumed"
	SSEEventPhaseCompleted     SSEEventType = "phase_completed"
	SSEEventPhaseFailed        SSEEventType = "phase_failed"
	SSEEventPhaseAutoStarted   SSEEventType = "phase_auto_started"
	SSEEventDomainGenerated    SSEEventType = "domain_generated"
	SSEEventDomainValidated    SSEEventType = "domain_validated"
	SSEEventDomainStatusDelta  SSEEventType = "domain_status_delta"
	SSEEventCountersReconciled SSEEventType = "counters_reconciled"
	SSEEventAnalysisCompleted  SSEEventType = "analysis_completed"
	SSEEventModeChanged        SSEEventType = "mode_changed"
	// Keyword set lifecycle events
	SSEEventKeywordSetCreated SSEEventType = "keyword_set_created"
	SSEEventKeywordSetUpdated SSEEventType = "keyword_set_updated"
	SSEEventKeywordSetDeleted SSEEventType = "keyword_set_deleted"
	SSEEventKeepAlive         SSEEventType = "keep_alive"
	SSEEventError             SSEEventType = "error"
)

type SSEService

type SSEService struct {
	// contains filtered or unexported fields
}

SSEService manages Server-Sent Events connections and broadcasting

func NewSSEService

func NewSSEService() *SSEService

NewSSEService creates a new SSE service

func (*SSEService) BroadcastEvent

func (s *SSEService) BroadcastEvent(event SSEEvent)

BroadcastEvent sends an event to all connected clients

func (*SSEService) BroadcastToCampaign

func (s *SSEService) BroadcastToCampaign(campaignID uuid.UUID, event SSEEvent)

BroadcastToCampaign sends an event to all clients watching a specific campaign

func (*SSEService) BroadcastToUser

func (s *SSEService) BroadcastToUser(userID uuid.UUID, event SSEEvent)

BroadcastToUser sends an event to all clients for a specific user

func (*SSEService) Cleanup

func (s *SSEService) Cleanup()

Cleanup removes stale clients

func (*SSEService) GetClientCount

func (s *SSEService) GetClientCount() int

GetClientCount returns the current number of connected clients

func (*SSEService) GetClientsForUser

func (s *SSEService) GetClientsForUser(userID uuid.UUID) int

GetClientsForUser returns the number of clients connected for a specific user

func (*SSEService) GetTotalEvents

func (s *SSEService) GetTotalEvents() int

GetTotalEvents returns the total number of events sent since service start

func (*SSEService) GetUptime

func (s *SSEService) GetUptime() time.Duration

GetUptime returns the duration since the SSE service started

func (*SSEService) RegisterClient

func (s *SSEService) RegisterClient(ctx context.Context, w http.ResponseWriter, userID uuid.UUID, campaignID *uuid.UUID, allowedOrigin string) (*SSEClient, error)

RegisterClient registers a new SSE client

func (*SSEService) Start

func (s *SSEService) Start(ctx context.Context)

Start begins periodic cleanup for stale SSE clients.

func (*SSEService) UnregisterClient

func (s *SSEService) UnregisterClient(clientID string)

UnregisterClient removes a client from the service

type SessionData

type SessionData struct {
	ID                     string
	UserID                 uuid.UUID
	IPAddress              string
	UserAgent              string
	Fingerprint            string
	BrowserFingerprint     string
	ScreenResolution       string
	CreatedAt              time.Time
	LastActivity           time.Time
	ExpiresAt              time.Time
	IsActive               bool
	RequiresPasswordChange bool
}

SessionData represents session information stored in memory

type SessionMetrics

type SessionMetrics struct {
	TotalSessions  int64
	ActiveSessions int64
	CacheHitRate   float64
	AvgLookupTime  time.Duration
	CleanupCount   int64
	SecurityEvents int64
	// contains filtered or unexported fields
}

SessionMetrics tracks session performance metrics

type SessionService

type SessionService struct {
	// contains filtered or unexported fields
}

SessionService provides comprehensive session management

func NewSessionService

func NewSessionService(db *sqlx.DB, config *config.SessionConfig, auditLogStore store.AuditLogStore) (*SessionService, error)

NewSessionService creates a new session service

func (*SessionService) CreateSession

func (s *SessionService) CreateSession(userID uuid.UUID, ipAddress, userAgent string) (*SessionData, error)

CreateSession creates a new session with fingerprinting

func (*SessionService) ExtendSession

func (s *SessionService) ExtendSession(sessionID string, newExpiry time.Time) error

ExtendSession extends a session's expiration time

func (*SessionService) ExtendSessionWithSliding

func (s *SessionService) ExtendSessionWithSliding(sessionID string, currentExpiresAt time.Time) (time.Time, bool)

ExtendSessionWithSliding extends a session using sliding window expiration. Uses atomic UPDATE to prevent race conditions. Returns the new expiry time and whether the extension was successful.

func (*SessionService) GetConfig

func (s *SessionService) GetConfig() *config.SessionConfig

GetConfig returns the session configuration

func (*SessionService) GetMetrics

func (s *SessionService) GetMetrics() *SessionMetrics

GetMetrics returns session metrics

func (*SessionService) InvalidateAllUserSessions

func (s *SessionService) InvalidateAllUserSessions(userID uuid.UUID) error

InvalidateAllUserSessions invalidates all sessions for a user

func (*SessionService) InvalidateSession

func (s *SessionService) InvalidateSession(sessionID string) error

InvalidateSession invalidates a specific session

func (*SessionService) Stop

func (s *SessionService) Stop()

Stop stops the session service cleanup

func (*SessionService) ValidateSession

func (s *SessionService) ValidateSession(sessionID, clientIP string) (*SessionData, error)

ValidateSession validates a session and returns session data

type TOTPSecret

type TOTPSecret struct {
	UserID      string    `json:"userId"`
	Secret      string    `json:"secret"`
	QRCode      string    `json:"qrCode"`
	BackupCodes []string  `json:"backupCodes"`
	CreatedAt   time.Time `json:"createdAt"`
}

TOTPSecret represents a TOTP secret for a user

type TransitionError409

type TransitionError409 struct {
	Code            TransitionErrorCode    `json:"code"`
	CurrentState    models.PhaseStatusEnum `json:"current_state"`
	AttemptedAction string                 `json:"attempted_action"`
	Message         string                 `json:"message"`
	// Optional fields for rerun/retry failures
	Reason        string `json:"reason,omitempty"`
	BlockingPhase string `json:"blocking_phase,omitempty"`
	// P3.2: expected_state precondition fields
	ExpectedState *models.PhaseStatusEnum `json:"expected_state,omitempty"`
}

TransitionError409 is the structured 409 Conflict response per the contract. All invalid transition responses use this standardized error shape.

func NewExpectedStateMismatchError409

func NewExpectedStateMismatchError409(currentState, expectedState models.PhaseStatusEnum, attemptedAction string) *TransitionError409

NewExpectedStateMismatchError409 creates a 409 error when expected_state precondition fails (P3.2). This is returned when the client provides expected_state but the actual state differs.

func NewRerunPreconditionError409

func NewRerunPreconditionError409(currentState models.PhaseStatusEnum, reason, blockingPhase string) *TransitionError409

NewRerunPreconditionError409 creates a 409 error for failed rerun/retry preconditions.

func NewTransitionError409

func NewTransitionError409(currentState models.PhaseStatusEnum, attemptedAction string) *TransitionError409

NewTransitionError409 creates a 409 error for an invalid transition.

func (*TransitionError409) Error

func (e *TransitionError409) Error() string

func (*TransitionError409) MarshalJSON

func (e *TransitionError409) MarshalJSON() ([]byte, error)

MarshalJSON ensures proper JSON serialization for API responses.

type TransitionErrorCode

type TransitionErrorCode string

TransitionErrorCode is a machine-readable code for transition failures.

const (
	// ErrorCodeInvalidTransition indicates the state transition is not allowed.
	ErrorCodeInvalidTransition TransitionErrorCode = "INVALID_PHASE_TRANSITION"
	// ErrorCodeRerunPreconditionFailed indicates rerun/retry preconditions not met.
	ErrorCodeRerunPreconditionFailed TransitionErrorCode = "RERUN_PRECONDITION_FAILED"
	// ErrorCodeNoControlPhase indicates no active phase to control.
	ErrorCodeNoControlPhase TransitionErrorCode = "NO_CONTROL_PHASE"
	// ErrorCodeExpectedStateMismatch indicates expected_state precondition was not met (P3.2).
	ErrorCodeExpectedStateMismatch TransitionErrorCode = "EXPECTED_STATE_MISMATCH"
)

type TransitionTrigger

type TransitionTrigger string

TransitionTrigger describes what action caused a state transition.

const (
	TriggerStart     TransitionTrigger = "start"
	TriggerPause     TransitionTrigger = "pause"
	TriggerResume    TransitionTrigger = "resume"
	TriggerComplete  TransitionTrigger = "complete"
	TriggerFail      TransitionTrigger = "fail"
	TriggerRerun     TransitionTrigger = "rerun"
	TriggerRetry     TransitionTrigger = "retry"
	TriggerSkip      TransitionTrigger = "skip"
	TriggerConfigure TransitionTrigger = "configure"
)

func GetTriggerForTransition

func GetTriggerForTransition(from, to models.PhaseStatusEnum) TransitionTrigger

GetTriggerForTransition returns the trigger that causes this transition, or empty string if invalid.

type UpdateCampaignRequest

type UpdateCampaignRequest struct {
	Name                 *string                 `json:"name,omitempty"`
	CampaignType         *models.JobTypeEnum     `json:"campaignType,omitempty"`
	Status               *models.PhaseStatusEnum `json:"status,omitempty"`
	KeywordSetIDs        *[]uuid.UUID            `json:"keywordSetIds,omitempty"`
	PersonaIDs           *[]uuid.UUID            `json:"personaIds,omitempty"`
	ProxyPoolID          *uuid.UUID              `json:"proxyPoolId,omitempty"`
	NumDomainsToGenerate *int64                  `json:"numDomainsToGenerate,omitempty"`
	VariableLength       *int                    `json:"variableLength,omitempty"`
	CharacterSet         *string                 `json:"characterSet,omitempty"`
	ConstantString       *string                 `json:"constantString,omitempty"`
	TLD                  *string                 `json:"tld,omitempty"`
}

--- Campaign Update Request DTOs ---

type WorkerCompatibleService

type WorkerCompatibleService interface {
	StartPhase(ctx context.Context, campaignID uuid.UUID, phaseType string) error
	GetCampaignDetails(ctx context.Context, campaignID uuid.UUID) (*models.LeadGenerationCampaign, interface{}, error)
	SetCampaignStatus(ctx context.Context, campaignID uuid.UUID, status models.PhaseStatusEnum) error
	SetCampaignErrorStatus(ctx context.Context, campaignID uuid.UUID, errorMessage string) error
	HandleCampaignCompletion(ctx context.Context, campaignID uuid.UUID) error
}

WorkerCompatibleService defines the minimal interface needed by the worker service This allows CampaignOrchestrator to be used with the worker

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL