"""Small shared helpers: stable JSON and the hash that identifies a config.

The hash is computed over the *effective layer set* for one instance, not over
the whole hive document: publishing a canary layer must not make every other
machine re-ack identical content. The hive and the instance compute it the
same way, so an ack can be compared by string.
"""

from __future__ import annotations

import hashlib
import json


def canonical_json(value: object) -> str:
    return json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=False)


def content_hash(value: object) -> str:
    digest = hashlib.sha256(canonical_json(value).encode("utf-8")).hexdigest()
    return f"sha256:{digest}"
