build(agent): semicolon#54de0b iteration

This commit is contained in:
agent-54de0bcc6a17828b 2026-04-24 18:15:54 +02:00
parent 291373459b
commit c264fd38ca
13 changed files with 756 additions and 2 deletions

21
.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
node_modules/
.npmrc
.env
.env.*
__tests__/
coverage/
.nyc_output/
dist/
build/
.cache/
*.log
.DS_Store
tmp/
.tmp/
__pycache__/
*.pyc
.venv/
venv/
*.egg-info/
.pytest_cache/
READY_TO_PUBLISH

37
AGENTS.md Normal file
View File

@ -0,0 +1,37 @@
# AGENTS.md
## Repository Shape
- `src/idea109_secureex_hardware_accelerated/`: package code.
- `tests/`: unit tests.
- `test.sh`: canonical verification entrypoint.
- `README.md`: architecture and usage.
## Tech Stack
- Python 3.10+
- Standard library only for runtime code.
- SQLite for the governance ledger.
- Setuptools for packaging.
## Architecture
- `primitives.py`: canonical trading and governance dataclasses.
- `adapters.py`: FIX and WebSocket-to-canonical adapters.
- `enclave.py`: deterministic enclave execution and attestation model.
- `governance.py`: append-only, hash-chained SQLite ledger.
- `delta_sync.py`: deterministic reconciliation helpers.
- `replay.py`: offline deterministic replay harness and CLI.
## Rules
- Keep new logic deterministic unless explicit randomness is required and seeded.
- Preserve the hash chain in the governance ledger.
- Do not weaken validation in adapters or attestation verification.
- Prefer the smallest correct change.
- Update tests when changing canonical payload shapes or replay behavior.
## Verification
- `bash test.sh`
- The script must run unit tests and `python3 -m build`.

View File

@ -1,3 +1,86 @@
# idea109-secureex-hardware-accelerated
# SecureEx
Source logic for Idea #109
SecureEx is a deterministic compliance and replay core for cross-venue trading workflows.
It provides:
- Canonical market primitives for venue normalization.
- FIX and WebSocket adapters.
- A deterministic enclave execution model with attestation.
- A SQLite-backed hash-chained governance ledger.
- Delta reconciliation helpers for disconnect recovery.
- An offline replay harness for regression testing.
## What This Repository Does
This codebase models the minimum trusted control plane needed for a SecureEx-style system:
- normalize market data into `LocalMarket`
- aggregate it into `SharedSignals`
- produce a deterministic `PlanDelta`
- attest the enclave measurement and decision path
- persist the decision trail into an auditable SQLite ledger
- replay the same inputs deterministically after a disconnect
## Architecture
### Canonical primitives
- `LocalMarket`: venue-level bid/ask state.
- `SharedSignals`: aggregated cross-venue signal output.
- `PlanDelta`: the next hedge or quote action.
- `PrivacyBudget`: guards signal leakage.
- `AuditLogEntry`: the attested event record.
### Adapters
- `FixAdapter`: parses FIX-style tag/value payloads.
- `WebSocketAdapter`: parses JSON market updates.
### Enclave and attestation
- `SecureEnclave.compute()` is deterministic for a given market set.
- `SecureEnclave.attest()` returns a signed measurement report.
- `verify_attestation()` checks the report signature and measurement.
### Governance ledger
- `GovernanceLedger` stores an append-only hash chain in SQLite.
- `verify_chain()` recomputes the full chain for audit validation.
### Delta sync and replay
- `DeltaSync` tracks sequence progress per venue and asset.
- `reconcile_markets()` computes the deterministic recovery delta.
- `replay.py` can run a local replay from a JSON event file.
## Install
```bash
python3 -m pip install -e .
```
## Run Tests
```bash
bash test.sh
```
## Replay CLI
```bash
secureex-replay --events events.json
```
Example `events.json`:
```json
[
{"adapter": "fix", "venue": "VENUE_A", "message": "55=ABC|132=10.1|133=10.2|134=100|135=120|34=7|52=1.5"},
{"adapter": "ws", "venue": "VENUE_B", "message": {"asset": "ABC", "bid": 10.0, "ask": 10.3, "bid_size": 80, "ask_size": 60, "sequence": 8, "timestamp": 1.7}}
]
```
## Packaging
The package name is `idea109-secureex-hardware-accelerated` and the long description is sourced from this `README.md`.

21
pyproject.toml Normal file
View File

@ -0,0 +1,21 @@
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "idea109-secureex-hardware-accelerated"
version = "0.1.0"
description = "SecureEx: a verifiable compliance and deterministic replay engine for cross-venue trading"
readme = "README.md"
requires-python = ">=3.10"
license = "MIT"
authors = [{name = "OpenCode"}]
[project.scripts]
secureex-replay = "idea109_secureex_hardware_accelerated.replay:main"
[tool.setuptools]
package-dir = {"" = "src"}
[tool.setuptools.packages.find]
where = ["src"]

View File

@ -0,0 +1,28 @@
"""SecureEx core package."""
from .adapters import FixAdapter, WebSocketAdapter
from .delta_sync import DeltaSync, reconcile_markets
from .enclave import SecureEnclave, verify_attestation
from .governance import GovernanceLedger
from .primitives import (
AuditLogEntry,
LocalMarket,
PlanDelta,
PrivacyBudget,
SharedSignals,
)
__all__ = [
"AuditLogEntry",
"DeltaSync",
"FixAdapter",
"GovernanceLedger",
"LocalMarket",
"PlanDelta",
"PrivacyBudget",
"SecureEnclave",
"SharedSignals",
"WebSocketAdapter",
"reconcile_markets",
"verify_attestation",
]

View File

@ -0,0 +1,63 @@
from __future__ import annotations
import json
from dataclasses import dataclass
from collections.abc import Mapping
from .primitives import LocalMarket
def _coerce_float(value: object) -> float:
if isinstance(value, (str, int, float)):
return float(value)
raise TypeError(f"cannot coerce {type(value)!r} to float")
def _coerce_int(value: object) -> int:
if isinstance(value, (str, int, float)):
return int(float(value))
raise TypeError(f"cannot coerce {type(value)!r} to int")
@dataclass(frozen=True, slots=True)
class FixAdapter:
venue: str
def parse_market(self, message: str) -> LocalMarket:
fields: dict[str, str] = {}
for pair in message.split("|"):
if not pair:
continue
if "=" not in pair:
continue
key, value = pair.split("=", 1)
fields[key] = value
return LocalMarket(
venue=self.venue,
asset=fields.get("55", fields.get("symbol", "UNKNOWN")),
bid=_coerce_float(fields.get("132", fields.get("bid", 0.0))),
ask=_coerce_float(fields.get("133", fields.get("ask", 0.0))),
bid_size=_coerce_float(fields.get("134", fields.get("bid_size", 0.0))),
ask_size=_coerce_float(fields.get("135", fields.get("ask_size", 0.0))),
sequence=_coerce_int(fields.get("34", fields.get("sequence", 0))),
timestamp=_coerce_float(fields.get("52", fields.get("timestamp", 0.0))),
)
@dataclass(frozen=True, slots=True)
class WebSocketAdapter:
venue: str
def parse_market(self, message: str | Mapping[str, object]) -> LocalMarket:
payload = json.loads(message) if isinstance(message, str) else dict(message)
return LocalMarket(
venue=self.venue,
asset=str(payload.get("asset", payload.get("symbol", "UNKNOWN"))),
bid=_coerce_float(payload.get("bid", 0.0)),
ask=_coerce_float(payload.get("ask", 0.0)),
bid_size=_coerce_float(payload.get("bid_size", payload.get("bidSize", 0.0))),
ask_size=_coerce_float(payload.get("ask_size", payload.get("askSize", 0.0))),
sequence=_coerce_int(payload.get("sequence", payload.get("seq", 0))),
timestamp=_coerce_float(payload.get("timestamp", 0.0)),
)

View File

@ -0,0 +1,59 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import Iterable, Sequence
from .primitives import LocalMarket
@dataclass(frozen=True, slots=True)
class MarketDelta:
asset: str
venue: str
previous_sequence: int
current_sequence: int
bid: float
ask: float
class DeltaSync:
def __init__(self) -> None:
self._last_sequences: dict[tuple[str, str], int] = {}
def snapshot(self, markets: Sequence[LocalMarket]) -> list[MarketDelta]:
deltas: list[MarketDelta] = []
for market in sorted(markets, key=lambda m: (m.asset, m.venue, m.sequence)):
key = (market.asset, market.venue)
previous_sequence = self._last_sequences.get(key, 0)
if market.sequence != previous_sequence:
deltas.append(
MarketDelta(
asset=market.asset,
venue=market.venue,
previous_sequence=previous_sequence,
current_sequence=market.sequence,
bid=market.bid,
ask=market.ask,
)
)
self._last_sequences[key] = market.sequence
return deltas
def reconcile_markets(local: Sequence[LocalMarket], remote: Sequence[LocalMarket]) -> list[MarketDelta]:
remote_index = {(m.asset, m.venue): m for m in remote}
deltas: list[MarketDelta] = []
for market in sorted(local, key=lambda m: (m.asset, m.venue, m.sequence)):
counterpart = remote_index.get((market.asset, market.venue))
if counterpart is None or counterpart.sequence != market.sequence or counterpart.bid != market.bid or counterpart.ask != market.ask:
deltas.append(
MarketDelta(
asset=market.asset,
venue=market.venue,
previous_sequence=counterpart.sequence if counterpart else 0,
current_sequence=market.sequence,
bid=market.bid,
ask=market.ask,
)
)
return deltas

View File

@ -0,0 +1,87 @@
from __future__ import annotations
import hashlib
import hmac
import json
from dataclasses import dataclass
from typing import Iterable, Sequence
from .primitives import LocalMarket, PlanDelta, PrivacyBudget, SharedSignals, EnclaveDecision
def _stable_json(value: object) -> str:
return json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
@dataclass(frozen=True, slots=True)
class AttestationReport:
measurement: str
nonce: str
signature: str
class SecureEnclave:
def __init__(self, enclave_id: str, secret: str, measurement: str | None = None) -> None:
self.enclave_id = enclave_id
self._secret = secret.encode("utf-8")
self.measurement = measurement or self._measure()
def _measure(self) -> str:
return hashlib.sha256(f"{self.enclave_id}:{self.__class__.__name__}".encode("utf-8")).hexdigest()
def attest(self, nonce: str) -> AttestationReport:
message = f"{self.measurement}:{nonce}:{self.enclave_id}".encode("utf-8")
signature = hmac.new(self._secret, message, hashlib.sha256).hexdigest()
return AttestationReport(measurement=self.measurement, nonce=nonce, signature=signature)
def compute(self, markets: Sequence[LocalMarket], privacy_budget: PrivacyBudget | None = None) -> EnclaveDecision:
if not markets:
raise ValueError("markets are required")
grouped: dict[str, list[LocalMarket]] = {}
for market in markets:
grouped.setdefault(market.asset, []).append(market)
asset, asset_markets = sorted(grouped.items())[0]
bids = sum(m.bid * m.bid_size for m in asset_markets)
asks = sum(m.ask * m.ask_size for m in asset_markets)
depth = sum(m.bid_size + m.ask_size for m in asset_markets)
bid = min(m.bid for m in asset_markets)
ask = max(m.ask for m in asset_markets)
mid = sum(m.mid for m in asset_markets) / len(asset_markets)
spread = ask - bid
budget = privacy_budget or PrivacyBudget(total_units=8)
budget = budget.consume(1)
signals = SharedSignals(
asset=asset,
mid=mid,
spread=spread,
venue_count=len({m.venue for m in asset_markets}),
aggregate_depth=depth,
privacy_budget_used=budget.used_units,
)
venue = sorted(asset_markets, key=lambda market: (market.ask, market.sequence, market.venue))[0].venue
side = "BUY" if bids < asks else "SELL"
quantity = max(1.0, round(depth / max(len(asset_markets), 1), 4))
limit_price = round(mid + (0.01 if side == "BUY" else -0.01), 4)
plan_source = _stable_json({"asset": asset, "mid": mid, "spread": spread, "venue": venue, "side": side})
plan_id = hashlib.sha256(plan_source.encode("utf-8")).hexdigest()[:16]
plan = PlanDelta(
plan_id=plan_id,
asset=asset,
venue=venue,
side=side,
quantity=quantity,
limit_price=limit_price,
rationale=f"cross-venue-deterministic-{side.lower()}",
sequence=max(m.sequence for m in asset_markets),
)
return EnclaveDecision(signals=signals, plan=plan, privacy_budget=budget)
def verify_attestation(report: AttestationReport, expected_measurement: str, secret: str, enclave_id: str) -> bool:
message = f"{expected_measurement}:{report.nonce}:{enclave_id}".encode("utf-8")
expected_signature = hmac.new(secret.encode("utf-8"), message, hashlib.sha256).hexdigest()
return report.measurement == expected_measurement and hmac.compare_digest(report.signature, expected_signature)

View File

@ -0,0 +1,140 @@
from __future__ import annotations
import hashlib
import json
import sqlite3
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Iterable
from .enclave import AttestationReport
from .primitives import AuditLogEntry
def _stable_json(value: Any) -> str:
return json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
@dataclass(frozen=True, slots=True)
class LedgerRecord:
sequence: int
entry_type: str
payload: dict[str, Any]
timestamp: float
previous_hash: str
entry_hash: str
attestation_measurement: str
attestation_nonce: str
attestation_signature: str
class GovernanceLedger:
def __init__(self, path: str | Path = ":memory:") -> None:
self.path = str(path)
self._conn = sqlite3.connect(self.path)
self._conn.row_factory = sqlite3.Row
self._initialize()
def _initialize(self) -> None:
self._conn.execute(
"""
CREATE TABLE IF NOT EXISTS governance_log (
sequence INTEGER PRIMARY KEY AUTOINCREMENT,
entry_type TEXT NOT NULL,
payload TEXT NOT NULL,
timestamp REAL NOT NULL,
previous_hash TEXT NOT NULL,
entry_hash TEXT NOT NULL,
attestation_measurement TEXT NOT NULL,
attestation_nonce TEXT NOT NULL,
attestation_signature TEXT NOT NULL
)
"""
)
self._conn.commit()
def head_hash(self) -> str:
row = self._conn.execute(
"SELECT entry_hash FROM governance_log ORDER BY sequence DESC LIMIT 1"
).fetchone()
return row["entry_hash"] if row else "GENESIS"
def append(self, entry_type: str, payload: dict[str, Any], timestamp: float, attestation: AttestationReport) -> LedgerRecord:
previous_hash = self.head_hash()
body = _stable_json({
"entry_type": entry_type,
"payload": payload,
"timestamp": timestamp,
"previous_hash": previous_hash,
"measurement": attestation.measurement,
"nonce": attestation.nonce,
"signature": attestation.signature,
})
entry_hash = hashlib.sha256(body.encode("utf-8")).hexdigest()
cursor = self._conn.execute(
"""
INSERT INTO governance_log (
entry_type, payload, timestamp, previous_hash, entry_hash,
attestation_measurement, attestation_nonce, attestation_signature
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""",
(
entry_type,
_stable_json(payload),
timestamp,
previous_hash,
entry_hash,
attestation.measurement,
attestation.nonce,
attestation.signature,
),
)
self._conn.commit()
return LedgerRecord(
sequence=int(cursor.lastrowid or 0),
entry_type=entry_type,
payload=payload,
timestamp=timestamp,
previous_hash=previous_hash,
entry_hash=entry_hash,
attestation_measurement=attestation.measurement,
attestation_nonce=attestation.nonce,
attestation_signature=attestation.signature,
)
def records(self) -> list[LedgerRecord]:
rows = self._conn.execute(
"SELECT * FROM governance_log ORDER BY sequence ASC"
).fetchall()
return [
LedgerRecord(
sequence=row["sequence"],
entry_type=row["entry_type"],
payload=json.loads(row["payload"]),
timestamp=row["timestamp"],
previous_hash=row["previous_hash"],
entry_hash=row["entry_hash"],
attestation_measurement=row["attestation_measurement"],
attestation_nonce=row["attestation_nonce"],
attestation_signature=row["attestation_signature"],
)
for row in rows
]
def verify_chain(self) -> bool:
previous_hash = "GENESIS"
for record in self.records():
body = _stable_json({
"entry_type": record.entry_type,
"payload": record.payload,
"timestamp": record.timestamp,
"previous_hash": record.previous_hash,
"measurement": record.attestation_measurement,
"nonce": record.attestation_nonce,
"signature": record.attestation_signature,
})
entry_hash = hashlib.sha256(body.encode("utf-8")).hexdigest()
if record.previous_hash != previous_hash or record.entry_hash != entry_hash:
return False
previous_hash = record.entry_hash
return True

View File

@ -0,0 +1,76 @@
from __future__ import annotations
from dataclasses import dataclass, field, asdict
from typing import Any, Mapping
@dataclass(frozen=True, slots=True)
class LocalMarket:
venue: str
asset: str
bid: float
ask: float
bid_size: float = 0.0
ask_size: float = 0.0
sequence: int = 0
timestamp: float = 0.0
@property
def mid(self) -> float:
return (self.bid + self.ask) / 2.0
@dataclass(frozen=True, slots=True)
class SharedSignals:
asset: str
mid: float
spread: float
venue_count: int
aggregate_depth: float
privacy_budget_used: int = 0
@dataclass(frozen=True, slots=True)
class PlanDelta:
plan_id: str
asset: str
venue: str
side: str
quantity: float
limit_price: float
rationale: str
sequence: int
@dataclass(frozen=True, slots=True)
class PrivacyBudget:
total_units: int
used_units: int = 0
def consume(self, units: int = 1) -> "PrivacyBudget":
new_used = self.used_units + units
if new_used > self.total_units:
raise ValueError("privacy budget exhausted")
return PrivacyBudget(total_units=self.total_units, used_units=new_used)
@dataclass(frozen=True, slots=True)
class AuditLogEntry:
entry_type: str
payload: Mapping[str, Any]
timestamp: float
previous_hash: str
entry_hash: str
attestation_measurement: str
attestation_nonce: str
attestation_signature: str
def to_record(self) -> dict[str, Any]:
return asdict(self)
@dataclass(frozen=True, slots=True)
class EnclaveDecision:
signals: SharedSignals
plan: PlanDelta
privacy_budget: PrivacyBudget = field(default_factory=lambda: PrivacyBudget(total_units=1))

View File

@ -0,0 +1,74 @@
from __future__ import annotations
import argparse
import json
from dataclasses import asdict
from pathlib import Path
from collections.abc import Mapping
from typing import Iterable, cast
from .adapters import FixAdapter, WebSocketAdapter
from .enclave import SecureEnclave, verify_attestation
from .governance import GovernanceLedger
from .primitives import LocalMarket
def replay_events(events: Iterable[dict[str, object]], *, enclave: SecureEnclave, ledger: GovernanceLedger) -> dict[str, object]:
markets: list[LocalMarket] = []
for event in events:
adapter_type = str(event["adapter"])
venue = str(event["venue"])
message = event["message"]
if adapter_type == "fix":
market = FixAdapter(venue=venue).parse_market(str(message))
elif adapter_type == "ws":
if isinstance(message, (str, Mapping)):
market = WebSocketAdapter(venue=venue).parse_market(
cast(str | Mapping[str, object], message)
)
else:
raise ValueError("ws message must be JSON string or mapping")
else:
raise ValueError(f"unknown adapter: {adapter_type}")
markets.append(market)
decision = enclave.compute(markets)
attestation = enclave.attest(nonce=f"replay-{decision.plan.plan_id}")
ledger.append(
"plan_delta",
{"signals": asdict(decision.signals), "plan": asdict(decision.plan)},
timestamp=float(len(markets)),
attestation=attestation,
)
return {
"signals": asdict(decision.signals),
"plan": asdict(decision.plan),
"attestation_verified": verify_attestation(attestation, enclave.measurement, enclave._secret.decode("utf-8"), enclave.enclave_id),
"ledger_head": ledger.head_hash(),
"ledger_consistent": ledger.verify_chain(),
}
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="Run a deterministic SecureEx replay")
parser.add_argument("--events", required=True, help="Path to JSON event file")
parser.add_argument("--ledger", default=":memory:", help="SQLite ledger path")
parser.add_argument("--enclave-id", default="edge-node-1")
parser.add_argument("--secret", default="secureex-demo-secret")
return parser
def main(argv: list[str] | None = None) -> int:
args = build_parser().parse_args(argv)
payload = json.loads(Path(args.events).read_text())
if not isinstance(payload, list):
raise SystemExit("events file must contain a JSON array")
enclave = SecureEnclave(enclave_id=args.enclave_id, secret=args.secret)
ledger = GovernanceLedger(args.ledger)
result = replay_events(payload, enclave=enclave, ledger=ledger)
print(json.dumps(result, sort_keys=True, indent=2))
return 0
if __name__ == "__main__":
raise SystemExit(main())

7
test.sh Normal file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail
export PYTHONPATH="src"
python3 -m pip install --quiet --upgrade build
python3 -m unittest discover -s tests -v
python3 -m build

58
tests/test_secureex.py Normal file
View File

@ -0,0 +1,58 @@
from __future__ import annotations
import json
import tempfile
import unittest
from pathlib import Path
from idea109_secureex_hardware_accelerated.adapters import FixAdapter, WebSocketAdapter
from idea109_secureex_hardware_accelerated.delta_sync import DeltaSync, reconcile_markets
from idea109_secureex_hardware_accelerated.enclave import SecureEnclave, verify_attestation
from idea109_secureex_hardware_accelerated.governance import GovernanceLedger
class SecureExTests(unittest.TestCase):
def test_adapters_parse_canonical_markets(self) -> None:
fix_market = FixAdapter(venue="VENUE_A").parse_market("35=W|55=ABC|132=10.1|133=10.2|134=100|135=120|34=7|52=1.5")
ws_market = WebSocketAdapter(venue="VENUE_B").parse_market(
{"asset": "ABC", "bid": 10.0, "ask": 10.3, "bid_size": 80, "ask_size": 60, "sequence": 8, "timestamp": 1.7}
)
self.assertEqual(fix_market.asset, "ABC")
self.assertEqual(ws_market.venue, "VENUE_B")
self.assertAlmostEqual(fix_market.mid, 10.15)
def test_enclave_attestation_and_deterministic_decision(self) -> None:
markets = [
FixAdapter(venue="VENUE_A").parse_market("55=ABC|132=10.1|133=10.2|134=100|135=120|34=7|52=1.5"),
WebSocketAdapter(venue="VENUE_B").parse_market("{\"asset\": \"ABC\", \"bid\": 10.0, \"ask\": 10.3, \"bid_size\": 80, \"ask_size\": 60, \"sequence\": 8, \"timestamp\": 1.7}")
]
enclave = SecureEnclave(enclave_id="edge-node-1", secret="demo-secret")
decision1 = enclave.compute(markets)
decision2 = enclave.compute(markets)
self.assertEqual(decision1.plan, decision2.plan)
report = enclave.attest("nonce-1")
self.assertTrue(verify_attestation(report, enclave.measurement, "demo-secret", enclave.enclave_id))
def test_ledger_chain_and_replay(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
ledger = GovernanceLedger(Path(tmp) / "ledger.sqlite3")
enclave = SecureEnclave(enclave_id="edge-node-1", secret="demo-secret")
report = enclave.attest("nonce-2")
ledger.append("plan_delta", {"plan_id": "x"}, 1.0, report)
self.assertTrue(ledger.verify_chain())
sync = DeltaSync()
markets = [
FixAdapter(venue="VENUE_A").parse_market("55=ABC|132=10.1|133=10.2|134=100|135=120|34=7|52=1.5"),
WebSocketAdapter(venue="VENUE_B").parse_market({"asset": "ABC", "bid": 10.0, "ask": 10.3, "sequence": 8}),
]
first = sync.snapshot(markets)
second = sync.snapshot(markets)
self.assertEqual(len(first), 2)
self.assertEqual(second, [])
delta = reconcile_markets(markets, markets[:1])
self.assertEqual(len(delta), 1)
if __name__ == "__main__":
unittest.main()