# Service Layer Template Standards for business logic services, commands, queries, policies, and specifications. Enterprise default: phases deliver these layers for in-scope capabilities — CRUD-only services are insufficient ([definition-of-done.md](definition-of-done.md), [mandatory-phase-artifacts.md](mandatory-phase-artifacts.md)). ## Responsibility Services: - Own domain rules and orchestration - Validate invariants (via validators / specifications) - Apply policies (authorization, entitlement, domain policy objects) - Expose **Commands** (state changes) and **Queries** (reads without write side-effects) - Write audit records - Write outbox/domain events in the **same transaction** as state changes - Call other services only via HTTP clients / events — never via foreign repos - Receive dependencies via explicit injection (constructor / factory / FastAPI deps) Services must **not**: - Depend on FastAPI `Request` / response objects - Emit raw SQL bypassing repositories (except rare documented cases) - Perform provider I/O without going through provider adapters owned by the service - Mutate another aggregate’s invariants across boundaries without explicit domain rules - Duplicate another service’s business logic ([boundary-rules.md](boundary-rules.md)) ## Commands | Rule | Detail | | --- | --- | | Location | `app/commands/` or clearly named command methods on services | | Naming | Verb phrases (`CreateMember`, `FreezeMembership`) | | Effect | Single use-case state change; emit audit + outbox as required | | Idempotency | Document for retried operations | ## Queries | Rule | Detail | | --- | --- | | Location | `app/queries/` or query services / read methods | | Effect | Read-only; no accidental writes or event emission | | Lists | Support pagination, filtering, sorting, searching as API requires | ## Specifications | Rule | Detail | | --- | --- | | Location | `app/specifications/` | | Purpose | Reusable query predicates and business specification objects | | Use | Repositories/services compose specs instead of duplicating filter logic | ## Policies | Rule | Detail | | --- | --- | | Location | `app/policies/` | | Purpose | Authorization, entitlement, and domain policy decisions reusable across commands | | Note | Route-level permission deps remain; policies encode richer domain rules | ## Conventions | Topic | Rule | | --- | --- | | Location | `app/services/` (+ commands/queries/policies/specifications) | | Naming | `{Capability}Service` | | Dependencies | Repositories, validators, specs, policies, event publisher, provider protocols | | DTOs | Accept/return schema objects or typed domain results — not ORM leakage to API | | Errors | Raise shared/domain exceptions with stable codes | | Idempotency | Document for retried operations (OTP, webhooks, messaging) | | DI | Explicit wiring; no hidden service locators for domain logic | ## Transaction & Events 1. State change + outbox row in one transaction ([ADR-006](../architecture/adr/ADR-006.md)). 2. Event types follow [event-template.md](event-template.md). 3. Failures calling remote systems must not corrupt local invariants; use async patterns where required (Communication pattern). ## Audit - Record actor, action, entity, tenant, timestamp for sensitive mutations. - Prefer dedicated audit tables where the service already has them. ## Testing Service / command / query / policy / specification tests cover business rules with DB or fakes — see [testing-template.md](testing-template.md). ## Related Documents - [Repository Template](repository-template.md) - [API Template](api-template.md) - [Mandatory Phase Artifacts](mandatory-phase-artifacts.md) - [Project Principles](../development/project-principles.md) - [Service Architecture](../architecture/service-architecture.md) - [Event-Driven Architecture](../architecture/event-driven-architecture.md)