"""Consumer-owned bounded time adapter; explicit opt-in, no configured fallback.""" from datetime import datetime, timezone, timedelta from functools import lru_cache from secrets_engine.errors import DecisionError @lru_cache(maxsize=8) def _clock(path): try: from railiance_clock.client import Clock, FileTrust return Clock(FileTrust(path)) except (ImportError, OSError, ValueError, TypeError, KeyError) as exc: raise DecisionError("Railiance clock unavailable or untrusted") from exc def read_window(cfg): path = getattr(cfg, "clock_trust_file", None) if not path: return None try: return _clock(str(path)).read() except (OSError, ValueError) as exc: raise DecisionError("Railiance clock unavailable or untrusted") from exc def validity_bounds(now=None, window=None): if window is None: current = (now or datetime.now(timezone.utc)).astimezone(timezone.utc) return current, current if now is not None: raise DecisionError("choose interval evidence or explicit test time, not both") try: lower, upper = window.lower_ns, window.upper_ns if type(lower) is not int or type(upper) is not int or not 0 <= lower <= upper: raise ValueError("invalid interval") epoch = datetime(1970, 1, 1, tzinfo=timezone.utc) return epoch + timedelta(microseconds=lower // 1000), epoch + timedelta(microseconds=(upper + 999) // 1000) except (ValueError, TypeError, AttributeError, OverflowError) as exc: raise DecisionError("invalid Railiance time interval") from exc def recheck_binding(cfg, binding): if not getattr(cfg, "clock_trust_file", None): return if not binding.decision_expires_at: raise DecisionError("bounded-time consume requires decision validity") lower, upper = validity_bounds(window=read_window(cfg)) expires = datetime.fromisoformat(binding.decision_expires_at.replace("Z", "+00:00")) start = datetime.fromisoformat(binding.decision_not_before.replace("Z", "+00:00")) if binding.decision_not_before else None if upper >= expires or (start is not None and lower < start): raise DecisionError("decision validity does not contain the Railiance interval")