symfonic.services.effects.revert¶
revert ¶
The security revert itself — one linearization point, then honest accounting.
The ordering below is not stylistic. Raising the fence and revoking the leases
it covers happen inside a single hold of the store lock, because that is what
makes "admitted before the revert" a decidable question rather than a race:
every checkpoint in :mod:admission takes the same lock, so an admission is
either wholly before the fence or refused by it.
Everything after that hold is accounting, and it is deliberately pessimistic. Cancellation is requested; the drain is bounded; what does not drain is contained; what already left through an irreversible port is exposed and compensated; and an invocation that ran an opaque extension takes the fencing claim down with it. A revert that could not reach the lease store reports itself degraded rather than reporting success it cannot substantiate.
SecurityRevertCoordinator ¶
SecurityRevertCoordinator(*, store: InMemoryLeaseStore, fences: FenceLedger, tracker: InFlightTracker, drain: BoundedDrain, quarantine: ResultQuarantine, accountant: OpaqueExposureAccountant, containment: ContainmentCoordinator, ports: FencedPortRegistry, clock: Callable[[], float] = time.time)
Closes admissions, blocks commits, contains what it cannot stop.
Source code in src/symfonic/services/effects/revert.py
refresh ¶
Re-read the suppression and quarantine ledgers for this incident.
A provider or tool result dispatched before the fence landed arrives
after revert returns, so the frozen record cannot contain it — the
late-result evidence would otherwise be structurally unreachable from
the incident. This re-reads both ledgers, still scoped to the tickets
this revert accounted for, and returns a new record with the same
incident_id. Nothing else is recomputed: the fence, the drain, and
the claims are findings about a moment, not a running total.
Source code in src/symfonic/services/effects/revert.py
revert
async
¶
revert(*, bundle_id: str, reason: str, actor: str, rejected_vector_hash: str | None = None, epoch_ceiling: int | None = None, tenant_scope_hash: str | None = None) -> SecurityRevertIncident
Raise the fence, then account for everything it could not stop.