ARF-Sandbox-API / app.py
petter2025's picture
Create app.py
8705a00 verified
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
import random
import time
app = FastAPI(
title="ARF Sandbox API",
description="Mock endpoint – does NOT use the real Bayesian engine. Simulated responses only.",
version="1.0.0",
docs_url="/docs",
redoc_url="/redoc",
)
# ---------- Request/Response Models ----------
class Metrics(BaseModel):
latency_ms: Optional[float] = None
error_rate: Optional[float] = None
throughput: Optional[float] = None
cpu_usage: Optional[float] = None
class EvaluateRequest(BaseModel):
service_name: str
event_type: str # e.g., "latency", "error_rate", "cpu_spike"
severity: str # "low", "medium", "high", "critical"
metrics: Optional[Metrics] = None
timestamp: Optional[float] = None
class EvaluateResponse(BaseModel):
status: str
recommendation: str # "APPROVE", "DENY", "ESCALATE"
risk_score: float
confidence: float
justification: str
policy_violations: list
# ---------- Mock Logic ----------
def generate_mock_response(request: EvaluateRequest) -> EvaluateResponse:
# Deterministic randomness based on service name and event type
seed = hash((request.service_name, request.event_type, request.severity)) % 1000
random.seed(seed)
# Simulate risk score based on severity
severity_map = {"low": 0.2, "medium": 0.4, "high": 0.7, "critical": 0.9}
base_risk = severity_map.get(request.severity, 0.5)
# Add small random noise
risk = min(0.99, max(0.01, base_risk + random.uniform(-0.1, 0.1)))
# Decision logic (mock)
if risk < 0.3:
rec = "APPROVE"
elif risk > 0.8:
rec = "DENY"
else:
rec = "ESCALATE"
# Confidence inversely related to uncertainty (simulated)
confidence = 1.0 - (risk * 0.3) + random.uniform(-0.05, 0.05)
confidence = min(0.99, max(0.5, confidence))
# Justification template
justification = (
f"Simulated evaluation for {request.service_name}: {request.event_type} severity={request.severity}. "
f"Risk score {risk:.2f}{rec}. (Mock response, not real inference.)"
)
return EvaluateResponse(
status="success",
recommendation=rec,
risk_score=round(risk, 4),
confidence=round(confidence, 4),
justification=justification,
policy_violations=[]
)
# ---------- Endpoints ----------
@app.get("/health", tags=["health"])
async def health():
return {"status": "ok", "timestamp": time.time()}
@app.post("/v1/evaluate", response_model=EvaluateResponse, tags=["evaluation"])
async def evaluate(request: EvaluateRequest):
# Simple input validation
if not request.service_name or not request.event_type:
raise HTTPException(status_code=400, detail="Missing service_name or event_type")
return generate_mock_response(request)
# ---------- Root redirect to docs ----------
@app.get("/", include_in_schema=False)
async def root():
return {"message": "ARF Sandbox API. See /docs for interactive documentation."}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)