canonical.py python
28 lines 1.1 KB
Raw
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83 chore(governance): sync handover+roadmap to 84db8c8 (drift:… Human 1 day ago
1 """Canonical JSON and entry hashing (§K9.7)."""
2
3 from __future__ import annotations
4
5 import hashlib
6 import json
7 from typing import Any
8
9
10 def canonical_json(value: Any) -> str:
11 """Serialize ``value`` as canonical JSON for hashing."""
12 return json.dumps(value, ensure_ascii=False, separators=(",", ":"), sort_keys=True)
13
14
15 def _hash_payload(body: dict[str, Any]) -> dict[str, Any]:
16 """Build the canonical-hash payload, excluding ``entry_hash`` and ``provenance.sig``."""
17 payload = {key: val for key, val in body.items() if key != "entry_hash"}
18 provenance = payload.get("provenance")
19 if isinstance(provenance, dict) and "sig" in provenance:
20 stripped = {key: val for key, val in provenance.items() if key != "sig"}
21 payload = {**payload, "provenance": stripped}
22 return payload
23
24
25 def compute_entry_hash(body: dict[str, Any]) -> str:
26 """Compute lowercase hex SHA-256 of canonical JSON without ``entry_hash`` or ``provenance.sig``."""
27 digest = hashlib.sha256(canonical_json(_hash_payload(body)).encode("utf-8")).hexdigest()
28 return digest.lower()
File History 1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199 fix(ISR): default require_independent_second_reviewer to require Human minor 1 day ago