Event-Driven Architecture¶
The factory is event-driven end to end. Asynchronous, observable events are how platforms collaborate without tight coupling, how the lifecycle stays traceable and replayable, and how runtime feedback flows back into knowledge. This page describes the EDA patterns; the Event-Driven Mindset covers the philosophy.
Messaging stack¶
| Concern | Choice |
|---|---|
| Broker | Azure Service Bus |
| Messaging framework | MassTransit (primary); NServiceBus supported alternative |
| Library | ConnectSoft.Extensions.MessagingModel.MassTransit, ConnectSoft.Extensions.Saas.Messaging.MassTransit |
| Envelope | Canonical event envelope |
| In-service project | ...FlowModel.MassTransit |
Event flow¶
flowchart LR
aggregate["Aggregate Root"] -->|emits| domainEvent["Domain Event"]
domainEvent -->|outbox| publisher["MassTransit Publisher"]
publisher --> topic["Azure Service Bus Topic"]
topic --> sub1["Subscription: in-platform"]
topic --> sub2["Subscription: cross-platform"]
sub1 --> consumer1["Platform Consumer"]
sub2 --> integration["Integration Event Consumers"]
integration --> knowledge["Knowledge Platform"]
integration --> observability["Observability & Feedback"]
Hold "Alt" / "Option" to enable pan & zoom
Patterns¶
| Pattern | Use in the factory |
|---|---|
| Transactional outbox | Aggregates persist state and pending events atomically; a publisher relays them, guaranteeing at-least-once delivery. |
| Topic-per-event-type / topic-per-context | Subscriptions filter on cs-event-type and cs-tenant-id application properties. |
| Saga / process manager | Long-running workflows in the Control Plane use MassTransit sagas correlated by correlationId. |
| Idempotent consumers | Dedup on eventId + idempotency key (see Metadata Schema). |
| Dead-letter + replay | Poison messages dead-letter with the full envelope; replay is supported by Control Plane and Knowledge replay services. |
| Event-carried state transfer | Integration events carry enough payload for consumers to act without synchronous callbacks. |
Correlation and causation¶
Every event carries traceId (lifecycle), correlationId (workflow), and causationId (direct cause). Together they reconstruct the full causal graph of a production run — the basis for Workflow Replay and lineage in the Knowledge Graph.
flowchart LR
e1["ProjectCreated<br/>causation: none"] --> e2["BlueprintValidated<br/>causation: e1"]
e2 --> e3["AgentTaskAssigned<br/>causation: e2"]
e3 --> e4["ArtifactCreated<br/>causation: e3"]
e4 --> e5["PullRequestOpened<br/>causation: e4"]
e5 --> e6["DeploymentPromoted<br/>causation: e5"]
Hold "Alt" / "Option" to enable pan & zoom
Governance of events¶
Sensitive payloads are classified and may be redacted before crossing platform boundaries (see Knowledge governance). The complete inventory of integration events is the Event Catalog.