"""Stable ID helpers for Atlas. These functions keep entity and claim identifiers deterministic across the app. The same stable hash should be used for: - atlas_id / entity IRI fragments - claim IDs - claim IRIs in Turtle exports Semantics live in triples; the IDs themselves stay opaque. """ from __future__ import annotations import hashlib def stable_hash(*parts: str, length: int = 16) -> str: material = "|".join((part or "").strip() for part in parts) return hashlib.sha1(material.encode("utf-8")).hexdigest()[:length] def claim_hash( subject: str, predicate: str, object_value: str, layer: str, status: str = "active", created_at: str | None = None, ) -> str: return stable_hash(subject, predicate, object_value, layer, status, created_at or "") def entity_hash(*parts: str, length: int = 16) -> str: return stable_hash(*parts, length=length)