Files
boc/landvex-admin-backend/app/routers/aid_intelligence_v2.py
T
Bernt aee0f09db8 landvex: Fixar och tester klara för alla komponenter
- Datafabrik: Dockerfile fix, agentorkestrering fungerar
- Vision: Identify-modell, FAISS, OCR alla testade
- API: Alla 7 integrationstester passerade
- Upplösare: Entitetsupplösning verifierad
2026-07-05 06:41:32 +00:00

484 lines
20 KiB
Python

"""
Landvex Aid Intelligence v2 - Evidence-Based Impact Verification
Independent platform for measuring, verifying and improving development aid outcomes.
"""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List, Optional, Dict, Any
from datetime import datetime
from enum import Enum
from app.database import get_db
from app.core.security import get_current_user
from app.models import User
router = APIRouter(prefix="/aid-v2", tags=["aid_intelligence_v2"])
class VerificationStatus(str, Enum):
VERIFIED = "verified"
PARTIALLY_VERIFIED = "partially_verified"
INSUFFICIENT_EVIDENCE = "insufficient_evidence"
CONTRADICTION_DETECTED = "contradiction_detected"
NOT_VERIFIED = "not_verified"
class EvidenceType(str, Enum):
SATELLITE = "satellite"
FIELD_OBSERVATION = "field_observation"
AI_ANALYSIS = "ai_analysis"
OPEN_DATA = "open_data"
OFFICIAL_REPORT = "official_report"
COMMUNITY_FEEDBACK = "community_feedback"
# ─── PUBLIC ENDPOINTS ─────────────────────────────────────────────────────────
@router.get("/public/philosophy")
async def get_philosophy():
"""Core philosophy and brand position."""
return {
"mission": "Build Landvex Aid Intelligence as the world's leading independent platform for measuring, verifying and improving the real-world impact of development aid.",
"principles": [
"Evidence over speculation",
"Transparency over opacity",
"Continuous learning over blame",
"Independent verification over assumptions",
"Long-term societal outcomes over short-term activity metrics",
],
"position": "We believe development aid should create measurable, sustainable improvements. We measure observable progress rather than assuming success or failure.",
"commitment": "Our purpose is not to advocate for or against any organization. Our purpose is to increase transparency, accountability and learning by making observable outcomes measurable.",
}
@router.get("/public/projects")
async def list_projects(
country: Optional[str] = None,
sector: Optional[str] = None,
verification_status: Optional[VerificationStatus] = None,
):
"""List development projects with verification status."""
projects = [
{
"id": "proj-001",
"name": "Mogadishu Primary School Renovation",
"country": "Somalia",
"region": "East Africa",
"sector": "education",
"funding_agency": "UNICEF",
"budget_usd": 250000,
"verification_status": "partially_verified",
"confidence_score": 72,
"evidence_count": 156,
"last_observation": "2026-07-03",
"key_findings": [
"Infrastructure 85% complete (observed)",
"Interior work ongoing",
"2 weeks behind reported schedule",
],
"discrepancies": [
{
"type": "schedule_variance",
"description": "Reported completion 95% vs observed 85%",
"confidence": 78,
"severity": "medium",
}
],
},
{
"id": "proj-002",
"name": "Kampala Water Supply Extension",
"country": "Uganda",
"region": "East Africa",
"sector": "water",
"funding_agency": "World Bank",
"budget_usd": 1200000,
"verification_status": "verified",
"confidence_score": 88,
"evidence_count": 203,
"last_observation": "2026-07-02",
"key_findings": [
"Infrastructure operational",
"Community utilization high",
"Maintenance schedule followed",
],
"discrepancies": [],
},
]
if country:
projects = [p for p in projects if p["country"].lower() == country.lower()]
if sector:
projects = [p for p in projects if p["sector"] == sector]
if verification_status:
projects = [p for p in projects if p["verification_status"] == verification_status.value]
return {
"projects": projects,
"total": len(projects),
"methodology": "All findings are evidence-based and include confidence scores. Discrepancies are signals for further review, not conclusions of wrongdoing.",
}
@router.get("/public/projects/{project_id}/evidence")
async def get_project_evidence(project_id: str):
"""Get all evidence for a project with transparency layer."""
return {
"project_id": project_id,
"evidence_chain": [
{
"id": "ev-001",
"type": "field_observation",
"date": "2026-07-03",
"source": "QUIXZOOM contributor",
"location": {"lat": 2.0469, "lng": 45.3182},
"media": ["https://cdn.landvex.com/obs/001-a.jpg"],
"ai_analysis": {
"construction_progress": 85,
"material_quality": "good",
"activity_level": "high",
},
"confidence": 88,
"verified": True,
},
{
"id": "ev-002",
"type": "satellite",
"date": "2026-07-01",
"source": "Sentinel-2",
"analysis": {
"change_detected": True,
"construction_activity": "active",
"completion_estimate": 82,
},
"confidence": 92,
"verified": True,
},
{
"id": "ev-003",
"type": "official_report",
"date": "2026-06-15",
"source": "UNICEF quarterly report",
"claimed_progress": 95,
"confidence": 100, # Official report
},
],
"transparency": {
"methodology": "Evidence is weighted by source reliability and cross-validated when possible.",
"known_uncertainties": [
"Interior completion percentage is estimate based on visual observation",
"Satellite data may not detect recent changes (< 5 days)",
],
"confidence_calculation": "Weighted average of evidence scores, adjusted for source reliability and recency.",
},
}
@router.get("/public/verification-framework")
async def get_verification_framework():
"""Impact Verification Framework - multidimensional evaluation."""
return {
"framework_name": "Landvex Impact Verification Framework v1.0",
"dimensions": [
{
"name": "Infrastructure Completion",
"description": "Observable physical completion of planned infrastructure",
"indicators": ["Construction progress", "Material quality", "Specification compliance"],
"measurement": "Visual observation, AI analysis, satellite comparison",
},
{
"name": "Operational Continuity",
"description": "Whether facilities remain operational over time",
"indicators": ["Activity levels", "Staff presence", "Service availability"],
"measurement": "Repeated field observations, community feedback",
},
{
"name": "Maintenance Quality",
"description": "Observable maintenance and upkeep",
"indicators": ["Physical condition", "Repair frequency", "Cleanliness"],
"measurement": "Visual inspection, deterioration tracking",
},
{
"name": "Accessibility",
"description": "Physical and economic access for target population",
"indicators": ["Transport links", "Operating hours", "Cost barriers"],
"measurement": "Field observation, community surveys",
},
{
"name": "Community Utilization",
"description": "Actual use by intended beneficiaries",
"indicators": ["Visitor counts", "User satisfaction", "Usage patterns"],
"measurement": "Observation, surveys, usage data",
},
{
"name": "Environmental Sustainability",
"description": "Environmental impact and sustainability",
"indicators": ["Resource efficiency", "Pollution", "Ecosystem impact"],
"measurement": "Satellite, environmental sensors, observation",
},
{
"name": "Economic Enablement",
"description": "Economic activity generated or enabled",
"indicators": ["Local employment", "Market activity", "Income effects"],
"measurement": "Economic observation, satellite (night lights), surveys",
},
],
"scoring": {
"scale": "0-100 per dimension",
"confidence_interval": "Always included",
"minimum_evidence": "At least 3 independent observations required",
},
}
@router.get("/public/sustainable-impact-index")
async def get_sustainable_impact_index():
"""Sustainable Impact Index - long-term observable contribution."""
return {
"index_name": "Landvex Sustainable Impact Index (SII)",
"version": "1.0",
"description": "Estimates long-term observable contribution of development projects",
"dimensions": [
{"name": "Longevity", "weight": 0.15, "description": "Years of continuous operation"},
{"name": "Community Benefit", "weight": 0.15, "description": "Observable community value"},
{"name": "Infrastructure Durability", "weight": 0.15, "description": "Physical condition over time"},
{"name": "Maintenance", "weight": 0.10, "description": "Observable upkeep quality"},
{"name": "Operational Continuity", "weight": 0.10, "description": "Uninterrupted service"},
{"name": "Population Reach", "weight": 0.10, "description": "Number of beneficiaries"},
{"name": "Economic Enablement", "weight": 0.10, "description": "Economic activity generated"},
{"name": "Education Impact", "weight": 0.05, "description": "Learning outcomes (where measurable)"},
{"name": "Health Impact", "weight": 0.05, "description": "Health outcomes (where measurable)"},
{"name": "Environmental Outcomes", "weight": 0.05, "description": "Environmental effects"},
],
"methodology": "Each dimension scored 0-100 based on measurable indicators. Weighted average produces final SII score. Confidence interval always included.",
"example_scores": [
{"project": "Accra Solar Microgrid", "sii_score": 89, "confidence": 92},
{"project": "Mogadishu Primary School", "sii_score": 72, "confidence": 78},
{"project": "Kampala Water Supply", "sii_score": 85, "confidence": 88},
],
}
@router.get("/public/contradictions")
async def list_contradictions():
"""Identified discrepancies between reported and observed data."""
return {
"disclaimer": "These findings are signals for further review, not conclusions of wrongdoing. They indicate areas where additional verification may be valuable.",
"contradictions": [
{
"id": "contr-001",
"project": "Mogadishu Primary School Renovation",
"type": "schedule_variance",
"reported": "95% complete (June 2026)",
"observed": "85% complete (July 2026)",
"evidence_sources": ["Field observation", "Satellite", "AI analysis"],
"confidence": 78,
"severity": "medium",
"recommended_action": "Follow-up observation in 30 days",
},
{
"id": "contr-002",
"project": "Lagos Road Rehabilitation",
"type": "activity_gap",
"reported": "Active construction",
"observed": "No activity for 90 days, equipment removed",
"evidence_sources": ["Field observation", "Satellite time-series"],
"confidence": 92,
"severity": "high",
"recommended_action": "Contact implementing partner for status update",
},
],
}
@router.get("/public/positive-outcomes")
async def list_positive_outcomes():
"""Projects demonstrating strong observable outcomes."""
return {
"description": "Projects that consistently demonstrate strong implementation and sustained operation. These enable benchmarking and dissemination of successful practices.",
"projects": [
{
"id": "proj-003",
"name": "Accra Solar Microgrid",
"country": "Ghana",
"sector": "energy",
"strengths": [
"Strong implementation (observed)",
"Sustained operation (24+ months)",
"High community utilization",
"Long-term maintenance observed",
"Positive environmental outcomes",
"Transparent reporting",
],
"sii_score": 89,
"confidence": 92,
"benchmark_category": "Energy Infrastructure",
},
{
"id": "proj-004",
"name": "Nairobi Digital Health Records",
"country": "Kenya",
"sector": "health",
"strengths": [
"Operational continuity",
"Staff training evident",
"Patient utilization increasing",
"Data transparency",
],
"sii_score": 84,
"confidence": 86,
"benchmark_category": "Digital Health",
},
],
}
@router.get("/public/continuous-monitoring")
async def get_monitoring_capabilities():
"""Continuous monitoring capabilities and data sources."""
return {
"monitoring_types": [
{
"type": "Satellite Imagery",
"frequency": "Every 5 days (Sentinel-2)",
"capabilities": ["Change detection", "Construction progress", "Environmental monitoring"],
"coverage": "Global",
},
{
"type": "QUIXZOOM Field Observations",
"frequency": "On-demand missions",
"capabilities": ["Ground truth", "Activity verification", "Condition assessment"],
"coverage": "20+ countries",
},
{
"type": "AI Image Analysis",
"frequency": "Real-time",
"capabilities": ["Progress estimation", "Quality assessment", "Anomaly detection"],
"coverage": "All observed projects",
},
{
"type": "Open Data Integration",
"frequency": "Continuous",
"capabilities": ["Procurement tracking", "Financial transparency", "Report comparison"],
"coverage": "Partner organizations",
},
],
}
@router.get("/public/research")
async def get_research_program():
"""Development Effectiveness Science research track."""
return {
"program_name": "Landvex Development Effectiveness Science",
"mission": "Develop scientifically grounded indices and models for measuring long-term societal impact",
"research_areas": [
{
"name": "Impact Measurement Methodology",
"description": "Rigorous methods for measuring development outcomes",
"approach": "Combine established frameworks with novel AI-assisted techniques",
},
{
"name": "Longitudinal Impact Analysis",
"description": "Track project outcomes over 5-10 year periods",
"approach": "Satellite time-series, repeated observations, outcome correlation",
},
{
"name": "Bias Detection & Correction",
"description": "Identify and correct for observational and selection biases",
"approach": "Statistical methods, control groups, multi-source validation",
},
{
"name": "Predictive Sustainability Modeling",
"description": "Predict long-term sustainability based on early indicators",
"approach": "Machine learning on historical project data",
},
],
"publications": [
{
"title": "The Landvex Sustainable Impact Index: A Multidimensional Framework",
"status": "In development",
"expected_release": "2027 Q1",
},
],
}
# ─── AUTHENTICATED ENDPOINTS ─────────────────────────────────────────────────
@router.get("/dashboard")
async def get_dashboard(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Admin dashboard for Aid Intelligence."""
return {
"organization": "Landvex Aid Intelligence",
"timestamp": datetime.now().isoformat(),
"summary": {
"projects_monitored": 1250,
"projects_verified": 890,
"projects_with_discrepancies": 45,
"projects_exemplary": 120,
"observations_total": 45000,
"evidence_sources": 5,
"countries_covered": 9,
},
"verification_summary": {
"verified": 890,
"partially_verified": 280,
"insufficient_evidence": 65,
"contradiction_detected": 15,
},
"key_metrics": {
"average_confidence": 82,
"average_sii_score": 74,
"verification_rate": 94,
"evidence_growth_monthly": 3200,
},
"recent_activity": [
{
"type": "observation",
"project": "Mogadishu Primary School",
"description": "New field observation added",
"time": "2026-07-03T14:30:00Z",
},
{
"type": "discrepancy",
"project": "Lagos Road Rehabilitation",
"description": "Activity gap detected - no construction for 90 days",
"time": "2026-07-02T09:15:00Z",
},
{
"type": "positive_outcome",
"project": "Accra Solar Microgrid",
"description": "24 months continuous operation verified",
"time": "2026-07-01T16:00:00Z",
},
],
}
@router.post("/projects/{project_id}/flag-for-review")
async def flag_project_for_review(
project_id: str,
reason: str,
evidence_ids: List[str],
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""Flag a project for additional review (not accusation)."""
return {
"status": "flagged_for_review",
"project_id": project_id,
"reason": reason,
"evidence_count": len(evidence_ids),
"flagged_by": current_user.id if hasattr(current_user, 'id') else 'admin',
"flagged_at": datetime.now().isoformat(),
"next_steps": [
"Contact implementing partner for clarification",
"Schedule follow-up observation",
"Review additional evidence sources",
],
}