From e5c8ab2647a6d3d7ed929bea86c3d3b107b255c8 Mon Sep 17 00:00:00 2001 From: agent-db0ec53c058f1326 Date: Wed, 15 Apr 2026 21:14:42 +0200 Subject: [PATCH] build(agent): molt-z#db0ec5 iteration --- README.md | 10 ++- .../__init__.py | 4 ++ .../adapters/conformance.py | 34 ++++++++++ .../contract_registry.py | 23 +++++++ .../dsl.py | 25 ++++++++ .../governance.py | 63 +++++++++++++++++++ 6 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 marketmesh_privacy_preserving_federated_/adapters/conformance.py create mode 100644 marketmesh_privacy_preserving_federated_/contract_registry.py create mode 100644 marketmesh_privacy_preserving_federated_/dsl.py create mode 100644 marketmesh_privacy_preserving_federated_/governance.py diff --git a/README.md b/README.md index a24f470..a40373e 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,20 @@ Overview - Lightweight, open-source federation platform for sharing anonymized growth KPIs to generate cross-market benchmarks without exposing raw data. - MVP features: contract-driven data exchange, privacy budgets, secure/DP aggregation, delta-sync, governance ledger, adapters marketplace, and a CatOpt-inspired interoperability abstraction. -Getting Started +- Getting Started - Install (editable): python -m build pip install . - Run tests: ./test.sh +MVP Extensions (What’s next) +- Governance ledger: tamper-evident audit logs for reproducibility and compliance. +- Contract registry: versioned contract management for cross-adapter interoperability. +- DSL scaffold: LocalExperiment/SharedStats primitives to describe experiments and signals. +- Adapter conformance: lightweight checks to ensure adapters map to canonical signals as per contracts. +- Delta-sync enhancements: bounded-staleness, version vectors, and deterministic reconciliation on reconnects. +- Run tests: ./test.sh + Project Structure (high level) - marketmesh_privacy_preserving_federated_: Core package with protocol, aggregation, governance and adapters scaffolding. - marketmesh_privacy_preserving_federated_/adapters: Stripe and Shopify adapters (minimum viable implementations). diff --git a/marketmesh_privacy_preserving_federated_/__init__.py b/marketmesh_privacy_preserving_federated_/__init__.py index 281c2c6..3945569 100644 --- a/marketmesh_privacy_preserving_federated_/__init__.py +++ b/marketmesh_privacy_preserving_federated_/__init__.py @@ -8,6 +8,8 @@ This minimalist MVP exposes core primitives: from .core import Contract, DeltaSync, Aggregator from .adapters import StripeAdapter, ShopifyAdapter +from .governance import GovernanceLedger +from .contract_registry import ContractRegistry __all__ = [ "Contract", @@ -15,4 +17,6 @@ __all__ = [ "Aggregator", "StripeAdapter", "ShopifyAdapter", + "GovernanceLedger", + "ContractRegistry", ] diff --git a/marketmesh_privacy_preserving_federated_/adapters/conformance.py b/marketmesh_privacy_preserving_federated_/adapters/conformance.py new file mode 100644 index 0000000..309fc34 --- /dev/null +++ b/marketmesh_privacy_preserving_federated_/adapters/conformance.py @@ -0,0 +1,34 @@ +"""Adapter conformance helpers for MarketMesh MVP.""" +from __future__ import annotations +from typing import Any, Dict + +from marketmesh_privacy_preserving_federated_.core import Contract + + +def conformance_report(adapter, contract: Contract, sample_input: Dict[str, Any] | None = None) -> Dict[str, Any]: + """Return a lightweight report showing which canonical KPIs are produced by the adapter. + + If sample_input is provided, we'll map it and compare keys to the contract KPIs. + """ + result = { + "adapter": getattr(adapter, "__class__", str(adapter)).__name__, + "contract_id": contract.contract_id, + "contract_kpis": list(contract.kpis), + "produced_kpis": [], + "missing_kpis": [], + "sample_mapping": None, + } + if sample_input is None: + return result + + try: + mapping = adapter.map_to_canonical(sample_input) + result["sample_mapping"] = mapping + produced = list(mapping.keys()) + result["produced_kpis"] = produced + result["missing_kpis"] = [k for k in contract.kpis if k not in produced] + except Exception as e: + result["error"] = str(e) + result["produced_kpis"] = [] + result["missing_kpis"] = list(contract.kpis) + return result diff --git a/marketmesh_privacy_preserving_federated_/contract_registry.py b/marketmesh_privacy_preserving_federated_/contract_registry.py new file mode 100644 index 0000000..41be454 --- /dev/null +++ b/marketmesh_privacy_preserving_federated_/contract_registry.py @@ -0,0 +1,23 @@ +"""Simple in-memory contract registry for MarketMesh MVP.""" +from __future__ import annotations + +from typing import Dict, List + +from .core import Contract + + +class ContractRegistry: + """Register and look up versioned contracts by id.""" + + def __init__(self) -> None: + self._contracts: Dict[str, Contract] = {} + + def register_contract(self, contract: Contract) -> None: + # If the same contract_id exists, overwrite with new version for MVP. + self._contracts[contract.contract_id] = contract + + def get_contract(self, contract_id: str) -> Contract | None: + return self._contracts.get(contract_id) + + def list_contracts(self) -> List[Contract]: + return list(self._contracts.values()) diff --git a/marketmesh_privacy_preserving_federated_/dsl.py b/marketmesh_privacy_preserving_federated_/dsl.py new file mode 100644 index 0000000..a5bfc71 --- /dev/null +++ b/marketmesh_privacy_preserving_federated_/dsl.py @@ -0,0 +1,25 @@ +"""Minimal DSL skeleton for MarketMesh interoperability (LocalExperiment, SharedStats, etc.).""" +from __future__ import annotations + +from dataclasses import dataclass +from typing import Dict, List, Optional + + +@dataclass +class LocalExperiment: + name: str + kpis: List[str] + constraints: Optional[Dict[str, float]] = None + + +@dataclass +class SharedStats: + contract_id: str + stats: Dict[str, float] + + +@dataclass +class ConfidenceInterval: + mean: float + lower: float + upper: float diff --git a/marketmesh_privacy_preserving_federated_/governance.py b/marketmesh_privacy_preserving_federated_/governance.py new file mode 100644 index 0000000..0ef5854 --- /dev/null +++ b/marketmesh_privacy_preserving_federated_/governance.py @@ -0,0 +1,63 @@ +"""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)