namespace ZB.MOM.WW.ScadaBridge.Transport.Import;
///
/// Register row 52: a sliding window of bundle-unlock attempts that is shared across the
/// central pair, so TransportOptions.MaxUnlockAttemptsPerIpPerHour is a FLEET cap
/// rather than a per-node, per-process one.
///
/// Implementations are expected to THROW on store failure. The fail-open decision belongs
/// to , which owns the policy (log a Warning and
/// permit the attempt), not to the storage layer.
///
///
public interface IBundleUnlockAttemptWindow
{
///
/// Registers one unlock attempt against the shared window and reports whether it was
/// within budget. Implementations must NOT record an attempt they are rejecting —
/// a denial burns no budget, matching the in-memory limiter's contract (register
/// row 44), so a client that keeps hammering cannot extend its own lockout.
///
/// Throttle bucket — the caller's remote IP, or the shared unattributed bucket.
/// The trailing-window cap (MaxUnlockAttemptsPerIpPerHour).
/// Trailing window the attempts are counted over (one hour in production).
/// Cancellation token.
/// true when the attempt was recorded (within budget); false when the bucket is exhausted.
Task TryRegisterAttemptAsync(
string clientKey, int maxAttemptsPerWindow, TimeSpan window, CancellationToken ct = default);
///
/// Register row 65: drives one retention sweep of aged-out attempt rows independently
/// of the unlock path. The prune used to ride
/// only, so a cluster that stopped importing entirely left its last rows in place
/// indefinitely; BundleSessionEvictionService — Transport's periodic
/// central-only sweep — now also ticks this, which closes that.
///
/// Unlike , implementations must NOT throw on
/// store failure: this is pure retention maintenance with no caller to report to, and
/// the sweep that drives it must never be taken down by a database blip. Implementations
/// are also expected to keep their own cadence claim, so calling this more often than
/// the intended prune interval is harmless.
///
///
/// Trailing window the attempts are counted over (one hour in production); rows are retained for a multiple of it.
/// Cancellation token.
/// A task that completes when the prune attempt has finished (or been skipped for cadence).
Task PruneAsync(TimeSpan window, CancellationToken ct = default);
}