ADR-0010: Remediation state machine, idempotency, and drift
Status: Accepted · 2026-07-14Decision
ActionRequest state machine:
Draft → Validated → AwaitingApproval → Approved → Executing → Verifying → Succeeded | PartiallySucceeded | Failed | Cancelled | Drifted
with transitions enforced in one module and by DB constraints.
- Envelope: tenant, typed action + version, target snapshot (asset + source version at preview time), current/desired state, initiator, justification, approval policy, idempotency key, execution attempts, verification evidence.
- Separation of duties: the requester cannot approve their own action (policy
check + test). Approval requires
action.approvecapability scoped to the action type/domain. - Idempotency: executor deduplicates on
(tenantId, idempotencyKey); duplicate delivery of an approved action performs exactly one source mutation (tested with duplicated queue delivery). - Drift: before execution, the connector re-reads the target; if source version
differs from the approved snapshot, the action transitions to
Driftedand requires re-preview (no silent convergence by default). - Verification: after execution, the source state is re-read and stored as a
RemediationVerifiedobservation; executor success text alone never marks success. - MVP action types: internal remediation task (fully live), Purview label assign/change (adapter real; live execution config-gated on protected/metered API enablement — blocked state reported honestly), label downgrade/removal requires justification + approval by policy default.
Consequences
- Duplicate delivery, drift, and self-approval are all covered by automated tests.
- Rollback is recorded only where genuinely supported (internal tasks); no implied rollback guarantee for label operations.