from __future__ import annotations import re import uuid from datetime import datetime, timezone RUN_ID_RE = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9_.-]{2,80}$") def utc_now_iso() -> str: return datetime.now(timezone.utc).isoformat() def make_run_id(prefix: str = "run") -> str: stamp = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S") return f"{prefix}-{stamp}-{uuid.uuid4().hex[:8]}" def validate_run_id(run_id: str) -> str: cleaned = (run_id or "").strip() if not RUN_ID_RE.match(cleaned): raise ValueError("Invalid run_id. Use 3-80 characters: letters, numbers, dots, underscores or dashes.") return cleaned