Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    brokle-ai

    brokle-backend-dev

    brokle-ai/brokle-backend-dev
    Coding
    3

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Use this skill when developing, implementing, or modifying Go backend code for the Brokle platform.

    SKILL.md

    Brokle Backend Development Skill

    This skill provides comprehensive guidance for Go backend development following Brokle's scalable monolith architecture with Domain-Driven Design.

    Architecture Overview

    Scalable Monolith with Independent Scaling

    • Separate Binaries: HTTP server (cmd/server) + Background workers (cmd/worker)
    • Shared Codebase: Single codebase with modular DI container
    • Multi-Database Strategy: PostgreSQL (transactional) + ClickHouse (analytics) + Redis (cache/queues)
    • Domain-Driven Design: Clean layer separation with domain-driven architecture

    Application Structure

    internal/
    ├── core/
    │   ├── domain/{domain}/      # Entities, interfaces (see internal/core/domain/)
    │   └── services/{domain}/    # Business logic implementations
    ├── infrastructure/
    │   ├── database/
    │   │   ├── postgres/repository/
    │   │   └── clickhouse/repository/
    │   └── repository/           # Main repository layer
    ├── transport/http/
    │   ├── handlers/{domain}/
    │   ├── middleware/
    │   └── server.go
    ├── app/                      # DI container
    └── workers/                  # Background jobs
    

    Domains

    Primary domains in internal/core/domain/:

    • auth - Authentication, sessions, API keys
    • billing - Usage tracking, subscriptions
    • common - Shared transaction patterns, utilities
    • gateway - AI provider routing and management
    • observability - Traces, spans, quality scores
    • organization - Multi-tenant org management
    • user - User management and profiles

    Pattern: Each domain has entities.go, repository.go, service.go, errors.go Reference: See internal/core/domain/ directory for complete list and implementation status

    Critical Development Patterns

    1. Domain Alias Pattern (MANDATORY)

    Always use professional domain aliases for imports:

    // ✅ Correct
    import (
        "context"
        "fmt"
    
        "gorm.io/gorm"
    
        authDomain "brokle/internal/core/domain/auth"
        orgDomain "brokle/internal/core/domain/organization"
        userDomain "brokle/internal/core/domain/user"
        "brokle/pkg/ulid"
    )
    
    // ❌ Incorrect
    import (
        "brokle/internal/core/domain/auth"
    )
    

    Standard Domain Aliases:

    Domain Alias Usage
    auth authDomain authDomain.User, authDomain.ErrNotFound
    organization orgDomain orgDomain.Organization
    user userDomain userDomain.User
    billing billingDomain billingDomain.Subscription
    observability obsDomain obsDomain.Trace

    2. Industrial Error Handling (MANDATORY)

    Three-Layer Pattern: Repository (Domain Errors) → Service (AppErrors) → Handler (HTTP Response)

    Repository Layer (Standard Pattern - errors.Is() for GORM):

    All repositories use errors.Is() for GORM error checking (standardized for wrapped error compatibility).

    ✅ Standard Pattern:

    import "errors"
    
    if errors.Is(err, gorm.ErrRecordNotFound) {  // ✅ Standardized
        return nil, fmt.Errorf("context: %w", domainError)
    }
    

    ❌ Don't Use:

    if err == gorm.ErrRecordNotFound {  // ❌ Old pattern - don't use
    

    Example:

    func (r *userRepository) GetByID(ctx context.Context, id ulid.ULID) (*authDomain.User, error) {
        var user authDomain.User
        err := r.db.WithContext(ctx).Where("id = ?", id).First(&user).Error
        if err != nil {
            if errors.Is(err, gorm.ErrRecordNotFound) {  // ✅ Standardized pattern
                return nil, fmt.Errorf("get user by ID %s: %w", id, authDomain.ErrNotFound)
            }
            return nil, fmt.Errorf("database query failed for user ID %s: %w", id, err)
        }
        return &user, nil
    }
    

    Service Layer:

    func (s *userService) GetUser(ctx context.Context, id ulid.ULID) (*GetUserResponse, error) {
        user, err := s.userRepo.GetByID(ctx, id)
        if err != nil {
            if errors.Is(err, authDomain.ErrNotFound) {
                return nil, appErrors.NewNotFoundError("User not found")
            }
            return nil, appErrors.NewInternalError("Failed to retrieve user")
        }
        return &GetUserResponse{User: user}, nil
    }
    

    Handler Layer:

    func (h *userHandler) GetUser(c *gin.Context) {
        userID := c.Param("id")
        id, err := ulid.Parse(userID)
        if err != nil {
            response.Error(c, appErrors.NewValidationError("Invalid user ID format", "id must be a valid ULID"))
            return
        }
    
        resp, err := h.userService.GetUser(c.Request.Context(), id)
        if err != nil {
            response.Error(c, err)  // Automatic HTTP mapping
            return
        }
    
        response.Success(c, resp)
    }
    

    Common AppError Constructors (see pkg/errors/errors.go for complete list):

    • appErrors.NewValidationError(message, details string)
    • appErrors.NewNotFoundError(resource string)
    • appErrors.NewConflictError(message string)
    • appErrors.NewUnauthorizedError(message string)
    • appErrors.NewForbiddenError(message string)
    • appErrors.NewInternalError(message string, err error)
    • appErrors.NewRateLimitError(message string)

    3. Authentication Patterns

    Two Authentication Systems:

    SDK Routes (/v1/*): API Key Authentication

    // Middleware: SDKAuthMiddleware
    // Extract context: middleware.GetSDKAuthContext(c)
    // Rate limiting: API key-based
    
    sdkRoutes := r.Group("/v1")
    sdkRoutes.Use(sdkAuthMiddleware.RequireSDKAuth())
    sdkRoutes.Use(rateLimitMiddleware.RateLimitByAPIKey())
    

    Dashboard Routes (/api/v1/*): JWT Authentication

    // Middleware: Authentication()
    // Extract user: middleware.GetUserID(c)
    // Rate limiting: IP + user-based
    
    // Middleware instances injected via DI (server.go:219-223)
    protected := router.Group("")
    protected.Use(s.authMiddleware.RequireAuth())           // Instance method - JWT validation
    protected.Use(s.csrfMiddleware.ValidateCSRF())          // Instance method - CSRF protection
    protected.Use(s.rateLimitMiddleware.RateLimitByUser()) // Instance method - User rate limiting
    

    API Key Format: bk_{40_char_random} with SHA-256 hashing

    4. Testing Philosophy (CRITICAL)

    Test Business Logic, Not Framework Behavior

    ✅ What to Test:

    • Complex business logic and calculations
    • Batch operations and orchestration workflows
    • Error handling patterns and retry mechanisms
    • Analytics, aggregations, and metrics
    • Multi-step operations with dependencies

    ❌ What NOT to Test:

    • Simple CRUD operations without business logic
    • Field validation (already in domain layer)
    • Trivial constructors and getters
    • Framework behavior (ULID, time.Now(), errors.Is)
    • Static constant definitions

    Test Pattern (Table-Driven):

    func TestUserService_CreateUser(t *testing.T) {
        tests := []struct {
            name        string
            input       *CreateUserRequest
            mockSetup   func(*MockUserRepository)
            expectedErr error
            checkResult func(*testing.T, *CreateUserResponse)
        }{
            {
                name: "success - valid user",
                input: &CreateUserRequest{
                    Email: "test@example.com",
                    Name:  "Test User",
                },
                mockSetup: func(repo *MockUserRepository) {
                    repo.On("Create", mock.Anything, mock.Anything).Return(nil)
                },
                expectedErr: nil,
                checkResult: func(t *testing.T, resp *CreateUserResponse) {
                    assert.NotNil(t, resp)
                    assert.NotEqual(t, ulid.ULID{}, resp.User.ID)
                },
            },
            // More test cases...
        }
    
        for _, tt := range tests {
            t.Run(tt.name, func(t *testing.T) {
                mockRepo := new(MockUserRepository)
                tt.mockSetup(mockRepo)
    
                service := NewUserService(mockRepo)
                result, err := service.CreateUser(context.Background(), tt.input)
    
                if tt.expectedErr != nil {
                    assert.ErrorIs(t, err, tt.expectedErr)
                } else {
                    assert.NoError(t, err)
                }
    
                if tt.checkResult != nil {
                    tt.checkResult(t, result)
                }
    
                mockRepo.AssertExpectations(t)
            })
        }
    }
    

    Code Templates

    See code-templates.md for complete repository, service, and handler templates.

    Development Commands

    # Start development stack
    make dev                    # Full stack (server + worker)
    make dev-server            # HTTP server only
    make dev-worker            # Workers only
    
    # Testing
    make test                  # All tests
    make test-unit            # Unit tests only
    make test-integration     # Integration tests
    
    # Database
    make migrate-up           # Run migrations
    make migrate-status       # Check status
    make seed-dev            # Load dev data
    
    # Code quality
    make lint                # Lint all code
    make fmt                 # Format code
    

    Key References

    When working on specific areas, invoke these specialized skills:

    • Domain Architecture: Use brokle-domain-architecture skill
    • API Routes: Use brokle-api-routes skill
    • Error Handling: Use brokle-error-handling skill
    • Testing: Use brokle-testing skill
    • Migrations: Use brokle-migration-workflow skill

    Documentation

    • Architecture Overview: CLAUDE.md
    • Error Handling: docs/development/ERROR_HANDLING_GUIDE.md
    • Domain Patterns: docs/development/DOMAIN_ALIAS_PATTERNS.md
    • API Development: docs/development/API_DEVELOPMENT_GUIDE.md
    • Testing Guide: docs/TESTING.md

    Development Workflow

    1. Analyze First: Use Read, Grep, Glob to understand existing patterns
    2. Find Similar Code: Search for existing implementations
    3. Follow Patterns: Match the established architecture
    4. Test Business Logic: Write pragmatic tests for complex logic only
    5. Review Errors: Ensure proper error handling across all layers

    Multi-Tenant Scoping

    All entities must be organization-scoped:

    type Project struct {
        ID             ulid.ULID
        OrganizationID ulid.ULID  // Required for multi-tenancy
        Name           string
        // ... other fields
    }
    

    Enterprise Edition Pattern

    Use build tags for enterprise features:

    # OSS build
    go build ./cmd/server
    
    # Enterprise build
    go build -tags="enterprise" ./cmd/server
    

    Enterprise features go in internal/ee/ with stub implementations for OSS.

    Quick Decision Tree

    Creating new functionality?

    1. Is it a new domain? → Use brokle-domain-architecture skill
    2. Is it an API endpoint? → Use brokle-api-routes skill
    3. Is it complex business logic? → Follow service layer pattern + write tests
    4. Does it need database schema? → Use brokle-migration-workflow skill

    Debugging errors?

    1. Check error handling layer (repo vs service vs handler)
    2. Verify domain alias imports
    3. Ensure AppError constructors in services
    4. Confirm response.Error() in handlers

    Adding tests?

    1. Is it complex business logic? → Write tests
    2. Is it simple CRUD? → Skip tests
    3. Use table-driven test pattern
    4. Mock complete interfaces
    5. Verify expectations with AssertExpectations(t)
    Repository
    brokle-ai/brokle
    Files