## Crate-Specific Constraints

- This crate is mid-refactor toward runtime-agnostic feature services. Existing uses of Tokio scheduling, Tokio channels, or broadcast senders inside feature services/workflows are temporary compatibility debt. Do not copy those patterns into new code, and remove them when touching the affected flow if practical.
- Follow the existing vertical slice boundaries. Prefer extending the owning domain/feature, keep feature boundaries strict, and keep feature-internal structure lightweight. Do not force every feature to have the same number of modules or layers; choose the smallest structure that keeps the use case readable.
- Domain/feature modules own business models, errors, and any ports they define. Adapter layers own transport and persistence details; do not move business types into database or transport modules.
- Keep dependency flow one-way: composition/app -> services/use cases -> feature core plus feature-defined ports -> adapters/infrastructure.
- Core/service code must stay runtime- and transport-agnostic: no Diesel/schema modules, transport types, or Tokio scheduling/channel primitives. Model those needs as feature ports, implement them in application/adapter code, and keep `spawn_blocking`, task tracking, and channel lifecycle outside feature service code.
- Use publisher/input ports only when they are the simplest real boundary for workflow notifications or streamed inputs. Return values carry the primary domain result; runtime-specific stream/channel types stop at the application/transport boundary.
- Feature/service errors describe business failures and feature-port failures only. Map Tokio, transport, framework, and adapter-specific failures at application/adapter boundaries.
- For simple CRUD-heavy features, prefer a thin local adapter over a shared generic repository abstraction. Simplify adapter thickness, not feature boundaries; service/business code must remain unaware of Diesel models and schema modules.
- Inside a feature, add ports or traits only for real external boundaries such as persistence, transport-adjacent input/output, or runtime handoff. Prefer explicit request/response structs, enums, newtypes, and `From`/`TryFrom` conversions for boundary control; avoid local test-indirection traits and mechanical wrappers that add no meaning or invariants.
- Prefer direct tests for pure feature logic, integration tests for end-to-end workflows, and narrow adapter tests for persistence/transport details. Do not introduce extra abstraction layers solely to preserve mock-heavy unit tests.
