"""REST API for findings (across all scans).""" from fastapi import APIRouter, Depends, Query from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from guarddog_nexus.database import get_session from guarddog_nexus.models import Finding router = APIRouter(prefix="/api/v1/findings", tags=["findings"]) @router.get("") async def list_findings( limit: int = Query(50, le=200), offset: int = Query(0, ge=0), rule: str | None = Query(None), severity: str | None = Query(None), scan_id: int | None = Query(None), session: AsyncSession = Depends(get_session), ): q = select(Finding) if rule: q = q.where(func.json_extract(Finding.data, "$.rule") == rule) if severity: q = q.where(func.json_extract(Finding.data, "$.severity") == severity) if scan_id: q = q.where(Finding.scan_id == scan_id) total = await session.scalar(select(func.count()).select_from(q.subquery())) findings = (await session.execute(q.offset(offset).limit(limit))).scalars().all() return { "total": total, "limit": limit, "offset": offset, "findings": [ { "id": f.id, "scan_id": f.scan_id, **f.data, "created_at": f.created_at.isoformat() if f.created_at else None, } for f in findings ], }