Skip to content

Control Plane — Aggregate Roots

The Control Plane domain comprises 20 aggregate roots, grouped by bounded context. Each aggregate is a consistency boundary: invariants are enforced within it, it is loaded and saved atomically through its repository, and it emits domain events in the canonical envelope. All aggregates carry the cross-cutting metadata fields (tenantId, traceId, createdAt, etc.), persisted as first-class columns. Persistence is NHibernate on Azure SQL / PostgreSQL with ConnectSoft.Extensions.Saas.NHibernate tenant filters.

Target Architecture — Final-State Design

Naming follows the conventions: aggregates and entities are singular PascalCase nouns; repositories are {AggregateRoot}Repository. Fields below show the essential domain state, not every column.


Tenant & Edition Context

Tenant

  • Purpose: The top-level isolation boundary — an isolated customer of the factory. Root of all tenant-scoped data.
  • Fields: tenantId (slug, identity), displayName, region, status (Provisioning/Active/Suspended/Retired), editionId, provisionedAt.
  • Entities: TenantContact, TenantSetting.
  • Value Objects: TenantSlug, Region, IsolationModel (shared/dedicated).
  • Invariants: slug is globally unique and immutable; a tenant must reference exactly one active edition; cannot transition to Active until provisioning completes.
  • Domain Events: TenantProvisioned, TenantSuspended, TenantRetired.
  • Repository: TenantRepository.
  • Persistence: Azure SQL (TenantService DB); slug uniquely indexed.

Edition

  • Purpose: A packaged capability tier — the bundle of feature flags and quota templates a tenant subscribes to.
  • Fields: editionId, name, version, status (Draft/Published/Retired), featureSet, quotaTemplate.
  • Entities: EditionFeature, EditionQuota.
  • Value Objects: FeatureKey, QuotaLimit, SemVer.
  • Invariants: a published edition is immutable (new tier = new version); quota template values are non-negative; cannot retire an edition with active subscriptions.
  • Domain Events: EditionPublished, EditionRetired.
  • Repository: EditionRepository.
  • Persistence: Azure SQL (EditionService DB).

Subscription

  • Purpose: The relationship between a tenant and an edition over time, with lifecycle status.
  • Fields: subscriptionId, tenantId, editionId, status (Trial/Active/PastDue/Cancelled), startedAt, renewsAt, cancelledAt.
  • Entities: SubscriptionTerm, BillingAnchor.
  • Value Objects: BillingPeriod, Money.
  • Invariants: at most one active subscription per tenant; cannot activate against a retired edition; cancellation is terminal.
  • Domain Events: SubscriptionActivated, SubscriptionRenewed, SubscriptionCancelled.
  • Repository: SubscriptionRepository.
  • Persistence: Azure SQL (SubscriptionService DB).

Project Management Context

Project

  • Purpose: A factory project — the SaaS product being produced. Owns environments and modules.
  • Fields: projectId (proj- prefixed), tenantId, name, slug, description, status (Active/Paused/Archived), createdAt.
  • Entities: ProjectMember, ProjectTag.
  • Value Objects: ProjectSlug, IntentSummary.
  • Invariants: slug unique per tenant; cannot archive a project with running workflow instances; must have at least one environment.
  • Domain Events: ProjectCreated, ProjectPaused, ProjectArchived.
  • Repository: ProjectRepository.
  • Persistence: Azure SQL (ProjectService DB).

Environment

  • Purpose: A deployment/config scope of a project (dev/test/staging/prod).
  • Fields: environmentId, projectId, name (enum), status (Provisioning/Active/Decommissioned), configScopeRef.
  • Entities: EnvironmentVariable, EnvironmentEndpoint.
  • Value Objects: EnvironmentName, ConfigScope.
  • Invariants: environment name unique within a project; prod requires an approved release gate before promotion; cannot decommission while referenced by an active deployment.
  • Domain Events: EnvironmentProvisioned, EnvironmentDecommissioned.
  • Repository: EnvironmentRepository.
  • Persistence: Azure SQL (EnvironmentService DB).

Module

  • Purpose: A unit the factory builds (microservice, UI, worker, library, gateway), tracked in the catalogue.
  • Fields: moduleId (module- prefixed), projectId, name, type (Microservice/UI/Worker/Library/Gateway), status, currentBlueprintVersionId.
  • Entities: ModuleEndpoint, ModuleArtifactRef.
  • Value Objects: ModuleType, ModuleName.
  • Invariants: module name unique within project; type is immutable after creation; must reference a valid blueprint version once assembled.
  • Domain Events: ModuleRegistered, ModuleRetired.
  • Repository: ModuleRepository.
  • Persistence: PostgreSQL (ModuleCatalogService DB).

ModuleDependency

  • Purpose: A directed dependency edge between two modules; the basis of the project dependency graph.
  • Fields: dependencyId, projectId, fromModuleId, toModuleId, kind (Build/Runtime/Contract), status (Declared/Resolved/Broken).
  • Entities: (none — edge aggregate).
  • Value Objects: DependencyKind, VersionConstraint.
  • Invariants: no self-dependency; the graph must remain acyclic (cycles raise DependencyCycleDetected); both endpoints must exist in the catalogue.
  • Domain Events: DependencyDeclared, DependencyResolved, DependencyCycleDetected.
  • Repository: ModuleDependencyRepository.
  • Persistence: PostgreSQL (DependencyService DB); graph-friendly indexing.

Blueprint Management Context

Blueprint

  • Purpose: A declarative specification of what the factory will build for a module/service, owning its version history.
  • Fields: blueprintId (bp- prefixed), projectId, name, kind (Service/Domain/ContextMap/Solution), status (Draft/Published/Deprecated), currentVersionId.
  • Entities: BlueprintVersion (see below), BlueprintParameter.
  • Value Objects: BlueprintKind, SpecRef.
  • Invariants: name unique per project; a published blueprint must have at least one validated version; current version always points to an existing version.
  • Domain Events: BlueprintCreated, BlueprintPublished, BlueprintDeprecated.
  • Repository: BlueprintRepository.
  • Persistence: Azure SQL (BlueprintService DB).

BlueprintVersion

  • Purpose: An immutable, validated version of a blueprint; the unit referenced by workflows and modules.
  • Fields: blueprintVersionId (bpv- prefixed), blueprintId, version (SemVer), specHash, validationStatus (Pending/Validated/Failed), validatedAt.
  • Entities: ValidationViolation, ParsedArtifactRef.
  • Value Objects: SemVer, SpecHash, RuleSetVersion.
  • Invariants: a version is immutable once Validated; specHash uniquely identifies content; cannot be referenced by a workflow until Validated.
  • Domain Events: BlueprintVersionSubmitted, BlueprintValidated, BlueprintValidationFailed.
  • Repository: BlueprintVersionRepository (often accessed via BlueprintRepository).
  • Persistence: Azure SQL (BlueprintService DB); validation results may project to PostgreSQL.

Workflow Orchestration Context (core)

WorkflowDefinition

  • Purpose: A reusable, versioned process template (e.g. Project Bootstrap, Sprint Execution, Milestone Lifecycle, Microservice Assembly, Release) seeded from the platform registry.
  • Fields: workflowDefinitionId, name, version (SemVer), status (Draft/Published/Deprecated), steps, gates, timeouts.
  • Entities: WorkflowStepDefinition, ApprovalGateDefinition, CompensationDefinition.
  • Value Objects: StepKind, RoleRequirement, SkillRequirement, TimeoutPolicy, RetryPolicy.
  • Invariants: a published definition is immutable; step graph is acyclic with a single start; every gate references a valid role/policy.
  • Domain Events: WorkflowDefinitionPublished, WorkflowDefinitionDeprecated.
  • Repository: WorkflowDefinitionRepository.
  • Persistence: Azure SQL (WorkflowDefinitionService DB). Grounded in orchestration domain and coordinators.

WorkflowInstance

  • Purpose: A running, event-sourced execution of a workflow definition for one project — the heart of orchestration.
  • Fields: workflowInstanceId (wf- prefixed), workflowDefinitionId+version, projectId, state (see state machine), currentStep, correlationId, startedAt, completedAt.
  • Entities: StepExecution, OpenApprovalRef, CompensationRecord.
  • Value Objects: WorkflowState, StepStatus, Deadline.
  • Invariants: state transitions follow the definition's allowed graph; an instance cannot complete with open approvals or pending steps; the event history is append-only and immutable (enables replay).
  • Domain Events: WorkflowInstanceStarted, WorkflowStepCompleted, WorkflowStepTimedOut, WorkflowInstanceCompleted, WorkflowInstanceFailed.
  • Repository: WorkflowInstanceRepository (MassTransit saga repository + event store).
  • Persistence: Azure SQL (WorkflowOrchestrator DB) — saga state + append-only event store; projection in ProcessStateService.

AgentTask

  • Purpose: The unit of work the Control Plane assigns to the Agent Mesh for a workflow step (contract).
  • Fields: taskId (task- prefixed), workflowInstanceId, agentRole, requestedSkill, inputs, constraints (modelPolicyId, maxCorrectionAttempts, deadline), status (Assigned/ContextLoading/Executing/Validating/Correcting/Completed/Failed), outputArtifacts.
  • Entities: TaskInput, TaskConstraint, TaskOutputRef.
  • Value Objects: AgentRole, SkillReference, RetryPolicy, Deadline.
  • Invariants: idempotent assignment (same taskId never duplicates execution); cannot complete without validated output; correction attempts cannot exceed maxCorrectionAttempts.
  • Domain Events: AgentTaskAssigned, AgentTaskReassigned, AgentTaskCompleted, AgentTaskFailed.
  • Repository: AgentTaskRepository.
  • Persistence: Azure SQL (TaskAssignmentService DB).

Agent Management Context

AgentDefinition

  • Purpose: A registered, versioned agent — its role, capabilities, and the task contract it satisfies. Governs (not runs) Agent Mesh agents.
  • Fields: agentId (ConnectSoft.Agent.*), role, version (SemVer), status (Active/Deprecated), capabilities, supportedSkills, defaultModelPolicyId.
  • Entities: AgentCapability, AgentVersionRecord.
  • Value Objects: AgentRole, Capability, SemVer.
  • Invariants: role+version unique; a deprecated agent cannot be assigned new tasks; supported skills must exist in the skill registry.
  • Domain Events: AgentDefinitionRegistered, AgentDefinitionDeprecated.
  • Repository: AgentDefinitionRepository.
  • Persistence: Azure SQL (AgentRegistryService DB).

SkillDefinition

  • Purpose: A registered, versioned skill with its input/output contract — the capability an agent invokes.
  • Fields: skillId (ConnectSoft.Skill.*), name, version (SemVer), status, inputSchema, outputSchema, requiredCapabilities.
  • Entities: SkillParameter, SkillVersionRecord.
  • Value Objects: SkillReference, IoSchema, SemVer.
  • Invariants: name+version unique; I/O schemas are immutable per version; a skill cannot be retired while referenced by an active agent definition.
  • Domain Events: SkillDefinitionRegistered, SkillDefinitionRetired.
  • Repository: SkillDefinitionRepository.
  • Persistence: Azure SQL (SkillRegistryService DB).

Governance Context

PolicyDefinition

  • Purpose: A declarative rule governing a sensitive action (e.g. production release, model usage, blueprint publish).
  • Fields: policyId (pol- prefixed), name, version, status (Draft/Active/Retired), target (action+resource matcher), effect (Allow/Deny/RequireApproval), obligations.
  • Entities: PolicyRule, PolicyObligation.
  • Value Objects: ActionMatcher, ResourceMatcher, Effect.
  • Invariants: an active policy is immutable (changes create a new version); deny takes precedence over allow on conflict; obligations reference valid roles.
  • Domain Events: PolicyDefinitionActivated, PolicyDefinitionRetired.
  • Repository: PolicyDefinitionRepository.
  • Persistence: Azure SQL (PolicyEngineService DB).

PolicyDecision

  • Purpose: An immutable record of a single policy evaluation outcome — the audit anchor for governance.
  • Fields: policyDecisionId (pd- prefixed), subject, action, resource, effect, matchedPolicyId+version, obligations, decidedAt, workflowInstanceId.
  • Entities: (none — value record).
  • Value Objects: Subject, Effect, Obligation.
  • Invariants: immutable once recorded; must reference the policy version that produced it; every RequireApproval decision links to an ApprovalRequest.
  • Domain Events: PolicyDecisionRecorded.
  • Repository: PolicyDecisionRepository.
  • Persistence: Azure SQL (PolicyEngineService DB), append-only.

ApprovalRequest

  • Purpose: A human approval gate within a workflow that must be resolved before proceeding.
  • Fields: approvalId (apr- prefixed), workflowInstanceId, policyDecisionId, requiredRole, status (Pending/Granted/Rejected/Expired), requestedAt, decidedBy, decidedAt, comment.
  • Entities: ApprovalDecisionRecord.
  • Value Objects: ApprovalStatus, RoleRequirement, Deadline.
  • Invariants: terminal once Granted/Rejected/Expired; decider must hold requiredRole; expiry escalates or fails the workflow step.
  • Domain Events: ApprovalRequested, ApprovalGranted, ApprovalRejected, ApprovalExpired.
  • Repository: ApprovalRequestRepository.
  • Persistence: Azure SQL (ApprovalService DB).

AuditEntry

  • Purpose: An immutable record of a governed action — the tamper-evident audit trail.
  • Fields: auditEntryId (aud- prefixed), tenantId, projectId, actor, action, resource, outcome, correlationId, occurredAt, hashChainPrev.
  • Entities: (none — append-only record).
  • Value Objects: Actor, Outcome, HashChainLink.
  • Invariants: append-only and immutable; each entry chains to the previous via hashChainPrev for tamper evidence; never deleted (only exported/retained).
  • Domain Events: AuditEntryRecorded, AuditExported.
  • Repository: AuditEntryRepository.
  • Persistence: PostgreSQL (AuditService DB), append-only; exported by the AuditExportWorker.

Cost & Usage Context

UsageRecord

  • Purpose: A metered consumption fact (tokens, compute minutes, agent tasks) attributed to a tenant/project for billing and quota.
  • Fields: usageRecordId, tenantId, projectId, metric (Tokens/ComputeMinutes/AgentTasks), quantity, source (taskId/modelInvocationId), occurredAt, period.
  • Entities: (none — fact record).
  • Value Objects: Metric, Quantity, BillingPeriod.
  • Invariants: quantity is non-negative; records are immutable; idempotent per (source, metric) to prevent double counting.
  • Domain Events: UsageRecorded, UsageRolledUp.
  • Repository: UsageRecordRepository.
  • Persistence: PostgreSQL time-series (CostUsageService DB); rolled up by UsageRollupWorker.

Integration Context

IntegrationConnection

  • Purpose: A managed connection to an external system (Git provider, identity provider, cloud, billing); the anti-corruption boundary.
  • Fields: integrationConnectionId (int- prefixed), tenantId, type (GitProvider/IdentityProvider/Cloud/Billing), provider, status (Connected/Degraded/Disconnected), configRef (Key Vault), lastCheckedAt.
  • Entities: IntegrationCredentialRef, IntegrationHealthCheck.
  • Value Objects: IntegrationType, ProviderName, SecretRef.
  • Invariants: secrets are never stored in the aggregate (only configRef to Key Vault); a connection must pass a health check before Connected; one active connection per (type, provider) per tenant unless multi-connect is enabled.
  • Domain Events: IntegrationConnected, IntegrationDegraded, IntegrationDisconnected.
  • Repository: IntegrationConnectionRepository.
  • Persistence: Azure SQL (IntegrationService DB); secrets in Azure Key Vault.

Aggregate-to-Context Summary

Context Aggregate Roots
Tenant & Edition Tenant, Edition, Subscription
Project Management Project, Environment, Module, ModuleDependency
Blueprint Management Blueprint, BlueprintVersion
Workflow Orchestration WorkflowDefinition, WorkflowInstance, AgentTask
Agent Management AgentDefinition, SkillDefinition
Governance PolicyDefinition, PolicyDecision, ApprovalRequest, AuditEntry
Cost & Usage UsageRecord
Integration IntegrationConnection