Governance — 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 |
|---|---|---|---|---|
| ApprovalRule | ApprovalPolicyService | ApprovalRule | ApprovalRuleActivated | ApprovalRules |
| RoutingEvaluation | ApprovalPolicyService | RoutingEvaluation | ApprovalRouted, ApprovalDecisionValidated | RoutingEvaluations |
| AuditEntry | AuditService | AuditEntry | AuditEntryRecorded, AuditChainVerified | AuditEntries, ChainHeads |
| ClassificationLabel | AuditService | ClassificationLabel | ClassificationChanged | Classifications, RedactionRules |
| Finding | AuditService | Finding | FindingRaised, FindingResolved | Findings |
| PolicyBundle | PolicyEngineService | PolicyBundle | PolicyRevisionActivated, PolicyRevisionRetired | PolicyBundles, PolicyRules |
| PolicyDecision | PolicyEngineService | PolicyDecision | PolicyDecisionRecorded | PolicyDecisions |
| SecretReference | SecretBrokerService | SecretReference | SecretReferenceRegistered, SecretRotated, SecretReferenceRevoked | SecretReferences, RotationReceipts |
| Issuance | SecretBrokerService | Issuance | CredentialIssued, CredentialRevoked | Issuances |
ApprovalRule (ApprovalPolicyService)¶
A rule for one scope and action class — approver roles, separation-of-duties constraints, quorum, expiry, break-glass allowance and the policy revision it belongs to.
| Field | Type | Required | Description |
|---|---|---|---|
ruleId |
string |
yes | |
tenantId |
string |
yes | |
scope |
string |
yes | platform |
actionClass |
string |
yes | shared-write |
actionPattern |
string |
no | Optional narrowing to an action family (tool id |
approverRoles |
list:string |
yes | |
excludeRequester |
bool |
yes | |
excludeAuthor |
bool |
yes | For publication actions the asset author may not approve. |
quorum |
int |
yes | |
expiryMinutes |
int |
yes | |
breakGlassAllowed |
bool |
yes | |
policyRevision |
string |
yes | |
active |
bool |
yes |
Invariants
- excludeRequester is always true (ADR-0015 point 6); a rule that sets it false is refused at activation.
- A project rule may only tighten the tenant rule (more roles excluded, shorter expiry, higher quorum, break-glass disabled), never loosen it.
- Expiry never exceeds the platform maximum; an expired request can only fail the action, never be revived.
RoutingEvaluation (ApprovalPolicyService)¶
The record of routing one approval request (eligible approvers, expiry) or validating one decision (eligibility, separation of duties, timeliness) under the rule in force.
| Field | Type | Required | Description |
|---|---|---|---|
evaluationId |
guid |
yes | |
tenantId |
string |
yes | |
approvalId |
guid |
yes | Run Control approval request id. |
runId |
guid |
no | |
ruleId |
string |
yes | |
actionClass |
string |
yes | |
requesterId |
string |
yes | |
authorId |
string |
no | |
eligibleApprovers |
list:string |
no | Resolved subjects or groups at routing time. |
deciderId |
string |
no | |
outcome |
enum:RoutingOutcome |
yes | |
breakGlass |
bool |
yes | |
expiresAt |
datetime |
yes | |
evaluatedAt |
datetime |
yes |
Invariants
- A decision by the requester or the author is Invalid regardless of role; a Platform admin break-glass decision is valid only with a reason and when the rule allows it, and is always audited.
- Eligibility is evaluated against memberships at decision time, not at routing time; a revoked role invalidates a pending decision.
AuditEntry (AuditService)¶
One immutable evidence record (audit-evidence-v1) — kind, actor, scope, action, target with version or hash, reason, outcome, correlation ids and the hash of the previous entry in the tenant's chain.
| Field | Type | Required | Description |
|---|---|---|---|
entryId |
guid |
yes | |
tenantId |
string |
yes | |
projectId |
string |
no | |
sequence |
long |
yes | Monotonic per tenant. |
kind |
enum:EvidenceKind |
yes | |
actor |
json |
yes | Identity kind and id, roles, delegation, break-glass flag |
action |
string |
yes | |
target |
json |
yes | Type, id, version or hash |
reason |
string |
no | |
outcome |
string |
yes | |
correlationId |
guid |
yes | |
causationId |
guid |
no | |
runId |
guid |
no | |
sourceEvent |
string |
yes | Producing service and event name. |
previousHash |
hash |
yes | |
entryHash |
hash |
yes | |
recordedAt |
datetime |
yes |
Invariants
- Entries are append-only and hash-chained per tenant; the chain head is signed daily and verified on a schedule; a broken chain is a Critical finding.
- Evidence never contains prompt text, payloads or secret values; it references hashes and artifact ids.
- Retention is 7 years (D31); personal identifiers are redacted after the project's retention window while the chain stays verifiable.
ClassificationLabel (AuditService)¶
The registry entry that classifies a resource type or instance (source, artifact kind, connection, profile) and binds retention, redaction and routing rules to the class.
| Field | Type | Required | Description |
|---|---|---|---|
labelId |
guid |
yes | |
tenantId |
string |
yes | |
resourceType |
string |
yes | |
resourceId |
string |
no | Null for a type-level default. |
dataClass |
enum:DataClass |
yes | |
retentionDays |
int |
yes | |
redactionRuleIds |
list:string |
yes | |
residency |
string |
yes | Region constraint. |
setBy |
string |
yes | |
setAt |
datetime |
yes |
Invariants
- An instance label may only be stricter than its type default; Restricted never leaves its region and is never promoted to Shared memory.
- Changing a label emits an event that retention sweepers, context assembly and the model gateway honour from the next operation on.
Entities: RedactionRule · Value objects: —
Finding (AuditService)¶
A compliance or security finding raised from evidence (chain break, policy prohibited attempts, uncertain effects unresolved, rotation overdue) with severity, owner and resolution.
| Field | Type | Required | Description |
|---|---|---|---|
findingId |
guid |
yes | |
tenantId |
string |
yes | |
severity |
enum:FindingSeverity |
yes | |
category |
string |
yes | |
evidenceEntryIds |
list:guid |
yes | |
owner |
string |
no | |
state |
string |
yes | open |
raisedAt |
datetime |
yes | |
resolvedAt |
datetime |
no |
Invariants
- A finding references the evidence entries that justify it; resolution is itself evidence.
PolicyBundle (PolicyEngineService)¶
Runtime read model of a Published policy asset — a versioned set of rules per domain for one scope (the YAML of the original design §43 made typed), with the revision id runs pin at acceptance.
| Field | Type | Required | Description |
|---|---|---|---|
revision |
string |
yes | Policy revision id pinned by runs (ADR-0014). |
tenantId |
string |
yes | |
scope |
enum:PolicyScope |
yes | |
scopeId |
string |
yes | Tenant id or project id; platform for platform scope. |
releaseId |
string |
yes | Published asset release (BC-04). |
parentRevision |
string |
no | The wider-scope revision this bundle tightens. |
rulesRef |
string |
yes | Artifact reference of the rule document. |
rulesHash |
hash |
yes | |
domains |
list:string |
yes | |
active |
bool |
yes | |
activatedAt |
datetime |
no |
Invariants
- A tenant bundle may only tighten the platform bundle and a project bundle may only tighten the tenant bundle; activation validates monotonic tightening per rule and refuses otherwise.
- Bundles are immutable per revision; a change is a new Published release and a new revision; accepted runs keep their pinned revision.
- Prohibited effects cannot be overridden by any approval; RequireApproval names the action class the approval must bind to (D21).
Entities: PolicyRule · Value objects: —
PolicyDecision (PolicyEngineService)¶
An immutable recorded decision (policy-decision-v1) for one subject, action and resource under one revision — effect, obligations, matched rules and reasons.
| Field | Type | Required | Description |
|---|---|---|---|
decisionId |
guid |
yes | |
tenantId |
string |
yes | |
projectId |
string |
no | |
environmentId |
string |
no | |
runId |
guid |
no | |
subject |
json |
yes | Identity kind and id (user, agent release, workload), roles, delegated scope |
domain |
enum:PolicyDomain |
yes | |
action |
string |
yes | Action identifier, for example tool:propose-change-set or model:invoke:code-agent |
actionClass |
string |
yes | Side-effect class after environment raising. |
resource |
json |
yes | Resource descriptor: tool, profile, source, connection, environment, data class |
inputsHash |
hash |
no | |
policyRevision |
string |
yes | |
effect |
enum:PolicyEffect |
yes | |
obligations |
json |
no | Redaction, limits, approver rule reference, logging requirements |
matchedRules |
list:string |
yes | |
reasons |
list:string |
yes | |
evaluatedAt |
datetime |
yes |
Invariants
- Decisions are immutable and reference the exact revision; the same inputs under the same revision give the same effect (deterministic evaluation).
- Every effect of RequireApproval names the action class; the approval that follows (BC-03, BC-20) binds to this decision id.
- Decisions never contain prompt text, secrets or payloads; they reference hashes.
SecretReference (SecretBrokerService)¶
A named reference to a secret held in Key Vault (or an exchangeable identity) with its kind, owner, allowed purposes, rotation policy and state; the value is never here.
| Field | Type | Required | Description |
|---|---|---|---|
referenceId |
string |
yes | Stable reference used by connections |
tenantId |
string |
yes | |
kind |
enum:SecretKind |
yes | |
vaultRef |
string |
yes | Key Vault secret or key identifier |
ownerKind |
string |
yes | connection |
ownerId |
string |
yes | |
allowedPurposes |
list:string |
yes | source-sync |
maxTtlSeconds |
int |
yes | |
rotationDays |
int |
yes | |
lastRotatedAt |
datetime |
no | |
revoked |
bool |
yes |
Invariants
- Values are never read into this service's store or logs; the broker holds them in memory only for the duration of an issuance.
- An issuance is allowed only for a purpose in allowedPurposes, for a subject with a policy decision Allow, and with a TTL not above maxTtlSeconds.
- Revoking a reference invalidates every live issuance and emits an event the owners act on.
Issuance (SecretBrokerService)¶
One short-lived credential issued to one subject for one purpose and scope — with its expiry, the policy decision that allowed it and the revocation state; the credential itself is delivered once and not stored.
| Field | Type | Required | Description |
|---|---|---|---|
issuanceId |
guid |
yes | |
tenantId |
string |
yes | |
referenceId |
string |
yes | |
subject |
json |
yes | Workload identity, run, attempt, invocation, sandbox lease |
purpose |
string |
yes | |
scope |
json |
yes | Narrowed scopes, hosts, operations |
policyDecisionId |
guid |
yes | |
state |
enum:IssuanceState |
yes | |
issuedAt |
datetime |
yes | |
expiresAt |
datetime |
yes | |
revokedAt |
datetime |
no |
Invariants
- A credential is delivered exactly once to the requesting subject over an authenticated channel and expires with the issuance; the broker never re-delivers.
- Issuances outlive neither their lease (attempt, invocation, sandbox) nor maxTtlSeconds; the broker revokes on lease end where the provider supports it.