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, use the automated Operational Readiness Review (ORR).
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.
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.
Why a distinct gate
Section titled “Why a distinct gate”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 surface | What it reviews | Why it is not the handoff gate |
|---|---|---|
| deployment-preflight | one deploy: can this change land in the target scope | scoped to a single terraform apply / fix PR, not the accumulated posture |
| assurance-twin proactive review | one change event: does this diff violate a rule | per-diff; a scope can pass every diff and still fail as a whole |
assurance-twin PostureAssessmentReport | the whole estate on demand | not 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.
Where it sits in the loop
Section titled “Where it sits in the loop”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.
Trigger
Section titled “Trigger”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.
Review dimensions
Section titled “Review dimensions”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:
| Dimension | Representative check | Sourced from |
|---|---|---|
policy_guardrail | disallowed resource types, public access, missing encryption | rule-catalog-collection.md |
identity_rbac | over-privileged workload identity, guest holding Owner, standing privileged access, wildcard-action role, Owner-count over limit | the workload RBAC least-privilege rule pack (managed-identity.role-assignment.*, subscription.role-assignment.*, resource-group.role-assignment.*) |
reliability | no backup / PITR, no diagnostic settings, no zone redundancy | catalog reliability rules |
dependency_ordering | required links (private endpoint, NSG, diagnostic settings) present before handoff | deployment-preflight probe |
best_practice | framework controls with explicit rule, probe, artifact, metric, drill, and approval requirements | rule-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.
ReadinessReport
Section titled “ReadinessReport”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_idand the unmetrequirement_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
lowthroughcritical, or preflightwarning/blocking. The coordinator records the resolved gate separately in the detected issue’sblockingboolean. - 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.
Decision semantics
Section titled “Decision semantics”| Decision | Meaning |
|---|---|
clear | no detected issues |
needs_review | detected issues exist but none is blocking (warnings only) |
blocked | at 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.
Observation-first
Section titled “Observation-first”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.
Action bridging
Section titled “Action bridging”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.
Proposal contract
Section titled “Proposal contract”The proposal builder is deterministic and holds these invariants:
| Invariant | Behavior |
|---|---|
| Grounded only | A 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 only | Every proposal carries shadow, even when the ORR gate itself runs in enforce. The review cannot raise an ActionType above its own promotion state. |
| Distinct approver | The 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 identity | A proposal records the submitter and approver as accountability facts only. It carries no credential, token, or executor principal. |
| Deterministic identity | The 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.
Environment promotion
Section titled “Environment promotion”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
environment-promotion contract;
the ORR consumes them and doesn’t define them.
Module placement
Section titled “Module placement”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.
| Component | Responsibility |
|---|---|
ownership_transfer signal | normalized event (scope + submitter + target environment) that triggers the review; emitted by a fork-wired handoff moment |
core/assurance_twin/report | run every applicable rule over the scope projection (reused) |
core/deploy_preflight | run the feasibility probes over the scope (reused) |
core/readiness/checklist | combine explicit requirement outcomes without treating missing evidence as a pass |
| ORR coordinator | compose posture, preflight, and checklist results, apply the environment gate, set blocks_handoff |
composition/readiness.py | run posture, preflight, and optional checklist evidence concurrently, audit success/failure, and publish the serialized report |
composition/readiness_evidence.py | project ARB artifacts, evidence expiry, and owner bindings into typed outcomes |
core/readiness/remediation | derive deterministic, grounded, observation mode-only fix proposals and reject self-approval |
fdai-service-contracts/readiness_remediation | define the content-addressed, no-authority observation mode request and its generated JSON Schema |
core/control_loop/readiness_remediation | validate the exact event source, ActionType trigger and arguments, and active ontology release digest; invoke the unified safety check without dispatch |
runtime/consumers.py and bootstrap | validate and deduplicate canonical ownership_transfer events, invoke the Forseti-accountable review after startup readiness, and dead-letter malformed payloads |
runtime/bootstrap_readiness.py | when the complete posture/report pair is active, select the upstream EventBus fix adapter from the active ontology release and active Rule fix declarations; an incomplete release or empty lever map leaves fix unavailable |
| delivery intent | a fork binds ReadinessReportPublisher to a Checks API annotation / console ReadPanel; Core selects the upstream RemediationProposalPublisher mechanically and the deployment still supplies no approval, promotion, or execution authority through that selection |
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.
Safety posture
Section titled “Safety posture”- 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:
HandoffApprovalcarries a distinct principal’s decision, andOperationalReadinessService.propose_remediationsdenies 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, workflow id, accountable Forseti attribution, 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.
Next steps
Section titled “Next steps”| To learn about | Read |
|---|---|
| The whole-graph review the ORR composes | assurance-twin.md |
| The single-deploy feasibility pass it reuses | deployment-preflight.md |
| The RBAC least-privilege rules the identity dimension fires | rule-catalog-collection.md |
| The cross-agent workflow that runs the gate | operational readiness handoff |
| The environment model the gate consumes | risk-classification.md § Environment Promotion |
| The risk classification each proposed fix resolves against | risk-classification.md |
Related docs
Section titled “Related docs”| To learn about | Read |
|---|---|
| Delivery status and remaining work | Implementation ledger |