Skip to content

Operational Readiness Review (dev-to-ops handoff gate)

Before a dev-owned scope (a resource group, a workload, an environment) becomes the operations team’s responsibility, the Operational Readiness Review (ORR) runs automatically: it evaluates the whole scope against the governance, security, RBAC, and reliability rules that ops depends on, grounds each detected issue in the exact rule that produced it, and returns one decision - clear, needs_review, or blocked - keyed to the ownership-transfer event. It is the deployment-preflight pass and the assurance-twin posture assessment, composed into a single handoff gate so nothing crosses the dev-to-ops boundary un-reviewed.

This closes a class of failures that a per-change review misses: a workload can be individually compliant on every merge yet still arrive at ops with an over-privileged managed identity, a guest principal holding Owner, no diagnostic settings, or no backup - because no single change introduced the whole gap. The ORR reviews the accumulated posture of the scope at the moment of handoff, not one diff.

Implementation status: The deterministic review and injected orchestration are implemented, but the upstream runtime doesn’t invoke them automatically. See Implementation status for the evidence and remaining integration work.

Customer-agnostic: the trigger label, the required-rule set, and the severity that gates a handoff are all config or fork-supplied. Upstream ships the machinery and the generic ReadinessReport shape, never a customer’s specific handoff policy (generic-scope.instructions.md).

Where it sits: the ORR is a read-only review built on the assurance twin. It holds no privileged identity and executes nothing. Every proposed fix still flows through risk-gate -> executor -> delivery, preserving the read-only surface rule in app-shape.instructions.md.

The pieces already exist; what was missing is the handoff as a first-class milestone. Three surfaces overlap but none of them, alone, is the dev-to-ops gate:

Existing surfaceWhat it reviewsWhy it is not the handoff gate
deployment-preflightone deploy: can this change land in the target scopescoped to a single terraform apply / fix PR, not the accumulated posture
assurance-twin proactive reviewone change event: does this diff violate a ruleper-diff; a scope can pass every diff and still fail as a whole
assurance-twin PostureAssessmentReportthe whole estate on demandnot bound to an ownership-transfer event; nobody is required to run it before ops takes over

The ORR binds the whole-scope assessment to the ownership-transfer event and makes it a required, audited, observation-first gate.

The ORR is triggered, not polled. When a scope is proposed for handoff, an ownership_transfer signal enters event-ingest, is normalized like any event, and drives one review pass:

ownership_transfer signal
-> event-ingest (normalize)
-> assurance-twin: run every applicable rule over the scope projection
-> deploy-preflight: run the feasibility probes over the scope
-> checklist evidence: evaluate rules, artifacts, metrics, drills, and approvals
-> compose -> ReadinessReport (clear | needs_review | blocked)
-> blocked + enforce mode -> gate the handoff, route fixes to risk-gate/HIL
-> audit (Saga)

Both inputs are deterministic-first (T0-flavored): static evaluation over the twin projection resolves most detected issues; bounded, read-only probes confirm the rest. Nothing in the pass mutates anything.

The ownership_transfer signal is the CSP-neutral event that starts the review. It is emitted by whatever the fork wires as the handoff moment:

  • a pull-request label (ops-handoff-requested) on the IaC repo, or
  • a resource tag applied to the scope (lifecycle-stage: handoff), or
  • an explicit operator request through the console (request_ops_handoff).

The signal carries the target scope (resource-group-equivalent or narrower, the same scope hierarchy the rule-governance overrides use), the submitter identity, and the target environment. It never carries a role or a privileged token.

The ORR runs the full applicable rule set over the scope. Five dimensions are the ones ops most depends on and that a per-change review most often misses:

DimensionRepresentative checkSourced from
policy_guardraildisallowed resource types, public access, missing encryptionrule-catalog-collection.md
identity_rbacover-privileged workload identity, guest holding Owner, standing privileged access, wildcard-action role, Owner-count over limitthe workload RBAC least-privilege rule pack (managed-identity.role-assignment.*, subscription.role-assignment.*, resource-group.role-assignment.*)
reliabilityno backup / PITR, no diagnostic settings, no zone redundancycatalog reliability rules
dependency_orderingrequired links (private endpoint, NSG, diagnostic settings) present before handoffdeployment-preflight probe
best_practiceframework controls with explicit rule, probe, artifact, metric, drill, and approval requirementsrule-catalog/best-practices/ plus ARB bindings

The identity_rbac dimension is the one the ORR adds that neither preflight nor per-change review covered before: preflight’s identity_rbac probe checks the executor’s permission to deploy, while the ORR checks the workload’s own least-privilege posture using the authored RBAC rules. See architecture.instructions.md § Rule Catalog.

The pass assembles detected issues into a ReadinessReport - a generalization of the PostureAssessmentReport (assurance-twin.md) bound to an ownership-transfer event. Each detected issue keeps the same three required parts:

  • evidence - a CSP-neutral citation of the rule, probe, or Best Practice control that produced it. Checklist detected issues also retain control_id and the unmet requirement_refs. A detected issue that cannot cite a source is a defect, the same rule the T2 verifier and preflight probes follow.
  • severity - preserves the source value: posture levels such as low through critical, or preflight warning / blocking. The coordinator records the resolved gate separately in the detected issue’s blocking boolean.
  • resolution - how to clear it, mapped to a concrete fix ActionType (for the RBAC dimension, remediate.right-size-role) or to guidance when no autofix exists.
DecisionMeaning
clearno detected issues
needs_reviewdetected issues exist but none is blocking (warnings only)
blockedat least one blocking detected issue

The report always records the truthful decision. Whether that decision gates the handoff is a separate flag, blocks_handoff, true only when the ORR ran in enforce mode - the same truthful-decision / separate-gate split the deployment-preflight blocks_deploy flag uses.

Every ORR ships in observation mode: it reports blockers truthfully but blocks_handoff stays false, so an unproven review can never wrongly stop a real handoff on a false positive. Promotion to enforce is per-environment and gated on a measured false-positive rate on the frozen scenario set, the same promotion discipline the ActionType contract and the preflight probes apply.

A blocked ORR does not just list problems. Each detected issue with an autofix carries a observation mode fix-PR proposal built from the rule’s fix ActionType, exactly as the assurance twin does. For the identity dimension that is remediate.right-size-role, which narrows an over-broad grant to least privilege; because RBAC changes carry a resource_group impact scope and AsymmetricRollback, they route to human approval through risk-classification.md and never auto-execute. The ORR proposes; a human approves; the executor applies. The console and ChatOps remain read-only surfaces.

The proposal builder is deterministic and holds these invariants:

InvariantBehavior
Grounded onlyA proposal exists only when the detected issue’s own cited control or rule maps to a fix ActionType in the caller-supplied lever map. An unmapped detected issue produces no proposal; the ORR holds for review rather than inventing a lever.
Observation mode onlyEvery proposal carries shadow, even when the ORR gate itself runs in enforce. The review cannot raise an ActionType above its own promotion state.
Distinct approverThe handoff submitter cannot approve their own fix. Principals are compared after Unicode NFKC folding, so an encoding variant of the submitter is still a self-approval attempt. Any such attempt is denied and audited before any proposal is built.
No executor identityA proposal records the submitter and approver as accountability facts only. It carries no credential, token, or executor principal.
Deterministic identityThe same scope, environment, cited evidence, resource, and ActionType always derive the same idempotency key, so a redelivered proposal is a downstream no-op.

Delivery is two-phase audited: the service records the proposal intent with the approver identity, publishes each proposal through the RemediationProposalPublisher seam, then records delivery. A publisher failure records the failed delivery with the delivered count and propagates; it never reports a silent success and never falls back to a direct call.

The ORR is the enforcement point for environment promotion (dev -> staging -> prod). The ownership_transfer signal carries the target environment, and the gate tightens with it: a promotion into prod treats any critical detected issue as blocking regardless of the profile default, reusing the prod-downgrade posture that every mutating ActionType already declares (risk-classification.md). The environment classifier and promotion order are specified in risk-classification.md; the ORR consumes them and doesn’t define them.

The ORR introduces no new privileged surface and minimal new code: it composes the existing core/assurance_twin/ and core/deploy_preflight/ subsystems and adds a thin coordinator plus one normalized signal.

ComponentResponsibility
ownership_transfer signalnormalized event (scope + submitter + target environment) that triggers the review; emitted by a fork-wired handoff moment
core/assurance_twin/reportrun every applicable rule over the scope projection (reused)
core/deploy_preflightrun the feasibility probes over the scope (reused)
core/readiness/checklistcombine explicit requirement outcomes without treating missing evidence as a pass
ORR coordinatorcompose posture, preflight, and checklist results, apply the environment gate, set blocks_handoff
composition/readiness.pyrun posture, preflight, and optional checklist evidence concurrently, audit success/failure, and publish the serialized report
composition/readiness_evidence.pyproject ARB artifacts, evidence expiry, and owner bindings into typed outcomes
core/readiness/remediationderive deterministic, grounded, observation mode-only fix proposals and reject self-approval
delivery intenta fork binds ReadinessReportPublisher to a Checks API annotation / console ReadPanel, and RemediationProposalPublisher to the risk-gate -> executor ingress

The coordinator imports only shared/ contracts and providers, like every other core subsystem (project-structure.md). It holds no cloud SDK and no privileged identity.

The repository implements the deterministic review and an injected application service. It doesn’t yet compose those pieces into the running control plane, so the current evidence supports implemented, not an operationally validated handoff gate.

AreaStateEvidenceNotes
Ownership-transfer signal, report model, detected issue reduction, environment gate, and Best Practice checklist evaluationimplementedcore/readiness/, test_coordinator.py, and test_checklist.pyThe pure coordinator preserves grounded detected issues, fails safely on unknown severity, and separates the truthful decision from blocks_handoff.
Concurrent posture, preflight, and checklist orchestration with append-only audit and report deliveryimplementedcomposition/readiness.py, test_readiness_service.py, and test_readiness_checklist_service.pyThe service uses injected providers. Assessment and delivery failures are audited and propagated.
Architecture Review Board (ARB) artifact, owner, freshness, and expiry projection into checklist outcomesimplementedcomposition/readiness_evidence.py and test_readiness_evidence.pyMissing bindings remain unknown, and expired evidence becomes failed; neither is treated as a pass.
Automatic ownership_transfer ingest and production posture, checklist, and report-publisher bindingsnot-startedProvider seams in shared/providers/readiness.py and the injected service aboveThe current runtime and bootstrap don’t construct or register OperationalReadinessService; callers can only invoke it through their own composition.
Grounded observation mode fix proposal, distinct-approver boundary, and two-phase delivery auditimplementedcore/readiness/remediation.py, composition/readiness.py, test_remediation.py, and test_readiness_remediation_service.pyProposals stay observation mode, cite a mapped lever or hold for review, record approver identity, block self-approval, and never reach an executor.
RemediationProposalPublisher binding to the safety check and executor ingressnot-startedProvider seam in shared/providers/readiness.pyNo composition root binds the seam, so no proposal reaches a live safety check yet.
DateStateChangeEvidenceRemaining
2026-08-13in-progressAdopted the implementation ledger; earlier provenance wasn’t reconstructed. Recorded the implemented deterministic and orchestration surfaces separately from the unbound runtime workflow.Current change; 48 passed from the five focused core and composition test files cited above.Bind the event, providers, publisher, approval, and fix path, then collect governed runtime evidence.
2026-08-16in-progressAdded the deterministic fix-proposal builder, the RemediationProposalPublisher seam, and the propose_remediations bridge that records approver identity, blocks self-approval, keeps proposals observation mode, and two-phase audits delivery.Current change; 86 passed from uv run pytest -q --no-cov services/core-control-plane/tests/core/readiness/ services/core-control-plane/tests/composition/test_readiness_remediation_service.py services/core-control-plane/tests/composition/test_readiness_service.py services/core-control-plane/tests/composition/test_readiness_checklist_service.py.Bind the proposal publisher to the safety check ingress, register ownership_transfer at event ingest, and collect a governed runtime receipt.
2026-08-16in-progressHardened the fix identity and the distinct-approver check: idempotency-key material is length-prefixed so a separator inside a field cannot collide two detected issues, and principals are compared after Unicode NFKC folding.Current change; 88 passed from uv run pytest -q --no-cov services/core-control-plane/tests/core/readiness/ services/core-control-plane/tests/composition/test_readiness_remediation_service.py services/core-control-plane/tests/composition/test_readiness_service.py services/core-control-plane/tests/composition/test_readiness_checklist_service.py.Unchanged from the row above.
  • Register and normalize ownership_transfer at event ingest, invoke the review through the accountable event-driven workflow, and add an integration test that proves replay-safe delivery.
  • Bind production posture, checklist evidence, and report-publisher implementations at the composition root, then record a governed runtime receipt for one complete observation mode review.
  • Emit grounded, observation mode-only fix proposals with a distinct-approver boundary, and add tests proving approver identity is recorded, self-approval is blocked, and the review service never executes a managed-resource change (test_remediation.py, test_readiness_remediation_service.py).
  • Bind RemediationProposalPublisher to the safety check ingress at the composition root and record one governed receipt showing a proposal reaching the Var approval flow without the review service holding an executor identity.
  • Keep enforcement disabled until frozen-scenario observation mode evidence meets the configured false-positive threshold and the authoritative promotion registry records the transition.
  • Read-only review, gated execution: the ORR and every detected issue are read-only; the only path to a mutation is a proposal that enters risk-gate -> executor, with the seven safeguards (stop-condition, rollback, impact scope limit, dry-run, resource lock, idempotency, audit entry) enforced there.
  • Approval and execution stay distinct: HandoffApproval carries a distinct principal’s decision, and OperationalReadinessService.propose_remediations denies and audits a self-approval attempt before building any proposal. The proposal publisher is not yet bound to the live safety check, so the end-to-end Var approval flow remains open.
  • Fail closed: a stale twin (inventory freshness beyond freshness_ttl) refuses to certify a handoff rather than certify on stale state; an ungroundable detected issue holds for review; an unproven review stays observation mode.
  • Audited: The current service records the ORR decision, blocks_handoff, submitter, target scope, environment, and delivery/assessment failures in append-only state-store audit entries. Fix entries additionally record the approver identity, the observation mode, the proposal count, and the delivered count on failure. Saga agent attribution must be added with the future event-driven approval workflow.
To learn aboutRead
The whole-graph review the ORR composesassurance-twin.md
The single-deploy feasibility pass it reusesdeployment-preflight.md
The RBAC least-privilege rules the identity dimension firesrule-catalog-collection.md
The cross-agent workflow that runs the gateagent-workflows.md § 11
The environment model the gate consumesrisk-classification.md § Environment Promotion
The risk classification each proposed fix resolves againstrisk-classification.md