Skip to content

Event Envelope

The event envelope is the single canonical structure that wraps every message moving through the ConnectSoft AI Software Factory — whether it is a factory lifecycle event, a domain event from a platform aggregate, or an integration event crossing a platform boundary. A uniform envelope is what makes the platform traceable, replayable, and observable end to end.

Why one envelope

Every meaningful action in the factory emits an event. Because all events share the same envelope, the Knowledge Platform, Observability & Feedback Platform, and Control Plane can correlate any artifact, agent task, commit, deployment, and runtime signal back to a single traceId — from business intent to running SaaS and back.

Canonical envelope

All events are published on Azure Service Bus (via MassTransit, the primary messaging stack) using the following envelope. Fields are stable across versions; the variable part is payload.

{
  "eventId": "evt-7b3c1f9a-2e44-4c1a-9b6d-0f2a8c3d5e10",
  "eventType": "ArtifactCreated",
  "tenantId": "connectsoft",
  "projectId": "proj-booking-saas",
  "moduleId": "module-reservations-api",
  "traceId": "trace-9f1c2b7d",
  "correlationId": "corr-3a6e1d40",
  "causationId": "evt-previous-event-id",
  "occurredAt": "2026-06-11T00:00:00Z",
  "payload": {}
}

Field contract

Field Type Required Purpose
eventId string (prefixed UUID) Yes Globally unique id of this event instance. Idempotency anchor for consumers.
eventType string Yes Event name in NounVerbPastTense form (e.g. ArtifactCreated, AgentTaskCompleted). See Naming Conventions.
tenantId string Yes Owning tenant. Enforces multi-tenant isolation in every consumer and store.
projectId string Conditional The factory project the event belongs to. Present for all project-scoped events.
moduleId string Conditional The module (microservice, UI, worker, library) the event concerns, when applicable.
traceId string Yes End-to-end trace identifier spanning the full prompt-to-runtime lifecycle.
correlationId string Yes Correlates all events within one logical workflow/conversation.
causationId string No The eventId of the event that directly caused this one. Builds the causation chain.
occurredAt string (ISO-8601 UTC) Yes When the event occurred at the producer.
payload object Yes Event-specific body. Versioned independently per eventType.

The identity fields above are a strict superset of the cross-cutting metadata schema; additional dimensions (agentId, skillId, artifactId, workflowId, environment, version) appear inside payload or as Service Bus message application properties when relevant for routing and filtering.

Message metadata (Azure Service Bus)

The envelope is carried as the message body; selected fields are mirrored into broker application properties so subscriptions can filter without deserializing the body.

Application property Source field Use
cs-event-type eventType Subscription rules / topic filters
cs-tenant-id tenantId Tenant-scoped subscriptions
cs-trace-id traceId Trace stitching and log correlation
cs-correlation-id correlationId Saga/workflow correlation in MassTransit
cs-schema-version envelope schema version Consumer compatibility checks

Event categories

flowchart LR
    Commands["Commands<br/>VerbNoun"] -->|handled by| Aggregate["Aggregate Root"]
    Aggregate -->|emits| DomainEvents["Domain Events<br/>NounVerbPastTense"]
    DomainEvents -->|published to| Topic["Azure Service Bus Topic"]
    Topic -->|in-platform| Subscribers["Platform Subscribers"]
    Topic -->|cross-platform| Integration["Integration Events"]
    Integration --> Knowledge["Knowledge Platform"]
    Integration --> Observability["Observability &amp; Feedback"]
Hold "Alt" / "Option" to enable pan & zoom
  • Commands (VerbNoun, e.g. BuildContextPackage) — imperative requests handled by exactly one aggregate. Not part of the public event stream.
  • Domain events (NounVerbPastTense) — facts emitted by an aggregate after a state change, published within the owning platform.
  • Integration events — domain events promoted to a cross-platform contract. These are the versioned, externally consumed events listed in the Event Catalog.

Versioning

  • eventType names never change meaning. Breaking changes create a new type (e.g. ArtifactCreatedV2) or an additive payload with a bumped cs-schema-version.
  • Consumers must tolerate unknown payload fields (forward compatibility) and unknown eventType values (ignore-and-log).
  • The Knowledge Replay and Workflow Replay capabilities depend on envelopes being immutable once published.

Consumer rules

  1. Idempotency — consumers deduplicate on eventId. Workers additionally use an idempotency key derived from eventId + handler name.
  2. Tenant guard — every handler asserts tenantId against the operation scope before touching a store.
  3. Trace propagationtraceId and correlationId flow into OpenTelemetry spans and Serilog log context (see Observability Architecture).
  4. Poison handling — unprocessable messages move to a dead-letter subqueue with the full envelope preserved for replay.