Generated SaaS Events¶
Target Architecture — Final-State Design
This page documents the event model of a Generated SaaS Product. Every event travels in the canonical event envelope on Azure Service Bus via MassTransit. Events use NounVerbPastTense; commands use VerbNoun, per the naming conventions. Products add domain-specific events; those below are the common SaaS spine events present in every product.
A generated product is event-driven at its core. State changes in any aggregate emit domain events; those promoted to cross-context contracts become integration events consumed by supporting services, workers, and — crucially — the factory's Observability & Feedback and Knowledge platforms. The uniform envelope is what lets a running product remain traceable back to the intent that generated it.
Commands (VerbNoun)¶
Commands express intent and are handled by exactly one aggregate. They are not part of the public event stream.
| Command | Target Aggregate | Effect |
|---|---|---|
RegisterTenant |
Tenant |
Create and begin provisioning a tenant |
InviteUser |
User |
Issue a user invitation |
AssignRole |
User |
Assign a role to a user |
ActivateSubscription |
Subscription |
Activate or upgrade a subscription to an edition |
ToggleFeatureFlag |
FeatureFlag |
Enable/disable or roll out a feature flag |
SendNotification |
Notification |
Request delivery of a notification |
GenerateReport |
ReportDefinition |
Request a report run |
RecordAuditEntry |
AuditEntry |
Append an immutable audit record |
Domain events (NounVerbPastTense)¶
Facts emitted by an aggregate after a state change, published within the owning context.
| Domain Event | Emitting Aggregate | Meaning |
|---|---|---|
TenantRegistered |
Tenant |
A tenant was created and provisioning started |
TenantSuspended |
Tenant |
A tenant was suspended |
UserInvited |
User |
A user invitation was issued |
UserActivated |
User |
An invited user completed activation |
RoleAssigned |
User / Role |
A role was assigned to a user |
SubscriptionActivated |
Subscription |
A subscription became active on an edition |
SubscriptionCancelled |
Subscription |
A subscription was cancelled |
FeatureFlagToggled |
FeatureFlag |
A feature flag's state or rollout changed |
NotificationSent |
Notification |
A notification was delivered on a channel |
AuditEntryRecorded |
AuditEntry |
An auditable action was recorded |
ReportGenerated |
ReportDefinition |
A report run produced an artifact |
Integration events¶
Domain events promoted to versioned, cross-context (and cross-platform) contracts. The common SaaS integration event set:
TenantRegistered— consumed by Subscription, Notification, Audit, and the factory's Observability & Feedback platform.UserInvited— consumed by Notification (to send the invite) and Audit.SubscriptionActivated— consumed by Configuration (to apply entitlements), Notification, and Audit.FeatureFlagToggled— consumed by domain services (to flip behavior) and Audit.NotificationSent— consumed by Reporting (delivery analytics) and Audit.AuditEntryRecorded— consumed by the Audit Export Worker and Reporting.ReportGenerated— consumed by Notification (to alert requester) and the customer portal.
Envelope¶
All events use the canonical event envelope. A representative SubscriptionActivated:
{
"eventId": "evt-5c1a9f2b-7d44-4e10-9a3c-1b2e4f6a8c90",
"eventType": "SubscriptionActivated",
"tenantId": "contoso",
"projectId": "proj-contoso-saas",
"moduleId": "module-subscription-service",
"traceId": "trace-7b2e9c1d",
"correlationId": "corr-1f4a8d20",
"causationId": "evt-tenant-registered-id",
"occurredAt": "2026-06-11T09:02:00Z",
"payload": {
"subscriptionId": "sub-4f7c",
"editionCode": "enterprise",
"billingCycle": "Annual",
"currentPeriodEnd": "2027-06-11T00:00:00Z"
}
}
Selected fields are mirrored to Service Bus application properties (cs-event-type, cs-tenant-id, cs-trace-id, cs-correlation-id, cs-schema-version) so subscriptions filter without deserializing the body.
Topic topology¶
Each generated product uses one topic per event type (or per aggregate, configurable), with per-service subscriptions filtered by cs-tenant-id and cs-event-type.
| Topic | Publishers | Key Subscribers |
|---|---|---|
tenant-events |
Tenant Management | Subscription, Notification, Audit, Observability |
identity-events |
Identity Service | Notification, Audit |
subscription-events |
Subscription & Billing | Configuration, Notification, Audit |
config-events |
Configuration Service | Domain services, Audit |
notification-events |
Notification Service | Reporting, Audit |
audit-events |
Audit Trail Service | AuditExportWorker, Reporting |
report-events |
Reporting & Analytics | Notification, Customer Portal |
domain-events |
Domain microservices | Notification, Reporting, Audit, Integration |
Event-flow diagram¶
flowchart LR
TenantSvc["Tenant Management"] -->|"TenantRegistered"| Bus["Azure Service Bus"]
Identity["Identity Service"] -->|"UserInvited"| Bus
SubSvc["Subscription & Billing"] -->|"SubscriptionActivated"| Bus
Config["Configuration Service"] -->|"FeatureFlagToggled"| Bus
NotifSvc["Notification Service"] -->|"NotificationSent"| Bus
AuditSvc["Audit Trail Service"] -->|"AuditEntryRecorded"| Bus
Reporting["Reporting & Analytics"] -->|"ReportGenerated"| Bus
Bus -->|"TenantRegistered, SubscriptionActivated"| Config
Bus -->|"UserInvited, ReportGenerated"| NotifSvc
Bus -->|"all auditable"| AuditSvc
Bus -->|"NotificationSent, AuditEntryRecorded"| Reporting
Bus -->|"integration events"| OBS["Factory Observability & Feedback"]
Bus -->|"lineage"| KP["Factory Knowledge Platform"]
Versioning rules¶
eventTypenames never change meaning; breaking changes append a version suffix (SubscriptionActivatedV2) or add topayloadwith a bumpedcs-schema-version.- Consumers tolerate unknown
payloadfields (forward compatibility) and unknowneventTypevalues (ignore-and-log). - Published envelopes are immutable, enabling replay by workers and by the factory's Knowledge replay capability.
How events contribute to the pillars¶
- Traceability —
traceId/correlationId/causationIdbuild a full causation chain from command to downstream effects across services and into the factory. - Reusability — the spine event set is identical across products, so consumers and dashboards are portable.
- Autonomy — agents generate publishers and consumers from blueprint event maps; the contracts are machine-checkable.
- Governance —
AuditEntryRecordedand the audit topic make every sensitive action a durable event. - Observability — every event is a telemetry signal; integration events feed factory dashboards directly.
- Multi-tenant scale —
tenantIdin the envelope andcs-tenant-idfilters enable per-tenant subscription and fan-out.