digest.py python
51 lines 1.6 KB
Raw
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83 chore(governance): sync handover+roadmap to 84db8c8 (drift:… Human 2 days ago
1 """Footprint digest computation per §K4.7."""
2
3 from __future__ import annotations
4
5 import hashlib
6 import re
7 from dataclasses import dataclass
8
9
10 @dataclass(frozen=True)
11 class FootprintRecord:
12 """Per-file digest record for manifest and aggregate hash."""
13
14 path: str
15 sha256_hex: str
16
17
18 def canonical_bytes(data: bytes) -> bytes:
19 """Normalize line endings to LF without altering trailing newline count."""
20 text = data.decode("utf-8")
21 normalized = text.replace("\r\n", "\n").replace("\r", "\n")
22 return normalized.encode("utf-8")
23
24
25 def sha256_hex(data: bytes) -> str:
26 """Return lowercase hex sha256 of canonical bytes."""
27 return hashlib.sha256(canonical_bytes(data)).hexdigest()
28
29
30 def sha256_hex_raw(data: bytes) -> str:
31 """Return lowercase hex sha256 of raw bytes (for manifest aggregate)."""
32 return hashlib.sha256(data).hexdigest()
33
34
35 def build_manifest_lines(records: list[FootprintRecord]) -> str:
36 """Build the sorted sha256sum-style manifest string."""
37 sorted_records = sorted(records, key=lambda r: r.path)
38 lines = [f"{rec.sha256_hex} {rec.path}\n" for rec in sorted_records]
39 return "".join(lines)
40
41
42 def compute_footprint_digest(records: list[FootprintRecord]) -> str:
43 """Compute aggregate ``sha256:<hex>`` digest over sorted manifest lines."""
44 manifest = build_manifest_lines(records)
45 digest_hex = sha256_hex_raw(manifest.encode("utf-8"))
46 return f"sha256:{digest_hex}"
47
48
49 def records_from_bytes(path: str, content: bytes) -> FootprintRecord:
50 """Create a per-file record from raw file bytes."""
51 return FootprintRecord(path=path, sha256_hex=sha256_hex(content))
File History 1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199 fix(ISR): default require_independent_second_reviewer to require Human minor 2 days ago