98f581ec97
- Updated cursor rules to emphasize the importance of dependency injection and logging practices. - Introduced a new user management domain, including entities, services, handlers, and validation. - Implemented user authentication features such as login, registration, and role-based access control. - Added Redis integration for token management and caching. - Enhanced API documentation with Swagger for user-related endpoints. - Updated configuration to support new JWT settings and Redis connection parameters.
400 lines
15 KiB
Plaintext
400 lines
15 KiB
Plaintext
---
|
|
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 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 |