--- alwaysApply: true --- # Cursor Rules for Tender Management Go Backend ## Project Context This is a Go backend API for a tender management system following Clean Architecture principles with minimal complexity, designed to be AI-friendly and easy to maintain. ## ๐Ÿ—๏ธ Architecture Guidelines ### Clean Architecture Layers - **Domain Layer** (`internal/domain/`): Business entities, interfaces, and core business rules - **Service Layer** (`internal/service/`): Business logic and use cases - **Handler Layer** (`internal/handler/`): HTTP controllers and request/response handling - **Repository Layer** (`internal/repository/`): Data access implementations - **Infrastructure Layer** (`internal/infrastructure/`): External dependencies (DB, cache, queues) ### Dependency Rules - Always depend on interfaces, not concrete implementations - Use dependency injection through constructors - Inner layers should never depend on outer layers - All dependencies flow inward toward the domain ## ๐Ÿ’ป Go Best Practices ### Code Structure - Use standard Go project layout with `internal/` for private code - Group related functionality in packages - Keep packages focused on single responsibility - Use meaningful package names (not generic like `utils` or `helpers`) ### Naming Conventions - Use Go naming conventions: camelCase for private, PascalCase for public - Interface names should describe what they do (e.g., `UserRepository`, `AuthService`) - Use descriptive variable names, avoid abbreviations - Constants should be in ALL_CAPS with underscores ### Error Handling - Always handle errors explicitly, never ignore them - Use structured error messages with context - Wrap errors with additional context using `fmt.Errorf("context: %w", err)` - Log errors at the point they occur with relevant fields - Return domain-specific error types when appropriate ### Function Design - Keep functions small and focused (max 20-30 lines) - Use early returns to reduce nesting - Validate inputs at function entry points - Use descriptive parameter names - Limit function parameters (max 3-4, use structs for more) ## ๐Ÿ”Œ Interface Design ### Repository Interfaces - Always create interfaces in the domain layer - Use context.Context as first parameter for all methods - Return domain entities, not database models - Include common operations: Create, GetByID, Update, Delete, List - Use specific query methods (e.g., `GetByEmail`, `GetActiveUsers`) ### Service Interfaces - Define business operations clearly - Use request/response DTOs for complex operations - Include validation in service methods - Handle business logic, not infrastructure concerns ## ๐Ÿ“ Logging Standards ### Using Zap Logger - Always use structured logging with fields - Include relevant context (user_id, request_id, etc.) - Use appropriate log levels: - `Debug`: Detailed debugging information - `Info`: General operational messages - `Warn`: Warning conditions that should be addressed - `Error`: Error conditions that need attention - `Fatal`: Critical errors that cause program termination ### Logging Examples ```go // Good log.Info("User authenticated successfully", map[string]interface{}{ "user_id": user.ID.String(), "email": user.Email, "ip": clientIP, }) // Bad log.Info("User login") ``` ### Error Logging - Log errors with full context - Include error details and relevant fields - Don't log the same error multiple times in the call stack ## ๐Ÿ—„๏ธ Database & Repository Patterns ### Repository Implementation - Implement repository interfaces in `internal/repository/` - Use proper database transactions for related operations - Handle database errors gracefully - Use prepared statements or ORM query builders - Implement proper pagination ### Data Models - Separate database models from domain entities - Convert between database models and domain entities in repositories - Use proper database field tags (bson, json) - Include audit fields (created_at, updated_at) ## ๐ŸŒ HTTP Handler Guidelines ### Request Handling - Validate all incoming requests using struct tags - Use proper HTTP status codes - Return consistent API response format using `pkg/response` - Handle CORS appropriately - Include request timeout handling ### Response Format - Always use standardized response structure from `pkg/response` - Include appropriate metadata for paginated responses - Provide meaningful error messages - Never expose internal errors to clients ### Security - Validate and sanitize all inputs - Use proper authentication middleware - Implement rate limiting - Never log sensitive information (passwords, tokens) - Use HTTPS in production ## ๐Ÿงช Testing Guidelines ### Test Structure - Write unit tests for all business logic - Use table-driven tests for multiple scenarios - Mock external dependencies using interfaces - Test error cases, not just happy paths - Use meaningful test names that describe the scenario ### Test Organization - Place tests in same package as code being tested - Use `_test.go` suffix for test files - Create test utilities in `testutil` package if needed - Use setup/teardown functions for common test data ## ๐Ÿ“‹ Configuration Management ### Configuration Files - Use YAML for configuration files - Support environment variable overrides - Validate configuration on startup - Use default values for optional settings - Document all configuration options ### Environment Variables - Use consistent naming convention (e.g., `TM_DATABASE_URI`) - Never commit secrets in configuration files - Use different configs for different environments ## ๐Ÿš€ Performance Guidelines ### Optimization - Use database indexes appropriately - Implement caching for frequently accessed data - Use connection pooling for databases - Avoid N+1 queries - Profile performance bottlenecks ### Memory Management - Close resources properly (database connections, files) - Use context for cancellation and timeouts - Avoid memory leaks in goroutines - Use sync.Pool for frequently allocated objects ## ๐Ÿ“š Documentation Standards ### Code Documentation - Write clear comments for complex business logic - Document all public interfaces and types - Use Go doc comments format - Include examples for complex functions - Keep comments up to date with code changes ### API Documentation - Use OpenAPI/Swagger annotations - Document all endpoints with examples - Include error response examples - Document authentication requirements ## ๐Ÿ” Security Best Practices ### Authentication & Authorization - Use JWT tokens with proper expiration - Implement refresh token rotation - Use bcrypt for password hashing - Validate token claims properly - Implement proper RBAC ### Input Validation - Validate all inputs at API boundaries - Use whitelist validation, not blacklist - Sanitize inputs to prevent injection attacks - Validate file uploads properly ## ๐Ÿ“ฆ Dependency Management ### Go Modules - Keep go.mod clean and organized - Pin major versions for stability - Regular dependency updates with testing - Remove unused dependencies - Use vendor directory for critical dependencies ### External Libraries - Prefer standard library when possible - Choose well-maintained libraries - Avoid dependencies with security issues - Keep dependencies minimal ## ๐Ÿ”„ Code Review Guidelines ### Before Committing - Run `go fmt`, `go vet`, and linting tools - Ensure all tests pass - Check for proper error handling - Verify logging is appropriate - Confirm no sensitive data is exposed ### Code Quality - Follow single responsibility principle - Avoid code duplication - Use meaningful variable names - Keep functions and files reasonably sized - Maintain consistent code style ## ๐Ÿšจ Error Patterns to Avoid ### Anti-patterns - Don't use panic for regular error handling - Avoid global variables for application state - Don't ignore context cancellation - Avoid deeply nested if statements - Don't use reflection unless absolutely necessary ### Common Mistakes - Not handling database connection errors - Forgetting to close resources - Not validating user inputs - Exposing internal errors to clients - Not using proper HTTP status codes ## ๐Ÿ“‹ Checklist for New Features ### Before Implementation - [ ] Define interfaces in domain layer - [ ] Create proper request/response DTOs - [ ] Plan error handling strategy - [ ] Design database schema if needed - [ ] Consider caching requirements ### During Implementation - [ ] Follow clean architecture layers - [ ] Use dependency injection - [ ] Implement proper logging - [ ] Add input validation - [ ] Handle errors gracefully ### After Implementation - [ ] Write unit tests - [ ] Update API documentation - [ ] Test error scenarios - [ ] Verify security implications - [ ] Check performance impact ## ๐ŸŽฏ Code Examples ### Service Implementation Template ```go type UserServiceImpl struct { userRepo domain.UserRepository logger logger.Logger } func NewUserService(userRepo domain.UserRepository, logger logger.Logger) domain.UserService { return &UserServiceImpl{ userRepo: userRepo, logger: logger, } } func (s *UserServiceImpl) CreateUser(ctx context.Context, req domain.CreateUserRequest) (*domain.User, error) { // Validate input if err := validateCreateUserRequest(req); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } // Business logic user := &domain.User{ ID: uuid.New(), Email: req.Email, // ... other fields CreatedAt: time.Now(), UpdatedAt: time.Now(), } // Repository call if err := s.userRepo.Create(ctx, user); err != nil { s.logger.Error("Failed to create user", map[string]interface{}{ "error": err.Error(), "email": req.Email, }) return nil, fmt.Errorf("failed to create user: %w", err) } s.logger.Info("User created successfully", map[string]interface{}{ "user_id": user.ID.String(), "email": user.Email, }) return user, nil } ``` ### Handler Implementation Template ```go func (h *UserHandler) CreateUser(c echo.Context) error { var req domain.CreateUserRequest // Bind and validate request if err := c.Bind(&req); err != nil { return response.BadRequest(c, "Invalid request format", err.Error()) } if err := h.validator.Struct(&req); err != nil { return response.ValidationError(c, "Validation failed", err.Error()) } // Call service user, err := h.userService.CreateUser(c.Request().Context(), req) if err != nil { h.logger.Error("Create user failed", map[string]interface{}{ "error": err.Error(), "email": req.Email, }) return response.InternalServerError(c, "Failed to create user") } return response.Created(c, user, "User created successfully") } ``` ## ๐Ÿš€ Remember - Prioritize simplicity and readability over cleverness - Make code self-documenting through clear naming - Always consider the person who will maintain this code - Test your code thoroughly - Security and performance are not optional # Cursor Rules for Tender Management Go Backend ## Project Context This is a Go backend API for a tender management system following Clean Architecture principles with minimal complexity, designed to be AI-friendly and easy to maintain. ## ๐Ÿ—๏ธ Architecture Guidelines ### Clean Architecture Layers - **Domain Layer** (`internal/domain/`): Business entities, interfaces, and core business rules - **Service Layer** (`internal/service/`): Business logic and use cases - **Handler Layer** (`internal/handler/`): HTTP controllers and request/response handling - **Repository Layer** (`internal/repository/`): Data access implementations - **Infrastructure Layer** (`internal/infrastructure/`): External dependencies (DB, cache, queues) ### Dependency Rules - Always depend on interfaces, not concrete implementations - Use dependency injection through constructors - Inner layers should never depend on outer layers - All dependencies flow inward toward the domain ## ๐Ÿ’ป Go Best Practices ### Code Structure - Use standard Go project layout with `internal/` for private code - Group related functionality in packages - Keep packages focused on single responsibility - Use meaningful package names (not generic like `utils` or `helpers`) ### Naming Conventions - Use Go naming conventions: camelCase for private, PascalCase for public - Interface names should describe what they do (e.g., `UserRepository`, `AuthService`) - Use descriptive variable names, avoid abbreviations - Constants should be in ALL_CAPS with underscores ### Error Handling - Always handle errors explicitly, never ignore them - Use structured error messages with context - Wrap errors with additional context using `fmt.Errorf("context: %w", err)` - Log errors at the point they occur with relevant fields - Return domain-specific error types when appropriate ### Function Design - Keep functions small and focused (max 20-30 lines) - Use early returns to reduce nesting - Validate inputs at function entry points - Use descriptive parameter names - Limit function parameters (max 3-4, use structs for more) ## ๐Ÿ”Œ Interface Design ### Repository Interfaces - Always create interfaces in the domain layer - Use context.Context as first parameter for all methods - Return domain entities, not database models - Include common operations: Create, GetByID, Update, Delete, List - Use specific query methods (e.g., `GetByEmail`, `GetActiveUsers`) ### Service Interfaces - Define business operations clearly - Use request/response DTOs for complex operations - Include validation in service methods - Handle business logic, not infrastructure concerns ## ๐Ÿ“ Logging Standards ### Using Zap Logger - Always use structured logging with fields - Include relevant context (user_id, request_id, etc.) - Use appropriate log levels: - `Debug`: Detailed debugging information - `Info`: General operational messages - `Warn`: Warning conditions that should be addressed - `Error`: Error conditions that need attention - `Fatal`: Critical errors that cause program termination ### Logging Examples ```go // Good log.Info("User authenticated successfully", map[string]interface{}{ "user_id": user.ID.String(), "email": user.Email, "ip": clientIP, }) // Bad log.Info("User login") ``` ### Error Logging - Log errors with full context - Include error details and relevant fields - Don't log the same error multiple times in the call stack ## ๐Ÿ—„๏ธ Database & Repository Patterns ### Repository Implementation - Implement repository interfaces in `internal/repository/` - Use proper database transactions for related operations - Handle database errors gracefully - Use prepared statements or ORM query builders - Implement proper pagination ### Data Models - Separate database models from domain entities - Convert between database models and domain entities in repositories - Use proper database field tags (bson, json) - Include audit fields (created_at, updated_at) ## ๐ŸŒ HTTP Handler Guidelines ### Request Handling - Validate all incoming requests using struct tags - Use proper HTTP status codes - Return consistent API response format using `pkg/response` - Handle CORS appropriately - Include request timeout handling ### Response Format - Always use standardized response structure from `pkg/response` - Include appropriate metadata for paginated responses - Provide meaningful error messages - Never expose internal errors to clients ### Security - Validate and sanitize all inputs - Use proper authentication middleware - Implement rate limiting - Never log sensitive information (passwords, tokens) - Use HTTPS in production ## ๐Ÿงช Testing Guidelines ### Test Structure - Write unit tests for all business logic - Use table-driven tests for multiple scenarios - Mock external dependencies using interfaces - Test error cases, not just happy paths - Use meaningful test names that describe the scenario ### Test Organization - Place tests in same package as code being tested - Use `_test.go` suffix for test files - Create test utilities in `testutil` package if needed - Use setup/teardown functions for common test data ## ๐Ÿ“‹ Configuration Management ### Configuration Files - Use YAML for configuration files - Support environment variable overrides - Validate configuration on startup - Use default values for optional settings - Document all configuration options ### Environment Variables - Use consistent naming convention (e.g., `TM_DATABASE_URI`) - Never commit secrets in configuration files - Use different configs for different environments ## ๐Ÿš€ Performance Guidelines ### Optimization - Use database indexes appropriately - Implement caching for frequently accessed data - Use connection pooling for databases - Avoid N+1 queries - Profile performance bottlenecks ### Memory Management - Close resources properly (database connections, files) - Use context for cancellation and timeouts - Avoid memory leaks in goroutines - Use sync.Pool for frequently allocated objects ## ๐Ÿ“š Documentation Standards ### Code Documentation - Write clear comments for complex business logic - Document all public interfaces and types - Use Go doc comments format - Include examples for complex functions - Keep comments up to date with code changes ### API Documentation - Use OpenAPI/Swagger annotations - Document all endpoints with examples - Include error response examples - Document authentication requirements ## ๐Ÿ” Security Best Practices ### Authentication & Authorization - Use JWT tokens with proper expiration - Implement refresh token rotation - Use bcrypt for password hashing - Validate token claims properly - Implement proper RBAC ### Input Validation - Validate all inputs at API boundaries - Use whitelist validation, not blacklist - Sanitize inputs to prevent injection attacks - Validate file uploads properly ## ๐Ÿ“ฆ Dependency Management ### Go Modules - Keep go.mod clean and organized - Pin major versions for stability - Regular dependency updates with testing - Remove unused dependencies - Use vendor directory for critical dependencies ### External Libraries - Prefer standard library when possible - Choose well-maintained libraries - Avoid dependencies with security issues - Keep dependencies minimal ## ๐Ÿ”„ Code Review Guidelines ### Before Committing - Run `go fmt`, `go vet`, and linting tools - Ensure all tests pass - Check for proper error handling - Verify logging is appropriate - Confirm no sensitive data is exposed ### Code Quality - Follow single responsibility principle - Avoid code duplication - Use meaningful variable names - Keep functions and files reasonably sized - Maintain consistent code style ## ๐Ÿšจ Error Patterns to Avoid ### Anti-patterns - Don't use panic for regular error handling - Avoid global variables for application state - Don't ignore context cancellation - Avoid deeply nested if statements - Don't use reflection unless absolutely necessary ### Common Mistakes - Not handling database connection errors - Forgetting to close resources - Not validating user inputs - Exposing internal errors to clients - Not using proper HTTP status codes ## ๐Ÿ“‹ Checklist for New Features ### Before Implementation - [ ] Define interfaces in domain layer - [ ] Create proper request/response DTOs - [ ] Plan error handling strategy - [ ] Design database schema if needed - [ ] Consider caching requirements ### During Implementation - [ ] Follow clean architecture layers - [ ] Use dependency injection - [ ] Implement proper logging - [ ] Add input validation - [ ] Handle errors gracefully ### After Implementation - [ ] Write unit tests - [ ] Update API documentation - [ ] Test error scenarios - [ ] Verify security implications - [ ] Check performance impact ## ๐ŸŽฏ Code Examples ### Service Implementation Template ```go type UserServiceImpl struct { userRepo domain.UserRepository logger logger.Logger } func NewUserService(userRepo domain.UserRepository, logger logger.Logger) domain.UserService { return &UserServiceImpl{ userRepo: userRepo, logger: logger, } } func (s *UserServiceImpl) CreateUser(ctx context.Context, req domain.CreateUserRequest) (*domain.User, error) { // Validate input if err := validateCreateUserRequest(req); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } // Business logic user := &domain.User{ ID: uuid.New(), Email: req.Email, // ... other fields CreatedAt: time.Now(), UpdatedAt: time.Now(), } // Repository call if err := s.userRepo.Create(ctx, user); err != nil { s.logger.Error("Failed to create user", map[string]interface{}{ "error": err.Error(), "email": req.Email, }) return nil, fmt.Errorf("failed to create user: %w", err) } s.logger.Info("User created successfully", map[string]interface{}{ "user_id": user.ID.String(), "email": user.Email, }) return user, nil } ``` ### Handler Implementation Template ```go func (h *UserHandler) CreateUser(c echo.Context) error { var req domain.CreateUserRequest // Bind and validate request if err := c.Bind(&req); err != nil { return response.BadRequest(c, "Invalid request format", err.Error()) } if err := h.validator.Struct(&req); err != nil { return response.ValidationError(c, "Validation failed", err.Error()) } // Call service user, err := h.userService.CreateUser(c.Request().Context(), req) if err != nil { h.logger.Error("Create user failed", map[string]interface{}{ "error": err.Error(), "email": req.Email, }) return response.InternalServerError(c, "Failed to create user") } return response.Created(c, user, "User created successfully") } ``` ## ๐Ÿš€ Remember - Prioritize simplicity and readability over cleverness - Make code self-documenting through clear naming - Always consider the person who will maintain this code - Test your code thoroughly - Security and performance are not optional