Control Plane — aggregate roots¶
Generated from the architecture model
This page is rendered from model/**/*.yaml by tools/docs_model during mkdocs build. Edit the YAML, not this page; hand-written design lives on the linked service, platform and plane pages.
| Aggregate | Service | Root entity | Events | Tables |
|---|---|---|---|---|
| AgentCard | AgentCardService | AgentCard | AgentCardPublished, AgentCardWithdrawn | AgentCards |
| AssetRelease | AgentRegistryService | AssetRelease | AssetReleaseSubmitted, AssetReleasePublished, AssetReleaseDeprecated, AssetReleaseRevoked | AssetReleases, ReleaseClosure, ReleaseAliases |
| Budget | CostUsageService | Budget | BudgetUpdated | Budgets |
| Reservation | CostUsageService | Reservation | BudgetReserved, BudgetReservationDenied, ReservationSettled | Reservations |
| UsageRecord | CostUsageService | UsageRecord | UsageRecorded, UsageReconciled | UsageRecords, PricingRevisions |
| Environment | EnvironmentService | Environment | EnvironmentCreated, EnvironmentStateChanged | Environments, EnvironmentConnections |
| FactorySubscription | FactoryCommercialService | FactorySubscription | SubscriptionChanged, InvoiceIssued | FactorySubscriptions, Invoices |
| Project | ProjectService | Project | ProjectCreated, ProjectStateChanged, MembershipChanged, DelegationChanged, SourceScopeChanged | Projects, Memberships, Delegations, SourceScopes |
| Run | RunControlService | Run | RunAccepted, RunStateChanged, RunCompleted, RunFailed, RunCancelled | Runs, CancellationIntents, RecoveryJournal |
| Step | RunControlService | Step | — | Steps |
| Attempt | RunControlService | Attempt | AttemptDispatched, AttemptOutcomeRecorded | Attempts |
| Lease | RunControlService | Lease | LeaseExpired | Leases |
| ApprovalRequest | RunControlService | ApprovalRequest | ApprovalRequested, ApprovalDecided | ApprovalRequests |
AgentCard (AgentCardService)¶
Discovery document of one Published agent release: skills, descriptors, authentication, task endpoint and release hash.
| Field | Type | Required | Description |
|---|---|---|---|
cardId |
guid |
yes | |
tenantId |
string |
yes | |
agentId |
string |
yes | |
releaseId |
string |
yes | |
visibility |
enum:CardVisibility |
yes | |
skills |
list:string |
yes | Skill ids exposed as A2A skills. |
inputDescriptors |
list:string |
yes | |
outputDescriptors |
list:string |
yes | |
authenticationSchemes |
list:string |
yes | oauth2 (Authorization Server), partner-federation |
taskEndpoint |
uri |
yes | Behind GW-01; tasks become runs. |
releaseHash |
hash |
yes | |
publishedAt |
datetime |
yes |
Invariants
- A card exists only for a Published release and is withdrawn when the release is deprecated or revoked.
- A card never exposes Draft or InReview assets, tool descriptors or policies.
AssetRelease (AgentRegistryService)¶
One immutable release of one asset with its complete dependency closure, source commit, hashes, evaluation verdict and approval.
| Field | Type | Required | Description |
|---|---|---|---|
releaseId |
string |
yes | |
tenantId |
string |
yes | Tenant that owns the asset; ConnectSoft-published assets use the platform tenant. |
assetKind |
enum:AssetKind |
yes | |
assetId |
string |
yes | |
version |
string |
yes | |
state |
enum:ReleaseState |
yes | |
sourceRepository |
string |
yes | |
sourceCommit |
string |
yes | |
manifestHash |
hash |
yes | Hash over the release manifest (release-manifest-v1). |
evaluationRecordRef |
string |
no | Artifact reference of the evaluation record (ADR-0021). |
approvalId |
guid |
no | |
publishedAt |
datetime |
no | |
publishedBy |
string |
no | |
version_ |
long |
yes | Optimistic concurrency token. |
Invariants
- Publication is blocked while any closure entry is missing, not Published, or incompatible with the declared runtime adapter.
- The same inputs produce the same manifestHash; a changed dependency changes the release id.
- A Published release is immutable; changes produce a new version. Deprecation keeps the manifest readable.
- A release reaches Published only with an evaluation verdict of passed (or a recorded waiver) and a Reviewer approval that is not the author (ADR-0021, D18).
States (ReleaseState)
stateDiagram-v2
Draft --> InReview : SubmitForReview
InReview --> Published : GatesPassedAndApproved
InReview --> Draft : RejectedOrChanged
Published --> Deprecated : Deprecate
Entities: ClosureEntry, Alias · Value objects: Signature
Budget (CostUsageService)¶
A spending limit for a project or tenant with the spend-approval threshold and the current committed amount.
| Field | Type | Required | Description |
|---|---|---|---|
budgetId |
guid |
yes | |
tenantId |
string |
yes | |
projectId |
guid |
no | Null for a tenant-wide budget. |
period |
string |
yes | monthly |
limitUsd |
decimal |
yes | |
committedUsd |
decimal |
yes | Reserved plus settled in the period. |
approvalThresholdUsd |
decimal |
yes | Predicted run cost above which approval is required (D21); platform ceiling, project may lower. |
version |
long |
yes |
Invariants
- committedUsd never exceeds limitUsd; a reservation that would exceed it is Denied.
- The approval threshold of a project budget is never higher than the platform threshold.
Reservation (CostUsageService)¶
An amount held for a run before dispatch and settled from observed usage afterwards.
| Field | Type | Required | Description |
|---|---|---|---|
reservationId |
guid |
yes | |
tenantId |
string |
yes | |
projectId |
guid |
yes | |
runId |
guid |
yes | |
budgetId |
guid |
yes | |
estimatedUsd |
decimal |
yes | |
settledUsd |
decimal |
no | |
state |
enum:ReservationState |
yes | |
approvalId |
guid |
no | |
expiresAt |
datetime |
yes |
Invariants
- One active reservation per run; settlement is idempotent on the set of receipts settled.
- A reservation above the threshold is created in Reserved only after the spend approval is granted.
States (ReservationState)
stateDiagram-v2
Reserved --> Settled : RunTerminal
Reserved --> Released : RunCancelledBeforeDispatch
Reserved --> Expired : ExpiryWithoutRun
UsageRecord (CostUsageService)¶
One metered quantity attributed to tenant, project, run and attempt, priced with a pricing revision and carrying a reconciliation status.
| Field | Type | Required | Description |
|---|---|---|---|
usageId |
guid |
yes | |
tenantId |
string |
yes | |
projectId |
guid |
yes | |
runId |
guid |
no | |
attemptId |
guid |
no | |
meter |
enum:Meter |
yes | |
dimensions |
json |
yes | profile, provider, model, tool, pool, store, product, sloTier |
quantity |
decimal |
yes | |
status |
enum:UsageStatus |
yes | |
pricingRevision |
string |
yes | |
estimatedCostUsd |
decimal |
no | |
confirmedCostUsd |
decimal |
no | |
sourceReceipt |
string |
no | |
occurredAt |
datetime |
yes |
Invariants
- A record is created from a receipt exactly once (sourceReceipt unique per meter).
- Uncertain usage is never zeroed; it is reconciled by a later receipt or by a provider statement.
Environment (EnvironmentService)¶
A named target inside a project with a policy class, connections and desired deployment references.
| Field | Type | Required | Description |
|---|---|---|---|
environmentId |
guid |
yes | |
projectId |
guid |
yes | |
tenantId |
string |
yes | |
name |
string |
yes | |
class |
enum:EnvironmentClass |
yes | |
state |
enum:EnvironmentState |
yes | |
region |
string |
yes | |
connectionIds |
list:guid |
yes | Connections (BC-16) usable from this environment. |
desiredDeploymentRef |
string |
no | Reference to the desired deployment spec owned by BC-25. |
version |
long |
yes |
Invariants
- Environment names are unique within a project.
- A Production-class environment cannot be targeted by a run whose release is not Published.
- Frozen environments reject every shared-write and production action until unfrozen by a Workspace admin.
States (EnvironmentState)
stateDiagram-v2
Draft --> Active : Activate
Active --> Frozen : Freeze
Frozen --> Active : Unfreeze
Active --> Retired : Retire
Frozen --> Retired : Retire
FactorySubscription (FactoryCommercialService)¶
A tenant's subscription to an edition with seats, quotas and billing terms; the Factory's own instance of the SaaS Billing Subscription aggregate.
| Field | Type | Required | Description |
|---|---|---|---|
subscriptionId |
guid |
yes | |
tenantId |
string |
yes | |
edition |
enum:EditionCode |
yes | |
editionReleaseId |
string |
yes | Published edition definition (BC-04). |
seats |
int |
yes | |
state |
enum:SubscriptionState |
yes | |
billingModel |
string |
yes | internal-budget |
currentPeriodStart |
datetime |
yes | |
currentPeriodEnd |
datetime |
yes | |
version |
long |
yes |
Invariants
- A tenant has at most one active subscription; edition changes are recorded as a new period.
- Entitlement checks (BC-33) read the subscription's edition release, never a mutable edition definition.
States (SubscriptionState)
stateDiagram-v2
Trial --> Active : Convert
Active --> PastDue : InvoiceOverdue
PastDue --> Active : Paid
PastDue --> Suspended : GracePeriodEnded
Suspended --> Active : Paid
Active --> Cancelled : Cancel
Project (ProjectService)¶
A workspace inside a tenant with memberships, source scope, policy overrides and environments; the unit of budget, approval policy and data retention.
| Field | Type | Required | Description |
|---|---|---|---|
projectId |
guid |
yes | |
tenantId |
string |
yes | |
key |
string |
yes | Short unique key within the tenant (used in URLs and labels). |
name |
string |
yes | |
state |
enum:ProjectState |
yes | |
region |
string |
yes | Inherited from the tenant; recorded for audit (ADR-0019). |
policyOverrideRevision |
string |
no | Project policy revision; may only tighten platform policy (D18). |
retentionDays |
int |
yes | Run and artifact retention (default 365; D31). |
budgetId |
guid |
no | Project budget in Usage Accounting (BC-05). |
version |
long |
yes |
Invariants
- Project keys are unique within a tenant and immutable after creation.
- Memberships reference identities that exist in the Identity Service; the Factory never stores credentials.
- A project policy override may only be stricter than the platform policy (validated by BC-18 at save).
- Closing a project cancels its open runs, revokes delegations and starts export or deletion per tenant policy before Closed.
States (ProjectState)
stateDiagram-v2
Active --> Suspended : Suspend
Suspended --> Active : Resume
Active --> Closing : Close
Suspended --> Closing : Close
Closing --> Closed : OffboardingCompleted
Entities: Membership, Delegation, SourceScopeEntry · Value objects: ProjectKey
Run (RunControlService)¶
One accepted unit of work pinned to an immutable asset release and policy revision; the only object whose state the Studio and workers read as truth.
| Field | Type | Required | Description |
|---|---|---|---|
runId |
guid |
yes | Run identity (ADR-0014 envelope field). |
tenantId |
string |
yes | Trusted tenant from the authenticated context (ADR-0015). |
projectId |
string |
yes | Trusted project scope. |
environmentId |
string |
no | Environment within the project, when the workflow targets one. |
idempotencyKey |
string |
yes | Client key; same key + same input returns the same run. |
workflowId |
string |
yes | Published workflow definition id (BC-38). |
releaseId |
string |
yes | Pinned asset release (BC-04). |
policyRevision |
string |
yes | Policy revision evaluated at acceptance (BC-18). |
modelProfileId |
string |
yes | Approved model profile requested at submission (BC-07). |
state |
enum:RunState |
yes | |
inputHash |
hash |
yes | Hash of the canonical submission payload. |
snapshotId |
guid |
yes | Resolved execution snapshot (immutable after acceptance). |
budgetReservationId |
guid |
no | Reservation from Usage Accounting (BC-05). |
requestedBy |
string |
yes | Subject id of the requester (never a reviewer of this run; D18). |
version |
long |
yes | Optimistic concurrency token. |
Invariants
- Same idempotencyKey with the same inputHash returns the existing run; a different inputHash is a conflict (409).
- A run pins releaseId, policyRevision and snapshotId at acceptance; alias moves never change them.
- Every state transition is committed in the same transaction as its outbox record; publication alone is never proof of a transition.
- Cancellation records intent first; completed external effects stay visible and are never rolled back silently.
- The requester of a run is never eligible to decide an approval of that run (D18 separation of duties).
States (RunState)
stateDiagram-v2
Accepted --> Running : FirstAttemptDispatched
Running --> WaitingForApproval : ApprovalRequested
WaitingForApproval --> Running : ApprovalGranted
WaitingForApproval --> Failed : ApprovalRejectedOrExpired
Accepted --> Cancelled : CancelRequestedBeforeDispatch
Running --> Cancelling : CancelRequested
WaitingForApproval --> Cancelling : CancelRequested
Cancelling --> Cancelled : AllAttemptsSettled
Running --> Completed : LastStepSucceeded
Running --> Failed : StepFailedTerminally
Entities: CancellationIntent, RecoveryJournalEntry · Value objects: ReleaseRef, PolicyRef
Step (RunControlService)¶
An ordered unit of a run bound to one agent/skill binding of the pinned release.
| Field | Type | Required | Description |
|---|---|---|---|
stepId |
guid |
yes | |
runId |
ref:Run |
yes | |
tenantId |
string |
yes | |
ordinal |
int |
yes | |
agentId |
string |
yes | Agent definition id from the release. |
skillId |
string |
no | |
state |
enum:StepState |
yes | |
maxAttempts |
int |
yes | |
gate |
string |
no | none |
Invariants
- Only one non-terminal attempt may exist per step.
- A step cannot be dispatched while the run is WaitingForApproval or Cancelling.
Attempt (RunControlService)¶
One execution try of a step; the outcome is reported exactly once by the current lease holder.
| Field | Type | Required | Description |
|---|---|---|---|
attemptId |
guid |
yes | |
stepId |
ref:Step |
yes | |
tenantId |
string |
yes | |
number |
int |
yes | |
leaseId |
guid |
no | |
outcome |
enum:AttemptOutcome |
no | |
outcomeHash |
hash |
no | Hash of the outcome receipt. |
failureClass |
string |
no | transient |
dispatchedAt |
datetime |
yes | |
settledAt |
datetime |
no |
Invariants
- An outcome is accepted only from the holder of the current lease and only once; a stale fencing token is rejected and audited.
- An Uncertain outcome never retries automatically when the step's side-effect class is shared-write or above.
Lease (RunControlService)¶
Time-boxed exclusive right of one runtime worker to execute an attempt, with a fencing token.
| Field | Type | Required | Description |
|---|---|---|---|
leaseId |
guid |
yes | |
attemptId |
ref:Attempt |
yes | |
tenantId |
string |
yes | |
holder |
string |
yes | Runtime worker identity (BC-06 / BC-26). |
expiresAt |
datetime |
yes | |
fencingToken |
long |
yes |
Invariants
- Exactly one current lease per attempt; an expired lease is reconciled before any retry is dispatched.
- fencingToken strictly increases per attempt.
ApprovalRequest (RunControlService)¶
A human decision bound to the exact proposed artifact or action version of a run (approvals page; policy from BC-20).
| Field | Type | Required | Description |
|---|---|---|---|
approvalId |
guid |
yes | |
runId |
ref:Run |
yes | |
stepId |
ref:Step |
yes | |
tenantId |
string |
yes | |
actionClass |
string |
yes | Side-effect class of the gated action (D21). |
proposalHash |
hash |
yes | Hash of the exact artifact, diff, manifest or tool arguments. |
policyRevision |
string |
yes | |
approverRule |
string |
yes | Eligibility rule resolved from BC-20 (role, scope, separation of duties). |
expiresAt |
datetime |
yes | |
state |
enum:ApprovalState |
yes | |
decidedBy |
string |
no | |
decidedAt |
datetime |
no | |
reason |
string |
no | |
version |
long |
yes |
Invariants
- A decision authorizes exactly the referenced proposalHash; a regenerated proposal makes the pending request Stale.
- One valid decision per request; a second decision is a conflict (409).
- A wrong-tenant, expired, duplicate or stale decision never advances the run.
States (ApprovalState)
stateDiagram-v2
Pending --> Approved : Approve
Pending --> Rejected : Reject
Pending --> Expired : ExpiryReminder
Pending --> Stale : ProposalChanged
Pending --> Cancelled : RunCancelled