Skip to content

Workflows

Target Architecture — Final-State Design

This page describes the final-state governance workflows. They are realised as MassTransit-coordinated flows and stateful aggregates across the Policy and Approval contexts, grounded in the canonical Event Envelope.

The platform's signature workflow is the governance approval flow: a sensitive action is evaluated against policy; if a gate is required, a human approval is requested and the action proceeds or is blocked on the decision. Supporting flows are policy evaluation, the approval state machine, and escalation/timeout.

Governance Approval Flow

This is the end-to-end flow when a platform (e.g. the Control Plane or DevOps & GitOps) attempts a sensitive action.

sequenceDiagram
    participant Caller as Calling Platform
    participant Engine as PolicyEngineService
    participant Eval as PolicyEvaluationService
    participant Approval as ApprovalService
    participant Human as Human Approver
    participant Audit as AuditService

    Caller->>Engine: POST /policies/evaluate (action)
    Engine->>Eval: evaluate(subject, resource, action, risk)
    Eval-->>Engine: matched rules + effect
    Engine->>Audit: record PolicyDecision
    alt Allow
        Engine-->>Caller: decision = Allow
        Caller->>Caller: proceed with action
    else Deny
        Engine-->>Caller: decision = Deny
        Caller->>Caller: block action
    else RequiresApproval (gate)
        Engine->>Approval: RequestApproval(policyDecisionId)
        Approval->>Audit: record ApprovalRequested
        Approval-->>Engine: approvalRequestId
        Engine-->>Caller: decision = RequiresApproval (pending)
        Human->>Approval: approve / reject
        Approval->>Audit: record ApprovalDecision
        alt Approved
            Approval-->>Caller: ApprovalGranted (event)
            Caller->>Caller: proceed with action
        else Rejected
            Approval-->>Caller: ApprovalRejected (event)
            Caller->>Caller: block action
        end
    end
Hold "Alt" / "Option" to enable pan & zoom

The calling platform never proceeds with a gated action until it receives an ApprovalGranted event (or a synchronous Allow). Every step writes an AuditEntry, so the full decision chain is provable and replayable via traceId.

Policy Evaluation Flow

How PolicyEngineService produces a decision, composing rule evaluation with ABAC suppliers and risk.

flowchart TB
    Start["Evaluate request"] --> Load["Load applicable PolicyDefinitions (by domain + scope)"]
    Load --> Attrs["Gather ABAC attributes"]
    Attrs --> Iso["TenantIsolationPolicyService: isolation attrs"]
    Attrs --> Class["DataClassificationService: classification labels"]
    Attrs --> Risk["RiskScoringService: risk score"]
    Iso --> Match["Match rules by priority"]
    Class --> Match
    Risk --> Match
    Match --> Effect{"Resolved effect?"}
    Effect -->|Allow| RecordA["Record PolicyDecision = Allow"]
    Effect -->|Deny| RecordD["Record PolicyDecision = Deny"]
    Effect -->|Gate| RecordG["Record PolicyDecision = RequiresApproval"]
    RecordG --> OpenApproval["Open ApprovalRequest"]
    RecordA --> Emit["Emit PolicyDecisionRecorded + AuditEntry"]
    RecordD --> Emit
    OpenApproval --> Emit
Hold "Alt" / "Option" to enable pan & zoom

Evaluation is deterministic: rules are matched in priority order, the highest-priority matching rule's effect wins, and a Deny always overrides an Allow at equal priority. A RequiresApproval gate is selected when a matched rule's gate is HumanApproval or when the supplied RiskScore crosses the policy's risk threshold.

ApprovalRequest State Machine

The lifecycle of an ApprovalRequest aggregate.

stateDiagram-v2
    [*] --> Pending: ApprovalRequested
    Pending --> Approved: approver grants
    Pending --> Rejected: approver rejects
    Pending --> Escalated: timeout (escalatable)
    Pending --> Expired: timeout (final)
    Escalated --> Approved: escalated approver grants
    Escalated --> Rejected: escalated approver rejects
    Escalated --> Expired: max escalation reached
    Approved --> [*]
    Rejected --> [*]
    Expired --> [*]
Hold "Alt" / "Option" to enable pan & zoom
State Meaning Exit
Pending Open, awaiting an authorized approver. Approve / Reject / Escalate / Expire.
Escalated Timed out at the current level; routed to the next approver tier. Approve / Reject / Expire.
Approved Granted by an authorized approver — terminal.
Rejected Rejected by an approver or auto-rejected — terminal.
Expired Timed out with no escalation path — terminal (treated as a block).

Escalation & Timeout

The ApprovalTimeoutWorker ticks every minute and reconciles open requests against their expiresAt.

flowchart TB
    Tick["ApprovalTimeoutWorker (1 min)"] --> Find["Find Pending/Escalated requests past expiresAt"]
    Find --> Decide{"Escalation level < max?"}
    Decide -->|Yes| Escalate["Escalate to next approver tier"]
    Escalate --> Reset["Reset timer, increment escalationLevel"]
    Reset --> Notify["Re-emit ApprovalRequested (escalation)"]
    Decide -->|No| AutoReject["Auto-reject (Expired)"]
    AutoReject --> EmitRej["Emit ApprovalRejected + AuditEntry"]
Hold "Alt" / "Option" to enable pan & zoom
  • Escalation policy is part of the matched policy: each tier has a timeout and a target approver set (e.g. ReleaseManagerSecurityLeadComplianceOfficer).
  • Default-deny on expiry — if no escalation path remains, the request expires and the action is blocked (fail-safe, never fail-open).
  • Segregation of duties — escalation never routes a request to its raising subject; every grant/reject records the approverId, comment, and justification for audit.

How the Workflows Tie Back

  • Traceability — every decision, approval, and audit entry shares the traceId from the originating action, so the whole chain is one queryable thread.
  • AutonomyAllow/Deny resolve synchronously with no human; only gated actions pause for approval.
  • Governance — nothing irreversible proceeds without a recorded PolicyDecision and (when gated) an ApprovalDecision.
  • Observability — flow transitions emit canonical events consumed by Observability & Feedback.