Spaces:
Sleeping
Sleeping
| from dataclasses import asdict | |
| import asyncio | |
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel, HttpUrl | |
| from starlette.concurrency import run_in_threadpool | |
| from .engine import assess | |
| from .fetcher import ProfileNotFound, fetch_profile | |
| from .link_resolver import resolve_link | |
| app = FastAPI(title="BMC RiskEngine API", version="1.0.0") | |
| class AssessRequest(BaseModel): | |
| bmc_url: HttpUrl | |
| class ErrorResponse(BaseModel): | |
| detail: str | |
| class AssessResponse(BaseModel): | |
| risk_score: int | |
| risk_level: str | |
| recommended_action: str | |
| evidence: list | |
| limitations: list | |
| async def _analyze(bmc_url: str): | |
| profile = await run_in_threadpool(fetch_profile, bmc_url) | |
| resolved_links = [] | |
| # for link in profile.external_links: | |
| # resolved = await run_in_threadpool(resolve_link, link) | |
| # resolved_links.append(resolved) | |
| tasks = [run_in_threadpool(resolve_link, link) for link in profile.external_links] | |
| resolved_links = await asyncio.gather(*tasks) | |
| assessment = assess(profile, resolved_links) | |
| return asdict(assessment) | |
| async def assess_profile(payload: AssessRequest): | |
| try: | |
| result = await _analyze(str(payload.bmc_url)) | |
| except ProfileNotFound as exc: | |
| raise HTTPException(status_code=404, detail="Profile not found") from exc | |
| except Exception as exc: | |
| # TODO: need to log real exceptions | |
| raise HTTPException(status_code=500, detail="Internal server error") from exc | |
| return result | |
| async def root(): | |
| return { | |
| "message": "Welcome to the BMC RiskEngine API. Use the /assess endpoint to evaluate a BMC profile." | |
| } | |