package user import ( "context" "time" ) // User represents a user in the system type User struct { ID uint `json:"id" gorm:"primaryKey"` CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"` UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` DeletedAt *time.Time `json:"deleted_at,omitempty" gorm:"index"` Username string `json:"username" gorm:"unique;not null" validate:"required,min=3,max=50"` PasswordHash string `json:"-" gorm:"not null"` Description *string `json:"description,omitempty"` CurrentGoal *string `json:"current_goal,omitempty"` IsAdmin bool `json:"is_admin" gorm:"default:false"` AllowPasswordReset bool `json:"allow_password_reset" gorm:"default:false"` LastLogin *time.Time `json:"last_login,omitempty"` } // UserRepository defines the interface for user persistence type UserRepository interface { CreateUser(ctx context.Context, user *User) error GetUserByUsername(ctx context.Context, username string) (*User, error) GetUserByID(ctx context.Context, id uint) (*User, error) UpdateUser(ctx context.Context, user *User) error DeleteUser(ctx context.Context, id uint) error AllowPasswordReset(ctx context.Context, username string) error CompletePasswordReset(ctx context.Context, username, newPassword string) error UserExists(ctx context.Context, username string) (bool, error) CheckDatabaseHealth(ctx context.Context) error } // AuthService defines interface for authentication operations type AuthService interface { Authenticate(ctx context.Context, username, password string) (*User, error) GenerateJWT(ctx context.Context, user *User) (string, error) ValidateJWT(ctx context.Context, token string) (*User, error) AdminAuthenticate(ctx context.Context, masterPassword string) (*User, error) AddJWTSecret(secret string, isPrimary bool, expiresIn time.Duration) RotateJWTSecret(newSecret string) GetJWTSecretByIndex(index int) (string, bool) ResetJWTSecrets() // Reset JWT secrets to initial state for test cleanup // StartJWTSecretCleanupLoop starts a goroutine that periodically calls // RemoveExpiredJWTSecrets at the given interval, stopping when ctx is // cancelled. Implements the cleanup half of ADR-0021. interval <= 0 // disables the loop. StartJWTSecretCleanupLoop(ctx context.Context, interval time.Duration) // RemoveExpiredJWTSecrets triggers an immediate cleanup pass and returns // the count of removed non-primary expired secrets. Useful for tests // driving cleanup synchronously. RemoveExpiredJWTSecrets() int } // UserManager defines interface for user management operations type UserManager interface { UserExists(ctx context.Context, username string) (bool, error) CreateUser(ctx context.Context, user *User) error } // PasswordService defines interface for password operations type PasswordService interface { HashPassword(ctx context.Context, password string) (string, error) RequestPasswordReset(ctx context.Context, username string) error CompletePasswordReset(ctx context.Context, username, newPassword string) error } // UserService composes all user-related interfaces using Go's interface composition // This is cleaner than aggregation and better for testing type UserService interface { AuthService UserManager PasswordService } // PasswordResetService defines the interface for password reset workflow type PasswordResetService interface { RequestPasswordReset(ctx context.Context, username string) error CompletePasswordReset(ctx context.Context, username, newPassword string) error }