# Intent.Application.Mediator.DomainEvents

Dispatches the domain events raised by your entities through the source-generated [Mediator](https://github.com/martinothamar/Mediator) library, and generates the handlers that react to them. Every handler body is written by an AI agent from the interactions you model, not by the Software Factory.

This module is the domain-event satellite of `Intent.Application.Mediator`. The core module installs it automatically when `Intent.DomainEvents` is present in the application.

## What this module generates

| Output | Generated when | Purpose |
| --- | --- | --- |
| `DomainEventNotification<TDomainEvent>` | Always | Abstract base class implementing Mediator's `INotification`. Exposes the wrapped event as `DomainEvent`. Written to `Common/Models` in the Application layer. |
| `{DomainEventName}Notification` | One per domain event in the Domain designer | Sealed wrapper deriving from `DomainEventNotification<TDomainEvent>`. |
| `DomainEventNotificationFactory` | Always | Static class with a `Create` switch that maps a domain event to its wrapper. |
| `DomainEventService` | Always | Implements the `IDomainEventService` interface from `Intent.DomainEvents`, and publishes the wrapped event through Mediator's `IPublisher`. Registered with the Infrastructure DI concern at per-service-call (scoped) lifetime. |
| Explicit domain event handler | One per Domain Event Handler element in the Services designer | `INotificationHandler<T>` implementation with one `Handle` method per handled domain event. Each `Handle` is a stub. |
| Default domain event handler | One per domain event with no modelled handler, only when **Create implicit domain event handlers** is on | A `{DomainEventName}Handler` class with a single stub `Handle`. |
| `mediator-domain-event-handler` skill | Always | A `SKILL.md` teaching an AI agent how to write the handler bodies. |

No AI task is raised. An agent finds the handlers to write through the skill (see below): a handler still needs writing while its body holds the `// IntentInitialGen` marker and throws `NotImplementedException`.

NuGet packages added to the generated application: `Mediator.Abstractions` 3.0.2 (locked) and `Microsoft.Extensions.Logging` 10.0.9.

## Settings

Application settings, group **Domain Event Settings**:

| Setting | Default | Effect |
| --- | --- | --- |
| Create implicit domain event handlers | Off | When on, a default handler stub is generated for every domain event that is not handled by any modelled Domain Event Handler. When off, a domain event with no modelled handler has no handler, and publishing it is a no-op. |

The default is off because every generated handler is a stub that throws until an agent implements it. An implicit handler for an event nobody asked to handle would throw on every publish until then.

## How events are dispatched

1. An entity raises a domain event.
2. The infrastructure calls `DomainEventService.Publish`, which logs the event and calls `DomainEventNotificationFactory.Create`.
3. The factory returns the sealed wrapper for the event, and `DomainEventService` publishes it with `IPublisher.Publish`.
4. Mediator delivers the wrapper to every `INotificationHandler<T>` registered for it.

The wrappers and the factory exist because Mediator's source generator cannot see an open generic type such as `DomainEventNotification<T>`. Each domain event gets a concrete wrapper, and the factory chooses the right one with a plain `switch`, without reflection.

Things to know about the factory:

- Every domain event has a case. A derived event is placed before its base event so the base case does not swallow it.
- An event with no case throws `InvalidOperationException` rather than being dropped.

Publishing is sequential and handler failures propagate to the caller. That behaviour comes from the Mediator configuration generated by `Intent.Application.Mediator`, not from this module.

## Generated shapes

Names below are illustrative.

The wrapper for a domain event:

```csharp
public sealed class OrderPlacedDomainEventNotification : DomainEventNotification<OrderPlacedDomainEvent>
{
    public OrderPlacedDomainEventNotification(OrderPlacedDomainEvent domainEvent) : base(domainEvent)
    {
    }
}
```

An explicit handler, as first generated:

```csharp
[IntentManaged(Mode.Merge, Signature = Mode.Fully)]
public class OrderPlacedDomainEventHandler : INotificationHandler<OrderPlacedDomainEventNotification>
{
    [IntentManaged(Mode.Merge)]
    public OrderPlacedDomainEventHandler()
    {
    }

    [IntentManaged(Mode.Fully, Body = Mode.Merge)]
    public async ValueTask Handle(OrderPlacedDomainEventNotification notification, CancellationToken cancellationToken)
    {
        // IntentInitialGen
        // TODO: Implement Handle (OrderPlacedDomainEventHandler) functionality
        throw new NotImplementedException("Your implementation here...");
    }
}
```

A handler that handles several domain events implements `INotificationHandler<T>` once per event and has one `Handle` method per event.

The class and signatures stay under the Software Factory's control. The constructor is merge-managed so an agent can add injected dependencies. The `Handle` body is the part that belongs to the agent.

## AI-written handlers

This module never turns modelled interactions into code. It generates the stub, tells the agent what to implement, and leaves the body alone afterwards.

### The model is the specification

Model the handler in the Services designer: a Domain Event Handler element, associated to each domain event it handles, with the interactions that should happen drawn from each handled event. Field mappings are not modelled and not read. The agent decides which event data populates which property from names and meaning.

### The skill

`mediator-domain-event-handler` is generated as `SKILL.md` into the application's AI skills folder. It covers:

- how the handler receives the event (`notification.DomainEvent`) and why the signature is never edited;
- how to read the handler's associations from the Services designer and implement them in order, and what each interaction type means;
- keeping the handler in step with the model: re-read the associations whenever the handler is implemented or revisited, because adding or changing an association changes no generated file;
- eventing, saving and idempotency rules, and the layer boundaries to respect.

Each generated handler class also carries an AI summary and context line pointing at this skill.

### Revisiting a handler after a model change

Changing the associations of an implemented handler produces no generated change, so no task is raised. Ask the agent to revisit the handler, or have it re-read the associations as the skill instructs. Nothing in this module detects the change for you.

### A rule on the Domain Event Handler element

This module adds an AI rule to the Domain Event Handler element in the Services designer. It tells an agent that is editing the model that the handler body is AI-written, and that creating a handler, or changing its associations, means revisiting the handler body in the same piece of work. An agent that edits the model without reading the element's rules will miss it, so the skill carries the same guidance.

## Requirements

This module expects these modules in the application:

- `Intent.Application.Mediator`, the core module. It owns the Mediator configuration and pipeline.
- `Intent.DomainEvents`, which generates the domain event classes, the event base type and the `IDomainEventService` interface this module builds on.
- `Intent.Modelers.Domain.Events` and `Intent.Modelers.Services`, for the Domain Event and Domain Event Handler elements.

Interactions drawn from a handled domain event can only be modelled if the designer extensions that provide them are installed. The task text recognises these interaction types: Create, Update, Delete and Query Entity; Call Service Operation; Send Command; Publish Integration Event; Send Integration Command.

This module does not depend on `Intent.Application.DomainInteractions`.

## Moving from another domain-event module

Do not run this module alongside `Intent.MediatR.DomainEvents` or `Intent.Application.Wolverine.DomainEvents`. Each generates its own `DomainEventService` for the same `IDomainEventService` interface and its own handlers.

When moving from `Intent.MediatR.DomainEvents`, the handler parameter type changes from `DomainEventNotification<X>` to the generated `XNotification`. Before swapping modules, mark each existing handler's whole `Handle` method `[IntentManaged(Mode.Ignore)]`, and the handler's fields and constructor too. A body-only ignore no longer matches the new signature, so the Software Factory would replace the method with a stub. After the swap, the old method survives beside the new stub: move the body across and delete the old method. The core module's README describes the whole MediatR migration.

## Related modules

- `Intent.Application.Mediator`: the core module this one extends.
- [Intent.DomainEvents](https://docs.intentarchitect.com/articles/modules-dotnet/intent-domainevents/intent-domainevents.html): generates the domain event classes and the `IDomainEventService` interface.
