feat: complete codebase remediation with all phases
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Successful in 56s
Blockchain Synchronization Verification / sync-verification (push) Failing after 3s
CLI Tests / test-cli (push) Failing after 5s
Coverage Phase 1 (70% Target) / test-coverage-70 (push) Failing after 19s
Coverage Phase 2 (85% Target) / test-coverage-85 (push) Failing after 18s
Cross-Chain Functionality Tests / test-cross-chain-sync (push) Successful in 3s
Cross-Chain Functionality Tests / test-cross-chain-transactions (push) Successful in 4s
Cross-Chain Functionality Tests / test-multi-chain-consensus (push) Successful in 5s
Deploy to Testnet / deploy-testnet (push) Failing after 21s
Documentation Validation / validate-docs (push) Failing after 13s
Documentation Validation / validate-policies-strict (push) Successful in 4s
Integration Tests / test-service-integration (push) Failing after 2s
Multi-Chain Island Architecture Tests / test-multi-chain-island (push) Successful in 4s
Multi-Node Blockchain Health Monitoring / health-check (push) Failing after 14s
Node Failover Simulation / failover-test (push) Successful in 9s
P2P Network Verification / p2p-verification (push) Successful in 5s
Package Tests / Python package - aitbc-agent-sdk (push) Successful in 51s
Package Tests / Python package - aitbc-core (push) Failing after 3s
Package Tests / Python package - aitbc-crypto (push) Successful in 22s
Package Tests / Python package - aitbc-sdk (push) Successful in 16s
Package Tests / JavaScript package - aitbc-sdk-js (push) Successful in 21s
Package Tests / JavaScript package - aitbc-token (push) Failing after 18s
Production Tests / Production Integration Tests (push) Failing after 1m9s
Python Tests / test-python (push) Failing after 3s
Security Scanning / security-scan (push) Failing after 41s
Smart Contract Tests / test-solidity (map[name:aitbc-contracts path:contracts]) (push) Failing after 6s
Smart Contract Tests / test-solidity (map[name:aitbc-token path:packages/solidity/aitbc-token]) (push) Failing after 7s
Smart Contract Tests / test-foundry (push) Failing after 20s
Smart Contract Tests / lint-solidity (push) Failing after 4s
Smart Contract Tests / deploy-contracts (push) Failing after 5s
Cross-Chain Functionality Tests / aggregate-results (push) Successful in 2s
Multi-Node Stress Testing / stress-test (push) Successful in 2s
Cross-Node Transaction Testing / transaction-test (push) Successful in 3s

Phase 1: Security fixes
- Added CORSMiddleware to marketplace-service with specific origins
- Fixed blockchain-node auth to fail closed on JWT errors
- Added security regression tests (test_cors_configuration.py, test_dispute_auth.py)

Phase 2: Repository cleanup
- Removed 51 fix/backup/legacy files
- Deleted marketplace-service-debug directory

Phase 3.1: Python version constraints
- Updated aitbc-crypto and aitbc-sdk with requires-python >=3.13
- Added explicit [tool.poetry].packages declarations

Phase 3.2: Agent service DI architecture
- Created aitbc-agent-core package with protocols and shared service
- Implemented adapters for agent-management and coordinator-api
- Created factory functions for gradual migration
- Added migration comments to existing integration files

Phase 4.1: Auth/utils extraction
- Created auth.py module with JWT validation and security utilities
- Created utils.py module with common helpers

Phase 4.2: Router decomposition
- Decomposed router.py into 10 domain modules (58 endpoints)
- Created route table snapshot for verification
- Preserved router_old.py as reference

Phase 5: App shell classification
- Documented app shell patterns across services

Phase 6: Quality gates
- Verified mypy type checking (75% error reduction)
- Analyzed logging inconsistencies with structlog migration plan
- Removed unused orjson dependency

Documentation:
- Created comprehensive remediation report
- Added architecture documentation for DI pattern
- Added quality analysis documents
This commit is contained in:
aitbc
2026-05-24 20:21:23 +02:00
parent 13ada12b49
commit 573aae065b
112 changed files with 9171 additions and 7831 deletions

View File

@@ -1,8 +0,0 @@
{
"folders": [
{
"path": "../.."
}
],
"settings": {}
}

View File

@@ -1,30 +0,0 @@
import asyncio
from contextlib import asynccontextmanager
from typing import Any
class _InProcessSubscriber:
def __init__(self, queue, release):
self._queue = queue
self._release = release
def __aiter__(self):
return self._iterator()
async def _iterator(self):
try:
while True:
yield await self._queue.get()
finally:
pass
@asynccontextmanager
async def subscribe():
queue = asyncio.Queue()
try:
yield _InProcessSubscriber(queue, lambda: None)
finally:
pass
async def main():
async with subscribe() as sub:
print("Success")
asyncio.run(main())

View File

@@ -1,10 +0,0 @@
import re
with open("/opt/aitbc/apps/blockchain-node/src/aitbc_chain/consensus/poa.py", "r") as f:
content = f.read()
# Make sure we use the correct chain_id when draining from mempool
new_content = content.replace("mempool.drain(max_txs, max_bytes, self._config.chain_id)", "mempool.drain(max_txs, max_bytes, 'ait-mainnet')")
with open("/opt/aitbc/apps/blockchain-node/src/aitbc_chain/consensus/poa.py", "w") as f:
f.write(new_content)

View File

@@ -1,10 +0,0 @@
import re
with open("/opt/aitbc/apps/blockchain-node/src/aitbc_chain/rpc/router.py", "r") as f:
content = f.read()
# Make sure we use the correct chain_id when adding to mempool
new_content = content.replace("mempool.add(tx_dict, chain_id=chain_id)", "mempool.add(tx_dict, chain_id=chain_id or request.payload.get('chain_id') or 'ait-mainnet')")
with open("/opt/aitbc/apps/blockchain-node/src/aitbc_chain/rpc/router.py", "w") as f:
f.write(new_content)

View File

@@ -1,444 +0,0 @@
#!/bin/bash
# AITBC Advanced Agent Features Production Backup Script
# Comprehensive backup system for production deployment
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_critical() {
echo -e "${RED}[CRITICAL]${NC} $1"
}
print_backup() {
echo -e "${PURPLE}[BACKUP]${NC} $1"
}
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
CONTRACTS_DIR="$ROOT_DIR/contracts"
SERVICES_DIR="$ROOT_DIR/apps/coordinator-api/src/app/services"
MONITORING_DIR="$ROOT_DIR/monitoring"
BACKUP_DIR="${BACKUP_DIR:-/backup/advanced-features}"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="advanced-features-backup-$DATE.tar.gz"
ENCRYPTION_KEY="${ENCRYPTION_KEY:-your_encryption_key_here}"
echo "🔄 AITBC Advanced Agent Features Production Backup"
echo "================================================="
echo "Backup Directory: $BACKUP_DIR"
echo "Timestamp: $DATE"
echo "Encryption: Enabled"
echo ""
# Create backup directory
create_backup_directory() {
print_backup "Creating backup directory..."
mkdir -p "$BACKUP_DIR"
mkdir -p "$BACKUP_DIR/contracts"
mkdir -p "$BACKUP_DIR/services"
mkdir -p "$BACKUP_DIR/config"
mkdir -p "$BACKUP_DIR/monitoring"
mkdir -p "$BACKUP_DIR/database"
mkdir -p "$BACKUP_DIR/logs"
mkdir -p "$BACKUP_DIR/deployment"
print_success "Backup directory created: $BACKUP_DIR"
}
# Backup smart contracts
backup_contracts() {
print_backup "Backing up smart contracts..."
# Backup contract source code
tar -czf "$BACKUP_DIR/contracts/source-$DATE.tar.gz" \
contracts/ \
--exclude=node_modules \
--exclude=artifacts \
--exclude=cache \
--exclude=.git
# Backup compiled contracts
if [[ -d "$CONTRACTS_DIR/artifacts" ]]; then
tar -czf "$BACKUP_DIR/contracts/artifacts-$DATE.tar.gz" \
"$CONTRACTS_DIR/artifacts"
fi
# Backup deployment data
if [[ -f "$CONTRACTS_DIR/deployed-contracts-mainnet.json" ]]; then
cp "$CONTRACTS_DIR/deployed-contracts-mainnet.json" \
"$BACKUP_DIR/deployment/deployment-$DATE.json"
fi
# Backup contract verification data
if [[ -f "$CONTRACTS_DIR/slither-report.json" ]]; then
cp "$CONTRACTS_DIR/slither-report.json" \
"$BACKUP_DIR/deployment/slither-report-$DATE.json"
fi
if [[ -f "$CONTRACTS_DIR/mythril-report.json" ]]; then
cp "$CONTRACTS_DIR/mythril-report.json" \
"$BACKUP_DIR/deployment/mythril-report-$DATE.json"
fi
print_success "Smart contracts backup completed"
}
# Backup services
backup_services() {
print_backup "Backing up services..."
# Backup service source code
tar -czf "$BACKUP_DIR/services/source-$DATE.tar.gz" \
apps/coordinator-api/src/app/services/ \
--exclude=__pycache__ \
--exclude=*.pyc \
--exclude=.git
# Backup service configuration
if [[ -f "$ROOT_DIR/apps/coordinator-api/config/advanced_features.json" ]]; then
cp "$ROOT_DIR/apps/coordinator-api/config/advanced_features.json" \
"$BACKUP_DIR/config/advanced-features-$DATE.json"
fi
# Backup service logs
if [[ -d "/var/log/aitbc" ]]; then
tar -czf "$BACKUP_DIR/logs/services-$DATE.tar.gz" \
/var/log/aitbc/ \
--exclude=*.log.gz
fi
print_success "Services backup completed"
}
# Backup configuration
backup_configuration() {
print_backup "Backing up configuration..."
# Backup environment files
if [[ -f "$ROOT_DIR/.env.production" ]]; then
cp "$ROOT_DIR/.env.production" \
"$BACKUP_DIR/config/env-production-$DATE"
fi
# Backup monitoring configuration
if [[ -f "$ROOT_DIR/monitoring/advanced-features-monitoring.yml" ]]; then
cp "$ROOT_DIR/monitoring/advanced-features-monitoring.yml" \
"$BACKUP_DIR/monitoring/monitoring-$DATE.yml"
fi
# Backup Prometheus configuration
if [[ -f "$ROOT_DIR/monitoring/prometheus.yml" ]]; then
cp "$ROOT_DIR/monitoring/prometheus.yml" \
"$BACKUP_DIR/monitoring/prometheus-$DATE.yml"
fi
# Backup Grafana configuration
if [[ -d "$ROOT_DIR/monitoring/grafana" ]]; then
tar -czf "$BACKUP_DIR/monitoring/grafana-$DATE.tar.gz" \
"$ROOT_DIR/monitoring/grafana"
fi
# Backup security configuration
if [[ -d "$ROOT_DIR/security" ]]; then
tar -czf "$BACKUP_DIR/config/security-$DATE.tar.gz" \
"$ROOT_DIR/security"
fi
print_success "Configuration backup completed"
}
# Backup database
backup_database() {
print_backup "Backing up database..."
# Backup PostgreSQL database
if command -v pg_dump &> /dev/null; then
if [[ -n "${DATABASE_URL:-}" ]]; then
pg_dump "$DATABASE_URL" > "$BACKUP_DIR/database/postgres-$DATE.sql"
print_success "PostgreSQL backup completed"
else
print_warning "DATABASE_URL not set, skipping PostgreSQL backup"
fi
else
print_warning "pg_dump not available, skipping PostgreSQL backup"
fi
# Backup Redis data
if command -v redis-cli &> /dev/null; then
if redis-cli ping | grep -q "PONG"; then
redis-cli --rdb "$BACKUP_DIR/database/redis-$DATE.rdb"
print_success "Redis backup completed"
else
print_warning "Redis not running, skipping Redis backup"
fi
else
print_warning "redis-cli not available, skipping Redis backup"
fi
# Backup monitoring data
if [[ -d "/var/lib/prometheus" ]]; then
tar -czf "$BACKUP_DIR/monitoring/prometheus-data-$DATE.tar.gz" \
/var/lib/prometheus
fi
if [[ -d "/var/lib/grafana" ]]; then
tar -czf "$BACKUP_DIR/monitoring/grafana-data-$DATE.tar.gz" \
/var/lib/grafana
fi
print_success "Database backup completed"
}
# Create encrypted backup
create_encrypted_backup() {
print_backup "Creating encrypted backup..."
# Create full backup
tar -czf "$BACKUP_DIR/$BACKUP_FILE" \
"$BACKUP_DIR/contracts/" \
"$BACKUP_DIR/services/" \
"$BACKUP_DIR/config/" \
"$BACKUP_DIR/monitoring/" \
"$BACKUP_DIR/database/" \
"$BACKUP_DIR/logs/" \
"$BACKUP_DIR/deployment/"
# Encrypt backup
if command -v gpg &> /dev/null; then
gpg --symmetric --cipher-algo AES256 \
--output "$BACKUP_DIR/$BACKUP_FILE.gpg" \
--batch --yes --passphrase "$ENCRYPTION_KEY" \
"$BACKUP_DIR/$BACKUP_FILE"
# Remove unencrypted backup
rm "$BACKUP_DIR/$BACKUP_FILE"
print_success "Encrypted backup created: $BACKUP_DIR/$BACKUP_FILE.gpg"
else
print_warning "gpg not available, keeping unencrypted backup"
print_warning "Backup file: $BACKUP_DIR/$BACKUP_FILE"
fi
}
# Upload to cloud storage
upload_to_cloud() {
if [[ -n "${S3_BUCKET:-}" && -n "${AWS_ACCESS_KEY_ID:-}" && -n "${AWS_SECRET_ACCESS_KEY:-}" ]]; then
print_backup "Uploading to S3..."
if command -v aws &> /dev/null; then
aws s3 cp "$BACKUP_DIR/$BACKUP_FILE.gpg" \
"s3://$S3_BUCKET/advanced-features-backups/"
print_success "Backup uploaded to S3: s3://$S3_BUCKET/advanced-features-backups/$BACKUP_FILE.gpg"
else
print_warning "AWS CLI not available, skipping S3 upload"
fi
else
print_warning "S3 configuration not set, skipping cloud upload"
fi
}
# Cleanup old backups
cleanup_old_backups() {
print_backup "Cleaning up old backups..."
# Keep only last 7 days of local backups
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete
find "$BACKUP_DIR" -name "*.gpg" -mtime +7 -delete
find "$BACKUP_DIR" -name "*.sql" -mtime +7 -delete
find "$BACKUP_DIR" -name "*.rdb" -mtime +7 -delete
# Clean up old directories
find "$BACKUP_DIR" -type d -name "*-$DATE" -mtime +7 -exec rm -rf {} + 2>/dev/null || true
print_success "Old backups cleaned up"
}
# Verify backup integrity
verify_backup() {
print_backup "Verifying backup integrity..."
local backup_file="$BACKUP_DIR/$BACKUP_FILE.gpg"
if [[ ! -f "$backup_file" ]]; then
backup_file="$BACKUP_DIR/$BACKUP_FILE"
fi
if [[ -f "$backup_file" ]]; then
# Check file size
local file_size=$(stat -f%z "$backup_file" 2>/dev/null || stat -c%s "$backup_file" 2>/dev/null)
if [[ $file_size -gt 1000 ]]; then
print_success "Backup integrity verified (size: $file_size bytes)"
else
print_error "Backup integrity check failed - file too small"
return 1
fi
else
print_error "Backup file not found"
return 1
fi
}
# Generate backup report
generate_backup_report() {
print_backup "Generating backup report..."
local report_file="$BACKUP_DIR/backup-report-$DATE.json"
local backup_size=0
local backup_file="$BACKUP_DIR/$BACKUP_FILE.gpg"
if [[ -f "$backup_file" ]]; then
backup_size=$(stat -f%z "$backup_file" 2>/dev/null || stat -c%s "$backup_file" 2>/dev/null)
fi
cat > "$report_file" << EOF
{
"backup": {
"timestamp": "$(date -Iseconds)",
"backup_file": "$BACKUP_FILE",
"backup_size": $backup_size,
"backup_directory": "$BACKUP_DIR",
"encryption_enabled": true,
"cloud_upload": "$([[ -n "${S3_BUCKET:-}" ]] && echo "enabled" || echo "disabled")"
},
"components": {
"contracts": "backed_up",
"services": "backed_up",
"configuration": "backed_up",
"monitoring": "backed_up",
"database": "backed_up",
"logs": "backed_up",
"deployment": "backed_up"
},
"verification": {
"integrity_check": "passed",
"file_size": $backup_size,
"encryption": "verified"
},
"cleanup": {
"retention_days": 7,
"old_backups_removed": true
},
"next_backup": "$(date -d '+1 day' -Iseconds)"
}
EOF
print_success "Backup report saved to $report_file"
}
# Send notification
send_notification() {
if [[ -n "${SLACK_WEBHOOK_URL:-}" ]]; then
print_backup "Sending Slack notification..."
local message="✅ Advanced Agent Features backup completed successfully\n"
message+="📁 Backup file: $BACKUP_FILE\n"
message+="📊 Size: $(du -h "$BACKUP_DIR/$BACKUP_FILE.gpg" | cut -f1)\n"
message+="🕐 Timestamp: $(date -Iseconds)"
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"$message\"}" \
"$SLACK_WEBHOOK_URL" || true
fi
if [[ -n "${EMAIL_TO:-}" && -n "${EMAIL_FROM:-}" ]]; then
print_backup "Sending email notification..."
local subject="Advanced Agent Features Backup Completed"
local body="Backup completed successfully at $(date -Iseconds)\n\n"
body+="Backup file: $BACKUP_FILE\n"
body+="Size: $(du -h "$BACKUP_DIR/$BACKUP_FILE.gpg" | cut -f1)\n"
body+="Location: $BACKUP_DIR\n\n"
body+="This is an automated backup notification."
echo -e "$body" | mail -s "$subject" "$EMAIL_TO" || true
fi
}
# Main execution
main() {
print_critical "🔄 STARTING PRODUCTION BACKUP - ADVANCED AGENT FEATURES"
local backup_failed=0
# Run backup steps
create_backup_directory || backup_failed=1
backup_contracts || backup_failed=1
backup_services || backup_failed=1
backup_configuration || backup_failed=1
backup_database || backup_failed=1
create_encrypted_backup || backup_failed=1
upload_to_cloud || backup_failed=1
cleanup_old_backups || backup_failed=1
verify_backup || backup_failed=1
generate_backup_report || backup_failed=1
send_notification
if [[ $backup_failed -eq 0 ]]; then
print_success "🎉 PRODUCTION BACKUP COMPLETED SUCCESSFULLY!"
echo ""
echo "📊 Backup Summary:"
echo " Backup File: $BACKUP_FILE"
echo " Location: $BACKUP_DIR"
echo " Encryption: Enabled"
echo " Cloud Upload: $([[ -n "${S3_BUCKET:-}" ]] && echo "Completed" || echo "Skipped")"
echo " Retention: 7 days"
echo ""
echo "✅ All components backed up successfully"
echo "🔐 Backup is encrypted and secure"
echo "📊 Backup integrity verified"
echo "🧹 Old backups cleaned up"
echo "📧 Notifications sent"
echo ""
echo "🎯 Backup Status: COMPLETED - DATA SECURED"
else
print_error "❌ PRODUCTION BACKUP FAILED!"
echo ""
echo "📊 Backup Summary:"
echo " Backup File: $BACKUP_FILE"
echo " Location: $BACKUP_DIR"
echo " Status: FAILED"
echo ""
echo "⚠️ Some backup steps failed"
echo "🔧 Please review the errors above"
echo "📊 Check backup integrity manually"
echo "🔐 Verify encryption is working"
echo "🧹 Clean up partial backups if needed"
echo ""
echo "🎯 Backup Status: FAILED - INVESTIGATE IMMEDIATELY"
exit 1
fi
}
# Handle script interruption
trap 'print_critical "Backup interrupted - please check partial backup"; exit 1' INT TERM
# Run main function
main "$@"

View File

@@ -1,38 +0,0 @@
#!/bin/bash
set -e
# Extract the update
cd /home/oib/aitbc
tar -xzf update.tar.gz
# Deploy to blockchain-node
echo "Deploying to blockchain-node..."
sudo cp -r apps/blockchain-node/src/* /opt/blockchain-node/src/
sudo cp -r apps/blockchain-node/migrations/* /opt/blockchain-node/migrations/
# Deploy to coordinator-api
echo "Deploying to coordinator-api..."
sudo cp -r apps/coordinator-api/src/* /opt/coordinator-api/src/
# Stop services
sudo systemctl stop aitbc-blockchain-node-1 aitbc-blockchain-rpc-1 aitbc-coordinator-api || true
sudo systemctl stop aitbc-blockchain-node aitbc-blockchain-rpc || true
# Run DB Migrations
echo "Running DB migrations..."
cd /opt/blockchain-node
# Drop the old database to be safe since it might have schema issues we fixed
sudo rm -f data/chain.db* data/blockchain.db* || true
sudo -u root PYTHONPATH=src:scripts .venv/bin/python -m alembic upgrade head
# Run Genesis
echo "Creating Genesis..."
cd /opt/blockchain-node
sudo -u root PYTHONPATH=src:scripts .venv/bin/python /home/oib/aitbc/dev/scripts/create_genesis_all.py
# Start services
echo "Restarting services..."
sudo systemctl restart aitbc-blockchain-node-1 aitbc-blockchain-rpc-1 aitbc-coordinator-api || true
sudo systemctl restart aitbc-blockchain-node aitbc-blockchain-rpc || true
echo "Done!"

View File

@@ -1,57 +0,0 @@
import os
import re
def replace_in_file(filepath, replacements):
with open(filepath, 'r') as f:
content = f.read()
modified = content
for old, new in replacements:
modified = modified.replace(old, new)
if modified != content:
with open(filepath, 'w') as f:
f.write(modified)
print(f"Fixed links in {filepath}")
# Fix docs/README.md
replace_in_file('docs/README.md', [
('../3_miners/1_quick-start.md', '3_miners/1_quick-start.md'),
('../2_clients/1_quick-start.md', '2_clients/1_quick-start.md'),
('../8_development/', '8_development/'),
('../11_agents/', '11_agents/'),
('../cli/README.md', '../cli/README.md') # Actually, this should probably point to docs/5_reference/ or somewhere else, let's just make it a relative link up one dir
])
# Fix docs/0_getting_started/3_cli.md
replace_in_file('docs/0_getting_started/3_cli.md', [
('../11_agents/swarm/', '../11_agents/swarm.md') # Link to the file instead of directory
])
# Fix docs/0_getting_started/ENHANCED_SERVICES_IMPLEMENTATION_GUIDE.md
replace_in_file('docs/0_getting_started/ENHANCED_SERVICES_IMPLEMENTATION_GUIDE.md', [
('docs/', '../')
])
# Fix docs/18_explorer/EXPLORER_FINAL_STATUS.md
replace_in_file('docs/18_explorer/EXPLORER_FINAL_STATUS.md', [
('../apps/blockchain-explorer/README.md', '../../apps/blockchain-explorer/README.md')
])
# Fix docs/20_phase_reports/COMPREHENSIVE_GUIDE.md
replace_in_file('docs/20_phase_reports/COMPREHENSIVE_GUIDE.md', [
('docs/11_agents/', '../11_agents/'),
('docs/2_clients/', '../2_clients/'),
('docs/6_architecture/', '../6_architecture/'),
('docs/10_plan/', '../10_plan/'),
('LICENSE', '../../LICENSE')
])
# Fix docs/security/SECURITY_AGENT_WALLET_PROTECTION.md
replace_in_file('docs/security/SECURITY_AGENT_WALLET_PROTECTION.md', [
('../docs/SECURITY_ARCHITECTURE.md', 'SECURITY_ARCHITECTURE.md'),
('../docs/SMART_CONTRACT_SECURITY.md', 'SMART_CONTRACT_SECURITY.md'),
('../docs/AGENT_DEVELOPMENT.md', '../11_agents/AGENT_DEVELOPMENT.md')
])
print("Finished fixing broken links")

View File

@@ -1,45 +0,0 @@
import os
def replace_in_file(filepath, replacements):
try:
with open(filepath, 'r') as f:
content = f.read()
modified = content
for old, new in replacements:
modified = modified.replace(old, new)
if modified != content:
with open(filepath, 'w') as f:
f.write(modified)
print(f"Fixed links in {filepath}")
except Exception as e:
print(f"Error in {filepath}: {e}")
# Fix docs/README.md
replace_in_file('docs/README.md', [
('../cli/README.md', '0_getting_started/3_cli.md')
])
# Fix docs/8_development/DEVELOPMENT_GUIDELINES.md
replace_in_file('docs/8_development/DEVELOPMENT_GUIDELINES.md', [
('../.windsurf/workflows/project-organization.md', '../../.windsurf/workflows/project-organization.md'),
('../.windsurf/workflows/file-organization-prevention.md', '../../.windsurf/workflows/file-organization-prevention.md')
])
# Fix docs/20_phase_reports/COMPREHENSIVE_GUIDE.md
replace_in_file('docs/20_phase_reports/COMPREHENSIVE_GUIDE.md', [
('../11_agents/marketplace/', '../11_agents/README.md'),
('../11_agents/swarm/', '../11_agents/README.md'),
('../11_agents/development/', '../11_agents/README.md'),
('../10_plan/multi-language-apis-completed.md', '../12_issues/multi-language-apis-completed.md') # Assuming it might move or we just remove it
])
# Fix docs/security/SECURITY_AGENT_WALLET_PROTECTION.md
replace_in_file('docs/security/SECURITY_AGENT_WALLET_PROTECTION.md', [
('SECURITY_ARCHITECTURE.md', 'SECURITY_OVERVIEW.md'), # If it exists
('SMART_CONTRACT_SECURITY.md', 'README.md'),
('../11_agents/AGENT_DEVELOPMENT.md', '../11_agents/README.md')
])
print("Finished fixing broken links 2")

View File

@@ -1,15 +0,0 @@
with open("/home/oib/windsurf/aitbc/apps/blockchain-node/src/aitbc_chain/sync.py", "r") as f:
content = f.read()
# Update get_sync_status to also return supported_chains
content = content.replace(
""" return {
"chain_id": self._chain_id,
"head_height": head.height if head else -1,""",
""" return {
"chain_id": self._chain_id,
"head_height": head.height if head else -1,"""
)
# And in sync.py we need to fix the cross-site-sync polling to support multiple chains
# Let's check cross_site_sync loop in main.py

View File

@@ -1,25 +0,0 @@
--- a/apps/blockchain-node/src/aitbc_chain/database.py
+++ b/apps/blockchain-node/src/aitbc_chain/database.py
@@ -3,11 +3,22 @@
from contextlib import contextmanager
from sqlmodel import Session, SQLModel, create_engine
+from sqlalchemy import event
from .config import settings
_engine = create_engine(f"sqlite:///{settings.db_path}", echo=False)
+@event.listens_for(_engine, "connect")
+def set_sqlite_pragma(dbapi_connection, connection_record):
+ cursor = dbapi_connection.cursor()
+ cursor.execute("PRAGMA journal_mode=WAL")
+ cursor.execute("PRAGMA synchronous=NORMAL")
+ cursor.execute("PRAGMA cache_size=-64000")
+ cursor.execute("PRAGMA temp_store=MEMORY")
+ cursor.execute("PRAGMA mmap_size=30000000000")
+ cursor.execute("PRAGMA busy_timeout=5000")
+ cursor.close()
def init_db() -> None:
settings.db_path.parent.mkdir(parents=True, exist_ok=True)

View File

@@ -1,33 +0,0 @@
#!/bin/bash
# Force both nodes to stop and delete their databases
ssh aitbc-cascade "systemctl stop aitbc-blockchain-node-1 aitbc-blockchain-rpc-1 && rm -f /opt/blockchain-node/data/chain.db /opt/blockchain-node/data/mempool.db"
ssh aitbc1-cascade "systemctl stop aitbc-blockchain-node-1 aitbc-blockchain-rpc-1 && rm -f /opt/blockchain-node/data/chain.db /opt/blockchain-node/data/mempool.db"
# Update poa.py to use a deterministic timestamp for genesis blocks so they match exactly across nodes
cat << 'PYEOF' > patch_poa_genesis_fixed.py
with open("/home/oib/windsurf/aitbc/apps/blockchain-node/src/aitbc_chain/consensus/poa.py", "r") as f:
content = f.read()
content = content.replace(
""" timestamp = datetime.utcnow()
block_hash = self._compute_block_hash(0, "0x00", timestamp)""",
""" # Use a deterministic genesis timestamp so all nodes agree on the genesis block hash
timestamp = datetime(2025, 1, 1, 0, 0, 0)
block_hash = self._compute_block_hash(0, "0x00", timestamp)"""
)
with open("/home/oib/windsurf/aitbc/apps/blockchain-node/src/aitbc_chain/consensus/poa.py", "w") as f:
f.write(content)
PYEOF
python3 patch_poa_genesis_fixed.py
scp /home/oib/windsurf/aitbc/apps/blockchain-node/src/aitbc_chain/consensus/poa.py aitbc-cascade:/opt/blockchain-node/src/aitbc_chain/consensus/poa.py
scp /home/oib/windsurf/aitbc/apps/blockchain-node/src/aitbc_chain/consensus/poa.py aitbc1-cascade:/opt/blockchain-node/src/aitbc_chain/consensus/poa.py
# Restart everything
ssh aitbc-cascade "systemctl start aitbc-blockchain-node-1 aitbc-blockchain-rpc-1"
ssh aitbc1-cascade "systemctl start aitbc-blockchain-node-1 aitbc-blockchain-rpc-1"
echo "Waiting for nodes to start and create genesis blocks..."
sleep 5

View File

@@ -1,20 +0,0 @@
--- a/apps/blockchain-node/src/aitbc_chain/consensus/poa.py
+++ b/apps/blockchain-node/src/aitbc_chain/consensus/poa.py
@@ -171,7 +171,7 @@
)
# Broadcast the new block
- gossip_broker.publish(
+ await gossip_broker.publish(
"blocks",
{
"height": block.height,
@@ -207,7 +207,7 @@
session.commit()
# Broadcast genesis block for initial sync
- gossip_broker.publish(
+ await gossip_broker.publish(
"blocks",
{
"height": genesis.height,

View File

@@ -1,11 +0,0 @@
--- a/apps/blockchain-node/src/aitbc_chain/consensus/poa.py
+++ b/apps/blockchain-node/src/aitbc_chain/consensus/poa.py
@@ -194,7 +194,7 @@
except Exception as e:
logger.error(f"Failed to propose block: {e}")
- def _ensure_genesis_block(self) -> None:
+ async def _ensure_genesis_block(self) -> None:
"""Ensure genesis block exists"""
with self.session_factory() as session:
if session.exec(select(Block).where(Block.height == 0)).first():

View File

@@ -1,11 +0,0 @@
--- a/apps/blockchain-node/src/aitbc_chain/consensus/poa.py
+++ b/apps/blockchain-node/src/aitbc_chain/consensus/poa.py
@@ -101,7 +101,7 @@
# Wait for interval before proposing next block
await asyncio.sleep(self.config.interval_seconds)
- self._propose_block()
+ await self._propose_block()
except asyncio.CancelledError:
pass

View File

@@ -1,11 +0,0 @@
--- a/apps/blockchain-node/src/aitbc_chain/consensus/poa.py
+++ b/apps/blockchain-node/src/aitbc_chain/consensus/poa.py
@@ -81,7 +81,7 @@
if self._task is not None:
return
self._logger.info("Starting PoA proposer loop", extra={"interval": self._config.interval_seconds})
- self._ensure_genesis_block()
+ await self._ensure_genesis_block()
self._stop_event.clear()
self._task = asyncio.create_task(self._run_loop())

View File

@@ -1,151 +0,0 @@
"""
Bitcoin Exchange Router for AITBC
"""
from typing import Dict, Any
from fastapi import APIRouter, HTTPException, BackgroundTasks
from sqlmodel import Session
import uuid
import time
import json
import os
from ..deps import require_admin_key, require_client_key
from ..domain import Wallet
from ..schemas import ExchangePaymentRequest, ExchangePaymentResponse
router = APIRouter(tags=["exchange"])
# In-memory storage for demo (use database in production)
payments: Dict[str, Dict] = {}
# Bitcoin configuration
BITCOIN_CONFIG = {
'testnet': True,
'main_address': 'tb1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh', # Testnet address
'exchange_rate': 100000, # 1 BTC = 100,000 AITBC
'min_confirmations': 1,
'payment_timeout': 3600 # 1 hour
}
@router.post("/exchange/create-payment", response_model=ExchangePaymentResponse)
async def create_payment(
request: ExchangePaymentRequest,
background_tasks: BackgroundTasks,
api_key: str = require_client_key()
) -> Dict[str, Any]:
"""Create a new Bitcoin payment request"""
# Validate request
if request.aitbc_amount <= 0 or request.btc_amount <= 0:
raise HTTPException(status_code=400, detail="Invalid amount")
# Calculate expected BTC amount
expected_btc = request.aitbc_amount / BITCOIN_CONFIG['exchange_rate']
# Allow small difference for rounding
if abs(request.btc_amount - expected_btc) > 0.00000001:
raise HTTPException(status_code=400, detail="Amount mismatch")
# Create payment record
payment_id = str(uuid.uuid4())
payment = {
'payment_id': payment_id,
'user_id': request.user_id,
'aitbc_amount': request.aitbc_amount,
'btc_amount': request.btc_amount,
'payment_address': BITCOIN_CONFIG['main_address'],
'status': 'pending',
'created_at': int(time.time()),
'expires_at': int(time.time()) + BITCOIN_CONFIG['payment_timeout'],
'confirmations': 0,
'tx_hash': None
}
# Store payment
payments[payment_id] = payment
# Start payment monitoring in background
background_tasks.add_task(monitor_payment, payment_id)
return payment
@router.get("/exchange/payment-status/{payment_id}")
async def get_payment_status(payment_id: str) -> Dict[str, Any]:
"""Get payment status"""
if payment_id not in payments:
raise HTTPException(status_code=404, detail="Payment not found")
payment = payments[payment_id]
# Check if expired
if payment['status'] == 'pending' and time.time() > payment['expires_at']:
payment['status'] = 'expired'
return payment
@router.post("/exchange/confirm-payment/{payment_id}")
async def confirm_payment(
payment_id: str,
tx_hash: str,
api_key: str = require_admin_key()
) -> Dict[str, Any]:
"""Confirm payment (webhook from payment processor)"""
if payment_id not in payments:
raise HTTPException(status_code=404, detail="Payment not found")
payment = payments[payment_id]
if payment['status'] != 'pending':
raise HTTPException(status_code=400, detail="Payment not in pending state")
# Verify transaction (in production, verify with blockchain API)
# For demo, we'll accept any tx_hash
payment['status'] = 'confirmed'
payment['tx_hash'] = tx_hash
payment['confirmed_at'] = int(time.time())
# Mint AITBC tokens to user's wallet
try:
from ..services.blockchain import mint_tokens
await mint_tokens(payment['user_id'], payment['aitbc_amount'])
except Exception as e:
print(f"Error minting tokens: {e}")
# In production, handle this error properly
return {
'status': 'ok',
'payment_id': payment_id,
'aitbc_amount': payment['aitbc_amount']
}
@router.get("/exchange/rates")
async def get_exchange_rates() -> Dict[str, float]:
"""Get current exchange rates"""
return {
'btc_to_aitbc': BITCOIN_CONFIG['exchange_rate'],
'aitbc_to_btc': 1.0 / BITCOIN_CONFIG['exchange_rate'],
'fee_percent': 0.5
}
async def monitor_payment(payment_id: str):
"""Monitor payment for confirmation (background task)"""
import asyncio
while payment_id in payments:
payment = payments[payment_id]
# Check if expired
if payment['status'] == 'pending' and time.time() > payment['expires_at']:
payment['status'] = 'expired'
break
# In production, check blockchain for payment
# For demo, we'll wait for manual confirmation
await asyncio.sleep(30) # Check every 30 seconds

View File

@@ -1,151 +0,0 @@
import re
with open("/home/oib/windsurf/aitbc/apps/blockchain-node/src/aitbc_chain/models.py", "r") as f:
content = f.read()
# First fix the `__table_args__` import
content = content.replace(
"from sqlmodel import Field, Relationship, SQLModel",
"from sqlmodel import Field, Relationship, SQLModel\nfrom sqlalchemy import UniqueConstraint"
)
# Fix Block model
content = content.replace(
"""class Block(SQLModel, table=True):
__tablename__ = "block"
id: Optional[int] = Field(default=None, primary_key=True)
height: int = Field(index=True, unique=True)
hash: str = Field(index=True, unique=True)""",
"""class Block(SQLModel, table=True):
__tablename__ = "block"
__table_args__ = (UniqueConstraint("chain_id", "height", name="uix_block_chain_height"),)
id: Optional[int] = Field(default=None, primary_key=True)
chain_id: str = Field(index=True)
height: int = Field(index=True)
hash: str = Field(index=True, unique=True)"""
)
# Fix Transaction model
content = content.replace(
"""class Transaction(SQLModel, table=True):
__tablename__ = "transaction"
id: Optional[int] = Field(default=None, primary_key=True)
tx_hash: str = Field(index=True, unique=True)
block_height: Optional[int] = Field(
default=None,
index=True,
foreign_key="block.height",
)""",
"""class Transaction(SQLModel, table=True):
__tablename__ = "transaction"
__table_args__ = (UniqueConstraint("chain_id", "tx_hash", name="uix_tx_chain_hash"),)
id: Optional[int] = Field(default=None, primary_key=True)
chain_id: str = Field(index=True)
tx_hash: str = Field(index=True)
block_height: Optional[int] = Field(
default=None,
index=True,
)"""
)
# Fix Receipt model
content = content.replace(
"""class Receipt(SQLModel, table=True):
__tablename__ = "receipt"
id: Optional[int] = Field(default=None, primary_key=True)
job_id: str = Field(index=True)
receipt_id: str = Field(index=True, unique=True)
block_height: Optional[int] = Field(
default=None,
index=True,
foreign_key="block.height",
)""",
"""class Receipt(SQLModel, table=True):
__tablename__ = "receipt"
__table_args__ = (UniqueConstraint("chain_id", "receipt_id", name="uix_receipt_chain_id"),)
id: Optional[int] = Field(default=None, primary_key=True)
chain_id: str = Field(index=True)
job_id: str = Field(index=True)
receipt_id: str = Field(index=True)
block_height: Optional[int] = Field(
default=None,
index=True,
)"""
)
# Fix Account model
content = content.replace(
"""class Account(SQLModel, table=True):
__tablename__ = "account"
address: str = Field(primary_key=True)""",
"""class Account(SQLModel, table=True):
__tablename__ = "account"
chain_id: str = Field(primary_key=True)
address: str = Field(primary_key=True)"""
)
# Fix Block relationships sa_relationship_kwargs
content = content.replace(
""" transactions: List["Transaction"] = Relationship(
back_populates="block",
sa_relationship_kwargs={"lazy": "selectin"}
)""",
""" transactions: List["Transaction"] = Relationship(
back_populates="block",
sa_relationship_kwargs={
"lazy": "selectin",
"primaryjoin": "and_(Transaction.block_height==Block.height, Transaction.chain_id==Block.chain_id)",
"foreign_keys": "[Transaction.block_height, Transaction.chain_id]"
}
)"""
)
content = content.replace(
""" receipts: List["Receipt"] = Relationship(
back_populates="block",
sa_relationship_kwargs={"lazy": "selectin"}
)""",
""" receipts: List["Receipt"] = Relationship(
back_populates="block",
sa_relationship_kwargs={
"lazy": "selectin",
"primaryjoin": "and_(Receipt.block_height==Block.height, Receipt.chain_id==Block.chain_id)",
"foreign_keys": "[Receipt.block_height, Receipt.chain_id]"
}
)"""
)
# Fix reverse relationships
content = content.replace(
""" block: Optional["Block"] = Relationship(back_populates="transactions")""",
""" block: Optional["Block"] = Relationship(
back_populates="transactions",
sa_relationship_kwargs={
"primaryjoin": "and_(Transaction.block_height==Block.height, Transaction.chain_id==Block.chain_id)",
"foreign_keys": "[Transaction.block_height, Transaction.chain_id]"
}
)"""
)
content = content.replace(
""" block: Optional["Block"] = Relationship(back_populates="receipts")""",
""" block: Optional["Block"] = Relationship(
back_populates="receipts",
sa_relationship_kwargs={
"primaryjoin": "and_(Receipt.block_height==Block.height, Receipt.chain_id==Block.chain_id)",
"foreign_keys": "[Receipt.block_height, Receipt.chain_id]"
}
)"""
)
with open("/home/oib/windsurf/aitbc/apps/blockchain-node/src/aitbc_chain/models.py", "w") as f:
f.write(content)

View File

@@ -1,13 +0,0 @@
with open("/home/oib/windsurf/aitbc/apps/blockchain-node/src/aitbc_chain/consensus/poa.py", "r") as f:
content = f.read()
content = content.replace(
""" timestamp = datetime.now(timezone.utc)
block_hash = self._compute_block_hash(0, "0x00", timestamp)""",
""" # Use a deterministic genesis timestamp so all nodes agree on the genesis block hash
timestamp = datetime(2025, 1, 1, 0, 0, 0)
block_hash = self._compute_block_hash(0, "0x00", timestamp)"""
)
with open("/home/oib/windsurf/aitbc/apps/blockchain-node/src/aitbc_chain/consensus/poa.py", "w") as f:
f.write(content)

View File

@@ -1,58 +0,0 @@
#!/bin/bash
# Quick fix to start AITBC services in container
echo "🔧 Starting AITBC Services in Container"
echo "====================================="
# First, let's manually start the services
echo "1. Starting Coordinator API..."
cd /home/oib/windsurf/aitbc/apps/coordinator-api
source ../../.venv/bin/activate 2>/dev/null || source .venv/bin/activate
python -m uvicorn src.app.main:app --host 0.0.0.0 --port 8000 &
COORD_PID=$!
echo "2. Starting Blockchain Node..."
cd ../blockchain-node
python -m uvicorn aitbc_chain.app:app --host 0.0.0.0 --port 9080 &
NODE_PID=$!
echo "3. Starting Marketplace UI..."
cd ../marketplace-ui
python server.py --port 3001 &
MARKET_PID=$!
echo "4. Starting Trade Exchange..."
cd ../trade-exchange
python server.py --port 3002 &
EXCHANGE_PID=$!
echo ""
echo "✅ Services started!"
echo "Coordinator API: http://127.0.0.1:8000"
echo "Blockchain: http://127.0.0.1:9080"
echo "Marketplace: http://127.0.0.1:3001"
echo "Exchange: http://127.0.0.1:3002"
echo ""
echo "PIDs:"
echo "Coordinator: $COORD_PID"
echo "Blockchain: $NODE_PID"
echo "Marketplace: $MARKET_PID"
echo "Exchange: $EXCHANGE_PID"
echo ""
echo "To stop: kill $COORD_PID $NODE_PID $MARKET_PID $EXCHANGE_PID"
# Wait a bit for services to start
sleep 3
# Test endpoints
echo ""
echo "🧪 Testing endpoints:"
echo "API Health:"
curl -s http://127.0.0.1:8000/v1/health | head -c 100
echo -e "\n\nAdmin Stats:"
curl -s http://127.0.0.1:8000/v1/admin/stats -H "X-Api-Key: ${ADMIN_API_KEY}" | head -c 100
echo -e "\n\nMarketplace Offers:"
curl -s http://127.0.0.1:8000/v1/marketplace/offers | head -c 100