# TODO-AI.md - NVR Backend API Gateway

## Project Overview

Build a production-ready backend API Gateway for an AI-powered NVR system.

The AI ingestion pipeline already exists and performs:

* RTSP camera ingestion
* YOLO object detection
* Video segmentation
* Upload of detected clips to MinIO
* Metadata storage in MongoDB

This project is ONLY responsible for:

* Authentication
* Metadata querying
* Video playback access
* Camera management
* Event timeline APIs
* Signed URL generation
* Frontend-facing REST API

---

# Technology Stack

Required:

* Python 3.12+
* FastAPI
* Pydantic v2
* Motor (async MongoDB driver)
* MinIO Python SDK
* JWT Authentication
* Docker
* Docker Compose

Optional:

* Redis (caching)
* Prometheus metrics

---

# Architecture

Frontend
↓
FastAPI Gateway
↓ ↓
MongoDB MinIO

The frontend must NEVER access MongoDB or MinIO directly.

All access goes through the API Gateway.

---

# Folder Structure

backend/

app/

main.py

config.py

dependencies.py

database.py

auth/

jwt.py

passwords.py

schemas/

auth.py

camera.py

clip.py

event.py

routes/

auth.py

cameras.py

clips.py

events.py

health.py

services/

auth_service.py

camera_service.py

clip_service.py

storage_service.py

event_service.py

middleware/

logging.py

rate_limit.py

Dockerfile

docker-compose.yml

requirements.txt

.env

README.md

---

# MongoDB Schema

Current uploader stores:

{
"camera_id": 1,
"filename": "clip_xxx.mp4",
"s3_path": "cam_1/clip_xxx.mp4",
"timestamp": ISODate(),
"detected_object": "person",
"uploaded_at": ISODate()
}

Extend schema support for:

{
"_id": ObjectId,

"camera_id": 1,

"filename": "clip.mp4",

"s3_path": "cam_1/clip.mp4",

"timestamp": ISODate(),

"uploaded_at": ISODate(),

"detected_object": "person",

"duration_seconds": 10,

"size_bytes": 4235112,

"thumbnail_path": "cam_1/thumb.jpg"
}

---

# MongoDB Indexes

Create indexes automatically on startup.

camera_id + timestamp

{
camera_id: 1,
timestamp: -1
}

timestamp

{
timestamp: -1
}

detected_object

{
detected_object: 1
}

---

# Authentication

Implement JWT authentication.

Endpoints:

POST /api/auth/login

POST /api/auth/refresh

GET /api/auth/me

Requirements:

* bcrypt password hashing
* access token
* refresh token
* configurable expiration

Authorization header:

Bearer <token>

Protect all non-health endpoints.

---

# Health Endpoint

GET /health

Response:

{
"status": "ok"
}

Include:

* Mongo connectivity
* MinIO connectivity

Response:

{
"status": "ok",
"mongo": true,
"storage": true
}

---

# Camera Endpoints

GET /api/cameras

Returns all configured cameras.

Response:

[
{
"id": 1,
"name": "Front Door"
}
]

GET /api/cameras/{camera_id}

Returns camera details.

---

# Clip Search API

GET /api/clips

Query Parameters:

camera_id

detected_object

start

end

page

limit

sort

Example:

GET /api/clips?camera_id=1&detected_object=person&page=1&limit=50

Response:

{
"items": [],
"page": 1,
"limit": 50,
"total": 1234
}

Requirements:

* pagination
* filtering
* sorting
* date range filtering

---

# Clip Details Endpoint

GET /api/clips/{clip_id}

Return full metadata.

Response:

{
"id": "...",
"camera_id": 1,
"detected_object": "person",
"timestamp": "...",
"s3_path": "...",
"duration_seconds": 10
}

---

# Playback Endpoint

Frontend must not receive MinIO credentials.

Generate presigned URLs.

GET /api/clips/{clip_id}/playback

Response:

{
"url": "<signed-url>",
"expires_in": 900
}

Requirements:

* presigned URL expiration configurable
* default 15 minutes

---

# Thumbnail Endpoint

GET /api/clips/{clip_id}/thumbnail

Return:

{
"url": "<signed-url>"
}

Use MinIO presigned URL.

---

# Event Timeline API

GET /api/events

Query Parameters:

camera_id

detected_object

start

end

page

limit

Response:

{
"items": [
{
"camera_id": 1,
"detected_object": "person",
"timestamp": "...",
"clip_id": "..."
}
]
}

This endpoint powers the frontend event timeline.

---

# Live Stream API

MediaMTX exists separately.

Gateway should expose camera stream metadata.

GET /api/live-streams

Response:

[
{
"camera_id": 1,
"name": "Front Door",
"webrtc_url": "/stream/cam1"
}
]

No direct MediaMTX logic required.

Only return stream metadata.

---

# Services

## StorageService

Responsibilities:

* generate presigned URLs
* validate object existence
* retrieve metadata

Methods:

get_signed_video_url()

get_signed_thumbnail_url()

object_exists()

---

## ClipService

Responsibilities:

* search clips
* pagination
* clip lookup

Methods:

search_clips()

get_clip()

count_clips()

---

## EventService

Responsibilities:

* build event timeline
* event filtering

Methods:

search_events()

---

## CameraService

Responsibilities:

* camera metadata
* stream metadata

Methods:

list_cameras()

get_camera()

---

# Configuration

Use environment variables.

Required:

MONGO_URI

MONGO_DB

MONGO_COLLECTION

MINIO_ENDPOINT

MINIO_ACCESS_KEY

MINIO_SECRET_KEY

MINIO_BUCKET

JWT_SECRET

JWT_EXPIRATION_MINUTES

REFRESH_TOKEN_EXPIRATION_DAYS

---

# Logging

Implement structured JSON logging.

Log:

request_id

endpoint

method

latency_ms

status_code

user_id

Example:

{
"request_id":"...",
"endpoint":"/api/clips",
"latency_ms":12
}

---

# Error Handling

Create unified error format.

{
"error":"clip_not_found",
"message":"Clip does not exist"
}

Never return stack traces.

---

# Rate Limiting

Implement configurable rate limiting.

Default:

100 requests/minute per user

---

# Docker

Provide:

Dockerfile

docker-compose.yml

Services:

backend

mongodb

minio

Environment variables loaded from .env

---

# OpenAPI

Enable Swagger UI.

Requirements:

* endpoint descriptions
* request models
* response models
* auth integration

---

# Production Requirements

Must be:

* fully async
* type hinted
* lint clean
* mypy compatible
* production logging
* dependency injection
* modular service architecture
* no business logic in route handlers

Route handlers should call services only.

---

# Deliverables

Produce:

1. Complete FastAPI project
2. Dockerfile
3. Docker Compose
4. Requirements file
5. Environment example
6. Database initialization
7. JWT auth system
8. OpenAPI docs
9. README with startup instructions

The code should be production-ready and suitable for deployment behind Nginx or Traefik.
