# Service Layer Template

Standards for business logic services.

## Responsibility

Services:

- Own domain rules and orchestration
- Validate invariants (via validators)
- Authorize at domain level when required (with permission deps at API)
- 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

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

## Conventions

| Topic | Rule |
| --- | --- |
| Location | `app/services/` |
| Naming | `{Capability}Service` |
| Dependencies | Repositories, validators, 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) |

## 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 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)
- [Project Principles](../development/project-principles.md)
- [Service Architecture](../architecture/service-architecture.md)
- [Event-Driven Architecture](../architecture/event-driven-architecture.md)
