diff --git a/.hermes/plans/2026-05-12_102100-aitbc-codebase-analysis.md b/.hermes/plans/2026-05-12_102100-aitbc-codebase-analysis.md new file mode 100644 index 00000000..be810eff --- /dev/null +++ b/.hermes/plans/2026-05-12_102100-aitbc-codebase-analysis.md @@ -0,0 +1,411 @@ +# AITBC Codebase Analysis & Recommendations Plan + +**Date:** 2026-05-12 +**Scope:** Full analysis of /opt/aitbc/ -- architecture, performance, security, maintainability +**Codebase Version:** 0.6.0 +**Python:** 3.13.5 + +--- + +## Executive Summary + +AITBC is a large monorepo (~212K LOC Python, 75K LOC Solidity, 75K LOC CLI) implementing a blockchain-based AI agent compute network. The system has strong foundational infrastructure (28 systemd services, PoA consensus, multi-chain support, 20 Solidity contracts) but carries significant technical debt: a bloated coordinator-api (117K LOC, 91 files >500 lines), 925 print() statements in production code, 50 bare except clauses, 41 potentially hardcoded secrets, duplicated config/database modules across apps, and 14.3K LOC of stubs that may be dead code. The core blockchain-node (27K LOC) is well-structured, but the coordinator-api has grown into a monolith that needs decomposition. + +--- + +## 1. Codebase Scale Metrics + +| Component | Files | LOC | Notes | +|-----------|-------|-----|-------| +| **apps/** | 840 | 211,844 | Main application code | +| **cli/** | 232 | 74,805 | Unified CLI tool | +| **aitbc/** (core pkg) | 52 | 11,190 | Shared utilities | +| **packages/py/** | 42 | 5,458 | SDK packages | +| **contracts/** | 490 | 74,589 | Solidity contracts | +| **tests/** | 56 files | ~789 test functions | Good test count | +| **stubs/** | 65 | 14,300 | Placeholder services | +| **systemd/** | 28 | - | Service definitions | + +**App breakdown (largest):** +- `coordinator-api`: 338 files, 116,568 LOC (55% of all app code) +- `blockchain-node`: 127 files, 26,895 LOC +- `zk-circuits`: 52 files, 15,160 LOC +- `stubs`: 65 files, 14,300 LOC +- `pool-hub`: 48 files, 5,461 LOC +- `agent-coordinator`: 45 files, 9,983 LOC +- `exchange`: 19 files, 5,144 LOC +- `wallet`: 27 files, 3,482 LOC + +--- + +## 2. Architecture Analysis + +### 2.1 Current Architecture Pattern + +The codebase follows a **monorepo with per-app packaging** pattern: +- Root `pyproject.toml` at `/opt/aitbc/pyproject.toml` with shared deps +- 15 per-app `pyproject.toml` files for independent packaging +- 28 systemd services for process management +- Core shared library at `/opt/aitbc/aitbc/` (52 files) +- 3 Python packages in `/opt/aitbc/packages/py/` (crypto, sdk, agent-sdk) + +### 2.2 Strengths + +1. **Well-structured blockchain-node**: Clear separation of concerns with `consensus/`, `contracts/`, `network/`, `economics/`, `state/` subdirectories. Largest file is 1,278 lines (RPC router) which is reasonable. +2. **Solid middleware layer**: Core package provides `error_handler`, `performance`, `request_id`, `validation` middleware -- all properly implemented. +3. **Database migration support**: Alembic configs for blockchain-node (7 migrations), coordinator-api (2), pool-hub (5). +4. **Comprehensive infrastructure**: Terraform (15 files), Kubernetes (6 manifests), nginx config, Prometheus dashboards, Gitea CI/CD. +5. **Circuit breaker pattern**: Implemented in PoA consensus for resilience. +6. **Good test infrastructure**: 789 test functions across 56 files, 41 conftest.py files, pytest markers for unit/integration/e2e/slow. + +### 2.3 Architecture Issues + +#### CRITICAL: Coordinator-API Monolith (117K LOC) + +The coordinator-api at 116,568 LOC across 338 files is the single biggest architectural risk: +- **91 files over 500 lines** (27% of all files) +- Largest file: `advanced_reinforcement_learning.py` at 2,000 lines +- Service layer has 99 files + 24 sub-module files = 123 service files +- Router layer has 61 files +- Domain layer has 32 files +- This service alone is 55% of all application code + +**Root cause**: The coordinator-api has accumulated features without decomposition. It handles RL agents, marketplace, trading, certification, compliance, analytics, payments, staking, governance, AMM, AI surveillance, multi-language support, ZK proofs, and more -- all in one deployable unit. + +#### HIGH: Duplicated Cross-App Modules + +Each app independently implements: +- `config.py` in 6 different apps (blockchain-node, coordinator-api, agent-coordinator, blockchain-event-bridge, pool-hub) +- `database.py` in 4 apps (blockchain-node, coordinator-api, exchange, pool-hub) +- No shared database connection pooling across apps + +#### HIGH: Stubs Directory (14.3K LOC of Dead Code?) + +The `apps/stubs/` directory contains 65 files across 68 subdirectories totaling 14,300 LOC. These appear to be placeholder implementations. Including `compliance-service`, `exchange-integration`, `global-ai-agents`, `global-infrastructure`, `multi-region-load-balancer`, `plugin-analytics`, `plugin-marketplace`, `plugin-registry`, `plugin-security`, `simple-explorer`, `trading-engine`. Each has its own tests, suggesting they were meant to be real services but remain as stubs. + +#### MEDIUM: Missing Package Structure + +Only 128 of 1,026 app directories have `__init__.py` files (12.5%). This means most directories are not proper Python packages, which breaks relative imports and makes the codebase harder to navigate programmatically. + +#### MEDIUM: Overlapping Marketplace Services + +Three separate marketplace implementations exist: +- `apps/marketplace` (9 files, 1,762 LOC) -- appears to be the primary marketplace +- `apps/marketplace-service` (10 files, 875 LOC) -- unclear differentiation +- `apps/marketplace-service-debug` (8 files, 821 LOC) -- debug variant + +The relationship and boundary between these three is unclear. + +#### LOW: Coordinator-API Entry Point is a Stub + +`/opt/aitbc/apps/coordinator-api/src/app.py` is a single line: `# Import the FastAPI app from main.py for compatibility`. There is no `main.py` in the same directory -- the actual entry point appears to be elsewhere. + +--- + +## 3. Performance Analysis + +### 3.1 Strengths + +1. **Async-first architecture**: 362 files use `async def`, consistent with FastAPI best practices +2. **FastAPI Depends for DI**: 94 files use FastAPI's dependency injection system +3. **LRU caching implementation**: Core package provides `LRU cache` with hit/miss tracking +4. **Performance middleware**: `PerformanceLoggingMiddleware` tracks request duration and adds `X-Process-Time` headers +5. **Adaptive sync**: Blockchain sync uses tiered batch sizing (10K+ blocks: 500-1000 batch) +6. **Circuit breaker**: PoA consensus implements circuit breaker for fault tolerance + +### 3.2 Performance Issues + +#### HIGH: No Distributed Caching Layer + +Despite Redis being in `pyproject.toml` dependencies, grep found only 21 files mentioning Redis (mostly multi-language services and docs). There is no Redis-based caching layer for: +- API response caching +- Session storage +- Rate limiting state +- Blockchain state caching + +This means every request hits the database directly. + +#### HIGH: No Connection Pooling + +Despite `asyncpg` and `sqlalchemy` with async support being dependencies, there is no visible connection pool configuration across apps. Each app creates its own database connections independently. + +#### HIGH: No Background Task System + +No Celery, RQ, or FastAPI BackgroundTasks usage found outside of 3 files. Long-running operations (blockchain sync, analytics processing, RL training) appear to be handled inline or via systemd timers rather than a proper task queue. + +#### MEDIUM: No API Rate Limiting + +`slowapi` and `limits` are in production dependencies but only found in 3 files in coordinator-api routers. Most endpoints have no rate limiting. + +#### MEDIUM: No Request Batching + +The coordinator-api receives requests for 61 different router domains but implements no request batching for high-throughput operations like marketplace queries or analytics. + +#### LOW: Logging Performance + +The `PerformanceLoggingMiddleware` logs every request synchronously with `logger.info()`. At high throughput, this creates I/O bottlenecks. Should use `logger.debug()` or sampling. + +--- + +## 4. Security Analysis + +### 4.1 Strengths + +1. **Security hardening module**: `aitbc/security_hardening.py` (396 lines) provides input validation, sanitization, ethereum address validation, URL validation, email validation +2. **JWT infrastructure**: 30 files reference JWT authentication +3. **CORS configuration**: 23 files configure CORS policies +4. **HTTPS enforcement**: Security headers module (`aitbc/security_headers.py`) present +5. **Encryption at rest**: `database_encryption.py` in blockchain-node provides SQLCipher support +6. **Multi-sig wallets**: Mentioned in README as implemented +7. **Audit logging**: `audit_logging.py` service in coordinator-api (584 lines) +8. **Dev dependencies**: `bandit` (security linter) and `safety` (dependency vulnerability scanner) configured +9. **Pre-commit hooks**: `.pre-commit-config.yaml` configured +10. **Error handler middleware**: Properly returns generic 500 messages without leaking internals + +### 4.2 Security Issues + +#### CRITICAL: Potentially Hardcoded Secrets (41 instances) + +41 files contain patterns matching potential hardcoded secrets, API keys, or tokens: +- `coordinator-api/.../cross_chain_integration.py:191`: `private_key = "mock_private_key"` +- `coordinator-api/.../wallet_service.py:72`: `encrypted_private_key = "[ENCRYPTED_MOCK]"` +- Multiple test files with `api_key="test_key"` patterns + +While some are test files, production code also contains these patterns. Need audit to distinguish real secrets from test fixtures. + +#### HIGH: 50 Bare Except Clauses + +50 instances of bare `except:` in production code across: +- coordinator-api: 44 instances +- exchange: 1 instance +- Others: 5 instances + +Bare excepts catch `SystemExit`, `KeyboardInterrupt`, and `GeneratorExit`, making the application unkillable in some error scenarios and hiding real errors. + +#### HIGH: SQL Injection Risks (21 instances) + +21 files use f-strings in SQL execute statements: +- `multichain_ledger.py:98,110,123`: `cursor.execute(f"""...`) with table name interpolation +- Various migration scripts using `f"SELECT * FROM {table_name}"` + +While some are internal migration scripts, the `multichain_ledger.py` pattern is dangerous if table names come from user input. + +#### HIGH: Insufficient Rate Limiting + +Only 3 coordinator-api routers implement rate limiting. The remaining 58+ routers have no protection against: +- Brute force authentication attempts +- API abuse +- DDoS at the application layer + +#### MEDIUM: Feature Flags Not Utilized + +`/opt/aitbc/feature_flags.json` is an empty object `{}`. Despite having `aitbc/feature_flags.py` (a feature flag system), no features are actually flagged. This means: +- No gradual rollout capability +- No kill switches for problematic features +- No A/B testing infrastructure + +#### MEDIUM: CORS Configuration Cents + +23 files configure CORS but the configuration is scattered and inconsistent. No centralized CORS policy management. + +#### MEDIUM: Dependency Vulnerability Scanning Not Enforced + +While `safety` and `bandit` are in dev dependencies and pre-commit config, there is no evidence of CI/CD pipeline enforcement of security scanning. The Gitea workflows reference "security scanning optimized for changed files" but this should be comprehensive. + +#### LOW: Debug Mode References + +Several debug patterns found: +- `marketplace-service-debug` app (8 files) appears to be a debug variant +- `mock_coordinator.py` in blockchain-node observability + +--- + +## 5. Maintainability Analysis + +### 5.1 Strengths + +1. **Comprehensive documentation**: Full docs directory with architecture, deployment, security, and operations guides +2. **Standardized quality tools**: ruff (line length 127), mypy (relaxed mode for gradual adoption), black, isort, pre-commit +3. **Good test coverage infrastructure**: 789 test functions, pytest with coverage (50% minimum threshold), markers for test types +4. **API versioning**: `aitbc/api_versioning.py` provides API versioning support +5. **Distributed tracing**: `aitbc/distributed_tracing.py` exists for observability +6. **Blue-green deployment**: `aitbc/blue_green_deployment.py` for zero-downtime deploys +7. **Domain-driven design**: coordinator-api uses `domain/` subdirectory with bounded contexts +8. **Repository pattern**: coordinator-api has `repositories/` directory +9. **Skills documentation**: 8 operational skills docs for agents + +### 5.2 Maintainability Issues + +#### CRITICAL: 925 print() Statements in Production Code + +925 instances of `print()` in `/opt/aitbc/apps/` and `/opt/aitbc/packages/`. This is the most impactful maintainability issue: +- Prints bypass structured logging, making log aggregation impossible +- Prints cannot be filtered by severity level +- Prints go to stdout, not to configured log handlers +- In async code, prints can interleave unpredictably + +Most concentrated in: +- `agent-coordinator/src/coordinator.py` (many debug prints) +- `agent-compliance/src/compliance_agent.py` +- `blockchain-node/scripts/` (expected for scripts, but still 925 total) + +#### HIGH: 65 Stub Services (14.3K LOC) + +The `apps/stubs/` directory is a significant maintenance burden: +- Each stub has its own tests (increasing test suite time) +- Each stub has its own `pyproject.toml` (15 total per-app pyproject files) +- Creates confusion about which services are real vs. placeholders +- Must be maintained/skipped during CI/CD runs + +#### HIGH: Massive Service File Sizes + +The coordinator-api service layer has extreme file sizes: +- 2,000 lines: `advanced_reinforcement_learning.py` +- 1,368 lines: `certification_service.py` +- 1,324 lines: `multi_modal_fusion.py` +- 1,159 lines: `agent_integration.py` +- 1,127 lines: `enterprise_integration.py` +- 10 more files over 800 lines + +Single-responsibility principle is clearly violated. + +#### MEDIUM: Type Coverage Gaps + +While mypy is configured, it runs in very permissive mode: +- `check_untyped_defs = false` +- `disallow_intyped_defs = false` +- `disallow_untyped_defs = false` +- `no_implicit_optional = false` + +9 generator overrides exist that completely ignore errors in coordinator-api modules: +```python +[[tool.mypy.overrides]] +module = ["apps.coordinator-api.src.app.routers.*", ...] +ignore_errors = true +``` + +#### MEDIUM: Cross-App Module Duplication + +The same concerns are implemented independently across apps: +- **Config management**: 6 separate `config.py` files with no shared base +- **Database**: 4 separate `database.py` files +- **Validation**: Separate validation in each app + +The core `aitbc/` package provides utilities but apps don't consistently use them. + +#### MEDIUM: Per-App pyproject.toml Proliferation + +15 per-app `pyproject.toml` files create: +- Dependency version drift across apps +- Inconsistent linting/formatting rules +- Complex CI/CD matrix +- Harder to maintain security patches across all packages + +#### LOW: 25 Uncommitted Changes + +Repository has 25 uncommitted changes, indicating active development without proper commit hygiene. This makes it harder to track what changes are in production. + +#### LOW: TODO/FIXME/HACK Count is Zero + +While the analysis found 0 TODO/FIXME/HACK/XXX/BUG comments, this likely indicates these markers are not used rather than the absence of known issues. This is a maintainability concern because there's no in-code tracking of technical debt. + +--- + +## 6. Recommendations by Time Horizon + +### SHORT-TERM (0-2 weeks) -- Quick Wins + +| # | Recommendation | Effort | Impact | File(s) | +|---|---------------|--------|--------|---------| +| S1 | **Replace all print() with logger**: Run automated refactoring to replace `print()` with `logger.debug/info` across all production code. Use `sed`/`ruff` automated fix. | Low | Critical | All 925 instances | +| S2 | **Fix bare except clauses**: Replace `except:` with `except Exception:` at minimum. Prefer specific exceptions. | Low | High | 50 locations | +| S3 | **Remove or isolate stubs**: Move `apps/stubs/` to a separate repo or mark clearly as `examples/`. Remove from main test suite and CI/CD. | Low | Medium | `/opt/aitbc/apps/stubs/` | +| S4 | **Add `.coveragerc` or omit stubs from coverage**: Prevent stub code from diluting coverage metrics. | Low | Low | `pyproject.toml` | +| S5 | **Unify CORS configuration**: Create a single CORS policy in core `aitbc/` package, reference from all apps. | Low | Medium | 23 files | +| S6 | **Audit hardcoded secrets**: Review all 41 instances, move real secrets to environment variables/vault. | Medium | Critical | 41 locations | +| S7 | **Fix SQL injection risks**: Use parameterized queries in `multichain_ledger.py` and migration scripts. | Medium | High | 21 locations | + +### MEDIUM-TERM (2-6 weeks) -- Structural Improvements + +| # | Recommendation | Effort | Impact | File(s) | +|---|---------------|--------|--------|---------| +| M1 | **Decompose coordinator-api**: Split into bounded-context services: `rl-service`, `marketplace-router`, `analytics-service`, `certification-service`, `compliance-service`. Each gets its own deployable unit. | High | Critical | 338 files | +| M2 | **Implement shared config base class**: Create `aitbc.config.BaseSettings` that all apps inherit from, with common patterns for env var loading, secrets management, and validation. | Medium | High | 6 config files | +| M3 | **Add connection pool management**: Implement shared `aitbc.database.ConnectionPool` using `asyncpg` or SQLAlchemy async pool. All apps use the pool instead of creating independent connections. | Medium | High | 4 database files | +| M4 | **Implement distributed caching**: Deploy Redis cluster, add caching layer to coordinator-api for: API responses, session state, rate limiting counters, blockchain state reads. | Medium | High | `aitbc/caching.py` expansion | +| M5 | **Add rate limiting to all routers**: Apply `slowapi` limits to all 61 coordinator-api routers with tiered limits by endpoint sensitivity. | Medium | High | 61 router files | +| M6 | **Tighten mypy configuration**: Enable `check_untyped_defs`, `disallow_untyped_defs` incrementally. Remove `ignore_errors = true` overrides. Start with blockchain-node (best structured). | Medium | Medium | `pyproject.toml` | +| M7 | **Consolidate marketplace services**: Clarify boundaries between `marketplace`, `marketplace-service`, and `marketplace-service-debug`. Merge or clearly document the purpose of each. | Medium | Medium | 3 marketplace dirs | +| M8 | **Add background task system**: Implement Celery or ARQ for long-running tasks: RL training, analytics aggregation, blockchain event processing. | Medium | High | New infrastructure | + +### LONG-TERM (1-3 months) -- Strategic Improvements + +| # | Recommendation | Effort | Impact | File(s) | +|---|---------------|--------|--------|---------| +| L1 | **Implement API gateway pattern**: The `apps/api-gateway` (4 files, 425 LOC) should become the single entry point handling auth, rate limiting, routing, and load balancing for all backend services. | High | Critical | `apps/api-gateway/` | +| L2 | **Adopt event-driven architecture**: Implement message bus (Redis Streams, RabbitMQ, or NATS) for inter-service communication. Replace direct service-to-service calls with events. | High | High | Cross-cutting | +| L3 | **Implement feature flag system**: Populate `feature_flags.json` with actual flags. Use `aitbc/feature_flags.py` for gradual rollouts of: new RL algorithms, marketplace features, pricing changes. | Medium | Medium | `feature_flags.json` | +| L4 | **Add comprehensive observability**: Implement distributed tracing (OpenTelemetry), structured logging (structlog is already a dep), and metrics (Prometheus client is already a dep) across all services. | High | High | Cross-cutting | +| L5 | **Create shared test fixtures**: Extract common test setup into `packages/py/aitbc-test-utils/` with shared fixtures, factories, and mocks. Reduce duplication across 41 conftest.py files. | Medium | Medium | `tests/` | +| L6 | **Implement contract upgrade pattern**: Review Solidity contracts for proxy pattern usage. 20 contracts with no visible upgrade mechanism is a long-term risk. | High | Medium | `contracts/` | +| L7 | **Documentation-as-code**: Move operational runbooks from docs/ into executable skills. The 8 existing skills docs are a good start but should be executable. | Medium | Low | `docs/skills/` | + +--- + +## 7. Risk Matrix + +| Issue | Severity | Likelihood | Risk Score | Time to Fix | +|-------|----------|------------|------------|-------------| +| Coordinator-api monolith | High | High (growing) | **Critical** | 4-8 weeks | +| Hardcoded secrets | Critical | Medium | **Critical** | 1-2 weeks | +| print() in production | Medium | High (growing) | **High** | 1 week | +| Bare except clauses | High | Medium | **High** | 1 week | +| No rate limiting | High | Medium | **High** | 2-3 weeks | +| SQL injection risks | Critical | Low (internal) | **High** | 1-2 weeks | +| No connection pooling | Medium | High | **Medium** | 2-3 weeks | +| No distributed caching | Medium | High | **Medium** | 3-4 weeks | +| Stub code in main repo | Low | Low | **Low** | 1 week | +| Type coverage gaps | Medium | Medium | **Medium** | 4-6 weeks | + +--- + +## 8. Files Most Likely to Change + +Based on the analysis, these files/directories will be most impacted by the recommendations: + +1. `/opt/aitbc/apps/coordinator-api/src/app/services/` -- Decomposition target (123 files) +2. `/opt/aitbc/apps/coordinator-api/src/app/routers/` -- Rate limiting, CORS (61 files) +3. `/opt/aitbc/apps/coordinator-api/src/app/config.py` -- Shared config base +4. `/opt/aitbc/apps/coordinator-api/src/app/database.py` -- Connection pooling +5. `/opt/aitbc/aitbc/caching.py` -- Distributed caching expansion +6. `/opt/aitbc/aitbc/middleware/` -- CORS unification +7. `/opt/aitbc/apps/stubs/` -- Removal/isolation +8. `/opt/aitbc/pyproject.toml` -- mypy tightening, coverage config +9. `/opt/aitbc/apps/wallet/src/app/chain/multichain_ledger.py` -- SQL injection fix +10. `/opt/aitbc/apps/agent-coordinator/src/coordinator.py` -- print() removal + +--- + +## 9. Verification Steps + +After implementing recommendations, verify with: + +1. **print() elimination**: `grep -rn "print(" apps/ packages/ | grep -v "node_modules" | grep -v "__pycache__" | wc -l` should return 0 +2. **Bare except elimination**: `grep -rn "^\s*except\s*:" apps/ packages/ | wc -l` should return 0 +3. **Test suite**: `pytest --cov=apps --cov=packages --cov=cli --cov-fail-under=50` should pass +4. **Security scan**: `bandit -r apps/ packages/ cli/` should return 0 issues +5. **Type check**: `mypy apps/ packages/ cli/` should pass with tightened config +6. **Rate limiting**: `curl -s -o /dev/null -w "%{http_code}" http://localhost:9001/api/...` repeated rapidly should return 429 +7. **Health checks**: All 28 systemd services should report `active (running)` and `/health` endpoints should return 200 + +--- + +## 10. Open Questions + +1. **Stubs purpose**: Are the 65 stub files in `apps/stubs/` planned for implementation, or should they be archived? Who owns the decision? +2. **Coordinator-api decomposition**: What is the preferred decomposition strategy -- by domain (RL, marketplace, analytics) or by function (read vs write)? +3. **Redis deployment**: Is there an existing Redis cluster, or does one need to be provisioned? +4. **Background task system**: Is there a preference between Celery, ARQ, or FastAPI BackgroundTasks for the task queue? +5. **Contract upgrade strategy**: Are the Solidity contracts expected to be upgradeable, or is immutability intentional? +6. **Marketplace service boundary**: What is the intended relationship between `marketplace`, `marketplace-service`, and `marketplace-service-debug`? +7. **Feature flag ownership**: Who manages the feature flag lifecycle -- product or engineering? diff --git a/aitbc/__init__.py b/aitbc/__init__.py index 7af6d7ab..a4b50804 100644 --- a/aitbc/__init__.py +++ b/aitbc/__init__.py @@ -21,6 +21,7 @@ from .constants import ( LOG_DIR, MARKETPLACE_DATA_DIR, MARKETPLACE_PORT, + PACKAGE_VERSION, NODE_ENV_FILE, REPO_DIR, ) diff --git a/apps/blockchain-node/src/aitbc_chain/rpc/router.py b/apps/blockchain-node/src/aitbc_chain/rpc/router.py index 48f4205c..135f7114 100755 --- a/apps/blockchain-node/src/aitbc_chain/rpc/router.py +++ b/apps/blockchain-node/src/aitbc_chain/rpc/router.py @@ -792,6 +792,12 @@ async def import_block(block_data: dict) -> Dict[str, Any]: _last_import_time = time.time() chain_id = block_data.get("chain_id") or block_data.get("chainId") or get_chain_id(None) + block_hash = block_data["hash"] + + try: + block_height = int(block_data["height"]) + except (KeyError, TypeError, ValueError) as exc: + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid block height") from exc timestamp = block_data.get("timestamp") if isinstance(timestamp, str): @@ -803,8 +809,25 @@ async def import_block(block_data: dict) -> Dict[str, Any]: timestamp = datetime.now(timezone.utc) with session_scope(chain_id) as session: + existing_height_block = session.exec( + select(Block) + .where(Block.chain_id == chain_id) + .where(Block.height == block_height) + ).first() + if existing_height_block is not None: + if existing_height_block.hash == block_hash: + return { + "success": True, + "block_height": existing_height_block.height, + "block_hash": existing_height_block.hash, + "chain_id": chain_id + } + raise HTTPException( + status_code=status.HTTP_409_CONFLICT, + detail=f"Block height {block_height} already exists with different hash", + ) + # Check for hash conflicts across chains - block_hash = block_data["hash"] existing_block = session.execute( select(Block).where(Block.hash == block_hash) ).first() @@ -818,7 +841,7 @@ async def import_block(block_data: dict) -> Dict[str, Any]: # Create block block = Block( chain_id=chain_id, - height=block_data["height"], + height=block_height, hash=block_hash, parent_hash=block_data["parent_hash"], proposer=block_data["proposer"], @@ -835,6 +858,8 @@ async def import_block(block_data: dict) -> Dict[str, Any]: "block_hash": block.hash, "chain_id": chain_id } + except HTTPException: + raise except Exception as e: _logger.error(f"Error importing block: {e}") raise HTTPException(status_code=500, detail=f"Failed to import block: {str(e)}") diff --git a/apps/coordinator-api/src/app/routers/certification.py b/apps/coordinator-api/src/app/routers/certification.py index f1c68395..083b0b2b 100755 --- a/apps/coordinator-api/src/app/routers/certification.py +++ b/apps/coordinator-api/src/app/routers/certification.py @@ -31,7 +31,7 @@ from ..domain.certification import ( VerificationRecord, VerificationType, ) -from ..services.certification_service import ( +from ..services.certification import ( BadgeSystem, CertificationAndPartnershipService, CertificationSystem, @@ -74,6 +74,17 @@ class PartnershipApplicationRequest(BaseModel): application_data: Dict[str, Any] = Field(default_factory=dict, description="Application data") +class PartnershipProgramRequest(BaseModel): + """Request model for partnership program creation""" + program_name: str + program_type: PartnershipType + description: str + created_by: str + tier_levels: List[str] = Field(default_factory=lambda: ["basic", "premium"]) + max_participants: Optional[int] = Field(default=None, description="Maximum participants") + launch_immediately: bool = Field(default=False, description="Launch program immediately") + + class PartnershipResponse(BaseModel): """Response model for partnership""" partnership_id: str @@ -251,13 +262,7 @@ async def get_agent_certifications( @router.post("/partnerships/programs") async def create_partnership_program( - program_name: str, - program_type: PartnershipType, - description: str, - created_by: str, - tier_levels: List[str] = Field(default_factory=lambda: ["basic", "premium"]), - max_participants: Optional[int] = Field(default=None, description="Maximum participants"), - launch_immediately: bool = Field(default=False, description="Launch program immediately"), + request: PartnershipProgramRequest, session: Session = Depends(get_session) ) -> Dict[str, Any]: """Create a new partnership program""" @@ -267,13 +272,13 @@ async def create_partnership_program( try: program = await partnership_manager.create_partnership_program( session=session, - program_name=program_name, - program_type=program_type, - description=description, - created_by=created_by, - tier_levels=tier_levels, - max_participants=max_participants, - launch_immediately=launch_immediately + program_name=request.program_name, + program_type=request.program_type, + description=request.description, + created_by=request.created_by, + tier_levels=request.tier_levels, + max_participants=request.max_participants, + launch_immediately=request.launch_immediately ) return { diff --git a/apps/coordinator-api/src/app/services/advanced_ai_service.py b/apps/coordinator-api/src/app/services/advanced_ai_service.py index 59c64dd8..5826797b 100755 --- a/apps/coordinator-api/src/app/services/advanced_ai_service.py +++ b/apps/coordinator-api/src/app/services/advanced_ai_service.py @@ -14,15 +14,15 @@ import numpy as np import torch from fastapi import BackgroundTasks, FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware -from pydantic import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from aitbc import get_logger logger = get_logger(__name__) from .advanced_learning import AdvancedLearningService -from .advanced_reinforcement_learning import AdvancedReinforcementLearningEngine from .gpu_multimodal import GPUAcceleratedMultiModal +from .advanced_rl import AdvancedReinforcementLearningEngine from .multi_modal_fusion import MultiModalFusionEngine @@ -42,6 +42,8 @@ class MultiModalFusionRequest(BaseModel): class GPUOptimizationRequest(BaseModel): + model_config = ConfigDict(arbitrary_types_allowed=True) + modality_features: dict[str, np.ndarray] = Field(..., description="Features for each modality") attention_config: dict[str, Any] | None = Field(default=None, description="Attention configuration") @@ -81,7 +83,7 @@ app.add_middleware( # Service instances rl_engine = AdvancedReinforcementLearningEngine() fusion_engine = MultiModalFusionEngine() -advanced_learning = AdvancedLearningService() +advanced_learning = AdvancedLearningService({}) @app.on_event("startup") diff --git a/apps/coordinator-api/src/app/services/advanced_rl/__init__.py b/apps/coordinator-api/src/app/services/advanced_rl/__init__.py index 6b96fa27..766fa184 100644 --- a/apps/coordinator-api/src/app/services/advanced_rl/__init__.py +++ b/apps/coordinator-api/src/app/services/advanced_rl/__init__.py @@ -5,12 +5,20 @@ Service facade for backward compatibility with the original monolithic file This module provides a modular structure for RL algorithms: - agents/: Neural network agent implementations (PPO, SAC, Rainbow DQN) - engine.py: Main AdvancedReinforcementLearningEngine class +- marketplace_optimizer.py: Strategy optimization facade - algorithms/: Algorithm-specific implementations (future enhancement) The original advanced_reinforcement_learning.py has been deprecated in favor of this modular structure. """ from .engine import AdvancedReinforcementLearningEngine +from .marketplace_optimizer import MarketplaceStrategyOptimizer from .agents import PPOAgent, SACAgent, RainbowDQNAgent -__all__ = ['AdvancedReinforcementLearningEngine', 'PPOAgent', 'SACAgent', 'RainbowDQNAgent'] +__all__ = [ + 'AdvancedReinforcementLearningEngine', + 'MarketplaceStrategyOptimizer', + 'PPOAgent', + 'SACAgent', + 'RainbowDQNAgent', +] diff --git a/apps/coordinator-api/src/app/services/advanced_rl/agents.py b/apps/coordinator-api/src/app/services/advanced_rl/agents.py new file mode 100644 index 00000000..65eaafb3 --- /dev/null +++ b/apps/coordinator-api/src/app/services/advanced_rl/agents.py @@ -0,0 +1,102 @@ +""" +Reinforcement Learning Agent Models +PyTorch neural network models for various RL algorithms +""" + +import torch +import torch.nn as nn + + +class PPOAgent(nn.Module): + """Proximal Policy Optimization Agent""" + + def __init__(self, state_dim: int, action_dim: int, hidden_dim: int = 256): + super().__init__() + self.actor = nn.Sequential( + nn.Linear(state_dim, hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, action_dim), + nn.Softmax(dim=-1), + ) + self.critic = nn.Sequential( + nn.Linear(state_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, 1) + ) + + def forward(self, state): + action_probs = self.actor(state) + value = self.critic(state) + return action_probs, value + + +class SACAgent(nn.Module): + """Soft Actor-Critic Agent""" + + def __init__(self, state_dim: int, action_dim: int, hidden_dim: int = 256): + super().__init__() + self.actor_mean = nn.Sequential( + nn.Linear(state_dim, hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, action_dim), + ) + self.actor_log_std = nn.Parameter(torch.zeros(1, action_dim)) + + self.qf1 = nn.Sequential( + nn.Linear(state_dim + action_dim, hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, 1), + ) + + self.qf2 = nn.Sequential( + nn.Linear(state_dim + action_dim, hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, 1), + ) + + def forward(self, state): + mean = self.actor_mean(state) + std = torch.exp(self.actor_log_std) + return mean, std + + +class RainbowDQNAgent(nn.Module): + """Rainbow DQN Agent with multiple improvements""" + + def __init__(self, state_dim: int, action_dim: int, hidden_dim: int = 512, num_atoms: int = 51): + super().__init__() + self.num_atoms = num_atoms + self.action_dim = action_dim + + # Feature extractor + self.feature_layer = nn.Sequential( + nn.Linear(state_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), nn.ReLU() + ) + + # Dueling network architecture + self.value_stream = nn.Sequential( + nn.Linear(hidden_dim, hidden_dim // 2), nn.ReLU(), nn.Linear(hidden_dim // 2, num_atoms) + ) + + self.advantage_stream = nn.Sequential( + nn.Linear(hidden_dim, hidden_dim // 2), nn.ReLU(), nn.Linear(hidden_dim // 2, action_dim * num_atoms) + ) + + def forward(self, state): + features = self.feature_layer(state) + values = self.value_stream(features) + advantages = self.advantage_stream(features) + + # Reshape for distributional RL + advantages = advantages.view(-1, self.action_dim, self.num_atoms) + values = values.view(-1, 1, self.num_atoms) + + # Dueling architecture + q_atoms = values + advantages - advantages.mean(dim=1, keepdim=True) + return q_atoms diff --git a/apps/coordinator-api/src/app/services/advanced_rl/marketplace_optimizer.py b/apps/coordinator-api/src/app/services/advanced_rl/marketplace_optimizer.py new file mode 100644 index 00000000..9fc1d284 --- /dev/null +++ b/apps/coordinator-api/src/app/services/advanced_rl/marketplace_optimizer.py @@ -0,0 +1,164 @@ +""" +Marketplace Strategy Optimizer +Advanced marketplace strategy optimization using RL +""" + +import asyncio +from datetime import datetime, timezone +from typing import Any + +import numpy as np + +from aitbc import get_logger + +logger = get_logger(__name__) + +from sqlmodel import Session, select + +from ...domain.agent_performance import ReinforcementLearningConfig +from .engine import AdvancedReinforcementLearningEngine + + +class MarketplaceStrategyOptimizer: + """Advanced marketplace strategy optimization using RL""" + + def __init__(self): + self.rl_engine = AdvancedReinforcementLearningEngine() + self.strategy_types = { + "pricing_strategy": "price_optimization", + "trading_strategy": "marketplace_trading", + "resource_strategy": "resource_allocation", + "service_strategy": "service_selection", + "negotiation_strategy": "negotiation_strategy", + "portfolio_strategy": "portfolio_management", + } + + async def optimize_agent_strategy( + self, session: Session, agent_id: str, strategy_type: str, algorithm: str = "ppo", training_episodes: int = 500 + ) -> dict[str, Any]: + """Optimize agent strategy using RL""" + + # Get environment type for strategy + environment_type = self.strategy_types.get(strategy_type, "marketplace_trading") + + # Create RL agent + rl_config = await self.rl_engine.create_rl_agent( + session=session, + agent_id=agent_id, + environment_type=environment_type, + algorithm=algorithm, + training_config={"max_episodes": training_episodes}, + ) + + # Wait for training to complete + await asyncio.sleep(1) # Simulate training time + + # Get trained agent performance + trained_config = session.execute( + select(ReinforcementLearningConfig).where(ReinforcementLearningConfig.config_id == rl_config.config_id) + ).first() + + if trained_config and trained_config.status == "ready": + return { + "success": True, + "config_id": trained_config.config_id, + "strategy_type": strategy_type, + "algorithm": algorithm, + "final_performance": np.mean(trained_config.reward_history[-10:]) if trained_config.reward_history else 0.0, + "convergence_episode": trained_config.convergence_episode, + "training_episodes": len(trained_config.reward_history), + "success_rate": ( + np.mean(trained_config.success_rate_history[-10:]) if trained_config.success_rate_history else 0.0 + ), + } + else: + return {"success": False, "error": "Training failed or incomplete"} + + async def deploy_strategy(self, session: Session, config_id: str, deployment_context: dict[str, Any]) -> dict[str, Any]: + """Deploy trained strategy""" + + rl_config = session.execute( + select(ReinforcementLearningConfig).where(ReinforcementLearningConfig.config_id == config_id) + ).first() + + if not rl_config: + raise ValueError(f"RL config {config_id} not found") + + if rl_config.status != "ready": + raise ValueError(f"Strategy {config_id} is not ready for deployment") + + try: + # Update deployment performance + deployment_performance = self.simulate_deployment_performance(rl_config, deployment_context) + + rl_config.deployment_performance = deployment_performance + rl_config.deployment_count += 1 + rl_config.status = "deployed" + rl_config.deployed_at = datetime.now(timezone.utc) + + session.commit() + + return { + "success": True, + "config_id": config_id, + "deployment_performance": deployment_performance, + "deployed_at": rl_config.deployed_at.isoformat(), + } + + except Exception as e: + logger.error("Error deploying strategy: %s", e) + raise + + def simulate_deployment_performance( + self, rl_config: ReinforcementLearningConfig, context: dict[str, Any] + ) -> dict[str, float]: + """Simulate deployment performance""" + + # Simplified performance simulation + base_performance = np.mean(rl_config.reward_history[-10:]) if rl_config.reward_history else 0.5 + + # Adjust based on context + market_conditions = context.get("market_conditions", "normal") + if market_conditions == "bull": + multiplier = 1.2 + elif market_conditions == "bear": + multiplier = 0.8 + else: + multiplier = 1.0 + + deployment_performance = { + "expected_return": base_performance * multiplier, + "risk_score": np.random.random() * 0.3, + "stability_score": np.random.random() * 0.7 + 0.3, + "adaptability_score": np.random.random() * 0.5 + 0.5, + } + + return deployment_performance + + async def evaluate_strategy_performance( + self, session: Session, config_id: str, evaluation_period: int = 7 + ) -> dict[str, Any]: + """Evaluate deployed strategy performance""" + + rl_config = session.execute( + select(ReinforcementLearningConfig).where(ReinforcementLearningConfig.config_id == config_id) + ).first() + + if not rl_config: + raise ValueError(f"RL config {config_id} not found") + + if rl_config.status != "deployed": + raise ValueError(f"Strategy {config_id} is not deployed") + + # Simulate evaluation metrics + evaluation_metrics = { + "config_id": config_id, + "evaluation_period_days": evaluation_period, + "total_transactions": np.random.randint(100, 1000), + "success_rate": np.random.random() * 0.3 + 0.7, + "average_profit": np.random.random() * 100, + "market_share_change": np.random.random() * 0.2 - 0.1, + "deployment_age_days": (datetime.now(timezone.utc) - rl_config.deployed_at).days if rl_config.deployed_at else 0, + } + + return evaluation_metrics diff --git a/apps/coordinator-api/src/app/services/certification/service.py b/apps/coordinator-api/src/app/services/certification/service.py index ca96ba02..ca84de01 100644 --- a/apps/coordinator-api/src/app/services/certification/service.py +++ b/apps/coordinator-api/src/app/services/certification/service.py @@ -3,9 +3,18 @@ Certification and Partnership Service - Main service facade Combines certification, partnership, and badge systems """ +from typing import Any + from sqlmodel import Session, select -from ...domain.certification import AgentBadge, AgentCertification, AgentPartnership, AchievementBadge, CertificationStatus +from ...domain.certification import ( + AgentBadge, + AgentCertification, + AgentPartnership, + AchievementBadge, + CertificationStatus, + VerificationRecord, +) from .certification_system import CertificationSystem from .partnership_manager import PartnershipManager from .badge_system import BadgeSystem diff --git a/apps/stubs/ai-service/src/ai_service/main.py b/apps/stubs/ai-service/src/ai_service/main.py index 95f8a3a3..0f116f12 100644 --- a/apps/stubs/ai-service/src/ai_service/main.py +++ b/apps/stubs/ai-service/src/ai_service/main.py @@ -2,6 +2,7 @@ from __future__ import annotations +import os import logging from datetime import datetime, timezone from typing import Annotated @@ -403,4 +404,4 @@ async def optimization_health() -> dict[str, Any]: if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8106) + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8106) diff --git a/apps/stubs/compliance-service/main.py b/apps/stubs/compliance-service/main.py index e5d46172..d9a12d06 100755 --- a/apps/stubs/compliance-service/main.py +++ b/apps/stubs/compliance-service/main.py @@ -3,6 +3,7 @@ Production Compliance Service for AITBC Handles KYC/AML, regulatory compliance, and monitoring """ +import os import asyncio import json from datetime import datetime, timezone, timedelta @@ -430,4 +431,4 @@ async def periodic_compliance_checks(): if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8011, log_level="info") + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8011, log_level="info") diff --git a/apps/stubs/exchange-integration/main.py b/apps/stubs/exchange-integration/main.py index d0e217ff..cd19b658 100755 --- a/apps/stubs/exchange-integration/main.py +++ b/apps/stubs/exchange-integration/main.py @@ -3,6 +3,7 @@ Production Exchange API Integration Service Handles real exchange connections and trading operations """ +import os import asyncio import json from datetime import datetime, timezone @@ -320,4 +321,4 @@ async def shutdown_event(): if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8010, log_level="info") + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8010, log_level="info") diff --git a/apps/stubs/global-ai-agents/main.py b/apps/stubs/global-ai-agents/main.py index a45747c5..017fd76b 100755 --- a/apps/stubs/global-ai-agents/main.py +++ b/apps/stubs/global-ai-agents/main.py @@ -3,6 +3,7 @@ Global AI Agent Communication Service for AITBC Handles cross-chain and cross-region AI agent communication with global optimization """ +import os import asyncio import json from datetime import datetime, timezone, timedelta @@ -658,4 +659,4 @@ async def shutdown_event(): if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8018, log_level="info") + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8018, log_level="info") diff --git a/apps/stubs/global-infrastructure/main.py b/apps/stubs/global-infrastructure/main.py index 32df53dd..1aa4eaaf 100755 --- a/apps/stubs/global-infrastructure/main.py +++ b/apps/stubs/global-infrastructure/main.py @@ -3,6 +3,7 @@ Global Infrastructure Deployment Service for AITBC Handles multi-region deployment, load balancing, and global optimization """ +import os import asyncio import json from datetime import datetime, timezone, timedelta @@ -598,4 +599,4 @@ async def shutdown_event(): if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8017, log_level="info") + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8017, log_level="info") diff --git a/apps/stubs/hermes-service/src/hermes_service/main.py b/apps/stubs/hermes-service/src/hermes_service/main.py index 2ff0bfbf..215c5dcf 100644 --- a/apps/stubs/hermes-service/src/hermes_service/main.py +++ b/apps/stubs/hermes-service/src/hermes_service/main.py @@ -2,6 +2,7 @@ from __future__ import annotations +import os import logging from typing import Any @@ -118,4 +119,4 @@ async def develop_hermes_ecosystem(request: dict[str, Any]) -> dict[str, Any]: if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8108) + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8108) diff --git a/apps/stubs/monitoring-service/src/monitoring_service/main.py b/apps/stubs/monitoring-service/src/monitoring_service/main.py index df7d1f59..77028e3e 100644 --- a/apps/stubs/monitoring-service/src/monitoring_service/main.py +++ b/apps/stubs/monitoring-service/src/monitoring_service/main.py @@ -2,6 +2,7 @@ from __future__ import annotations +import os import logging import asyncio from datetime import datetime, timezone @@ -262,4 +263,4 @@ def calculate_overall_metrics(health_data: dict[str, Any]) -> dict[str, Any]: if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8107) + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8107) diff --git a/apps/stubs/multi-region-load-balancer/main.py b/apps/stubs/multi-region-load-balancer/main.py index 32307345..9c79e3e5 100755 --- a/apps/stubs/multi-region-load-balancer/main.py +++ b/apps/stubs/multi-region-load-balancer/main.py @@ -3,6 +3,7 @@ Multi-Region Load Balancing Service for AITBC Handles intelligent load distribution across global regions """ +import os import asyncio import json from datetime import datetime, timezone, timedelta @@ -692,4 +693,5 @@ async def shutdown_event(): if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8019, log_level="info") + import os + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8019, log_level="info") diff --git a/apps/stubs/plugin-analytics/main.py b/apps/stubs/plugin-analytics/main.py index 758f52c8..49789605 100755 --- a/apps/stubs/plugin-analytics/main.py +++ b/apps/stubs/plugin-analytics/main.py @@ -3,6 +3,7 @@ Plugin Analytics and Usage Tracking Service for AITBC Handles plugin analytics, usage tracking, and performance monitoring """ +import os import asyncio import json from datetime import datetime, timezone, timedelta @@ -651,4 +652,4 @@ async def shutdown_event(): if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8016, log_level="info") + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8016, log_level="info") diff --git a/apps/stubs/plugin-marketplace/main.py b/apps/stubs/plugin-marketplace/main.py index 7b19aef8..086ce783 100755 --- a/apps/stubs/plugin-marketplace/main.py +++ b/apps/stubs/plugin-marketplace/main.py @@ -3,6 +3,7 @@ Plugin Marketplace Frontend Service for AITBC Provides web interface and marketplace functionality for plugins """ +import os import asyncio import json from datetime import datetime, timezone, timedelta @@ -600,4 +601,4 @@ async def shutdown_event(): if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8014, log_level="info") + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8014, log_level="info") diff --git a/apps/stubs/plugin-registry/main.py b/apps/stubs/plugin-registry/main.py index 16e2fb1a..cc7d4217 100755 --- a/apps/stubs/plugin-registry/main.py +++ b/apps/stubs/plugin-registry/main.py @@ -3,6 +3,7 @@ Production Plugin Registry Service for AITBC Handles plugin registration, discovery, versioning, and security validation """ +import os import asyncio import json import hashlib @@ -481,4 +482,4 @@ async def shutdown_event(): if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8013, log_level="info") + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8013, log_level="info") diff --git a/apps/stubs/plugin-security/main.py b/apps/stubs/plugin-security/main.py index 55efb286..6584b751 100755 --- a/apps/stubs/plugin-security/main.py +++ b/apps/stubs/plugin-security/main.py @@ -656,4 +656,4 @@ def initialize_vulnerability_database(): if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8015, log_level="info") + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8015, log_level="info") diff --git a/apps/stubs/plugin-service/src/plugin_service/main.py b/apps/stubs/plugin-service/src/plugin_service/main.py index fad5bf3c..bb267d50 100644 --- a/apps/stubs/plugin-service/src/plugin_service/main.py +++ b/apps/stubs/plugin-service/src/plugin_service/main.py @@ -2,6 +2,7 @@ from __future__ import annotations +import os import logging from typing import Any @@ -67,4 +68,4 @@ async def get_plugin_analytics() -> dict[str, Any]: if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8109) + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8109) diff --git a/apps/stubs/simple-explorer/main.py b/apps/stubs/simple-explorer/main.py index 7f301655..3086b5a5 100644 --- a/apps/stubs/simple-explorer/main.py +++ b/apps/stubs/simple-explorer/main.py @@ -3,6 +3,7 @@ Simple AITBC Blockchain Explorer - Demonstrating the issues described in the analysis """ +import os import asyncio import re from datetime import datetime @@ -234,4 +235,4 @@ async def root(): return HTML_TEMPLATE if __name__ == "__main__": - uvicorn.run(app, host="0.0.0.0", port=8017) + uvicorn.run(app, host="127.0.0.1", port=8017) diff --git a/apps/stubs/trading-engine/main.py b/apps/stubs/trading-engine/main.py index 3bc16fd2..a522536a 100755 --- a/apps/stubs/trading-engine/main.py +++ b/apps/stubs/trading-engine/main.py @@ -3,6 +3,7 @@ Production Trading Engine for AITBC Handles order matching, trade execution, and settlement """ +import os import asyncio import json from collections import defaultdict, deque @@ -580,4 +581,4 @@ async def simulate_market_activity(): if __name__ == "__main__": import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8012, log_level="info") + uvicorn.run(app, host=os.getenv("BIND_HOST", "127.0.0.1"), port=8012, log_level="info") diff --git a/cli/aitbc_cli.py b/cli/aitbc_cli.py new file mode 100644 index 00000000..5ecdb44d --- /dev/null +++ b/cli/aitbc_cli.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 +"""Compatibility wrapper for the AITBC CLI entrypoint.""" + +from __future__ import annotations + +import importlib.util +import sys +from pathlib import Path +from types import ModuleType + +REPO_ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(REPO_ROOT)) + +from aitbc.constants import BLOCKCHAIN_RPC_PORT + +DEFAULT_RPC_URL = f"http://localhost:{BLOCKCHAIN_RPC_PORT}" +_LEGACY_MODULE: ModuleType | None = None + + +def _load_legacy_module() -> ModuleType: + global _LEGACY_MODULE + if _LEGACY_MODULE is not None: + return _LEGACY_MODULE + + legacy_path = Path(__file__).with_name("aitbc_cli.legacy.py") + spec = importlib.util.spec_from_file_location("aitbc_cli_legacy", legacy_path) + if spec is None or spec.loader is None: + raise ImportError(f"Unable to load legacy CLI entrypoint from {legacy_path}") + + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + _LEGACY_MODULE = module + return module + + +def main(argv=None): + return _load_legacy_module().main(argv) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index ae3b91bf..75c6cbaf 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -14,12 +14,6 @@ ### Codebase Quality & Technical Debt -#### CRITICAL (Short-term, 0-2 weeks) - -- [ ] Replace print() statements with proper logging in aitbc/decorators.py, aitbc/events.py, aitbc/queue_manager.py, aitbc/state.py -- [ ] Fix bare except: in config.py line 79 - add logger assignment at top of file -- [ ] Coordinator-API service exports - either expand all 101 services to __init__.py or document lazy import pattern - #### HIGH (Medium-term, 2-6 weeks) - [ ] Split massive service classes (advanced_reinforcement_learning.py 2,000 lines, certification_service.py 1,368 lines, multi_modal_fusion.py 1,324 lines) diff --git a/packages/py/aitbc-agent-sdk/tests/test_cli_atomic_swap.py b/packages/py/aitbc-agent-sdk/tests/test_cli_atomic_swap.py index ea25f176..a1ac73d3 100644 --- a/packages/py/aitbc-agent-sdk/tests/test_cli_atomic_swap.py +++ b/packages/py/aitbc-agent-sdk/tests/test_cli_atomic_swap.py @@ -6,6 +6,8 @@ import sys import os import logging +import pytest + # Setup logging logging.basicConfig(level=logging.INFO) @@ -25,6 +27,7 @@ sys.modules['aitbc.exceptions'].NetworkError = Exception from aitbc_agent.contract_integration import ContractConfig, create_agent_contract_integration +@pytest.mark.asyncio async def test_cli_client(): """Test CLI client atomic swap methods""" print("Testing CLI client atomic swap methods...") diff --git a/test_hierarchical_config.py b/tests/test_hierarchical_config.py similarity index 100% rename from test_hierarchical_config.py rename to tests/test_hierarchical_config.py diff --git a/tests/verification/test_cross_node_blockchain.py b/tests/verification/test_cross_node_blockchain.py index 71e85e45..f6946e03 100644 --- a/tests/verification/test_cross_node_blockchain.py +++ b/tests/verification/test_cross_node_blockchain.py @@ -4,6 +4,7 @@ Cross-node blockchain feature tests Tests new blockchain features across aitbc and aitbc1 nodes """ +import os import hashlib import subprocess from datetime import datetime, timezone @@ -28,6 +29,19 @@ NODES = { CHAIN_ID = "ait-mainnet" + +def _get_local_chain_id() -> str: + env_chain_id = os.getenv("CHAIN_ID", CHAIN_ID) + env_path = "/etc/aitbc/.env" + if not os.path.exists(env_path): + return env_chain_id + + with open(env_path, "r") as f: + for line in f: + if line.startswith("CHAIN_ID="): + return line.strip().split("=", 1)[1] + return env_chain_id + def compute_block_hash(height, parent_hash, timestamp): """Compute block hash using the same algorithm as PoA proposer""" payload = f"{CHAIN_ID}|{height}|{parent_hash}|{timestamp}".encode() @@ -62,14 +76,9 @@ def test_cross_node_chain_id_consistency(): chain_ids = {} for node_key in NODES: if node_key == "aitbc": - # Check local .env file - with open("/etc/aitbc/.env", "r") as f: - for line in f: - if line.startswith("CHAIN_ID="): - chain_id = line.strip().split("=")[1] - chain_ids[node_key] = chain_id - print(f"{NODES[node_key]['name']}: chain_id = {chain_id}") - break + chain_id = _get_local_chain_id() + chain_ids[node_key] = chain_id + print(f"{NODES[node_key]['name']}: chain_id = {chain_id}") else: # Check remote .env file via SSH result = subprocess.run(