Saga Compensation Engine
Engine for the choreography saga compensation flow.
Depends only on the persistence-agnostic SagaStepRepositoryPort and two collaborator hooks (SagaCompensationStepFactory and CompensationCommandHandler) so it is decoupled from the underlying storage technology (JPA today, others possible) and from the wire format of compensation events.
The type parameter TCommand is the service-local, strongly-typed compensation command (typically a Kotlin sealed interface mirroring the Avro tagged union). The engine never sees Map<String, Any?> or stringly-typed action discriminators — the Anti-Corruption Layer that decodes raw Kafka bytes into TCommand lives in each service's infrastructure module (an implementation of CompensationCommandDeserializer).
Exceptions thrown by CompensationCommandHandler are intentionally propagated so the inbound Kafka listener can trigger broker-level retry / DLT routing — the SagaWatchdog still provides a slower cooldown-based safety net for stuck sagas.