docs: add code quality and type checking workflows to master index
Some checks failed
Documentation Validation / validate-docs (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
API Endpoint Tests / test-api-endpoints (push) Has been cancelled
CLI Tests / test-cli (push) Has been cancelled
Integration Tests / test-service-integration (push) Has been cancelled
Package Tests / test-python-packages (map[name:aitbc-agent-sdk path:packages/py/aitbc-agent-sdk]) (push) Has been cancelled
Package Tests / test-python-packages (map[name:aitbc-core path:packages/py/aitbc-core]) (push) Has been cancelled
Package Tests / test-python-packages (map[name:aitbc-crypto path:packages/py/aitbc-crypto]) (push) Has been cancelled
Package Tests / test-python-packages (map[name:aitbc-sdk path:packages/py/aitbc-sdk]) (push) Has been cancelled
Package Tests / test-javascript-packages (map[name:aitbc-sdk-js path:packages/js/aitbc-sdk]) (push) Has been cancelled
Package Tests / test-javascript-packages (map[name:aitbc-token path:packages/solidity/aitbc-token]) (push) Has been cancelled
Security Scanning / security-scan (push) Has been cancelled
Systemd Sync / sync-systemd (push) Has been cancelled

- Add Code Quality Module section with pre-commit hooks and quality checks
- Add Type Checking CI/CD Module section with MyPy workflow and coverage
- Update README with code quality achievements and project structure
- Migrate FastAPI apps from deprecated on_event to lifespan context manager
- Update pyproject.toml files to reference consolidated dependencies
- Remove unused app.py import in coordinator-api
- Add type hints to agent
This commit is contained in:
aitbc
2026-03-31 21:45:43 +02:00
parent 26592ddf55
commit 9db720add8
308 changed files with 34194 additions and 34575 deletions

View File

@@ -5,19 +5,16 @@ Provides environment-based adapter selection and consolidated settings.
"""
import os
from pydantic import Field, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
from typing import List, Optional
from pathlib import Path
import secrets
import string
class DatabaseConfig(BaseSettings):
"""Database configuration with adapter selection."""
adapter: str = "sqlite" # sqlite, postgresql
url: Optional[str] = None
url: str | None = None
pool_size: int = 10
max_overflow: int = 20
pool_pre_ping: bool = True
@@ -35,17 +32,13 @@ class DatabaseConfig(BaseSettings):
# Default PostgreSQL connection string
return f"{self.adapter}://localhost:5432/coordinator"
model_config = SettingsConfigDict(
env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="allow"
)
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="allow")
class Settings(BaseSettings):
"""Unified application settings with environment-based configuration."""
model_config = SettingsConfigDict(
env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="allow"
)
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="allow")
# Environment
app_env: str = "dev"
@@ -55,7 +48,7 @@ class Settings(BaseSettings):
# Database
database: DatabaseConfig = DatabaseConfig()
# Database Connection Pooling
db_pool_size: int = Field(default=20, description="Database connection pool size")
db_max_overflow: int = Field(default=40, description="Maximum overflow connections")
@@ -64,60 +57,63 @@ class Settings(BaseSettings):
db_echo: bool = Field(default=False, description="Enable SQL query logging")
# API Keys
client_api_keys: List[str] = []
miner_api_keys: List[str] = []
admin_api_keys: List[str] = []
client_api_keys: list[str] = []
miner_api_keys: list[str] = []
admin_api_keys: list[str] = []
@field_validator('client_api_keys', 'miner_api_keys', 'admin_api_keys')
@field_validator("client_api_keys", "miner_api_keys", "admin_api_keys")
@classmethod
def validate_api_keys(cls, v: List[str]) -> List[str]:
def validate_api_keys(cls, v: list[str]) -> list[str]:
# Allow empty API keys in development/test environments
import os
if os.getenv('APP_ENV', 'dev') != 'production' and not v:
if os.getenv("APP_ENV", "dev") != "production" and not v:
return v
if not v:
raise ValueError('API keys cannot be empty in production')
raise ValueError("API keys cannot be empty in production")
for key in v:
if not key or key.startswith('$') or key == 'your_api_key_here':
raise ValueError('API keys must be set to valid values')
if not key or key.startswith("$") or key == "your_api_key_here":
raise ValueError("API keys must be set to valid values")
if len(key) < 16:
raise ValueError('API keys must be at least 16 characters long')
raise ValueError("API keys must be at least 16 characters long")
return v
# Security
hmac_secret: Optional[str] = None
jwt_secret: Optional[str] = None
hmac_secret: str | None = None
jwt_secret: str | None = None
jwt_algorithm: str = "HS256"
jwt_expiration_hours: int = 24
@field_validator('hmac_secret')
@field_validator("hmac_secret")
@classmethod
def validate_hmac_secret(cls, v: Optional[str]) -> Optional[str]:
def validate_hmac_secret(cls, v: str | None) -> str | None:
# Allow None in development/test environments
import os
if os.getenv('APP_ENV', 'dev') != 'production' and not v:
if os.getenv("APP_ENV", "dev") != "production" and not v:
return v
if not v or v.startswith('$') or v == 'your_secret_here':
raise ValueError('HMAC_SECRET must be set to a secure value')
if not v or v.startswith("$") or v == "your_secret_here":
raise ValueError("HMAC_SECRET must be set to a secure value")
if len(v) < 32:
raise ValueError('HMAC_SECRET must be at least 32 characters long')
raise ValueError("HMAC_SECRET must be at least 32 characters long")
return v
@field_validator('jwt_secret')
@field_validator("jwt_secret")
@classmethod
def validate_jwt_secret(cls, v: Optional[str]) -> Optional[str]:
def validate_jwt_secret(cls, v: str | None) -> str | None:
# Allow None in development/test environments
import os
if os.getenv('APP_ENV', 'dev') != 'production' and not v:
if os.getenv("APP_ENV", "dev") != "production" and not v:
return v
if not v or v.startswith('$') or v == 'your_secret_here':
raise ValueError('JWT_SECRET must be set to a secure value')
if not v or v.startswith("$") or v == "your_secret_here":
raise ValueError("JWT_SECRET must be set to a secure value")
if len(v) < 32:
raise ValueError('JWT_SECRET must be at least 32 characters long')
raise ValueError("JWT_SECRET must be at least 32 characters long")
return v
# CORS
allow_origins: List[str] = [
allow_origins: list[str] = [
"http://localhost:8000", # Coordinator API
"http://localhost:8001", # Exchange API
"http://localhost:8002", # Blockchain Node
@@ -151,8 +147,8 @@ class Settings(BaseSettings):
rate_limit_exchange_payment: str = "20/minute"
# Receipt Signing
receipt_signing_key_hex: Optional[str] = None
receipt_attestation_key_hex: Optional[str] = None
receipt_signing_key_hex: str | None = None
receipt_attestation_key_hex: str | None = None
# Logging
log_level: str = "INFO"
@@ -166,15 +162,13 @@ class Settings(BaseSettings):
# Test Configuration
test_mode: bool = False
test_database_url: Optional[str] = None
test_database_url: str | None = None
def validate_secrets(self) -> None:
"""Validate that all required secrets are provided."""
if self.app_env == "production":
if not self.jwt_secret:
raise ValueError(
"JWT_SECRET environment variable is required in production"
)
raise ValueError("JWT_SECRET environment variable is required in production")
if self.jwt_secret == "change-me-in-production":
raise ValueError("JWT_SECRET must be changed from default value")