Services Design Guide (Clean Architecture)

This document defines all service types used across the system and assigns clear, non-overlapping responsibilities.

It exists to remove ambiguity around the word “service”, which is heavily overloaded.

The rules below are strict.

⸻

Overview

The system contains four distinct service categories, each in a different layer:
	1.	Frontend Services
	2.	API Services
	3.	Core Application Services
	4.	Core Domain Services

They must never be mixed.

⸻

1. Frontend Services

Purpose

Frontend services orchestrate UI-driven workflows.

They answer the question:

“How does the UI obtain and submit data?”

⸻

Responsibilities

Frontend services MAY:
	•	call API clients
	•	apply client-side guards (blockers, throttles)
	•	create View Models
	•	orchestrate multiple API calls
	•	handle recoverable UI errors

Frontend services MUST NOT:
	•	contain business rules
	•	validate domain invariants
	•	modify domain state
	•	know about core domain objects

⸻

Placement

apps/website/lib/services/


⸻

Example
	•	LeagueService
	•	RaceService
	•	AuthService

Each service is UI-facing, not business-facing.

⸻

2. API Services (Application Services)

Purpose

API services adapt HTTP-level concerns to core use cases.

They answer the question:

“How does an external client interact with the core?”

⸻

Responsibilities

API services MAY:
	•	orchestrate multiple use cases
	•	perform authorization checks
	•	map transport input to use-case input
	•	coordinate transactions

API services MUST NOT:
	•	contain domain logic
	•	enforce business invariants
	•	build domain entities
	•	return domain objects

⸻

Placement

apps/api/**/ApplicationService.ts


⸻

Example
	•	LeagueApplicationService

API services are delivery-layer coordinators.

⸻

3. Core Application Services (Use Cases)

Purpose

Core application services implement business use cases.

They answer the question:

“What does the system do?”

⸻

Responsibilities

Use Cases MUST:
	•	accept primitive input only
	•	create Value Objects
	•	create or modify Entities
	•	enforce business rules
	•	call repositories via ports
	•	communicate results via output ports

Use Cases MUST NOT:
	•	know about HTTP, UI, or frameworks
	•	return DTOs
	•	perform persistence directly

⸻

Placement

core/<context>/application/commands/
core/<context>/application/queries/


⸻

Example
	•	CreateLeagueUseCase
	•	ApplyPenaltyUseCase
	•	GetLeagueStandingsQuery

Use Cases define system behavior.

⸻

4. Core Domain Services

Purpose

Domain services encapsulate domain logic that does not belong to a single entity.

They answer the question:

“What rules exist that span multiple domain objects?”

⸻

Responsibilities

Domain services MAY:
	•	coordinate multiple entities
	•	compute derived domain values
	•	enforce cross-aggregate rules

Domain services MUST:
	•	use only domain concepts
	•	return domain objects or primitives

Domain services MUST NOT:
	•	access repositories
	•	depend on application services
	•	perform IO

⸻

Placement

core/<context>/domain/services/


⸻

Example
	•	SeasonConfigurationFactory
	•	ChampionshipAggregator
	•	StrengthOfFieldCalculator

Domain services protect business integrity.

⸻

Dependency Rules (Non-Negotiable)

Frontend Service
  → API Client
    → API Service
      → Core Use Case
        → Domain Service / Entity

Reverse dependencies are forbidden.

⸻

Anti-Patterns (Forbidden)

❌ Frontend calling core directly
❌ API service constructing domain entities
❌ Use case returning DTOs
❌ Domain service accessing repositories
❌ Single class acting as multiple service types

⸻

Naming Conventions

Layer	Naming
Frontend	*Service
API	*ApplicationService
Core Application	*UseCase, *Query
Core Domain	*Service, *Factory, *Calculator


⸻

Mental Model (Final)

Services coordinate.
Use Cases decide.
Domain enforces truth.
Adapters translate.

If a class violates this mental model, it is in the wrong layer.

⸻

Final Summary
	•	“Service” means different things in different layers
	•	Mixing service types causes architectural decay
	•	Clean Architecture remains simple when roles stay pure

This document defines the only allowed service roles in the system.