Implement BAT-006: portfolio-hub ledger integration (REQ-017~019)
- REQ-017: LedgerPort contract (application/ledger_port.py) + portfolio-hub adapter + in-memory stub (adapters/ledger/), TREX_PORTFOLIO_HUB_* config - REQ-018: fill→ledger recording in execution loop; FillStatus carries execution_id (deterministic synth) + fee; paper/kis adapters updated - REQ-019: ledger outbox + retry worker (application/ledger_outbox.py), correlation_id idempotency, outcome vocabulary; 002_create_ledger_outbox.sql - Tests: in-memory/portfolio-hub ledger, execution ledger hook, outbox, domain import sweep Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
"""Static import sweep guarding the pure-domain boundary (REQ-017 AC-4, NFR-1).
|
||||
|
||||
`trex_core.domain` must NOT depend on portfolio-hub, HTTP, ledger adapters,
|
||||
or any other infrastructure module. The sweep walks the source tree of
|
||||
trex_core/domain and inspects every `import` statement.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
from pathlib import Path
|
||||
|
||||
_DOMAIN_ROOT = Path(__file__).resolve().parents[2] / "trex_core" / "domain"
|
||||
|
||||
_FORBIDDEN_PREFIXES = (
|
||||
"httpx",
|
||||
"fastapi",
|
||||
"uvicorn",
|
||||
"psycopg",
|
||||
"redis",
|
||||
"trex_core.adapters", # any adapter (broker, ledger, persistence, api)
|
||||
"trex_core.runtime", # daemon / config
|
||||
"trex_core.application", # ports/services live one layer up
|
||||
)
|
||||
|
||||
|
||||
def _iter_imports(path: Path):
|
||||
tree = ast.parse(path.read_text(), filename=str(path))
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
for alias in node.names:
|
||||
yield alias.name
|
||||
elif isinstance(node, ast.ImportFrom):
|
||||
if node.module:
|
||||
yield node.module
|
||||
|
||||
|
||||
def test_domain_has_no_forbidden_imports():
|
||||
offenders: list[tuple[str, str]] = []
|
||||
for py in _DOMAIN_ROOT.rglob("*.py"):
|
||||
for imp in _iter_imports(py):
|
||||
if any(imp == p or imp.startswith(p + ".") for p in _FORBIDDEN_PREFIXES):
|
||||
offenders.append((str(py.relative_to(_DOMAIN_ROOT.parent.parent)), imp))
|
||||
assert offenders == [], (
|
||||
"trex_core/domain must remain free of adapter/runtime/application imports; "
|
||||
f"found: {offenders}"
|
||||
)
|
||||
Reference in New Issue
Block a user