refactor: add rate limiting to agent coordinator routers
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Successful in 18s
Blockchain Synchronization Verification / sync-verification (push) Failing after 2s
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 2s
Cross-Node Transaction Testing / transaction-test (push) Successful in 2s
Deploy to Testnet / deploy-testnet (push) Successful in 1m21s
Documentation Validation / validate-docs (push) Failing after 9s
Documentation Validation / validate-policies-strict (push) Successful in 4s
Integration Tests / test-service-integration (push) Successful in 2m38s
Multi-Chain Island Architecture Tests / test-multi-chain-island (push) Successful in 2s
Multi-Node Blockchain Health Monitoring / health-check (push) Successful in 2s
Multi-Node Stress Testing / stress-test (push) Successful in 3s
Python Tests / test-python (push) Has been cancelled
Security Scanning / security-scan (push) Has been cancelled
Node Failover Simulation / failover-test (push) Failing after 1h44m34s
P2P Network Verification / p2p-verification (push) Successful in 22s
Production Tests / Production Integration Tests (push) Failing after 27s
Staking Tests / test-staking-service (push) Failing after 4s
Staking Tests / test-staking-integration (push) Has been skipped
Staking Tests / test-staking-contract (push) Has been skipped
Staking Tests / run-staking-test-runner (push) Has been skipped
Cross-Chain Functionality Tests / aggregate-results (push) Successful in 2s
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Successful in 18s
Blockchain Synchronization Verification / sync-verification (push) Failing after 2s
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 2s
Cross-Node Transaction Testing / transaction-test (push) Successful in 2s
Deploy to Testnet / deploy-testnet (push) Successful in 1m21s
Documentation Validation / validate-docs (push) Failing after 9s
Documentation Validation / validate-policies-strict (push) Successful in 4s
Integration Tests / test-service-integration (push) Successful in 2m38s
Multi-Chain Island Architecture Tests / test-multi-chain-island (push) Successful in 2s
Multi-Node Blockchain Health Monitoring / health-check (push) Successful in 2s
Multi-Node Stress Testing / stress-test (push) Successful in 3s
Python Tests / test-python (push) Has been cancelled
Security Scanning / security-scan (push) Has been cancelled
Node Failover Simulation / failover-test (push) Failing after 1h44m34s
P2P Network Verification / p2p-verification (push) Successful in 22s
Production Tests / Production Integration Tests (push) Failing after 27s
Staking Tests / test-staking-service (push) Failing after 4s
Staking Tests / test-staking-integration (push) Has been skipped
Staking Tests / test-staking-contract (push) Has been skipped
Staking Tests / run-staking-test-runner (push) Has been skipped
Cross-Chain Functionality Tests / aggregate-results (push) Successful in 2s
- Added Request parameter to all endpoint functions in agents.py, ai.py, alerts.py, auth.py, and consensus.py - Added @rate_limit decorator to all endpoints with appropriate limits: - Write operations (POST/PUT/DELETE): 50 requests per 60 seconds - Read operations (GET): 200 requests per 60 seconds - High-frequency operations (heartbeat, token refresh): 100 requests per 60 seconds - Renamed conflicting request parameters (request -> request_http, request_status)
This commit is contained in:
@@ -9,10 +9,11 @@ REST API for agent creativity enhancement, ideation, and cross-domain synthesis
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from aitbc import get_logger
|
||||
from aitbc.rate_limiting import rate_limit
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -83,7 +84,10 @@ class SynthesisRequest(BaseModel):
|
||||
|
||||
|
||||
@router.post("/capabilities", response_model=CreativeCapabilityResponse)
|
||||
async def create_creative_capability(request: CreativeCapabilityCreate, session: Annotated[Session, Depends(get_session)]) -> CreativeCapabilityResponse:
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def create_creative_capability(
|
||||
request_http: Request, request: CreativeCapabilityCreate, session: Annotated[Session, Depends(get_session)]
|
||||
) -> CreativeCapabilityResponse:
|
||||
"""Initialize a new creative capability for an agent"""
|
||||
engine = CreativityEnhancementEngine()
|
||||
|
||||
@@ -104,7 +108,9 @@ async def create_creative_capability(request: CreativeCapabilityCreate, session:
|
||||
|
||||
|
||||
@router.post("/capabilities/{capability_id}/enhance")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def enhance_creativity(
|
||||
request_http: Request,
|
||||
capability_id: str, request: EnhanceCreativityRequest, session: Annotated[Session, Depends(get_session)]
|
||||
) -> dict[str, Any]:
|
||||
"""Enhance a specific creative capability using specified algorithm"""
|
||||
@@ -123,7 +129,9 @@ async def enhance_creativity(
|
||||
|
||||
|
||||
@router.post("/capabilities/{capability_id}/evaluate")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def evaluate_creation(
|
||||
request_http: Request,
|
||||
capability_id: str, request: EvaluateCreationRequest, session: Annotated[Session, Depends(get_session)]
|
||||
) -> dict[str, Any]:
|
||||
"""Evaluate a creative output and update agent capability metrics"""
|
||||
@@ -145,7 +153,10 @@ async def evaluate_creation(
|
||||
|
||||
|
||||
@router.post("/ideation/generate")
|
||||
async def generate_ideas(request: IdeationRequest) -> dict[str, Any]:
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def generate_ideas(
|
||||
request_http: Request, request: IdeationRequest
|
||||
) -> dict[str, Any]:
|
||||
"""Generate innovative ideas using specialized ideation algorithms"""
|
||||
ideation_engine = IdeationAlgorithm()
|
||||
|
||||
@@ -164,7 +175,10 @@ async def generate_ideas(request: IdeationRequest) -> dict[str, Any]:
|
||||
|
||||
|
||||
@router.post("/synthesis/cross-domain")
|
||||
async def synthesize_cross_domain(request: SynthesisRequest, session: Annotated[Session, Depends(get_session)]) -> dict[str, Any]:
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def synthesize_cross_domain(
|
||||
request_http: Request, request: SynthesisRequest, session: Annotated[Session, Depends(get_session)]
|
||||
) -> dict[str, Any]:
|
||||
"""Synthesize concepts from multiple domains to create novel outputs"""
|
||||
integrator = CrossDomainCreativeIntegrator()
|
||||
|
||||
@@ -185,7 +199,10 @@ async def synthesize_cross_domain(request: SynthesisRequest, session: Annotated[
|
||||
|
||||
|
||||
@router.get("/capabilities/{agent_id}")
|
||||
async def list_agent_creative_capabilities(agent_id: str, session: Annotated[Session, Depends(get_session)]) -> list[CreativeCapability]:
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def list_agent_creative_capabilities(
|
||||
request: Request, agent_id: str, session: Annotated[Session, Depends(get_session)]
|
||||
) -> list[CreativeCapability]:
|
||||
"""List all creative capabilities for a specific agent"""
|
||||
try:
|
||||
capabilities = session.execute(select(CreativeCapability).where(CreativeCapability.agent_id == agent_id)).all()
|
||||
|
||||
@@ -5,9 +5,10 @@ Agent Integration and Deployment API Router for Verifiable AI Agent Orchestratio
|
||||
Provides REST API endpoints for production deployment and integration management
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
|
||||
from aitbc import get_logger
|
||||
from aitbc.rate_limiting import rate_limit
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -31,7 +32,9 @@ router = APIRouter(prefix="/agents/integration", tags=["Agent Integration"])
|
||||
|
||||
|
||||
@router.post("/deployments/config", response_model=AgentDeploymentConfig)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def create_deployment_config(
|
||||
request: Request,
|
||||
workflow_id: str,
|
||||
deployment_name: str,
|
||||
deployment_config: dict,
|
||||
@@ -65,7 +68,9 @@ async def create_deployment_config(
|
||||
|
||||
|
||||
@router.get("/deployments/configs", response_model=list[AgentDeploymentConfig])
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def list_deployment_configs(
|
||||
request: Request,
|
||||
workflow_id: str | None = None,
|
||||
status: DeploymentStatus | None = None,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
@@ -99,7 +104,9 @@ async def list_deployment_configs(
|
||||
|
||||
|
||||
@router.get("/deployments/configs/{config_id}", response_model=AgentDeploymentConfig)
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_deployment_config(
|
||||
request: Request,
|
||||
config_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -126,7 +133,9 @@ async def get_deployment_config(
|
||||
|
||||
|
||||
@router.post("/deployments/{config_id}/deploy")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def deploy_workflow(
|
||||
request: Request,
|
||||
config_id: str,
|
||||
target_environment: str = "production",
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
@@ -160,7 +169,9 @@ async def deploy_workflow(
|
||||
|
||||
|
||||
@router.get("/deployments/{config_id}/health")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_deployment_health(
|
||||
request: Request,
|
||||
config_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -190,7 +201,9 @@ async def get_deployment_health(
|
||||
|
||||
|
||||
@router.post("/deployments/{config_id}/scale")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def scale_deployment(
|
||||
request: Request,
|
||||
config_id: str,
|
||||
target_instances: int,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
@@ -224,7 +237,9 @@ async def scale_deployment(
|
||||
|
||||
|
||||
@router.post("/deployments/{config_id}/rollback")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def rollback_deployment(
|
||||
request: Request,
|
||||
config_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -255,7 +270,9 @@ async def rollback_deployment(
|
||||
|
||||
|
||||
@router.get("/deployments/instances", response_model=list[AgentDeploymentInstance])
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def list_deployment_instances(
|
||||
request: Request,
|
||||
deployment_id: str | None = None,
|
||||
environment: str | None = None,
|
||||
status: DeploymentStatus | None = None,
|
||||
@@ -295,7 +312,9 @@ async def list_deployment_instances(
|
||||
|
||||
|
||||
@router.get("/deployments/instances/{instance_id}", response_model=AgentDeploymentInstance)
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_deployment_instance(
|
||||
request: Request,
|
||||
instance_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -326,7 +345,9 @@ async def get_deployment_instance(
|
||||
|
||||
|
||||
@router.post("/integrations/zk/{execution_id}")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def integrate_with_zk_system(
|
||||
request: Request,
|
||||
execution_id: str,
|
||||
verification_level: VerificationLevel = VerificationLevel.BASIC,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
@@ -360,7 +381,9 @@ async def integrate_with_zk_system(
|
||||
|
||||
|
||||
@router.get("/metrics/deployments/{deployment_id}")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_deployment_metrics(
|
||||
request: Request,
|
||||
deployment_id: str,
|
||||
time_range: str = "1h",
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
@@ -391,7 +414,9 @@ async def get_deployment_metrics(
|
||||
|
||||
|
||||
@router.post("/production/deploy")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def deploy_to_production(
|
||||
request: Request,
|
||||
workflow_id: str,
|
||||
deployment_config: dict,
|
||||
integration_config: dict | None = None,
|
||||
@@ -425,7 +450,9 @@ async def deploy_to_production(
|
||||
|
||||
|
||||
@router.get("/production/dashboard")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_production_dashboard(
|
||||
request: Request,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]), current_user: str = Depends(require_admin_key())
|
||||
) -> dict[str, Any]:
|
||||
"""Get comprehensive production dashboard data"""
|
||||
@@ -479,7 +506,9 @@ async def get_production_dashboard(
|
||||
|
||||
|
||||
@router.get("/production/health")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_production_health(
|
||||
request: Request,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]), current_user: str = Depends(require_admin_key())
|
||||
) -> dict[str, Any]:
|
||||
"""Get overall production health status"""
|
||||
@@ -549,7 +578,9 @@ async def get_production_health(
|
||||
|
||||
|
||||
@router.get("/production/alerts")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_production_alerts(
|
||||
request: Request,
|
||||
severity: str | None = None,
|
||||
limit: int = 50,
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
|
||||
@@ -10,10 +10,11 @@ REST API for meta-learning, resource optimization, and performance enhancement
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from aitbc import get_logger
|
||||
from aitbc.rate_limiting import rate_limit
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -176,7 +177,9 @@ class CapabilityResponse(BaseModel):
|
||||
|
||||
|
||||
@router.post("/profiles", response_model=PerformanceProfileResponse)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def create_performance_profile(
|
||||
request: Request,
|
||||
profile_request: PerformanceProfileRequest, session: Annotated[Session, Depends(get_session)]
|
||||
) -> PerformanceProfileResponse:
|
||||
"""Create agent performance profile"""
|
||||
@@ -214,7 +217,10 @@ async def create_performance_profile(
|
||||
|
||||
|
||||
@router.get("/profiles/{agent_id}", response_model=Dict[str, Any])
|
||||
async def get_performance_profile(agent_id: str, session: Annotated[Session, Depends(get_session)]) -> Dict[str, Any]:
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_performance_profile(
|
||||
request: Request, agent_id: str, session: Annotated[Session, Depends(get_session)]
|
||||
) -> Dict[str, Any]:
|
||||
"""Get agent performance profile"""
|
||||
|
||||
performance_service = AgentPerformanceService(session)
|
||||
@@ -235,7 +241,9 @@ async def get_performance_profile(agent_id: str, session: Annotated[Session, Dep
|
||||
|
||||
|
||||
@router.post("/profiles/{agent_id}/metrics")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def update_performance_metrics(
|
||||
request: Request,
|
||||
agent_id: str,
|
||||
metrics: Dict[str, float],
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
@@ -264,7 +272,9 @@ async def update_performance_metrics(
|
||||
|
||||
|
||||
@router.post("/meta-learning/models", response_model=MetaLearningResponse)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def create_meta_learning_model(
|
||||
request: Request,
|
||||
model_request: MetaLearningRequest, session: Annotated[Session, Depends(get_session)]
|
||||
) -> MetaLearningResponse:
|
||||
"""Create meta-learning model"""
|
||||
@@ -300,7 +310,9 @@ async def create_meta_learning_model(
|
||||
|
||||
|
||||
@router.post("/meta-learning/models/{model_id}/adapt")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def adapt_model_to_task(
|
||||
request: Request,
|
||||
model_id: str,
|
||||
task_data: Dict[str, Any],
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
@@ -330,7 +342,9 @@ async def adapt_model_to_task(
|
||||
|
||||
|
||||
@router.get("/meta-learning/models")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def list_meta_learning_models(
|
||||
request: Request,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
status: Optional[str] = Query(default=None, description="Filter by status"),
|
||||
meta_strategy: Optional[str] = Query(default=None, description="Filter by meta strategy"),
|
||||
@@ -373,7 +387,9 @@ async def list_meta_learning_models(
|
||||
|
||||
|
||||
@router.post("/resources/allocate", response_model=ResourceAllocationResponse)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def allocate_resources(
|
||||
request: Request,
|
||||
allocation_request: ResourceAllocationRequest, session: Annotated[Session, Depends(get_session)]
|
||||
) -> ResourceAllocationResponse:
|
||||
"""Allocate resources for agent task"""
|
||||
@@ -408,7 +424,9 @@ async def allocate_resources(
|
||||
|
||||
|
||||
@router.get("/resources/{agent_id}")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_resource_allocations(
|
||||
request: Request,
|
||||
agent_id: str,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
status: Optional[str] = Query(default=None, description="Filter by status"),
|
||||
@@ -453,7 +471,9 @@ async def get_resource_allocations(
|
||||
|
||||
|
||||
@router.post("/optimization/optimize", response_model=PerformanceOptimizationResponse)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def optimize_performance(
|
||||
request: Request,
|
||||
optimization_request: PerformanceOptimizationRequest, session: Annotated[Session, Depends(get_session)]
|
||||
) -> PerformanceOptimizationResponse:
|
||||
"""Optimize agent performance"""
|
||||
@@ -488,7 +508,9 @@ async def optimize_performance(
|
||||
|
||||
|
||||
@router.get("/optimization/{agent_id}")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_optimization_history(
|
||||
request: Request,
|
||||
agent_id: str,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
status: Optional[str] = Query(default=None, description="Filter by status"),
|
||||
@@ -537,7 +559,9 @@ async def get_optimization_history(
|
||||
|
||||
|
||||
@router.post("/capabilities", response_model=CapabilityResponse)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def create_capability(
|
||||
request: Request,
|
||||
capability_request: CapabilityRequest, session: Annotated[Session, Depends(get_session)]
|
||||
) -> CapabilityResponse:
|
||||
"""Create agent capability"""
|
||||
@@ -580,7 +604,9 @@ async def create_capability(
|
||||
|
||||
|
||||
@router.get("/capabilities/{agent_id}")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_agent_capabilities(
|
||||
request: Request,
|
||||
agent_id: str,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
capability_type: Optional[str] = Query(default=None, description="Filter by capability type"),
|
||||
@@ -631,7 +657,9 @@ async def get_agent_capabilities(
|
||||
|
||||
|
||||
@router.get("/analytics/performance-summary")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_performance_summary(
|
||||
request: Request,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
agent_ids: List[str] = Query(default=[], description="List of agent IDs"),
|
||||
metric: Optional[str] = Query(default="overall_score", description="Metric to summarize"),
|
||||
@@ -713,7 +741,10 @@ def calculate_specialization_distribution(summaries: List[Dict[str, Any]]) -> Di
|
||||
|
||||
|
||||
@router.get("/health")
|
||||
async def health_check() -> Dict[str, Any]:
|
||||
@rate_limit(rate=1000, per=60)
|
||||
async def health_check(
|
||||
request: Request
|
||||
) -> Dict[str, Any]:
|
||||
"""Health check for agent performance service"""
|
||||
|
||||
return {
|
||||
|
||||
@@ -10,9 +10,10 @@ Provides REST API endpoints for agent workflow management and execution
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Request
|
||||
|
||||
from aitbc import get_logger
|
||||
from aitbc.rate_limiting import rate_limit
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -35,7 +36,9 @@ router = APIRouter(tags=["AI Agents"])
|
||||
|
||||
|
||||
@router.post("/workflows", response_model=AIAgentWorkflow)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def create_workflow(
|
||||
request: Request,
|
||||
workflow_data: AgentWorkflowCreate,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -58,7 +61,9 @@ async def create_workflow(
|
||||
|
||||
|
||||
@router.get("/workflows", response_model=list[AIAgentWorkflow])
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def list_workflows(
|
||||
request: Request,
|
||||
owner_id: str | None = None,
|
||||
is_public: bool | None = None,
|
||||
tags: list[str] | None = None,
|
||||
@@ -94,7 +99,9 @@ async def list_workflows(
|
||||
|
||||
|
||||
@router.get("/workflows/{workflow_id}", response_model=AIAgentWorkflow)
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_workflow(
|
||||
request: Request,
|
||||
workflow_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -120,7 +127,9 @@ async def get_workflow(
|
||||
|
||||
|
||||
@router.put("/workflows/{workflow_id}", response_model=AIAgentWorkflow)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def update_workflow(
|
||||
request: Request,
|
||||
workflow_id: str,
|
||||
workflow_data: AgentWorkflowUpdate,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
@@ -157,7 +166,9 @@ async def update_workflow(
|
||||
|
||||
|
||||
@router.delete("/workflows/{workflow_id}")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def delete_workflow(
|
||||
request: Request,
|
||||
workflow_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -187,7 +198,9 @@ async def delete_workflow(
|
||||
|
||||
|
||||
@router.post("/workflows/{workflow_id}/execute", response_model=AgentExecutionResponse)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def execute_workflow(
|
||||
request: Request,
|
||||
workflow_id: str,
|
||||
execution_request: AgentExecutionRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
@@ -233,7 +246,9 @@ async def execute_workflow(
|
||||
|
||||
|
||||
@router.get("/executions/{execution_id}/status", response_model=AgentExecutionStatus)
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_execution_status(
|
||||
request: Request,
|
||||
execution_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -264,7 +279,9 @@ async def get_execution_status(
|
||||
|
||||
|
||||
@router.get("/executions", response_model=list[AgentExecutionStatus])
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def list_executions(
|
||||
request: Request,
|
||||
workflow_id: str | None = None,
|
||||
status: AgentStatus | None = None,
|
||||
limit: int = 50,
|
||||
@@ -325,7 +342,9 @@ async def list_executions(
|
||||
|
||||
|
||||
@router.post("/executions/{execution_id}/cancel")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def cancel_execution(
|
||||
request: Request,
|
||||
execution_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -365,7 +384,9 @@ async def cancel_execution(
|
||||
|
||||
|
||||
@router.get("/executions/{execution_id}/logs")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_execution_logs(
|
||||
request: Request,
|
||||
execution_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -423,13 +444,18 @@ async def get_execution_logs(
|
||||
|
||||
|
||||
@router.get("/test")
|
||||
async def test_endpoint() -> dict[str, str]:
|
||||
@rate_limit(rate=1000, per=60)
|
||||
async def test_endpoint(
|
||||
request: Request
|
||||
) -> dict[str, str]:
|
||||
"""Test endpoint to verify router is working"""
|
||||
return {"message": "Agent router is working", "timestamp": datetime.now(timezone.utc).isoformat()}
|
||||
|
||||
|
||||
@router.post("/networks", response_model=dict, status_code=201)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def create_agent_network(
|
||||
request: Request,
|
||||
network_data: dict,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -469,7 +495,9 @@ async def create_agent_network(
|
||||
|
||||
|
||||
@router.get("/executions/{execution_id}/receipt")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_execution_receipt(
|
||||
request: Request,
|
||||
execution_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
|
||||
@@ -7,9 +7,13 @@ Agent Security API Router for Verifiable AI Agent Orchestration
|
||||
Provides REST API endpoints for security management and auditing
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
|
||||
from aitbc import get_logger
|
||||
from aitbc.rate_limiting import rate_limit
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -34,7 +38,9 @@ router = APIRouter(prefix="/agents/security", tags=["Agent Security"])
|
||||
|
||||
|
||||
@router.post("/policies", response_model=AgentSecurityPolicy)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def create_security_policy(
|
||||
request: Request,
|
||||
name: str,
|
||||
description: str,
|
||||
security_level: SecurityLevel,
|
||||
@@ -59,7 +65,9 @@ async def create_security_policy(
|
||||
|
||||
|
||||
@router.get("/policies", response_model=list[AgentSecurityPolicy])
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def list_security_policies(
|
||||
request: Request,
|
||||
security_level: SecurityLevel | None = None,
|
||||
is_active: bool | None = None,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
@@ -85,7 +93,9 @@ async def list_security_policies(
|
||||
|
||||
|
||||
@router.get("/policies/{policy_id}", response_model=AgentSecurityPolicy)
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_security_policy(
|
||||
request: Request,
|
||||
policy_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -107,7 +117,9 @@ async def get_security_policy(
|
||||
|
||||
|
||||
@router.put("/policies/{policy_id}", response_model=AgentSecurityPolicy)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def update_security_policy(
|
||||
request: Request,
|
||||
policy_id: str,
|
||||
policy_updates: dict,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
@@ -150,7 +162,9 @@ async def update_security_policy(
|
||||
|
||||
|
||||
@router.delete("/policies/{policy_id}")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def delete_security_policy(
|
||||
request: Request,
|
||||
policy_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -186,7 +200,9 @@ async def delete_security_policy(
|
||||
|
||||
|
||||
@router.post("/validate-workflow/{workflow_id}")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def validate_workflow_security(
|
||||
request: Request,
|
||||
workflow_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -215,7 +231,9 @@ async def validate_workflow_security(
|
||||
|
||||
|
||||
@router.get("/audit-logs", response_model=list[AgentAuditLog])
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def list_audit_logs(
|
||||
request: Request,
|
||||
event_type: AuditEventType | None = None,
|
||||
workflow_id: str | None = None,
|
||||
execution_id: str | None = None,
|
||||
@@ -267,7 +285,9 @@ async def list_audit_logs(
|
||||
|
||||
|
||||
@router.get("/audit-logs/{audit_id}", response_model=AgentAuditLog)
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_audit_log(
|
||||
request: Request,
|
||||
audit_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -290,7 +310,9 @@ async def get_audit_log(
|
||||
|
||||
|
||||
@router.get("/trust-scores")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def list_trust_scores(
|
||||
request: Request,
|
||||
entity_type: str | None = None,
|
||||
entity_id: str | None = None,
|
||||
min_score: float | None = None,
|
||||
@@ -330,7 +352,9 @@ async def list_trust_scores(
|
||||
|
||||
|
||||
@router.get("/trust-scores/{entity_type}/{entity_id}", response_model=AgentTrustScore)
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_trust_score(
|
||||
request: Request,
|
||||
entity_type: str,
|
||||
entity_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
@@ -360,7 +384,9 @@ async def get_trust_score(
|
||||
|
||||
|
||||
@router.post("/trust-scores/{entity_type}/{entity_id}/update")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def update_trust_score(
|
||||
request: Request,
|
||||
entity_type: str,
|
||||
entity_id: str,
|
||||
execution_success: bool,
|
||||
@@ -409,7 +435,9 @@ async def update_trust_score(
|
||||
|
||||
|
||||
@router.post("/sandbox/{execution_id}/create")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def create_sandbox(
|
||||
request: Request,
|
||||
execution_id: str,
|
||||
security_level: SecurityLevel = SecurityLevel.PUBLIC,
|
||||
workflow_requirements: dict | None = None,
|
||||
@@ -447,7 +475,9 @@ async def create_sandbox(
|
||||
|
||||
|
||||
@router.get("/sandbox/{execution_id}/monitor")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def monitor_sandbox(
|
||||
request: Request,
|
||||
execution_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -466,7 +496,9 @@ async def monitor_sandbox(
|
||||
|
||||
|
||||
@router.post("/sandbox/{execution_id}/cleanup")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def cleanup_sandbox(
|
||||
request: Request,
|
||||
execution_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
current_user: str = Depends(require_admin_key()),
|
||||
@@ -495,7 +527,9 @@ async def cleanup_sandbox(
|
||||
|
||||
|
||||
@router.post("/executions/{execution_id}/security-monitor")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def monitor_execution_security(
|
||||
request: Request,
|
||||
execution_id: str,
|
||||
workflow_id: str,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]),
|
||||
@@ -515,7 +549,9 @@ async def monitor_execution_security(
|
||||
|
||||
|
||||
@router.get("/security-dashboard")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_security_dashboard(
|
||||
request: Request,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]), current_user: str = Depends(require_admin_key())
|
||||
) -> dict[str, Any]:
|
||||
"""Get comprehensive security dashboard data"""
|
||||
@@ -570,7 +606,9 @@ async def get_security_dashboard(
|
||||
|
||||
|
||||
@router.get("/security-stats")
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_security_statistics(
|
||||
request: Request,
|
||||
session: Session = Depends(Annotated[Session, Depends(get_session)]), current_user: str = Depends(require_admin_key())
|
||||
) -> dict[str, Any]:
|
||||
"""Get security statistics and metrics"""
|
||||
|
||||
@@ -8,8 +8,9 @@ Services router for specific GPU workloads
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Depends, Header, HTTPException, status
|
||||
from fastapi import APIRouter, Depends, Header, HTTPException, Request, status
|
||||
|
||||
from aitbc.rate_limiting import rate_limit
|
||||
from ..deps import require_client_key
|
||||
from ..models.services import (
|
||||
BlenderRequest,
|
||||
@@ -37,7 +38,9 @@ router = APIRouter(tags=["services"])
|
||||
summary="Submit a service-specific job",
|
||||
deprecated=True,
|
||||
)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def submit_service_job(
|
||||
request_http: Request,
|
||||
service_type: ServiceType,
|
||||
request_data: dict[str, Any],
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
@@ -105,7 +108,9 @@ async def submit_service_job(
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
summary="Transcribe audio using Whisper",
|
||||
)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def whisper_transcribe(
|
||||
request_http: Request,
|
||||
request: WhisperRequest,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
client_id: str = Depends(require_client_key()),
|
||||
@@ -136,7 +141,9 @@ async def whisper_transcribe(
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
summary="Translate audio using Whisper",
|
||||
)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def whisper_translate(
|
||||
request_http: Request,
|
||||
request: WhisperRequest,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
client_id: str = Depends(require_client_key()),
|
||||
@@ -170,7 +177,9 @@ async def whisper_translate(
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
summary="Generate images using Stable Diffusion",
|
||||
)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def stable_diffusion_generate(
|
||||
request_http: Request,
|
||||
request: StableDiffusionRequest,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
client_id: str = Depends(require_client_key()),
|
||||
@@ -203,7 +212,9 @@ async def stable_diffusion_generate(
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
summary="Image-to-image generation",
|
||||
)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def stable_diffusion_img2img(
|
||||
request_http: Request,
|
||||
request: StableDiffusionRequest,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
client_id: str = Depends(require_client_key()),
|
||||
@@ -235,7 +246,9 @@ async def stable_diffusion_img2img(
|
||||
@router.post(
|
||||
"/services/llm/inference", response_model=ServiceResponse, status_code=status.HTTP_201_CREATED, summary="Run LLM inference"
|
||||
)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def llm_inference(
|
||||
request_http: Request,
|
||||
request: LLMRequest,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
client_id: str = Depends(require_client_key()),
|
||||
@@ -263,7 +276,9 @@ async def llm_inference(
|
||||
|
||||
|
||||
@router.post("/services/llm/stream", summary="Stream LLM inference")
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def llm_stream(
|
||||
request_http: Request,
|
||||
request: LLMRequest,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
client_id: str = Depends(require_client_key()),
|
||||
@@ -299,7 +314,9 @@ async def llm_stream(
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
summary="Transcode video using FFmpeg",
|
||||
)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def ffmpeg_transcode(
|
||||
request_http: Request,
|
||||
request: FFmpegRequest,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
client_id: str = Depends(require_client_key()),
|
||||
@@ -334,7 +351,9 @@ async def ffmpeg_transcode(
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
summary="Render using Blender",
|
||||
)
|
||||
@rate_limit(rate=50, per=60)
|
||||
async def blender_render(
|
||||
request_http: Request,
|
||||
request: BlenderRequest,
|
||||
session: Annotated[Session, Depends(get_session)],
|
||||
client_id: str = Depends(require_client_key()),
|
||||
@@ -366,7 +385,10 @@ async def blender_render(
|
||||
|
||||
# Utility endpoints
|
||||
@router.get("/services", summary="List available services")
|
||||
async def list_services() -> dict[str, Any]:
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def list_services(
|
||||
request: Request
|
||||
) -> dict[str, Any]:
|
||||
"""List all available service types and their capabilities"""
|
||||
return {
|
||||
"services": [
|
||||
@@ -425,7 +447,10 @@ async def list_services() -> dict[str, Any]:
|
||||
|
||||
|
||||
@router.get("/services/{service_type}/schema", summary="Get service request schema", deprecated=True)
|
||||
async def get_service_schema(service_type: ServiceType) -> dict[str, Any]:
|
||||
@rate_limit(rate=200, per=60)
|
||||
async def get_service_schema(
|
||||
request: Request, service_type: ServiceType
|
||||
) -> dict[str, Any]:
|
||||
"""Get the JSON schema for a specific service type
|
||||
|
||||
DEPRECATED: Use /v1/registry/services/{service_id}/schema instead.
|
||||
|
||||
Reference in New Issue
Block a user