14 KiB
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
# 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 exampleexternal- QApix external API integration exampletracerr- Error handling demonstrationlogger- Logging format demonstration
Log Formats
Use -f or -logs-format flag:
json- Structured JSON logs (default, for production)text- Plain text logstint1- Single-line colored logs (best for local development)tint2- Two-line colored logs
Testing and Linting
# 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
# 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
# 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 messagingconfig/- TOML configuration loadingdata/- Data provider implementationsstore/- 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 runnerexample/- 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 middlewaretracerr/- Error handling with stack trace capturesecuretoken/- JWT token encryption/validation
REST API Architecture
The REST API uses Gin framework with the following patterns:
Authentication Strategies:
- Cookie-based - HTTP-only secure cookie with Redis-backed session (20-minute TTL)
- Bearer token - Format:
Bearer email:token - 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 handlerAuthRequired()- Validates cookie or Authorization headerTokenAuth()- Bearer token validationJWTTokenAuth()- JWT service token validationCookieAuth()- Session cookie validation- Role-based:
SuperUser(),BackOfficeUser(),PartyAdmin(), etc.
Key files:
server.go- Server initialization, Redis pool setup, trusted proxiescontroller.go- HTTP handlers (Login, Refresh, GetUser)routes.go- Route definitions with middleware chainsmodel.go- Request/response DTOsvalidator.go- Input validationtraslator.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.Asyncerinterface
Configuration System
Configuration uses TOML files with two-level structure:
- Global config (
../global_conf.toml) - Shared settings across services - 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 CORSdemo,open-demo- Demo environmentsprod- Production mode, release logging, strict security
Dependency Injection Pattern
Dependencies flow from main.go → runners → infrastructure:
// 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:
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:
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
- Add handler method to
src/client/api/rest/controller.go - Define request/response models in
model.go - Add route in
routes.gowith appropriate middleware - Update Swagger comments (use
// @annotations) - Run
make swagto regenerate docs - Test with
make test
Adding a New Async Message Handler
- In your runner, subscribe to topic:
asyncManager.Subscribe("my-topic", func(topic string, msg []byte) {
// Handle message
})
- Publish messages:
asyncManager.Publish("my-topic", myMessage)
Adding a New Notifier
- Create package in
src/client/notify/{provider}/ - Implement
domain.Notifierinterface - Add configuration to
src/app/model.go - Wire in
main.goor usenotify/all/all.gofor multi-channel
Extending the Store
Add repository methods to src/client/store/manager.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:
- Update
go.modmodule path (e.g.,quantex.com/myservice) - Replace all imports from
quantex.com/skeletontoquantex.com/myservice - Update
PROJECTandDOMAINinMakefile.common - Update
ISSUE_PREFIXinMakefile.common(e.g.,MYPROJ)
Code Generation
Enums
The project uses go-enum for type-safe enums. Files ending in _enum.go are generated:
# Generate enums (run after modifying enum comments)
make gogenerate
Example enum definition in source files:
// ENUM(Test, Web, Panic, Error)
type MessageChannel string
Swagger Documentation
Swagger docs are auto-generated from comments:
// @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):
- Standard library
- Third-party packages
- Quantex packages (prefixed with
quantex.com)
Run make fmt to auto-format.
Error Handling
- Always check errors
- Use
tracerrfor 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.gofiles 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 branchcommand - Reference issue numbers in commits (e.g.,
SKL-123) - Run
make cibefore 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 accessSecure: truein production - HTTPS onlySameSite: Strictin 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:
# 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):
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:
[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.
## ℹ️ 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.
## 🐛 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 configurationtools/check/- Linter exclusions and settings