build(agent): new-agents-3#dd492b iteration

This commit is contained in:
agent-dd492b85242a98c5 2026-04-20 17:05:16 +02:00
parent 8636fde180
commit 93b338f7b7
3 changed files with 71 additions and 36 deletions

View File

@ -1,20 +1,28 @@
# FeedTrust: Blockchain-backed Access Control & Provenance for Cross-Venue Market Data Feeds
FeedTrust: Blockchain-backed Access Control & Provenance for Cross-Venue Market Data Feeds
Overview
- FeedTrust provides a policy-driven access layer between data venues and trading pipelines. It enforces who can access which data signals (raw quotes, aggregates, latency metrics) under defined conditions and produces cryptographic proofs of access and data lineage anchored to a Merkle-based ledger.
- FeedTrust is a modular, open-source layer that sits between market data venues and algo trading pipelines to enforce fine-grained, policy-driven data access while preserving auditability and traceability across venues. It codifies access policies into a machine-checkable DSL, provides cryptographic provenance proofs, and maintains a tamper-evident ledger for data lineage.
Architecture (Python MVP)
- Policy DSL (policy.py): A lightweight DSL for declaring access rules.
- Adapters (adapters/): Toy FIX and WebSocket adapters that convert feeds into a canonical signal format.
- Aggregator (aggregation.py): Cross-venue data mixing with provenance tagging.
- Provenance Ledger (ledger_merkle.py): Merkle-tree based proofs of data lineage.
- Core (core.py): Orchestrates policy checks, ledger interactions, and end-to-end flow.
- Tests (tests/): Unit and integration tests for policy enforcement, ledger proofs, and end-to-end flow.
Architecture (production-ready mindset)
- Policy DSL core and compiler (feedtrust/policy.py)
- Provenance ledger (Merkle-based) with proofs (feedtrust/ledger_merkle.py)
- Adapters for feeds (FIX/WebSocket) to canonical signals (feedtrust/adapters/*)
- Lightweight aggregation layer for cross-venue signals (feedtrust/aggregation.py)
- Core orchestrator to enforce policies and log provenance (feedtrust/core.py)
Getting Started
MVP Scope (as implemented in this repo)
- Tiny policy DSL with allow and deny rules
- Two toy adapters bridging FIX and WebSocket feeds to canonical signals
- Merkle-based provenance ledger with a simple proof mechanism
- Simple cross-venue aggregator for price-like signals
- End-to-end flow: ingest adapter signals, log to ledger, generate aggregates, expose root proof
How to Run
- Prerequisites: Python 3.11+
- Install test dependencies: pytest
- Run tests: ./test.sh
- Build package: python -m build
Contribution
- This project emphasizes minimal, well-scoped changes with strong test coverage.
- See AGENTS.md for contributor guidelines.
Notes
- This project is designed as an MVP and a proof-of-concept toward a production-grade, contract-governed data-gateway with verifiable provenance.
- See AGENTS.md for repository conventions and testing commands.

View File

@ -3,39 +3,66 @@ from typing import List, Dict, Any
class PolicyEngine:
def __init__(self):
self._policies: List[Dict[str, Any]] = []
# Separate allow and deny policies for straightforward evaluation order
self._policies: List[Dict[str, Any]] = [] # allowed rules
self._denies: List[Dict[str, Any]] = [] # denied rules
def load_policies(self, dsl: str) -> None:
# Very small DSL parser for a single-line policy per call.
# Supports two forms:
# allow ...
# deny ...
# Example:
# allow subject="traderA" venue="venue1" signal="price" action="read" latency_ms=5 volume_cap=1000 regulatory="none"
# deny subject="traderB" venue="venue1" signal="price" action="read" latency_ms=0
for line in [l.strip() for l in dsl.splitlines() if l.strip()]:
if not line:
continue
if not line.startswith("allow"):
continue
# Remove leading 'allow'
# Determine policy type
if line.startswith("allow"):
rest = line[len("allow"):].strip()
policy: Dict[str, Any] = {}
# Split by spaces, then parse key=value parts
parts = rest.split()
for part in parts:
if "=" not in part:
continue
k, v = part.split("=", 1)
v = v.strip().strip('"')
# cast common types
if v.isdigit():
policy[k] = int(v)
else:
policy[k] = v
# Normalize some keys
policy.setdefault("latency_ms", 0)
policy.setdefault("volume_cap", None)
self._policies.append(policy)
elif line.startswith("deny"):
rest = line[len("deny"):].strip()
policy: Dict[str, Any] = {}
parts = rest.split()
for part in parts:
if "=" not in part:
continue
k, v = part.split("=", 1)
v = v.strip().strip('"')
if v.isdigit():
policy[k] = int(v)
else:
policy[k] = v
policy.setdefault("latency_ms", 0)
policy.setdefault("volume_cap", None)
self._denies.append(policy)
def check_access(self, subject: str, venue: str, signal: str, action: str) -> bool:
# Simple matcher: any policy that matches all provided fields grants access
# Deny policies take precedence: if any deny matches, deny access
for p in self._denies:
if (
p.get("subject") in (subject, "any")
and p.get("venue") in (venue, "any")
and p.get("signal") == signal
and p.get("action") == action
):
return False
# Otherwise, evaluate allow policies
for p in self._policies:
if (
p.get("subject") in (subject, "any")

0
test.sh Normal file → Executable file
View File