# 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 Domain-Driven Design (DDD) patterns, designed to be AI-friendly and easy to maintain. ## ๐Ÿ—๏ธ Architecture Guidelines ### Clean Architecture Layers - **Domain Layer** (`internal/{domain}/domain/`): Business entities, aggregates, interfaces, and core business rules - **Service Layer** (`internal/{domain}/service/`): Business logic and use cases - **Handler Layer** (`internal/{domain}/handler/`): HTTP controllers and request/response handling - **Repository Layer** (`internal/{domain}/domain/`): Data access implementations (embedded in domain) - **Infrastructure Layer** (`infra/`): External dependencies (DB, cache, queues, config) ### Domain Structure Pattern Each domain follows this flat structure: ``` internal/{domain}/ โ”œโ”€โ”€ entity.go # Core domain entities โ”œโ”€โ”€ aggregate.go # Aggregate roots and DTOs โ”œโ”€โ”€ repository.go # Repository interface and implementation โ”œโ”€โ”€ service.go # Business logic and use cases โ”œโ”€โ”€ form.go # Request/response forms with validation โ””โ”€โ”€ handler.go # HTTP controllers and request/response handling ``` **Package Structure**: All files in a domain use the same package name (e.g., `package customer`) ### Dependency Rules - Always depend on interfaces, not concrete implementations - Use dependency injection through constructors - All files in a domain use the same package name for easy access - Repository implementations are in the same package as interfaces - Keep dependencies minimal and focused - **NO GLOBAL VARIABLES**: Everything must be injected, including validation functions ## ๐Ÿ’ป Go Best Practices ### Code Structure - Use standard Go project layout with `internal/` for private code - Group related functionality in domain 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., `CustomerRepository`, `AuthService`) - Use descriptive variable names, avoid abbreviations - Constants should be in ALL_CAPS with underscores - Domain packages use singular form (e.g., `customer`, not `customers`) ### 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 same package (`repository.go`) - 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`, `GetByCompanyID`) - Repository implementation is in the same file as the interface ### Service Interfaces - Define business operations clearly in service.go - Use request/response forms for complex operations - Include validation in service methods - Handle business logic, not infrastructure concerns - Service implementation is in the same package as other domain files ## ๐Ÿ“ Logging Standards ### Logging Location - **NO LOGGING IN HANDLERS**: All logging must be done in the service layer - Handlers should only handle HTTP concerns (validation, response formatting) - Service layer is responsible for all business logic logging - Repository layer can log database operations ### Using Custom Logger Interface - Always use structured logging with fields - Include relevant context (user_id, customer_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 // Service layer - GOOD func (s *CustomerService) CreateCustomer(ctx context.Context, req CreateCustomerRequest) (*Customer, error) { s.logger.Info("Creating new customer", map[string]interface{}{ "email": req.Email, "company_id": req.CompanyID, }) // ... business logic } // Handler - BAD (no logging here) func (h *CustomerHandler) CreateCustomer(c *gin.Context) { // Only handle HTTP concerns, no logging } ``` ### Error Logging - Log errors with full context in service layer - 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 domain package (`{domain}.go`) - Use proper database transactions for related operations - Handle database errors gracefully - Use prepared statements or ORM query builders - Implement proper pagination with limit/offset - **Time Handling**: Always use Unix timestamps (int64) for database operations - **Timestamp Updates**: Use `time.Now().Unix()` for created_at and updated_at fields ### Data Models - Use domain entities directly with BSON tags for MongoDB - Include audit fields (created_at, updated_at) - Use proper database field tags (bson, json) - Never serialize sensitive fields (passwords) ### Time Handling Patterns - **Input**: Accept Unix timestamps (int64) for all time fields - **Database Storage**: Store as Unix timestamps (int64) in MongoDB - **Output**: Return Unix timestamps (int64) for all time fields in API responses - **Internal Processing**: Use Unix timestamps (int64) for all business logic - **Audit Fields**: Always use Unix timestamps for created_at, updated_at - **Consistency**: All time operations use Unix timestamps throughout the application ### MongoDB Patterns - Create indexes in repository constructor - Use proper BSON field names - Handle duplicate key errors appropriately - Use MongoDB-specific features (aggregations, etc.) - **Time Fields**: Store all time fields as Unix timestamps (int64) for consistency - **Queries**: Use Unix timestamps for time-based queries and filtering ## ๐ŸŒ HTTP Handler Guidelines ### Request Handling - Validate all incoming requests using govalidator - Use proper HTTP status codes - Return consistent API response format using `pkg/response` - Handle CORS appropriately - Include request timeout handling - **Time Input**: Accept Unix timestamps (int64) for all time fields in requests - **Time Validation**: Validate Unix timestamps are within reasonable ranges - **Time Consistency**: All time inputs must be Unix timestamps (int64) - **NO LOGGING**: Handlers should not contain any logging statements ### Govalidator Usage - Use govalidator for all request validation - Define validation tags in request structs - Use custom validation functions for complex rules - Validate at handler level before calling services - Return validation errors using `response.ValidationError()` - Use meaningful error messages for validation failures - **Validation Injection**: Pass validation functions as dependencies, never use global validation ### 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 - **Time Output**: Always return Unix timestamps (int64) for all time fields in API responses - **Time Consistency**: Ensure all time fields in responses use Unix timestamps consistently ### Security - Validate and sanitize all inputs - Use proper authentication middleware - Implement rate limiting - Never log sensitive information (passwords, tokens) - Use HTTPS in production ## ๐Ÿ“š Documentation Standards ### Code Documentation - **Only document infrastructure and complex business logic** - Don't over-document simple operations - Document public interfaces and types that might be confusing - Use Go doc comments format - Include examples for complex functions - Keep comments up to date with code changes ### API Documentation - **Use Swagger/OpenAPI comments for all API endpoints** - Document all endpoints with examples - Include error response examples - Document authentication requirements - Keep Swagger documentation up to date ### Swagger Comment Examples ```go // @Summary Create a new customer // @Description Create a new customer with the provided information // @Tags customers // @Accept json // @Produce json // @Param customer body CreateCustomerRequest true "Customer information" // @Success 201 {object} response.Response{data=Customer} // @Failure 400 {object} response.Response // @Failure 500 {object} response.Response // @Router /customers [post] func (h *CustomerHandler) CreateCustomer(c *gin.Context) { // Handler implementation } ``` ## ๐Ÿงช 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 Structure - Use YAML for configuration files - Support environment variable overrides - Validate configuration on startup - Use default values for optional settings - Document all configuration options ### Configuration Types - Server configuration (host, port, timeouts) - Database configuration (MongoDB URI, pool settings) - Cache configuration (Redis settings) - Queue configuration (RabbitMQ settings) - Auth configuration (JWT settings) - Logging configuration (level, format, output) ### 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 ## ๐Ÿ” 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 - **Don't log in handlers** - **Don't use global validation functions** ### 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 - **Logging in handlers instead of services** - **Using global variables for validation** ## ๐Ÿ“‹ Checklist for New Features ### Before Implementation - [ ] Define interfaces in the same package (`repository.go`) - [ ] Create proper request/response forms with govalidator tags (`form.go`) - [ ] Plan error handling strategy - [ ] Design database schema if needed - [ ] Consider caching requirements - [ ] Define custom validators if needed - [ ] Plan logging strategy (service layer only) - [ ] Plan dependency injection for validation ### During Implementation - [ ] Follow flat domain structure (all files in same package) - [ ] Use dependency injection - [ ] Implement proper logging in service layer only - [ ] Add govalidator validation tags to forms - [ ] Register custom validators as injected dependencies - [ ] Handle errors gracefully - [ ] Add Swagger comments to handlers - [ ] Ensure no global variables are used ### After Implementation - [ ] Write unit tests - [ ] Update API documentation (Swagger) - [ ] Test error scenarios - [ ] Verify security implications - [ ] Check performance impact - [ ] Test validation scenarios - [ ] Verify no logging in handlers - [ ] Verify all dependencies are injected ## ๐Ÿš€ 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 - **Follow the flat domain structure**: All files in a domain use the same package name - Use the custom logger interface consistently in service layer only - Implement proper error handling and logging - Follow the repository pattern with interface and implementation in same file - **Time Consistency**: Always use Unix timestamps (int64) for input, storage, and output - **Time Validation**: Validate all Unix timestamp inputs are within reasonable ranges - **Time Utilities**: Use centralized time utility functions for consistency across the application - **No Format Conversion**: Never convert between Unix timestamps and other time formats in the application - **Validation**: Always use govalidator for request validation with proper tags - **Form Design**: Define validation rules in request forms, not in handlers - **Custom Validators**: Register custom validators as injected dependencies - **Package Structure**: Keep all domain files in the same package for easy access and minimal imports - **NO GLOBAL VARIABLES**: Everything must be injected - **NO LOGGING IN HANDLERS**: All logging must be in service layer - **SWAGGER DOCUMENTATION**: Use Swagger comments for all API endpoints