"""Small deterministic primitives used by the domain core.""" from __future__ import annotations import hashlib import json import uuid from datetime import datetime, timezone from typing import Any def utc_now() -> datetime: return datetime.now(timezone.utc) def new_id(prefix: str) -> str: return f"{prefix}_{uuid.uuid4().hex}" def stable_json_dumps(value: Any) -> str: return json.dumps(value, sort_keys=True, separators=(",", ":"), default=str) def content_digest(content: str | bytes) -> str: data = content.encode("utf-8") if isinstance(content, str) else content return "sha256:" + hashlib.sha256(data).hexdigest() def mapping_digest(value: Any) -> str: return content_digest(stable_json_dumps(value)) def compact_dict(data: dict[str, Any]) -> dict[str, Any]: return {key: value for key, value in data.items() if value not in (None, {}, [])} def datetime_to_str(value: datetime | None) -> str | None: return value.isoformat() if value else None def datetime_from_str(value: str | None) -> datetime | None: return datetime.fromisoformat(value) if value else None