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.rs—AgentSessionaggregate root,AgentConfig,ProviderKindauth.rs—AuthContext,Role,Permission,SecurityPolicycredentials.rs—CredentialBundle, resolution ordererrors.rs—DomainErrorenum (allthiserror)events.rs—DomainEventvariantssession.rs— session value objectssettings.rs—PersistentSettingswiki.rs—WikiEntry,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 streamingSessionStore— session persistence (CQRS-aware)WikiStore— wiki entry persistenceToolDispatcher— tool invocationReplayLog— JSONL delta-encoded call logFetcherPort— data fetcher abstraction