feat(api): add POST/GET /v1/files with auth, error envelope, and request-id middleware

Why:
- Wires the ADR-0008 error envelope, per-request correlation id, and the
  /v1/files routes into the app.

Changes:
- Extend AppResources/lifespan with the ingestion CapacityLimiter and
  ObjectStorage adapter.

Impact:
- /v1 now exposes routes for the first time.
This commit is contained in:
2026-08-19 15:00:39 +03:30
parent c9cf7b368b
commit 3bced65926
10 changed files with 355 additions and 1 deletions

View File

@@ -1,11 +1,13 @@
from collections.abc import AsyncIterator
from dataclasses import dataclass
from anyio import CapacityLimiter
from fastapi import Request
from minio import Minio
from qdrant_client import AsyncQdrantClient
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker
from src.application.ports.object_storage import ObjectStorage
from src.config import Settings
@@ -16,6 +18,8 @@ class AppResources:
db_sessionmaker: async_sessionmaker[AsyncSession]
minio_client: Minio
qdrant_client: AsyncQdrantClient
object_storage: ObjectStorage
ingestion_limiter: CapacityLimiter
def _resources(request: Request) -> AppResources:
@@ -34,6 +38,25 @@ def get_qdrant_client(request: Request) -> AsyncQdrantClient:
return _resources(request).qdrant_client
def get_object_storage(request: Request) -> ObjectStorage:
return _resources(request).object_storage
def get_ingestion_limiter(request: Request) -> CapacityLimiter:
return _resources(request).ingestion_limiter
def get_sessionmaker(request: Request) -> async_sessionmaker[AsyncSession]:
"""The session *factory*, not a request-scoped session.
Application services that own more than one transaction in a single
request (ADR-0017's two-phase upload) need to open and close sessions
themselves rather than borrow one request-scoped session that would
otherwise stay open across the whole request.
"""
return _resources(request).db_sessionmaker
async def get_db_session(request: Request) -> AsyncIterator[AsyncSession]:
sessionmaker = _resources(request).db_sessionmaker
async with sessionmaker() as session: