build(agent): semicolon#54de0b iteration
This commit is contained in:
parent
6594b61e12
commit
012a70f60f
10
AGENTS.md
10
AGENTS.md
|
|
@ -2,11 +2,14 @@
|
|||
|
||||
Overview
|
||||
- BeVault is a modular backbone enforcing and proving Best Execution across multiple equity venues.
|
||||
- The MVP focuses on a Graph-of-Contracts (GoC) registry, two starter adapters, and deterministic delta-sync with signed deltas.
|
||||
- The current package includes a Graph-of-Contracts (GoC) registry, two starter adapters, a canonical IR bridge, a tamper-evident governance ledger, and deterministic delta-sync with signed deltas.
|
||||
|
||||
Tech Stack (Production-Ready)
|
||||
- Language: Python 3.8+
|
||||
- Core: lightweight dataclasses for LocalArbProblem, SharedSignals, HedgeDelta, AuditLog, PrivacyBudget
|
||||
- Bridge: CanonicalIR and stable payload serialization for replay and signing
|
||||
- Ledger: GovernanceLedger with hash chaining for auditability
|
||||
- Replay: DeltaSyncEngine with version vectors and signed envelopes
|
||||
- Registry: GoCRegistry and GraphOfContracts with versioned adapters
|
||||
- Adapters: PriceFeedAdapter, BrokerAdapter (starter)
|
||||
- Crypto: HMAC-SHA256 based delta signing (pluggable key material)
|
||||
|
|
@ -16,7 +19,10 @@ Tech Stack (Production-Ready)
|
|||
Project Structure
|
||||
- idea172_bevault_verifiable_best/
|
||||
- __init__.py
|
||||
- bridge.py
|
||||
- core.py
|
||||
- ledger.py
|
||||
- replay.py
|
||||
- signing.py
|
||||
- registry.py
|
||||
- adapters/
|
||||
|
|
@ -32,6 +38,6 @@ Project Structure
|
|||
- READY_TO_PUBLISH (empty when ready)
|
||||
|
||||
How to contribute
|
||||
- Start with the MVP: wire two adapters and ensure delta-signing and delta-sync are deterministic.
|
||||
- Start by preserving determinism: keep signing, replay, and ledger hashes stable for identical inputs.
|
||||
- Expand the GoC registry with new contracts/adapters following the toy DSL seeds.
|
||||
- Ensure tests cover core contracts, registry operations, and adapter conformance checks.
|
||||
|
|
|
|||
33
README.md
33
README.md
|
|
@ -1 +1,32 @@
|
|||
# BeVault: Verifiable Best-Execution Backbone (MVP)
|
||||
# BeVault: Verifiable Best-Execution Backbone
|
||||
|
||||
BeVault is a Python backbone for best-execution workflows across equity venues. It models local optimization problems, privacy-bounded market signals, signed hedge deltas, and tamper-evident governance logs in a small, testable package.
|
||||
|
||||
## What It Provides
|
||||
|
||||
- Canonical data contracts for `LocalArbProblem`, `SharedSignals`, `HedgeDelta`, `AuditLog`, and `PrivacyBudget`
|
||||
- HMAC-SHA256 delta signing and verification
|
||||
- A canonical IR bridge for replay and auditing
|
||||
- A hash-chained governance ledger
|
||||
- Deterministic delta-sync with version vectors
|
||||
- A GoC registry plus starter price-feed and broker adapters
|
||||
|
||||
## Modules
|
||||
|
||||
- `core.py`: data contracts and toy DSL helpers
|
||||
- `signing.py`: signing and verification
|
||||
- `bridge.py`: canonical IR serialization
|
||||
- `ledger.py`: append-only governance ledger
|
||||
- `replay.py`: signed delta sync and replay
|
||||
- `registry.py`: GoC registry and contract catalog
|
||||
- `adapters/`: starter price-feed and broker adapters
|
||||
|
||||
## Verification
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
bash test.sh
|
||||
```
|
||||
|
||||
This installs the package, runs pytest, and builds a source distribution and wheel with `python3 -m build`.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
"""BeVault Verifiable Best-Execution Core (package init)."""
|
||||
"""BeVault verifiable best-execution backbone."""
|
||||
|
||||
from .core import LocalArbProblem, SharedSignals, HedgeDelta, AuditLog, PrivacyBudget
|
||||
from .bridge import CanonicalIR, canonical_payload, to_canonical_ir
|
||||
from .ledger import GovernanceLedger
|
||||
from .adapters import PriceFeedAdapter, BrokerAdapter
|
||||
from .registry import GoCRegistry, GraphOfContracts
|
||||
from .signing import sign_delta
|
||||
from .replay import DeltaSyncEngine, SignedDeltaEnvelope, VersionVector
|
||||
from .signing import sign_delta, verify_delta
|
||||
|
||||
__all__ = [
|
||||
"LocalArbProblem",
|
||||
|
|
@ -10,7 +14,17 @@ __all__ = [
|
|||
"HedgeDelta",
|
||||
"AuditLog",
|
||||
"PrivacyBudget",
|
||||
"CanonicalIR",
|
||||
"canonical_payload",
|
||||
"to_canonical_ir",
|
||||
"GovernanceLedger",
|
||||
"PriceFeedAdapter",
|
||||
"BrokerAdapter",
|
||||
"GoCRegistry",
|
||||
"GraphOfContracts",
|
||||
"DeltaSyncEngine",
|
||||
"SignedDeltaEnvelope",
|
||||
"VersionVector",
|
||||
"sign_delta",
|
||||
"verify_delta",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
"""Adapter base package for BeVault MVP (price feed, broker)."""
|
||||
"""Adapter package for BeVault."""
|
||||
from .price_feed import PriceFeedAdapter
|
||||
from .broker import BrokerAdapter
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
"""Starter BrokerAdapter for BeVault MVP."""
|
||||
"""Broker adapter for BeVault."""
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List
|
||||
|
||||
from ..core import HedgeDelta
|
||||
|
||||
|
|
@ -8,12 +10,19 @@ from ..core import HedgeDelta
|
|||
@dataclass
|
||||
class BrokerAdapter:
|
||||
name: str = "broker-v1"
|
||||
version: str = "0.1"
|
||||
version: str = "1.0"
|
||||
sent_deltas: List[HedgeDelta] = field(default_factory=list)
|
||||
|
||||
def send_delta(self, delta: HedgeDelta) -> bool:
|
||||
# Placeholder: in real life this would push to venue/execution system
|
||||
# Here we simply return True to indicate success
|
||||
self.sent_deltas.append(delta)
|
||||
return True
|
||||
|
||||
def conformance_contract(self) -> dict:
|
||||
return {
|
||||
"name": self.name,
|
||||
"version": self.version,
|
||||
"accepts": ["HedgeDelta"],
|
||||
}
|
||||
|
||||
|
||||
__all__ = ["BrokerAdapter"]
|
||||
|
|
|
|||
|
|
@ -1,19 +1,45 @@
|
|||
"""Starter PriceFeedAdapter for BeVault MVP."""
|
||||
"""Price feed adapter for BeVault."""
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
|
||||
from ..core import HedgeDelta
|
||||
import hashlib
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from ..bridge import canonical_payload, to_canonical_ir
|
||||
from ..core import HedgeDelta, LocalArbProblem, SharedSignals
|
||||
|
||||
|
||||
@dataclass
|
||||
class PriceFeedAdapter:
|
||||
name: str = "price-feed-v1"
|
||||
version: str = "0.1"
|
||||
version: str = "1.0"
|
||||
|
||||
def generate_signal(self, asset: str, price: float, latency_ms: float) -> HedgeDelta:
|
||||
# Produce a minimal HedgeDelta as a placeholder signal payload
|
||||
# In a real system this would produce SharedSignals -> local arb -> delta
|
||||
return HedgeDelta(asset=asset, hedge_size=price, timestamp=latency_ms, policy_tag="price-feed")
|
||||
def generate_signal(self, asset: str, price: float, latency_ms: float) -> SharedSignals:
|
||||
return SharedSignals(asset=asset, price=price, latency_ms=latency_ms)
|
||||
|
||||
def build_delta(
|
||||
self,
|
||||
local: LocalArbProblem,
|
||||
signals: SharedSignals,
|
||||
hedge_size: Optional[float] = None,
|
||||
) -> HedgeDelta:
|
||||
hedge_size = signals.price if hedge_size is None else hedge_size
|
||||
ir = to_canonical_ir(local, signals)
|
||||
audit_ref = hashlib.sha256(canonical_payload(ir).encode("utf-8")).hexdigest()
|
||||
return HedgeDelta(
|
||||
asset=local.asset,
|
||||
hedge_size=hedge_size,
|
||||
timestamp=signals.timestamp,
|
||||
policy_tag="price-feed",
|
||||
audit_ref=audit_ref,
|
||||
)
|
||||
|
||||
def conformance_contract(self) -> dict:
|
||||
return {
|
||||
"name": self.name,
|
||||
"version": self.version,
|
||||
"produces": ["SharedSignals", "HedgeDelta"],
|
||||
}
|
||||
|
||||
|
||||
__all__ = ["PriceFeedAdapter"]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
"""Bridge: EnergiBridge-inspired IR mapper for BeVault MVP.
|
||||
"""Bridge: canonical IR mapper for BeVault.
|
||||
|
||||
This module introduces a minimal, canonical representation mapping BeVault
|
||||
primitives into a single, serializable IR (Objects/Morphisms/PlanDelta).
|
||||
|
|
@ -9,9 +9,9 @@ interactions and deterministic backtests later in the MVP.
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import asdict, dataclass
|
||||
from typing import Optional
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from .core import HedgeDelta, LocalArbProblem, SharedSignals
|
||||
from .core import AuditLog, HedgeDelta, LocalArbProblem, PrivacyBudget, SharedSignals
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -23,9 +23,11 @@ class CanonicalIR:
|
|||
"""
|
||||
|
||||
version: str
|
||||
objects: dict
|
||||
morphisms: dict
|
||||
plan_delta: Optional[dict] = None
|
||||
objects: Dict[str, Any]
|
||||
morphisms: Dict[str, Any]
|
||||
plan_delta: Optional[Dict[str, Any]] = None
|
||||
audit_log: Optional[Dict[str, Any]] = None
|
||||
privacy_budget: Optional[Dict[str, Any]] = None
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
|
|
@ -33,10 +35,18 @@ class CanonicalIR:
|
|||
"objects": self.objects,
|
||||
"morphisms": self.morphisms,
|
||||
"plan_delta": self.plan_delta,
|
||||
"audit_log": self.audit_log,
|
||||
"privacy_budget": self.privacy_budget,
|
||||
}
|
||||
|
||||
|
||||
def to_canonical_ir(local: LocalArbProblem, signals: SharedSignals, delta: Optional[HedgeDelta] = None) -> CanonicalIR:
|
||||
def to_canonical_ir(
|
||||
local: LocalArbProblem,
|
||||
signals: SharedSignals,
|
||||
delta: Optional[HedgeDelta] = None,
|
||||
audit_log: Optional[AuditLog] = None,
|
||||
privacy_budget: Optional[PrivacyBudget] = None,
|
||||
) -> CanonicalIR:
|
||||
"""Map BeVault MVP primitives to a CanonicalIR structure.
|
||||
|
||||
This function provides a tiny, deterministic bridge from the MVP domain
|
||||
|
|
@ -50,8 +60,17 @@ def to_canonical_ir(local: LocalArbProblem, signals: SharedSignals, delta: Optio
|
|||
"SharedSignals": asdict_safe(signals),
|
||||
}
|
||||
plan_delta = asdict_safe(delta) if delta is not None else None
|
||||
audit_payload = asdict_safe(audit_log) if audit_log is not None else None
|
||||
privacy_payload = asdict_safe(privacy_budget) if privacy_budget is not None else None
|
||||
|
||||
return CanonicalIR(version="0.1", objects=objects, morphisms=morphisms, plan_delta=plan_delta)
|
||||
return CanonicalIR(
|
||||
version="1.0",
|
||||
objects=objects,
|
||||
morphisms=morphisms,
|
||||
plan_delta=plan_delta,
|
||||
audit_log=audit_payload,
|
||||
privacy_budget=privacy_payload,
|
||||
)
|
||||
|
||||
|
||||
def asdict_safe(obj) -> dict:
|
||||
|
|
@ -66,4 +85,12 @@ def asdict_safe(obj) -> dict:
|
|||
return {"value": obj}
|
||||
|
||||
|
||||
__all__ = ["CanonicalIR", "to_canonical_ir"]
|
||||
def canonical_payload(ir: CanonicalIR) -> str:
|
||||
"""Serialize a CanonicalIR in a stable form for signing and replay."""
|
||||
|
||||
import json
|
||||
|
||||
return json.dumps(ir.to_dict(), sort_keys=True, separators=(",", ":"))
|
||||
|
||||
|
||||
__all__ = ["CanonicalIR", "to_canonical_ir", "canonical_payload"]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
"""Core data contracts for BeVault MVP (toy DSL seeds)."""
|
||||
"""Core data contracts for BeVault."""
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Optional
|
||||
|
||||
import json
|
||||
import time
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -10,7 +12,16 @@ class LocalArbProblem:
|
|||
asset: str
|
||||
objective: str # e.g., 'min_cost', 'maximize_profit'
|
||||
risk_budget: float
|
||||
constraints: dict = field(default_factory=dict)
|
||||
constraints: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
def validate(self) -> None:
|
||||
if not self.asset:
|
||||
raise ValueError("asset is required")
|
||||
if self.risk_budget < 0:
|
||||
raise ValueError("risk_budget must be non-negative")
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return asdict(self)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -19,7 +30,14 @@ class SharedSignals:
|
|||
price: float
|
||||
latency_ms: float
|
||||
timestamp: float = field(default_factory=lambda: time.time())
|
||||
metadata: dict = field(default_factory=dict)
|
||||
metadata: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return asdict(self)
|
||||
|
||||
def is_fresh(self, max_age_seconds: float, now: Optional[float] = None) -> bool:
|
||||
now = time.time() if now is None else now
|
||||
return (now - self.timestamp) <= max_age_seconds
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -29,13 +47,37 @@ class HedgeDelta:
|
|||
timestamp: float = field(default_factory=lambda: time.time())
|
||||
policy_tag: str = "default"
|
||||
signature: Optional[str] = None
|
||||
version_vector: Dict[str, int] = field(default_factory=dict)
|
||||
audit_ref: Optional[str] = None
|
||||
|
||||
def to_signable_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"asset": self.asset,
|
||||
"hedge_size": self.hedge_size,
|
||||
"timestamp": self.timestamp,
|
||||
"policy_tag": self.policy_tag,
|
||||
"version_vector": self.version_vector,
|
||||
"audit_ref": self.audit_ref,
|
||||
}
|
||||
|
||||
def to_json(self) -> str:
|
||||
return json.dumps(self.to_signable_dict(), sort_keys=True, separators=(",", ":"))
|
||||
|
||||
|
||||
@dataclass
|
||||
class AuditLog:
|
||||
events: List[str] = field(default_factory=list)
|
||||
events: List[Dict[str, Any]] = field(default_factory=list)
|
||||
entry_ts: float = field(default_factory=lambda: time.time())
|
||||
|
||||
def record(self, event_type: str, payload: Optional[Dict[str, Any]] = None) -> None:
|
||||
self.events.append(
|
||||
{
|
||||
"event_type": event_type,
|
||||
"payload": payload or {},
|
||||
"timestamp": time.time(),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class PrivacyBudget:
|
||||
|
|
@ -43,6 +85,14 @@ class PrivacyBudget:
|
|||
remaining: float
|
||||
reset_epoch: float = field(default_factory=lambda: time.time())
|
||||
|
||||
def consume(self, amount: float) -> bool:
|
||||
if amount < 0:
|
||||
raise ValueError("amount must be non-negative")
|
||||
if amount > self.remaining:
|
||||
return False
|
||||
self.remaining -= amount
|
||||
return True
|
||||
|
||||
|
||||
__all__ = [
|
||||
"LocalArbProblem",
|
||||
|
|
@ -65,8 +115,6 @@ def generate_toy_seed(asset: str = "AAPL", price: float = 100.0):
|
|||
This helper is intentionally lightweight and is meant for local testing
|
||||
and documentation purposes within the MVP boundaries.
|
||||
"""
|
||||
from time import time
|
||||
|
||||
local = LocalArbProblem(
|
||||
asset=asset,
|
||||
objective="min_cost",
|
||||
|
|
@ -78,7 +126,7 @@ def generate_toy_seed(asset: str = "AAPL", price: float = 100.0):
|
|||
asset=asset,
|
||||
price=price,
|
||||
latency_ms=0.5,
|
||||
timestamp=time(),
|
||||
timestamp=time.time(),
|
||||
metadata={"toy_seed": True},
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
"""Append-only governance ledger for BeVault."""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import time
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
|
||||
def _stable_hash(payload: Dict[str, Any]) -> str:
|
||||
encoded = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
||||
return hashlib.sha256(encoded).hexdigest()
|
||||
|
||||
|
||||
@dataclass
|
||||
class LedgerEntry:
|
||||
index: int
|
||||
event_type: str
|
||||
payload: Dict[str, Any]
|
||||
timestamp: float
|
||||
previous_hash: str
|
||||
entry_hash: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class GovernanceLedger:
|
||||
"""Tamper-evident event ledger with hash chaining."""
|
||||
|
||||
entries: List[LedgerEntry] = field(default_factory=list)
|
||||
|
||||
def append(self, event_type: str, payload: Optional[Dict[str, Any]] = None, timestamp: Optional[float] = None) -> LedgerEntry:
|
||||
timestamp = time.time() if timestamp is None else timestamp
|
||||
payload = payload or {}
|
||||
previous_hash = self.entries[-1].entry_hash if self.entries else ""
|
||||
entry = LedgerEntry(
|
||||
index=len(self.entries),
|
||||
event_type=event_type,
|
||||
payload=payload,
|
||||
timestamp=timestamp,
|
||||
previous_hash=previous_hash,
|
||||
entry_hash="",
|
||||
)
|
||||
entry.entry_hash = _stable_hash(
|
||||
{
|
||||
"index": entry.index,
|
||||
"event_type": entry.event_type,
|
||||
"payload": entry.payload,
|
||||
"timestamp": entry.timestamp,
|
||||
"previous_hash": entry.previous_hash,
|
||||
}
|
||||
)
|
||||
self.entries.append(entry)
|
||||
return entry
|
||||
|
||||
def verify(self) -> bool:
|
||||
previous_hash = ""
|
||||
for index, entry in enumerate(self.entries):
|
||||
if entry.index != index:
|
||||
return False
|
||||
if entry.previous_hash != previous_hash:
|
||||
return False
|
||||
expected_hash = _stable_hash(
|
||||
{
|
||||
"index": entry.index,
|
||||
"event_type": entry.event_type,
|
||||
"payload": entry.payload,
|
||||
"timestamp": entry.timestamp,
|
||||
"previous_hash": entry.previous_hash,
|
||||
}
|
||||
)
|
||||
if entry.entry_hash != expected_hash:
|
||||
return False
|
||||
previous_hash = entry.entry_hash
|
||||
return True
|
||||
|
||||
def anchor(self) -> str:
|
||||
return self.entries[-1].entry_hash if self.entries else ""
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"entries": [entry.__dict__ for entry in self.entries],
|
||||
"anchor": self.anchor(),
|
||||
}
|
||||
|
||||
|
||||
__all__ = ["GovernanceLedger", "LedgerEntry"]
|
||||
|
|
@ -1,21 +1,19 @@
|
|||
"""Graph-of-Contracts (GoC) registry and minimal adapters registry.
|
||||
|
||||
This is a lightweight, production-oriented scaffold for the MVP.
|
||||
"""
|
||||
"""Graph-of-Contracts (GoC) registry."""
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, Optional
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from .core import HedgeDelta
|
||||
# Import adapters to ensure their classes are discoverable when registry loads
|
||||
from .adapters.price_feed import PriceFeedAdapter
|
||||
from .adapters.broker import BrokerAdapter
|
||||
from .adapters.price_feed import PriceFeedAdapter
|
||||
from .core import HedgeDelta
|
||||
|
||||
|
||||
@dataclass
|
||||
class GoCRegistry:
|
||||
"""Registry for adapters and data contracts (toy GoC)."""
|
||||
"""Registry for adapters and data contracts."""
|
||||
adapters: Dict[str, object] = field(default_factory=dict)
|
||||
contracts: Dict[str, str] = field(default_factory=dict)
|
||||
metadata: Dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
def __post_init__(self):
|
||||
# Initialize to an empty mapping if not provided
|
||||
|
|
@ -28,20 +26,49 @@ class GoCRegistry:
|
|||
def get_adapter(self, name: str) -> Optional[object]:
|
||||
return self.adapters.get(name)
|
||||
|
||||
|
||||
class GraphOfContracts:
|
||||
"""Lightweight catalog for contract versions and replay metadata."""
|
||||
def __init__(self) -> None:
|
||||
self.contracts: Dict[str, str] = {}
|
||||
|
||||
def register_contract(self, name: str, version: str) -> None:
|
||||
self.contracts[name] = version
|
||||
|
||||
def get_contract(self, name: str) -> Optional[str]:
|
||||
return self.contracts.get(name)
|
||||
|
||||
def conformance_report(self, adapter_name: str) -> Dict[str, Any]:
|
||||
adapter = self.get_adapter(adapter_name)
|
||||
if adapter is None:
|
||||
return {"adapter": adapter_name, "registered": False, "conforms": False}
|
||||
|
||||
required_methods: List[str] = []
|
||||
if isinstance(adapter, PriceFeedAdapter):
|
||||
required_methods = ["generate_signal", "conformance_contract"]
|
||||
elif isinstance(adapter, BrokerAdapter):
|
||||
required_methods = ["send_delta", "conformance_contract"]
|
||||
|
||||
missing = [method for method in required_methods if not hasattr(adapter, method)]
|
||||
return {
|
||||
"adapter": adapter_name,
|
||||
"registered": True,
|
||||
"conforms": not missing,
|
||||
"missing": missing,
|
||||
"contract": getattr(adapter, "conformance_contract", lambda: None)(),
|
||||
}
|
||||
|
||||
|
||||
class GraphOfContracts:
|
||||
"""Catalog for contract versions and replay metadata."""
|
||||
def __init__(self) -> None:
|
||||
self.contracts: Dict[str, Dict[str, Any]] = {}
|
||||
|
||||
def register_contract(self, name: str, version: str, schema: Optional[Dict[str, Any]] = None) -> None:
|
||||
self.contracts[name] = {"version": version, "schema": schema or {}}
|
||||
|
||||
def get_contract(self, name: str) -> Optional[Dict[str, Any]]:
|
||||
return self.contracts.get(name)
|
||||
|
||||
def list_contracts(self):
|
||||
return list(self.contracts.items())
|
||||
|
||||
def to_dict(self) -> Dict[str, Dict[str, Any]]:
|
||||
return dict(self.contracts)
|
||||
|
||||
|
||||
__all__ = ["GoCRegistry", "GraphOfContracts"]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
"""Deterministic delta-sync and offline replay utilities."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Dict, Iterable, List, Optional, Tuple
|
||||
|
||||
from .core import HedgeDelta
|
||||
from .signing import sign_delta, verify_delta
|
||||
|
||||
|
||||
@dataclass
|
||||
class VersionVector:
|
||||
clocks: Dict[str, int] = field(default_factory=dict)
|
||||
|
||||
def bump(self, actor: str) -> None:
|
||||
self.clocks[actor] = self.clocks.get(actor, 0) + 1
|
||||
|
||||
def merge(self, other: "VersionVector") -> None:
|
||||
for actor, counter in other.clocks.items():
|
||||
self.clocks[actor] = max(self.clocks.get(actor, 0), counter)
|
||||
|
||||
def copy(self) -> "VersionVector":
|
||||
return VersionVector(clocks=dict(self.clocks))
|
||||
|
||||
def to_dict(self) -> Dict[str, int]:
|
||||
return dict(self.clocks)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SignedDeltaEnvelope:
|
||||
delta: HedgeDelta
|
||||
actor: str
|
||||
signature: str
|
||||
version_vector: VersionVector
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
"delta": self.delta.to_signable_dict(),
|
||||
"actor": self.actor,
|
||||
"signature": self.signature,
|
||||
"version_vector": self.version_vector.to_dict(),
|
||||
}
|
||||
|
||||
|
||||
class DeltaSyncEngine:
|
||||
"""Records and replays signed deltas deterministically."""
|
||||
|
||||
def __init__(self, signing_key: bytes) -> None:
|
||||
self.signing_key = signing_key
|
||||
self.version_vector = VersionVector()
|
||||
self.envelopes: List[SignedDeltaEnvelope] = []
|
||||
|
||||
def record(self, delta: HedgeDelta, actor: str) -> SignedDeltaEnvelope:
|
||||
self.version_vector.bump(actor)
|
||||
delta.version_vector = self.version_vector.to_dict()
|
||||
delta.signature = sign_delta(delta, self.signing_key)
|
||||
envelope = SignedDeltaEnvelope(delta=delta, actor=actor, signature=delta.signature, version_vector=self.version_vector.copy())
|
||||
self.envelopes.append(envelope)
|
||||
return envelope
|
||||
|
||||
def ingest(self, envelope: SignedDeltaEnvelope) -> bool:
|
||||
if not verify_delta(envelope.delta, self.signing_key, envelope.signature):
|
||||
return False
|
||||
self.version_vector.merge(envelope.version_vector)
|
||||
self.envelopes.append(envelope)
|
||||
return True
|
||||
|
||||
def replay(self) -> List[HedgeDelta]:
|
||||
ordered = sorted(
|
||||
self.envelopes,
|
||||
key=lambda item: (
|
||||
item.delta.timestamp,
|
||||
item.actor,
|
||||
item.signature,
|
||||
),
|
||||
)
|
||||
return [envelope.delta for envelope in ordered]
|
||||
|
||||
def history(self) -> List[Dict[str, Any]]:
|
||||
return [envelope.to_dict() for envelope in self.envelopes]
|
||||
|
||||
|
||||
__all__ = ["DeltaSyncEngine", "SignedDeltaEnvelope", "VersionVector"]
|
||||
|
|
@ -1,18 +1,24 @@
|
|||
"""Delta signing utilities for BeVault MVP."""
|
||||
"""Delta signing utilities for BeVault."""
|
||||
from __future__ import annotations
|
||||
import hmac
|
||||
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
|
||||
from .core import HedgeDelta
|
||||
|
||||
|
||||
def sign_delta(delta: HedgeDelta, key: bytes) -> str:
|
||||
"""Sign a HedgeDelta deterministically using HMAC-SHA256.
|
||||
"""Sign a HedgeDelta deterministically using HMAC-SHA256."""
|
||||
|
||||
The signature is derived from the delta contents (asset, hedge_size, timestamp, policy_tag).
|
||||
The resulting hex digest is stable for identical inputs and keys.
|
||||
"""
|
||||
payload = f"{delta.asset}:{delta.hedge_size}:{delta.timestamp}:{delta.policy_tag}"
|
||||
payload = json.dumps(delta.to_signable_dict(), sort_keys=True, separators=(",", ":"))
|
||||
return hmac.new(key, payload.encode("utf-8"), hashlib.sha256).hexdigest()
|
||||
|
||||
|
||||
__all__ = ["sign_delta"]
|
||||
def verify_delta(delta: HedgeDelta, key: bytes, signature: str) -> bool:
|
||||
"""Verify a delta signature in a deterministic way."""
|
||||
|
||||
return hmac.compare_digest(sign_delta(delta, key), signature)
|
||||
|
||||
|
||||
__all__ = ["sign_delta", "verify_delta"]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ version = "0.1.0"
|
|||
description = "BeVault: verifiable best-execution backbone prototype with Cross-Venue GoC adapters"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
license = {text = "MIT"}
|
||||
license = "MIT"
|
||||
authors = [ { name = "OpenCode Team" } ]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
|
|
|
|||
2
test.sh
2
test.sh
|
|
@ -4,7 +4,7 @@ set -euo pipefail
|
|||
echo "[BeVault] Running tests and packaging sanity checks..."
|
||||
|
||||
# Ensure pip tooling is up to date
|
||||
python3 -m pip install --upgrade pip setuptools wheel
|
||||
python3 -m pip install --upgrade pip setuptools wheel build
|
||||
|
||||
# Install the package in editable mode for testing imports
|
||||
python3 -m pip install -e .
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
"""Basic tests for BeVault MVP components."""
|
||||
import pytest
|
||||
|
||||
from idea172_bevault_verifiable_best.core import HedgeDelta
|
||||
from idea172_bevault_verifiable_best.signing import sign_delta
|
||||
from idea172_bevault_verifiable_best.registry import GoCRegistry
|
||||
from idea172_bevault_verifiable_best.adapters.price_feed import PriceFeedAdapter
|
||||
|
||||
|
||||
def test_sign_delta_deterministic():
|
||||
delta = HedgeDelta(asset="AAPL", hedge_size=1.0, timestamp=1.0, policy_tag="test")
|
||||
key = b"secret-key"
|
||||
sig1 = sign_delta(delta, key)
|
||||
sig2 = sign_delta(delta, key)
|
||||
assert isinstance(sig1, str) and isinstance(sig2, str)
|
||||
assert sig1 == sig2
|
||||
|
||||
|
||||
def test_registry_adapters_can_register_and_retrieve():
|
||||
reg = GoCRegistry()
|
||||
adapter = PriceFeedAdapter()
|
||||
reg.register_adapter(adapter)
|
||||
assert reg.get_adapter(adapter.name) is adapter
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
"""Tests for BeVault core behavior."""
|
||||
|
||||
from idea172_bevault_verifiable_best import (
|
||||
AuditLog,
|
||||
DeltaSyncEngine,
|
||||
GovernanceLedger,
|
||||
GoCRegistry,
|
||||
HedgeDelta,
|
||||
LocalArbProblem,
|
||||
PrivacyBudget,
|
||||
PriceFeedAdapter,
|
||||
BrokerAdapter,
|
||||
SharedSignals,
|
||||
canonical_payload,
|
||||
sign_delta,
|
||||
to_canonical_ir,
|
||||
verify_delta,
|
||||
)
|
||||
|
||||
|
||||
def test_sign_and_verify_delta_deterministically():
|
||||
delta = HedgeDelta(asset="AAPL", hedge_size=1.0, timestamp=1.0, policy_tag="test")
|
||||
key = b"secret-key"
|
||||
sig1 = sign_delta(delta, key)
|
||||
sig2 = sign_delta(delta, key)
|
||||
assert sig1 == sig2
|
||||
assert verify_delta(delta, key, sig1)
|
||||
|
||||
|
||||
def test_registry_reports_adapter_conformance():
|
||||
reg = GoCRegistry()
|
||||
price = PriceFeedAdapter()
|
||||
broker = BrokerAdapter()
|
||||
reg.register_adapter(price)
|
||||
reg.register_adapter(broker)
|
||||
reg.register_contract("LocalArbProblem", "1.0")
|
||||
|
||||
report = reg.conformance_report(price.name)
|
||||
assert report["conforms"] is True
|
||||
assert report["registered"] is True
|
||||
assert reg.get_adapter(broker.name) is broker
|
||||
assert reg.get_contract("LocalArbProblem") == "1.0"
|
||||
|
||||
|
||||
def test_canonical_ir_includes_governance_metadata():
|
||||
local = LocalArbProblem(asset="MSFT", objective="min_cost", risk_budget=10.0)
|
||||
signals = SharedSignals(asset="MSFT", price=250.0, latency_ms=2.0, timestamp=1.0)
|
||||
audit = AuditLog()
|
||||
audit.record("approve", {"desk": "equities"})
|
||||
budget = PrivacyBudget(asset="MSFT", remaining=5.0)
|
||||
|
||||
ir = to_canonical_ir(local, signals, audit_log=audit, privacy_budget=budget)
|
||||
payload = canonical_payload(ir)
|
||||
|
||||
assert ir.version == "1.0"
|
||||
assert "audit_log" in payload
|
||||
assert "privacy_budget" in payload
|
||||
|
||||
|
||||
def test_governance_ledger_hash_chain_verifies():
|
||||
ledger = GovernanceLedger()
|
||||
first = ledger.append("approve", {"ticket": "abc"}, timestamp=1.0)
|
||||
second = ledger.append("execute", {"ticket": "abc"}, timestamp=2.0)
|
||||
|
||||
assert ledger.verify() is True
|
||||
assert ledger.anchor() == second.entry_hash
|
||||
assert first.previous_hash == ""
|
||||
|
||||
ledger.entries[0].payload["ticket"] = "mutated"
|
||||
assert ledger.verify() is False
|
||||
|
||||
|
||||
def test_delta_sync_replays_deterministically():
|
||||
engine = DeltaSyncEngine(signing_key=b"sync-key")
|
||||
delta_one = HedgeDelta(asset="AAPL", hedge_size=1.0, timestamp=1.0, policy_tag="a")
|
||||
delta_two = HedgeDelta(asset="AAPL", hedge_size=2.0, timestamp=0.5, policy_tag="b")
|
||||
|
||||
engine.record(delta_one, actor="desk-a")
|
||||
engine.record(delta_two, actor="desk-b")
|
||||
|
||||
replayed = engine.replay()
|
||||
assert [delta.policy_tag for delta in replayed] == ["b", "a"]
|
||||
assert replayed[0].signature is not None
|
||||
|
||||
|
||||
def test_price_feed_builds_delta_and_broker_sends_it():
|
||||
adapter = PriceFeedAdapter()
|
||||
local = LocalArbProblem(asset="AAPL", objective="min_cost", risk_budget=10.0)
|
||||
signals = adapter.generate_signal(asset="AAPL", price=101.5, latency_ms=1.2)
|
||||
delta = adapter.build_delta(local, signals)
|
||||
|
||||
broker = BrokerAdapter()
|
||||
assert broker.send_delta(delta) is True
|
||||
assert broker.sent_deltas[-1] is delta
|
||||
assert delta.audit_ref is not None
|
||||
Loading…
Reference in New Issue