Preserve fractional approval expiry through atomic consumption

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
This commit is contained in:
tegwick 2026-10-16 17:35:53 +02:00
parent 3485415b82
commit d40e842052
6 changed files with 271 additions and 6 deletions

View file

@ -103,11 +103,11 @@ def utc_now(clock: Callable[[], datetime] | None = None) -> datetime:
now = datetime.now(timezone.utc)
if now.tzinfo is None:
now = now.replace(tzinfo=timezone.utc)
return now.astimezone(timezone.utc).replace(microsecond=0)
return now.astimezone(timezone.utc)
def iso(ts: datetime) -> str:
return ts.astimezone(timezone.utc).replace(microsecond=0).isoformat()
return ts.astimezone(timezone.utc).isoformat()
def parse_iso(value: str) -> datetime:
@ -768,7 +768,6 @@ class Engine:
):
raise Unprocessable("decision_id must be a non-empty string")
conn = self._conn()
now = iso(self.now())
idempotent = False
try:
conn.execute("BEGIN IMMEDIATE")
@ -794,7 +793,11 @@ class Engine:
if row["status"] != "approved":
conn.rollback()
raise Conflict(f"cannot consume from status {row['status']}")
if self.now() < parse_iso(row["not_before"]) or self.now() >= parse_iso(row["expires_at"]):
# Lock acquisition can wait past a validity boundary. One post-lock
# instant is authoritative for both the check and its durable proof.
consumed_at = self.now()
now = iso(consumed_at)
if consumed_at < parse_iso(row["not_before"]) or consumed_at >= parse_iso(row["expires_at"]):
conn.rollback()
raise Conflict("cannot consume outside validity window")
if row["human_control"]:
@ -819,6 +822,7 @@ class Engine:
"use",
approval_id,
actor=row["actor"],
observed_at=consumed_at,
extra={
"binding_digest": row["binding_digest"],
"binding": json.loads(row["binding_json"]),
@ -911,13 +915,14 @@ class Engine:
*,
actor: str | None,
extra: dict[str, Any] | None = None,
observed_at: datetime | None = None,
) -> str:
if self.fail_outbox:
raise StoreUnavailable("outbox insert failed")
if event_class not in EVENT_CLASSES:
raise Unprocessable(f"unknown event class {event_class}")
event_id = str(uuid4())
created = iso(self.now())
created = iso(observed_at if observed_at is not None else self.now())
resource = f"approval:{approval_id}" if approval_id else "approval-engine:heartbeat"
details = {"class": event_class, **(extra or {})}
if approval_id: