Claude-skill-registry brokle-domain-architecture
Use this skill when working with Brokle's domain-driven architecture, including creating new domains, modifying domain entities, designing cross-domain interactions, refactoring domain boundaries, or implementing complex domain logic. This is a specialized architectural skill.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/brokle-domain-architecture" ~/.claude/skills/majiayu000-claude-skill-registry-brokle-domain-architecture && rm -rf "$T"
manifest:
skills/data/brokle-domain-architecture/SKILL.mdsource content
Brokle Domain Architecture Skill
Expert guidance for Brokle's Domain-Driven Design (DDD) architecture.
Domains
Primary domains in
internal/core/domain/:
| Domain | Purpose |
|---|---|
| auth | Authentication, sessions, API keys |
| billing | Usage tracking, subscriptions |
| common | Shared transaction patterns, utilities |
| gateway | AI provider routing |
| observability | Traces, spans, quality scores |
| organization | Multi-tenant org management |
| user | User management and profiles |
Structure: Each domain has entities.go, repository.go, service.go, errors.go, types.go Reference: List domains with
ls -1 internal/core/domain/ to see current implementation status
Domain Layer Structure
internal/core/domain/{domain}/ ├── entities.go # Domain entities ├── repository.go # Repository interfaces ├── service.go # Service interfaces ├── errors.go # Domain-specific errors ├── types.go # Domain types and enums └── validators.go # Domain validation logic
Entity Pattern
// internal/core/domain/auth/entities.go package auth import ( "time" "brokle/pkg/ulid" ) type User struct { ID ulid.ULID Email string Name string Status UserStatus Role Role CreatedAt time.Time UpdatedAt time.Time } // Domain enums type UserStatus string const ( UserStatusActive UserStatus = "active" UserStatusInactive UserStatus = "inactive" UserStatusSuspended UserStatus = "suspended" ) type Role string const ( RoleOwner Role = "owner" RoleAdmin Role = "admin" RoleUser Role = "user" RoleViewer Role = "viewer" )
Domain Errors
// internal/core/domain/auth/errors.go package auth import "errors" var ( ErrNotFound = errors.New("user not found") ErrAlreadyExists = errors.New("user already exists") ErrInvalidCredentials = errors.New("invalid credentials") ErrSessionExpired = errors.New("session expired") )
Repository Interfaces
// internal/core/domain/auth/repository.go package auth import ( "context" "brokle/pkg/ulid" ) type UserRepository interface { Create(ctx context.Context, user *User) error GetByID(ctx context.Context, id ulid.ULID) (*User, error) GetByEmail(ctx context.Context, email string) (*User, error) Update(ctx context.Context, user *User) error Delete(ctx context.Context, id ulid.ULID) error List(ctx context.Context, filter UserFilter) ([]*User, error) }
Service Interfaces
// internal/core/domain/auth/service.go package auth import "context" type AuthService interface { Register(ctx context.Context, req *RegisterRequest) (*RegisterResponse, error) Login(ctx context.Context, req *LoginRequest) (*LoginResponse, error) Logout(ctx context.Context, token string) error ValidateSession(ctx context.Context, token string) (*User, error) }
Multi-Tenant Scoping Patterns
NOT all entities have
- scoping depends on entity type:organization_id
1. Organization-Scoped Entities (Direct organization_id
)
organization_id// organization/organization.go:54-57 type Project struct { ID ulid.ULID OrganizationID ulid.ULID `json:"organization_id" gorm:"type:char(26);not null"` Name string } // organization/organization.go:37-39 type Member struct { OrganizationID ulid.ULID `json:"organization_id" gorm:"type:char(26);not null;primaryKey"` UserID ulid.ULID }
2. Project-Scoped Entities (Organization via Project)
// auth/auth.go:94 - APIKey is project-scoped type APIKey struct { ID ulid.ULID ProjectID ulid.ULID `json:"project_id" gorm:"type:char(26);not null;index"` // Organization derived via Project join }
3. Scoped Entities (Flexible Scoping)
// auth/auth.go:113-114 - Role uses flexible scope_type pattern type Role struct { ID ulid.ULID ScopeType string `json:"scope_type" gorm:"size:20;not null"` // "organization", "project", "global" ScopeID *ulid.ULID `json:"scope_id,omitempty" gorm:"type:char(26);index"` }
4. Global Entities (No organization_id)
// user/user.go:14-39 - User is global with optional org reference type User struct { ID ulid.ULID Email string DefaultOrganizationID *ulid.ULID `json:"default_organization_id,omitempty" gorm:"type:char(26)"` // NOT required - users can belong to multiple orgs via Member table } // organization/organization.go:16 - Organization IS the tenant type Organization struct { ID ulid.ULID Name string // No organization_id - it IS the organization }
Reference Files:
- Organization-scoped:
internal/core/domain/organization/organization.go:54-73 - Project-scoped:
internal/core/domain/auth/auth.go:94 - Scoped (flexible):
internal/core/domain/auth/auth.go:113-114 - Global:
internal/core/domain/user/user.go:14-39
Cross-Domain Relationships
// Example: Organization domain referencing User domain package organization import ( userDomain "brokle/internal/core/domain/user" ) type Member struct { ID ulid.ULID OrganizationID ulid.ULID UserID ulid.ULID // References user domain Role string Status MemberStatus } // Service can accept interfaces from other domains type OrganizationService struct { orgRepo OrganizationRepository userRepo userDomain.UserRepository // Cross-domain dependency memberRepo MemberRepository }
Creating a New Domain
Step 1: Create Domain Structure
mkdir -p internal/core/domain/my-domain touch internal/core/domain/my-domain/{entities,repository,service,errors,types}.go
Step 2: Define Entities
// entities.go package mydomain import ( "time" "brokle/pkg/ulid" ) type MyEntity struct { ID ulid.ULID OrganizationID ulid.ULID // Always include for multi-tenancy Name string Status MyStatus CreatedAt time.Time UpdatedAt time.Time }
Step 3: Define Domain Errors
// errors.go package mydomain import "errors" var ( ErrNotFound = errors.New("entity not found") ErrAlreadyExists = errors.New("entity already exists") ErrInvalidInput = errors.New("invalid input") )
Step 4: Define Repository Interface
// repository.go package mydomain import ( "context" "brokle/pkg/ulid" ) type MyEntityRepository interface { Create(ctx context.Context, entity *MyEntity) error GetByID(ctx context.Context, id ulid.ULID) (*MyEntity, error) Update(ctx context.Context, entity *MyEntity) error Delete(ctx context.Context, id ulid.ULID) error }
Step 5: Define Service Interface
// service.go package mydomain import "context" type MyDomainService interface { CreateEntity(ctx context.Context, req *CreateEntityRequest) (*CreateEntityResponse, error) GetEntity(ctx context.Context, id ulid.ULID) (*GetEntityResponse, error) }
Step 6: Implement Service
In
internal/core/services/my-domain/
Step 7: Implement Repository
In
internal/infrastructure/repository/my-domain/
Step 8: Register in DI Container
In
internal/app/app.go
Domain Validation
// validators.go package auth import ( "errors" "regexp" ) func (u *User) Validate() error { if u.Email == "" { return errors.New("email is required") } if !isValidEmail(u.Email) { return errors.New("invalid email format") } if u.Name == "" { return errors.New("name is required") } return nil } func isValidEmail(email string) bool { return regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`).MatchString(email) }
Key Principles
- Domain Purity: Domain layer has no external dependencies
- Multi-Tenancy: All entities scoped by organization
- Domain Errors: Use domain-specific errors
- Validation: Domain entities validate themselves
- Interfaces: Define repository and service interfaces in domain
- Cross-Domain: Use domain aliases for cross-domain references
References
- Existing domains in
for patternsinternal/core/domain/
- Architecture overviewCLAUDE.md
- Domain patternsdocs/development/PATTERNS.md