Skip to content

Domain Documentation

Living documentation generated from the Koine model. Each bounded context has its own page with the ubiquitous language, aggregates, and Mermaid diagrams of its lifecycles.

  • Delivery — version 1 — Delivery bounded context — getting a delivery order to the customer’s door. It owns the Address value object (supplied downstream to nobody else here, but a customer-supplier candidate) and enforces the rule that anchors this context: a delivery order must carry a delivery address.
  • Kitchen — version 1 — Kitchen bounded context — turning a placed order into a cooked pizza. It watches the orders Ordering publishes and runs each one through the kitchen workflow: a ticket is queued, prepped, baked, and put up on the pass. Kept in its own context so “how the kitchen cooks” evolves independently of “how an order is taken”.
  • Menu — version 2 — Menu bounded context — the catalogue of pizzas, sizes and toppings the pizzeria sells. It is the upstream that publishes the ubiquitous language of money and toppings; Ordering shares its Currency as a shared kernel and conforms to its Topping weight (see context-map.koi). Version 2 of the published model: a kcal nutrition field was added in v2, demonstrating contract evolution with @since.
  • Ordering — version 1 — Ordering bounded context — taking and pricing a customer’s pizza order. This is the heart of the template: the Sales aggregate (root Order) is the headline aggregate, its lifecycle is an explicit state machine, it is priced from its line items, and it publishes OrderPlaced so Kitchen, Delivery and Payment can react.
  • Payment — version 1 — Payment bounded context — charging the customer for an order and keeping the books. It is downstream of a third-party card gateway whose model we do NOT control, so it shields itself with an anti-corruption layer: the raw gateway result is translated into our own PaymentReceipt (the acl block lives in context-map.koi). Two aggregates — Billing and Ledger — exercise a multi- aggregate context with a cross-aggregate policy. Naming note: the root entity is Charge, deliberately NOT Payment. A C# type must not share its enclosing namespace’s name, and this context emits into a Payment namespace; an entity called Payment would collide with it, exactly as the demo avoided by pairing a Payments context with a Payment entity.
  • Gateway — version 1 — Gateway bounded context — the external card processor whose model we do not control. Payment never references this directly; it goes through the generated anti-corruption translator interface (see the acl block in context-map.koi).
  • Promotions — version 1 — Promotions bounded context — the deals and discounts the pizzeria runs. It owns the rule that anchors this context: a discount can lower an order’s total, but it can never drive that total below zero. The rule is enforced as an invariant on a Discount value object, exposed as a reusable spec, and computed by a pure domain operation.