# DE0308: No HTTP in Domain
## What it does
Checks that domain modules do not reference HTTP types or status codes.
## Why is this bad?
Domain modules should be transport-agnostic:
- **HTTP is just one transport**: Domain logic should work with any protocol (gRPC, WebSockets, CLI)
- **Tight coupling**: Domain becomes dependent on web layer
- **Harder to reuse**: Cannot use domain logic in non-HTTP contexts
- **Violates separation of concerns**: HTTP is a delivery detail, not business logic
## Example
```rust
// ❌ Bad - HTTP types in domain
// File: src/domain/error.rs
use http::StatusCode;
pub enum DomainError {
NotFound(StatusCode), // HTTP leaking into domain
}
```
```rust
// ❌ Bad - HTTP status in domain function
use axum::http::StatusCode;
pub fn validate_user() -> StatusCode {
StatusCode::OK // Domain should not return HTTP types
}
```
Use instead:
```rust
// ✅ Good - domain errors are transport-agnostic
// File: src/domain/error.rs
use thiserror::Error;
use uuid::Uuid;
#[derive(Error, Debug)]
pub enum DomainError {
#[error("User not found: {id}")]
UserNotFound { id: Uuid },
#[error("Email '{email}' already exists")]
EmailAlreadyExists { email: String },
#[error("Validation failed: {field}: {message}")]
Validation { field: String, message: String },
#[error("Database error: {message}")]
Database { message: String },
}
```
```rust
// ✅ Good - API layer handles HTTP mapping
// File: src/api/rest/error.rs
use toolkit::api::problem::Problem;
use crate::domain::error::DomainError;
impl From<DomainError> for Problem {
fn from(e: DomainError) -> Self {
match &e {
DomainError::UserNotFound { id } => {
ErrorCode::user_not_found_v1()
.with_context(format!("User {id} not found"), "/", None)
}
DomainError::Validation { .. } => {
ErrorCode::validation_error_v1()
.with_context(e.to_string(), "/", None)
}
_ => ErrorCode::internal_error_v1()
.with_context("Internal error", "/", None)
}
}
}
```
## Configuration
This lint is configured to **deny** by default.
It checks all imports in `*/domain/*.rs` files for references to `http` crate types.
### See Also
- [DE0301](../de0301_no_infra_in_domain) - No Infrastructure in Domain Layer