Benard John
feat: implement feedback API endpoint and add new frontend views for status, legal, and documentation pages.
2a72aeb | """ | |
| Ukweli — Feedback Endpoint | |
| POST /feedback — Collect user ratings and corrections on RAG responses. | |
| Requires registered or higher tier (per Endpoint Security Matrix). | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| from fastapi import APIRouter, Depends, HTTPException, status | |
| from sqlalchemy import select | |
| from sqlalchemy.ext.asyncio import AsyncSession | |
| from app.api.auth import AuthContext, require_auth | |
| from app.db.session import get_db_session | |
| from app.models.database import Feedback, QueryLog | |
| from app.models.enums import AuthTier | |
| from app.models.schemas import FeedbackRequest, FeedbackResponse | |
| logger = logging.getLogger("ukweli.api.feedback") | |
| router = APIRouter(tags=["Feedback"]) | |
| async def submit_feedback( | |
| request: FeedbackRequest, | |
| db: AsyncSession = Depends(get_db_session), | |
| auth: AuthContext = Depends(require_auth), | |
| ) -> FeedbackResponse: | |
| """ | |
| Submit feedback on a query response. | |
| Validates that the query_id exists before recording. | |
| """ | |
| # Verify tier requirements (Registered or higher) | |
| if auth.tier == AuthTier.PUBLIC.value: | |
| raise HTTPException( | |
| status_code=status.HTTP_403_FORBIDDEN, | |
| detail="Feedback submission requires a registered account or API key.", | |
| ) | |
| # Verify the query exists | |
| result = await db.execute( | |
| select(QueryLog.id).where(QueryLog.id == request.query_id) | |
| ) | |
| query_exists = result.scalar_one_or_none() | |
| if query_exists is None: | |
| raise HTTPException( | |
| status_code=status.HTTP_404_NOT_FOUND, | |
| detail=f"Query ID {request.query_id} not found.", | |
| ) | |
| # Create feedback record | |
| feedback = Feedback( | |
| query_id=request.query_id, | |
| rating=request.rating.value, | |
| correction=request.correction, | |
| suggested_citation=request.suggested_citation, | |
| review_status="pending", | |
| ) | |
| db.add(feedback) | |
| await db.flush() | |
| logger.info( | |
| "Feedback recorded: query_id=%s, tier=%s, rating=%d, has_correction=%s", | |
| request.query_id, | |
| auth.tier, | |
| request.rating.value, | |
| request.correction is not None, | |
| ) | |
| return FeedbackResponse(status="recorded", review_status="pending") | |