64 lines
1.7 KiB
Python
64 lines
1.7 KiB
Python
"""Governance ledger for MarketMesh (tamper-evident audit logs).
|
|
|
|
This is a lightweight, in-memory audit log with a simple hash-chain to
|
|
provide tamper-evident properties for reproducibility and compliance.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, asdict
|
|
from time import time
|
|
import hashlib
|
|
from typing import Any, Dict, List
|
|
|
|
|
|
def _hash_chain(prev_hash: str, payload: Dict[str, Any]) -> str:
|
|
data = (prev_hash or "") + str(payload)
|
|
return hashlib.sha256(data.encode("utf-8")).hexdigest()
|
|
|
|
|
|
@dataclass
|
|
class AuditLogEntry:
|
|
index: int
|
|
timestamp: float
|
|
contract_id: str
|
|
action: str
|
|
details: Dict[str, Any]
|
|
previous_hash: str
|
|
hash: str
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return asdict(self)
|
|
|
|
|
|
class GovernanceLedger:
|
|
"""In-memory tamper-evident governance log."""
|
|
|
|
def __init__(self) -> None:
|
|
self._entries: List[AuditLogEntry] = []
|
|
self._last_hash: str = ""
|
|
|
|
def log(self, contract_id: str, action: str, details: Dict[str, Any] | None = None) -> AuditLogEntry:
|
|
details = details or {}
|
|
entry_index = len(self._entries) + 1
|
|
payload = {
|
|
"contract_id": contract_id,
|
|
"action": action,
|
|
"details": details,
|
|
}
|
|
entry_hash = _hash_chain(self._last_hash, payload)
|
|
entry = AuditLogEntry(
|
|
index=entry_index,
|
|
timestamp=time(),
|
|
contract_id=contract_id,
|
|
action=action,
|
|
details=details,
|
|
previous_hash=self._last_hash,
|
|
hash=entry_hash,
|
|
)
|
|
self._entries.append(entry)
|
|
self._last_hash = entry_hash
|
|
return entry
|
|
|
|
def get_logs(self) -> List[AuditLogEntry]:
|
|
return list(self._entries)
|