build(agent): weasel-1#856f80 iteration
This commit is contained in:
parent
b71a0d1e4b
commit
04ed82bc21
|
|
@ -3,6 +3,8 @@ from __future__ import annotations
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Dict, List, Optional, Any
|
from typing import Dict, List, Optional, Any
|
||||||
import time
|
import time
|
||||||
|
import json
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
@ -58,5 +60,30 @@ class GraphOfContractsRegistry:
|
||||||
raise KeyError(f"Contract {contract_id} not found")
|
raise KeyError(f"Contract {contract_id} not found")
|
||||||
rec.attestations.append(attestation)
|
rec.attestations.append(attestation)
|
||||||
|
|
||||||
|
def generate_attestation(self, contract_id: str) -> str:
|
||||||
|
"""Create a deterministic SHA-256 attestation for a registered contract.
|
||||||
|
|
||||||
|
The attestation is computed over a canonical JSON serialization of the
|
||||||
|
contract metadata (name, version, contract_id, schema, signer, timestamp)
|
||||||
|
to ensure repeatability for audits and replay checks.
|
||||||
|
"""
|
||||||
|
rec = self.contracts.get(contract_id)
|
||||||
|
if rec is None:
|
||||||
|
raise KeyError(f"Contract {contract_id} not found")
|
||||||
|
# Canonical JSON serialization for deterministic hashing
|
||||||
|
payload = {
|
||||||
|
"name": rec.name,
|
||||||
|
"version": rec.version,
|
||||||
|
"contract_id": rec.contract_id,
|
||||||
|
"schema": rec.schema,
|
||||||
|
"signer": rec.signer,
|
||||||
|
"timestamp": rec.timestamp,
|
||||||
|
}
|
||||||
|
data = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
||||||
|
h = hashlib.sha256(data).hexdigest()
|
||||||
|
att = f"sha256:{h}"
|
||||||
|
rec.attestations.append(att)
|
||||||
|
return att
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["ContractRecord", "GraphOfContractsRegistry"]
|
__all__ = ["ContractRecord", "GraphOfContractsRegistry"]
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,8 @@ def test_registry_basic_operations():
|
||||||
assert c.name == "toyAdapter"
|
assert c.name == "toyAdapter"
|
||||||
reg.add_attestation("idea-1", "attestation-123")
|
reg.add_attestation("idea-1", "attestation-123")
|
||||||
assert reg.get_contract("idea-1").attestations[-1] == "attestation-123"
|
assert reg.get_contract("idea-1").attestations[-1] == "attestation-123"
|
||||||
|
# generate deterministic sha256 attestation and ensure it's appended
|
||||||
|
att = reg.generate_attestation("idea-1")
|
||||||
|
assert isinstance(att, str)
|
||||||
|
assert att.startswith("sha256:")
|
||||||
|
assert reg.get_contract("idea-1").attestations[-1] == att
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue