497 lines
14 KiB
Markdown
497 lines
14 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## Project Overview
|
||
|
||
This is a Go microservice skeleton/template for Quantex projects. It implements a **Hexagonal Architecture** (Ports & Adapters) pattern with clear separation between domain logic, application orchestration, and infrastructure concerns. The skeleton supports multiple execution modes (REST API service, MQTT async messaging, external API integration examples) through a runner-based system.
|
||
|
||
## Development Commands
|
||
|
||
### Building and Running
|
||
|
||
```bash
|
||
# Run the REST API service (text logs)
|
||
QUANTEX_ENVIRONMENT="dev" go run main.go -c -run service
|
||
|
||
# Run the REST API service (JSON logs)
|
||
QUANTEX_ENVIRONMENT="dev" go run main.go -run service
|
||
|
||
# Run with debug mode and specific log format
|
||
QUANTEX_ENVIRONMENT="dev" go run main.go -d -f tint1 -run service
|
||
|
||
# Build for current platform
|
||
make build
|
||
|
||
# Build for Linux (production)
|
||
make linux-build
|
||
```
|
||
|
||
### Available Runners
|
||
|
||
The application supports multiple execution modes via the `-run` flag:
|
||
- `service` - Main REST API server (Gin framework)
|
||
- `async` - MQTT messaging example
|
||
- `external` - QApix external API integration example
|
||
- `tracerr` - Error handling demonstration
|
||
- `logger` - Logging format demonstration
|
||
|
||
### Log Formats
|
||
|
||
Use `-f` or `-logs-format` flag:
|
||
- `json` - Structured JSON logs (default, for production)
|
||
- `text` - Plain text logs
|
||
- `tint1` - Single-line colored logs (best for local development)
|
||
- `tint2` - Two-line colored logs
|
||
|
||
### Testing and Linting
|
||
|
||
```bash
|
||
# Run all tests
|
||
make test
|
||
|
||
# Run tests for specific package
|
||
go test ./src/client/api/rest/...
|
||
|
||
# Run single test
|
||
go test ./src/... -run TestFunctionName
|
||
|
||
# Run checks and linters
|
||
make check
|
||
|
||
# Format code (gofumpt, gci, goimports)
|
||
make fmt
|
||
|
||
# Full CI pipeline (format, tidy, checks)
|
||
make ci
|
||
|
||
# Regenerate Swagger docs
|
||
make swag
|
||
|
||
# Run development workflow (checklist + check)
|
||
make dev
|
||
```
|
||
|
||
### Branch Management
|
||
|
||
```bash
|
||
# Create new branch with naming convention
|
||
make branch t=feature u=jdoe n=39 m="add new endpoint"
|
||
# Creates: feature/jdoe/SKL-39/add_new_endpoint
|
||
|
||
# Valid types: feature, hotfix, refactor, improvement, doc, fix
|
||
```
|
||
|
||
### Deployment
|
||
|
||
```bash
|
||
# Deploy to environment (requires SSH alias in ~/.ssh/config)
|
||
make deploy e=dev
|
||
make deploy e=prod
|
||
|
||
# First-time deployment
|
||
make first-deploy e=dev
|
||
```
|
||
|
||
## Architecture
|
||
|
||
### Layer Structure
|
||
|
||
The codebase follows Hexagonal Architecture with four distinct layers:
|
||
|
||
```
|
||
main.go (entry point)
|
||
↓
|
||
src/cmd/ (Command/Runner layer - bootstrap & execution modes)
|
||
↓
|
||
src/app/ (Application layer - configuration & wiring)
|
||
↓
|
||
src/client/ (Infrastructure layer - external integrations)
|
||
↓
|
||
src/domain/ (Domain layer - business logic & contracts)
|
||
↓
|
||
src/common/ (Cross-cutting concerns)
|
||
```
|
||
|
||
### Directory Organization
|
||
|
||
- **`src/domain/`** - Core business models and interfaces (Asyncer, Notifier, UserDataProvider). Pure domain logic with no dependencies on infrastructure.
|
||
|
||
- **`src/app/`** - Application-level configuration structures, version information, and global settings. Bridges domain and infrastructure.
|
||
|
||
- **`src/client/`** - All infrastructure implementations:
|
||
- `api/rest/` - Gin HTTP server, controllers, routes, middleware (auth, CORS)
|
||
- `api/async/` - MQTT client for async messaging
|
||
- `config/` - TOML configuration loading
|
||
- `data/` - Data provider implementations
|
||
- `store/` - Database (MultiDB) and external API clients (QApix)
|
||
- `notify/` - Notification services (Google Chat, Slack)
|
||
- `res/` - Embedded resources
|
||
|
||
- **`src/cmd/`** - Runners for different execution modes:
|
||
- `service/` - Main REST API service runner
|
||
- `example/` - Example runners (async, external, tracerr, logger)
|
||
- `base.go` - Runner abstraction and factory
|
||
|
||
- **`src/common/`** - Shared utilities:
|
||
- `logger/` - Multi-format logging (JSON, text, tint) with Gin middleware
|
||
- `tracerr/` - Error handling with stack trace capture
|
||
- `securetoken/` - JWT token encryption/validation
|
||
|
||
### REST API Architecture
|
||
|
||
The REST API uses **Gin framework** with the following patterns:
|
||
|
||
**Authentication Strategies:**
|
||
1. **Cookie-based** - HTTP-only secure cookie with Redis-backed session (20-minute TTL)
|
||
2. **Bearer token** - Format: `Bearer email:token`
|
||
3. **JWT token** - Service-to-service auth with permission validation
|
||
|
||
**Middleware Chain:**
|
||
```
|
||
Request → Options (CORS) → AuthRequired → Role Check → Handler
|
||
```
|
||
|
||
**Available middlewares in `src/client/api/rest/midlewares.go`:**
|
||
- `Options()` - CORS preflight handler
|
||
- `AuthRequired()` - Validates cookie or Authorization header
|
||
- `TokenAuth()` - Bearer token validation
|
||
- `JWTTokenAuth()` - JWT service token validation
|
||
- `CookieAuth()` - Session cookie validation
|
||
- Role-based: `SuperUser()`, `BackOfficeUser()`, `PartyAdmin()`, etc.
|
||
|
||
**Key files:**
|
||
- `server.go` - Server initialization, Redis pool setup, trusted proxies
|
||
- `controller.go` - HTTP handlers (Login, Refresh, GetUser)
|
||
- `routes.go` - Route definitions with middleware chains
|
||
- `model.go` - Request/response DTOs
|
||
- `validator.go` - Input validation
|
||
- `traslator.go` - Response formatting
|
||
|
||
### Async/MQTT Architecture
|
||
|
||
Located in `src/client/api/async/`, uses Eclipse Paho MQTT client:
|
||
|
||
- JWT-based authentication (token generated with service name and expiry)
|
||
- Auto-reconnect with keep-alive
|
||
- Topic structure: `{subdomain}/quantex/{topic}`
|
||
- Error notifications integrated
|
||
- Implements `domain.Asyncer` interface
|
||
|
||
### Configuration System
|
||
|
||
Configuration uses **TOML files** with two-level structure:
|
||
|
||
1. **Global config** (`../global_conf.toml`) - Shared settings across services
|
||
2. **Service config** (`conf.toml`) - Service-specific settings
|
||
|
||
Key configuration sections:
|
||
- `[MQTT]` - Async messaging settings
|
||
- `[Gin]` - HTTP server configuration
|
||
- `[Notify]` - Notification channels (Google, Slack)
|
||
- `[ExtAuth]` - External authentication providers
|
||
|
||
Environment variable `QUANTEX_ENVIRONMENT` (required) determines runtime behavior:
|
||
- `dev` - Development mode, debug logging, relaxed CORS
|
||
- `demo`, `open-demo` - Demo environments
|
||
- `prod` - Production mode, release logging, strict security
|
||
|
||
### Dependency Injection Pattern
|
||
|
||
Dependencies flow from `main.go` → runners → infrastructure:
|
||
|
||
```go
|
||
// Example from service runner
|
||
api := rest.New(userData, appStore, restConfig, notify)
|
||
// Dependencies: UserDataProvider, Store, Config, Notifier
|
||
```
|
||
|
||
All dependencies are interface-based for testability and loose coupling.
|
||
|
||
### Error Handling
|
||
|
||
Use `src/common/tracerr/` for errors that need stack traces:
|
||
|
||
```go
|
||
import "quantex.com/skeleton/src/common/tracerr"
|
||
|
||
// Instead of fmt.Errorf:
|
||
return tracerr.Errorf("failed to process: %w", err)
|
||
|
||
// Errors automatically include stack traces
|
||
// Critical errors trigger notification via domain.Notifier
|
||
```
|
||
|
||
### Logging
|
||
|
||
Access via standard library `log/slog`:
|
||
|
||
```go
|
||
import "log/slog"
|
||
|
||
slog.Info("message", "key", value)
|
||
slog.Error("error occurred", "error", err)
|
||
slog.Debug("debug info") // Only visible with -d flag
|
||
```
|
||
|
||
Logger integrates with Gin middleware for request logging and sends error-level logs to notifier.
|
||
|
||
## Common Development Patterns
|
||
|
||
### Adding a New REST Endpoint
|
||
|
||
1. Add handler method to `src/client/api/rest/controller.go`
|
||
2. Define request/response models in `model.go`
|
||
3. Add route in `routes.go` with appropriate middleware
|
||
4. Update Swagger comments (use `// @` annotations)
|
||
5. Run `make swag` to regenerate docs
|
||
6. Test with `make test`
|
||
|
||
### Adding a New Async Message Handler
|
||
|
||
1. In your runner, subscribe to topic:
|
||
```go
|
||
asyncManager.Subscribe("my-topic", func(topic string, msg []byte) {
|
||
// Handle message
|
||
})
|
||
```
|
||
2. Publish messages:
|
||
```go
|
||
asyncManager.Publish("my-topic", myMessage)
|
||
```
|
||
|
||
### Adding a New Notifier
|
||
|
||
1. Create package in `src/client/notify/{provider}/`
|
||
2. Implement `domain.Notifier` interface
|
||
3. Add configuration to `src/app/model.go`
|
||
4. Wire in `main.go` or use `notify/all/all.go` for multi-channel
|
||
|
||
### Extending the Store
|
||
|
||
Add repository methods to `src/client/store/manager.go`:
|
||
|
||
```go
|
||
func (s *Store) GetSomething(ctx context.Context, id string) (*domain.Model, error) {
|
||
// Use s.db for database access
|
||
}
|
||
```
|
||
|
||
## Module Path Convention
|
||
|
||
When initializing a new project from this skeleton:
|
||
|
||
1. Update `go.mod` module path (e.g., `quantex.com/myservice`)
|
||
2. Replace all imports from `quantex.com/skeleton` to `quantex.com/myservice`
|
||
3. Update `PROJECT` and `DOMAIN` in `Makefile.common`
|
||
4. Update `ISSUE_PREFIX` in `Makefile.common` (e.g., `MYPROJ`)
|
||
|
||
## Code Generation
|
||
|
||
### Enums
|
||
|
||
The project uses `go-enum` for type-safe enums. Files ending in `_enum.go` are generated:
|
||
|
||
```bash
|
||
# Generate enums (run after modifying enum comments)
|
||
make gogenerate
|
||
```
|
||
|
||
Example enum definition in source files:
|
||
```go
|
||
// ENUM(Test, Web, Panic, Error)
|
||
type MessageChannel string
|
||
```
|
||
|
||
### Swagger Documentation
|
||
|
||
Swagger docs are auto-generated from comments:
|
||
|
||
```go
|
||
// @Summary Get user details
|
||
// @Description Retrieves user information by ID
|
||
// @Tags users
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param id path string true "User ID"
|
||
// @Success 200 {object} UserResponse
|
||
// @Router /users/{id} [get]
|
||
```
|
||
|
||
Always run `make swag` after modifying REST API contracts.
|
||
|
||
## Important Conventions
|
||
|
||
### Import Grouping
|
||
|
||
Imports must be grouped (enforced by `gci`):
|
||
1. Standard library
|
||
2. Third-party packages
|
||
3. Quantex packages (prefixed with `quantex.com`)
|
||
|
||
Run `make fmt` to auto-format.
|
||
|
||
### Error Handling
|
||
|
||
- Always check errors
|
||
- Use `tracerr` for errors that need debugging context
|
||
- Wrap errors with context: `tracerr.Errorf("context: %w", err)`
|
||
- Critical errors automatically notify via configured channels
|
||
|
||
### Logging Best Practices
|
||
|
||
- Use structured logging with key-value pairs
|
||
- Use appropriate log levels (Debug, Info, Warn, Error)
|
||
- Include relevant context in log messages
|
||
- Avoid logging sensitive information (tokens, passwords)
|
||
|
||
### Testing
|
||
|
||
- Place `*_test.go` files alongside source code
|
||
- Use table-driven tests for multiple cases
|
||
- Integration tests should check `QUANTEX_ENVIRONMENT`
|
||
- Run with race detector: `go test -race ./...`
|
||
|
||
### Git Workflow
|
||
|
||
- Create branches using `make branch` command
|
||
- Reference issue numbers in commits (e.g., `SKL-123`)
|
||
- Run `make ci` before pushing
|
||
- PRs must pass all checks
|
||
- Keep PRs under 500 lines of diff
|
||
- Follow the checklist in `checklist.md`
|
||
|
||
## Security Considerations
|
||
|
||
### Authentication
|
||
|
||
Sessions are stored in Redis with 20-minute TTL. Cookie settings:
|
||
- `HttpOnly: true` - Prevents JavaScript access
|
||
- `Secure: true` in production - HTTPS only
|
||
- `SameSite: Strict` in production - CSRF protection
|
||
|
||
### JWT Tokens
|
||
|
||
Service-to-service JWT tokens use encryption and permission validation. See `src/common/securetoken/` for implementation.
|
||
|
||
### Configuration Secrets
|
||
|
||
- Never commit secrets to repository
|
||
- Use environment variables for sensitive data
|
||
- Configuration files in repo should be templates only
|
||
- Production secrets should be managed via deployment pipeline
|
||
|
||
## Troubleshooting
|
||
|
||
### "git state is not clean" Error
|
||
|
||
The `make ci` and `make push` commands check for uncommitted changes. Commit or stash changes before running.
|
||
|
||
### MultiDB Permission Errors
|
||
|
||
MultiDB creates log folders with restrictive permissions. Either:
|
||
```bash
|
||
# Run with sudo
|
||
sudo QUANTEX_ENVIRONMENT="dev" go run main.go -run service
|
||
|
||
# Or change permissions
|
||
sudo chmod 644 multiDB
|
||
sudo chmod 644 multiDB/2024_11_22
|
||
```
|
||
|
||
### Swagger Generation Fails
|
||
|
||
Ensure `src/client/api/rest/docs/docs.go` exists (even if empty):
|
||
```bash
|
||
mkdir -p src/client/api/rest/docs
|
||
echo "package docs" > src/client/api/rest/docs/docs.go
|
||
make swag
|
||
```
|
||
|
||
### MQTT Connection Issues
|
||
|
||
Check configuration in `conf.toml`:
|
||
```toml
|
||
[MQTT]
|
||
Protocol = "wss"
|
||
URL = "async-non-prod.quantex.com.ar/mqtt/"
|
||
Subdomain = "dev"
|
||
Secret = "your-secret-here"
|
||
```
|
||
|
||
Ensure the secret matches the server configuration.
|
||
|
||
## Templates
|
||
|
||
### Ticket Creation Template:
|
||
|
||
**Important:** In the console write the template in markdown format so the user can copy paste it directly.
|
||
|
||
```markdown
|
||
## ℹ️ Issue Type
|
||
|
||
- [ ] feature
|
||
- [ ] hotfix
|
||
- [ ] refactor
|
||
- [ ] improvement
|
||
- [ ] doc
|
||
- [ ] fix
|
||
|
||
## ❌ Issue Description
|
||
|
||
Summary_of_what_is_the_issue_and_include_screenshots_and_links_of_slack_to_follow_the_problem
|
||
|
||
## ✅ Expected Behaviuor
|
||
|
||
Explain_little_about_how_it_should_be_working
|
||
|
||
## 📋 Steps to Reproduce
|
||
|
||
What_steps_should_someone_take_to_reproduce_the_issue_include_screenshots_and_links
|
||
|
||
## 🐛 Possible Impacts
|
||
|
||
What_other_areas_in_our_code_might_be_affected_or_is_it_possible_that_something_else_broke_with_these_changes
|
||
```
|
||
|
||
## Code Review Description Template
|
||
|
||
**Important:** In the console write the template in markdown format so the user can copy paste it directly.
|
||
|
||
```markdown
|
||
## 🐛 Reason to Be
|
||
|
||
Double_click_to_replace_with_a_brief_summary_of_what_this_MR_does_including_a_summary_of_the_original_issue_and_include_screenshots_and_links_to_designs_if_this_MR_has_a_UI_component
|
||
|
||
Resolves #Issue_number
|
||
|
||
Related #Issue_number
|
||
|
||
|
||
## ✅ Expected Behaviuor
|
||
|
||
Explain_little_about_how_is_it_working_in_the_current_MR
|
||
|
||
|
||
## 📋 How To Test
|
||
|
||
What_steps_should_someone_take_to_test_these_changes_include_screenshots_and_links_to_mocks_for_any_ui_work
|
||
|
||
|
||
## ⚠️ Check List
|
||
|
||
1. [ ] Title format _**SKL-33: Implement Logging using Qapix Endpoints**_ (PREFIX-Issue#: Message)
|
||
2. [ ] Run `make ci` at your end
|
||
3. [ ] Check the pipeline is **🟢 SUCCESS**
|
||
4. [ ] Set the Assignee and Reviewer
|
||
5. [ ] Create 2 PRs for ⚡ HOTFIX in master and develop️
|
||
```
|
||
|
||
## Related Documentation
|
||
|
||
- README.md - Project initialization steps and examples
|
||
- checklist.md - PR review checklist
|
||
- AGENTS.md - Repository guidelines (if exists)
|
||
- `.golangci.yml` - Linter configuration
|
||
- `tools/check/` - Linter exclusions and settings
|