build(agent): new-agents#a6e6ec iteration
This commit is contained in:
parent
403b674bf0
commit
c05b749d3c
|
|
@ -5,6 +5,7 @@ class DataContractRegistry:
|
||||||
self._contracts = {}
|
self._contracts = {}
|
||||||
|
|
||||||
def register(self, name: str, schema: dict, version: int = 1):
|
def register(self, name: str, schema: dict, version: int = 1):
|
||||||
|
# Store contract with versioning and associated schema
|
||||||
self._contracts[name] = {
|
self._contracts[name] = {
|
||||||
"version": version,
|
"version": version,
|
||||||
"schema": schema,
|
"schema": schema,
|
||||||
|
|
@ -15,3 +16,21 @@ class DataContractRegistry:
|
||||||
|
|
||||||
def list_contracts(self):
|
def list_contracts(self):
|
||||||
return {k: v for k, v in self._contracts.items()}
|
return {k: v for k, v in self._contracts.items()}
|
||||||
|
|
||||||
|
def conform(self, name: str, payload: dict) -> bool:
|
||||||
|
"""Basic conformance check for a given payload against a registered contract.
|
||||||
|
|
||||||
|
If a contract is registered with a 'fields' list inside its schema, we
|
||||||
|
require that all those fields exist in the payload. Extra fields are
|
||||||
|
allowed for forward-compatibility.
|
||||||
|
"""
|
||||||
|
contract = self._contracts.get(name)
|
||||||
|
if not contract:
|
||||||
|
# No contract defined; be permissive in MVP
|
||||||
|
return True
|
||||||
|
schema = contract.get("schema", {})
|
||||||
|
if isinstance(schema, dict) and "fields" in schema:
|
||||||
|
required = set(schema["fields"])
|
||||||
|
return required.issubset(set(payload.keys()))
|
||||||
|
# Fallback: no strict contract; assume conformant
|
||||||
|
return True
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,13 @@ class LocalLedger:
|
||||||
def register_contract(self, name: str, schema: dict, version: int = 1):
|
def register_contract(self, name: str, schema: dict, version: int = 1):
|
||||||
self.contracts.register(name, schema, version)
|
self.contracts.register(name, schema, version)
|
||||||
|
|
||||||
|
def anchor_delta_root(self, anchor: str) -> None:
|
||||||
|
"""Anchor the current delta root to an external reference (cloud/ground).
|
||||||
|
|
||||||
|
This is optional in MVP and helps provide long-term verifiability.
|
||||||
|
"""
|
||||||
|
self.delta_log.anchor_root(anchor)
|
||||||
|
|
||||||
def add_entry(self, entry_type: str, payload: dict, signer_name: str = None, contract_name: str = None) -> LedgerEntry:
|
def add_entry(self, entry_type: str, payload: dict, signer_name: str = None, contract_name: str = None) -> LedgerEntry:
|
||||||
if not self.contracts.get(entry_type) and contract_name is None:
|
if not self.contracts.get(entry_type) and contract_name is None:
|
||||||
# Allow ad-hoc entry without contract in MVP for simplicity
|
# Allow ad-hoc entry without contract in MVP for simplicity
|
||||||
|
|
@ -79,6 +86,10 @@ class LocalLedger:
|
||||||
else:
|
else:
|
||||||
contract = self.contracts.get(entry_type)
|
contract = self.contracts.get(entry_type)
|
||||||
contract_version = contract["version"] if contract else 1
|
contract_version = contract["version"] if contract else 1
|
||||||
|
# Enforce contract conformance if a contract is registered for this entry_type
|
||||||
|
if self.contracts.get(entry_type) is not None:
|
||||||
|
if not self.contracts.conform(entry_type, payload):
|
||||||
|
raise ValueError(f"Payload does not conform to contract for entry_type '{entry_type}'")
|
||||||
ts = time.time()
|
ts = time.time()
|
||||||
# Build a lightweight id: hash of type+ts+payload
|
# Build a lightweight id: hash of type+ts+payload
|
||||||
raw = json.dumps({"type": entry_type, "ts": ts, "payload": payload}, sort_keys=True).encode('utf-8')
|
raw = json.dumps({"type": entry_type, "ts": ts, "payload": payload}, sort_keys=True).encode('utf-8')
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue