# ADR 001: Hexagonal Architecture

**Status**: Accepted
**Date**: 2024-10-12
**Context**: Crafted Level - Long-term sustainability (10+ years)

## Context

We need an architecture that:
- Isolates business logic from external dependencies
- Enables independent evolution of domain and infrastructure
- Facilitates testing at all levels
- Supports multiple client types (web, mobile, API)
- Can scale with team size (10-200+ developers)

## Decision

We adopt **Hexagonal Architecture** (Ports & Adapters) with three distinct layers:

### 1. Domain Layer (Core)
- **Location**: `packages/domain/`
- **Dependencies**: ZERO external dependencies
- **Contents**:
  - Entities (rich domain models)
  - Value Objects (immutable, self-validating)
  - Use Cases (application logic)
  - Repository Interfaces (ports)
- **Testing**: 100% coverage, spec-first approach

### 2. Application Layer
- **Location**: `packages/api/src/routers/`
- **Purpose**: Ultra-thin orchestration (< 10 lines per procedure)
- **Responsibilities**:
  - Input validation (Zod schemas)
  - Use case instantiation and execution
  - Result serialization
- **Testing**: 100% coverage

### 3. Infrastructure Layer
- **Location**: `packages/infrastructure/`
- **Purpose**: External implementations (adapters)
- **Contents**:
  - Database repositories (Prisma)
  - Payment gateways (Stripe)
  - Email services (Resend)
  - External APIs
- **Testing**: 80% coverage

## Rationale

### Why Hexagonal Architecture?

1. **Testability**: Domain logic can be tested in isolation without databases or external services
2. **Flexibility**: Can swap infrastructure (e.g., Prisma → TypeORM) without changing domain
3. **Clarity**: Clear separation makes codebase easier to navigate and understand
4. **Longevity**: Domain logic remains stable while infrastructure evolves

### Result Pattern

We use the **Result pattern** instead of throwing exceptions in the domain layer:

```typescript
type Result<T, E> = Success<T> | Failure<E>
```

**Reasons**:
- Makes errors explicit in the type system
- Forces error handling at compile time
- Domain remains pure (no side effects)
- Better for functional composition

## Consequences

### Positive
- Pure business logic is highly testable
- Infrastructure can be changed without affecting domain
- Multiple UIs can reuse the same use cases
- Clear dependency rules prevent coupling

### Negative
- More initial setup compared to simpler architectures
- Requires discipline to maintain boundaries
- Learning curve for developers new to DDD/Hexagonal

### Neutral
- More files and folders (but better organized)
- Need to create both interfaces and implementations

## Alternatives Considered

1. **3-Layer Architecture** (Balanced level)
   - Rejected: Not strict enough for long-term sustainability

2. **Clean Architecture** (Uncle Bob)
   - Similar but more complex with additional layers
   - Hexagonal is simpler and sufficient for our needs

3. **Modular Monolith**
   - Could be combined with Hexagonal
   - Deferred for future consideration

## References

- [Hexagonal Architecture](https://alistair.cockburn.us/hexagonal-architecture/)
- [Domain-Driven Design](https://martinfowler.com/tags/domain%20driven%20design.html)
- [Result Pattern](https://fsharpforfunandprofit.com/posts/recipe-part2/)
