Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Hexagonal DDD

Redshank uses a DDD-Lite hexagonal architecture. The key invariant is the dependency rule: inner rings know nothing about outer rings.

          ┌─────────────────────────────────────┐
          │           Adapters (outer)           │
          │  ┌───────────────────────────────┐  │
          │  │      Application layer        │  │
          │  │  ┌─────────────────────────┐  │  │
          │  │  │    Domain (inner)        │  │  │
          │  │  │  Types, events, rules    │  │  │
          │  │  └─────────────────────────┘  │  │
          │  │  Commands / Queries / Services │  │
          │  └───────────────────────────────┘  │
          │  Providers / Tools / Persistence     │
          └─────────────────────────────────────┘

Domain layer (src/domain/)

Pure Rust structs and enums. No async, no tokio, no I/O of any kind.

  • agent.rsAgentSession aggregate root, AgentConfig, ProviderKind
  • auth.rsAuthContext, Role, Permission, SecurityPolicy
  • credentials.rsCredentialBundle, resolution order
  • errors.rsDomainError enum (all thiserror)
  • events.rsDomainEvent variants
  • session.rs — session value objects
  • settings.rsPersistentSettings
  • wiki.rsWikiEntry, WikiEntryId

Ports layer (src/ports/)

Trait interfaces that the domain and application layers call. Adapters implement these traits; the domain never sees the implementations.

  • ModelProvider — LLM completions with streaming
  • SessionStore — session persistence (CQRS-aware)
  • WikiStore — wiki entry persistence
  • ToolDispatcher — tool invocation
  • ReplayLog — JSONL delta-encoded call log
  • FetcherPort — data fetcher abstraction