Bounded Contexts¶
Target Architecture — Final-State Design
This page describes the final-state bounded-context decomposition of the Integration Platform. Contexts are designed for independent evolution, single ownership of aggregates, and explicit, governed interactions through the canonical event envelope.
The Integration Platform follows Clean Architecture + Domain-Driven Design. Its capabilities decompose into eight bounded contexts, each owning a coherent set of aggregate roots and exposing behaviour through well-defined APIs and events. Contexts never share a database; they integrate through events and explicit service contracts, which keeps connection ownership clear and the platform horizontally scalable across the multi-tenant estate. The Webhooks and Vendor Registry contexts are cross-cutting: every other context registers providers in the Vendor Registry and may both emit and consume webhooks.
Context Map¶
flowchart TB
Vendor["Vendor Registry"] -.provider catalog.-> SCM["Source Control Integration"]
Vendor -.provider catalog.-> Model["Model Providers"]
Vendor -.provider catalog.-> Cloud["Cloud Provider"]
Vendor -.provider catalog.-> Comm["Communication"]
Vendor -.provider catalog.-> Commerce["Commerce"]
Vendor -.provider catalog.-> Biz["Business Systems"]
SCM --> Hooks["Webhooks"]
Model --> Hooks
Cloud --> Hooks
Comm --> Hooks
Commerce --> Hooks
Biz --> Hooks
Hooks -->|"normalized events"| Bus["Azure Service Bus"]
SCM --> Bus
Model --> Bus
The map reads as a hub-and-spoke around two cross-cutting authorities. Vendor Registry is the upstream supplier of provider definitions and reusable API clients that every integration context consumes. The six domain contexts (Source Control, Model Providers, Cloud Provider, Communication, Commerce, Business Systems) each own connections, credentials, and runs for their vendor family. Webhooks is the shared ingress/egress boundary through which inbound callbacks are normalised and outbound deliveries are dispatched; all normalised traffic lands on Azure Service Bus in the canonical envelope.
Contexts, Aggregates, and Responsibilities¶
| Bounded Context | Owning Services (ConnectSoft.Factory.Integration.*) |
Aggregate Roots | Primary Responsibility |
|---|---|---|---|
| Source Control Integration | AzureDevOpsIntegrationService, GitHubIntegrationService |
IntegrationConnection, IntegrationCredential, IntegrationRun |
Drive repo, branch, PR, pipeline, and check operations on Azure DevOps and GitHub. |
| Model Providers | OpenAIIntegrationService, AzureOpenAIIntegrationService, OllamaIntegrationService, McpConnectorService |
IntegrationConnection, IntegrationCredential, IntegrationRun |
Front LLM providers and MCP tool servers for the Agent Mesh with governed, audited access. |
| Cloud Provider | CloudProviderAdapterService |
IntegrationConnection, IntegrationRun |
Normalise cloud control-plane operations behind a provider-agnostic adapter. |
| Communication | EmailIntegrationService, SmsIntegrationService |
IntegrationConnection, IntegrationCredential, IntegrationRun |
Send email and SMS through provider-abstracted gateways (Twilio / Israel019 / ACS). |
| Commerce | PaymentIntegrationService |
IntegrationConnection, IntegrationCredential, IntegrationRun, IntegrationFailure |
Integrate payment processors and reconcile commerce callbacks. |
| Business Systems | CrmIntegrationService, SupportIntegrationService |
IntegrationConnection, IntegrationCredential, IntegrationRun |
Integrate CRM and support/ticketing systems for business workflows. |
| Vendor Registry | VendorApiClientRegistryService |
IntegrationProvider, ExternalApiClient |
Catalogue supported providers, their capabilities and auth models, and versioned reusable API clients. |
| Webhooks | WebhookGatewayService |
WebhookSubscription, WebhookDelivery, IntegrationFailure |
Verify, normalise, and dispatch inbound webhooks; deliver signed factory events outward with retry. |
All aggregates carry the cross-cutting metadata fields (tenantId, projectId, moduleId, traceId, correlationId, causationId, environment, version, createdAt, updatedAt, status), which is what lets any connection, run, delivery, or failure be correlated back to the lifecycle that produced it. The full per-aggregate breakdown is in Aggregate Roots.
Context Interaction Principles¶
- Single ownership. Each aggregate instance is owned by exactly one context and persisted in exactly one store. No cross-context database joins.
- Events over coupling. Contexts publish domain events (
NounVerbPastTense) and react to integration events; they never call into each other's persistence. - Vendor Registry is the source of truth for providers. A connection cannot be established against a provider that is not registered, capability-described, and assigned a versioned
ExternalApiClient. - Webhooks is the only ingress. All inbound external callbacks enter through
WebhookGatewayService, which guarantees signature verification, tenancy resolution, idempotency, and normalisation before fan-out. - Credentials are never owned by the domain.
IntegrationCredentialaggregates hold only Key Vault references and rotation metadata; secret material is custodied in Azure Key Vault.
Inbound Normalisation Pipeline¶
Every inbound webhook enters through the Webhooks context, which runs a multi-stage pipeline before the callback becomes a canonical factory event.
flowchart LR
Ext["External Vendor Callback"] --> GW["WebhookGatewayService"]
GW --> Verify["Verify signature<br/>+ resolve tenant"]
Verify --> Dedup["Deduplicate<br/>(deliveryId / contentHash)"]
Dedup --> Persist["Persist raw payload<br/>(Azure Blob)"]
Persist --> Normalize["Normalize to<br/>canonical envelope"]
Normalize --> Record["Create WebhookDelivery"]
Record --> Publish["Publish event<br/>(Azure Service Bus)"]
Publish --> Bus[("Azure Service Bus")]
Stages: verify the vendor signature and resolve the owning tenantId; deduplicate on the vendor delivery id or content hash to enforce idempotency; persist the raw body to Azure Blob for replay and audit; normalize to the canonical envelope; record a WebhookDelivery carrying full metadata and lineage; and publish the normalised event. Each stage emits an event (WebhookDelivered, IntegrationFailed on rejection), so inbound processing is fully traceable and replayable. See Workflows and Events.