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

Design Philosophy

shadowforge-rs uses a collapsed hexagonal (ports-and-adapters) architecture with DDD-lite bounded contexts.

Why Hexagonal?

The core domain logic — cryptographic operations, steganographic encoding, Reed-Solomon correction — must be pure and testable without I/O. Hexagonal architecture enforces this by pushing all external interactions behind port traits.

┌─────────────────────────────────────────────┐
│                 interface/                   │
│              (CLI, future API)               │
├─────────────────────────────────────────────┤
│               application/                  │
│          (orchestration services)            │
├──────────────┬──────────────────────────────┤
│   domain/    │         adapters/            │
│  (pure logic │   (I/O, FFI, filesystem)     │
│   + ports)   │                              │
└──────────────┴──────────────────────────────┘

Dependencies always point inward:

  • adapters/ imports port traits from domain/ and implements them.
  • application/ accepts port trait references and orchestrates domain logic.
  • interface/ constructs concrete adapters, wires them into application services, and handles user interaction.
  • domain/ imports nothing from the outer layers. It defines the vocabulary, the rules, and the contracts.

Why “Collapsed”?

A full hexagonal architecture separates each bounded context into its own crate with explicit port modules. shadowforge-rs collapses this into a single crate with module boundaries instead of crate boundaries. The workspace structure (crates/) is intentional: future companion crates (e.g. shadowforge-web, shadowforge-api) add as new members without restructuring the core.

Why DDD-lite?

Each bounded context (crypto, stego, correction, etc.) owns its own logic and interacts with others only through the shared type vocabulary in domain/types.rs and the port traits in domain/ports.rs. There are no full aggregate roots or repository patterns — the “lite” means we take the context-boundary discipline without the ceremony.