symfonic.services.switching.mutation¶
mutation ¶
The one mutation path every switch-state change goes through.
Split out of :mod:.control_plane because it is the mechanism — authorize,
validate, check the freeze, compare-and-swap, chain the audit record — and the
control plane is the vocabulary built on top of it. Keeping them apart is
what makes "there is exactly one way switch state changes" checkable by
reading one class rather than auditing five methods for drift.
SwitchMutator ¶
SwitchMutator(*, store: InMemorySwitchStore, constraints: ConstraintSet, audit: HashChainAuditLog, authorizer: SwitchAuthorizer, validated_vectors: Sequence[GenerationVector] = (), clock: Callable[[], float] = time.time)
Authorize → validate → freeze-check → CAS → audit. In that order, once.