"""Governance ledger: append-only tamper-evident log with HMAC signatures. This ledger implements a minimal tamper-evident append-only log. Each entry carries the previous hash and an HMAC using a local key to simulate per-node signatures. The ledger supports append and verification. """ import hashlib import hmac import json import time from typing import List, Dict, Any class GovernanceLedger: def __init__(self, node_key: bytes): self.node_key = node_key self._chain: List[Dict[str, Any]] = [] def _entry_hash(self, entry: Dict[str, Any]) -> str: raw = json.dumps(entry, sort_keys=True, separators=(",", ":")) return hashlib.sha256(raw.encode("utf-8")).hexdigest() def _sign(self, payload: str) -> str: return hmac.new(self.node_key, payload.encode("utf-8"), hashlib.sha256).hexdigest() def append(self, author: str, payload: Dict[str, Any]) -> Dict[str, Any]: prev_hash = self._chain[-1]["hash"] if self._chain else "" entry = { "author": author, "payload": payload, "prev_hash": prev_hash, "ts": time.time(), } entry_hash = self._entry_hash(entry) signature = self._sign(entry_hash) entry["hash"] = entry_hash entry["sig"] = signature self._chain.append(entry) return entry def verify_chain(self) -> bool: prev = "" for entry in self._chain: if entry.get("prev_hash", "") != prev: return False # verify signature expected_sig = self._sign(entry["hash"]) if not hmac.compare_digest(expected_sig, entry.get("sig", "")): return False prev = entry["hash"] return True def entries(self) -> List[Dict[str, Any]]: return list(self._chain)