US06-01: Configure and Preflight Archive Destinations

This commit is contained in:
2026-08-16 17:37:47 +02:00
parent 3ccef58796
commit a18d40955c
11 changed files with 1350 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
"""Archive location and preflight API (US06-01).
Registering a location writes a marker onto the medium; preflight is a command
rather than a read, because it probes the destination, hashes the scope, and issues
the token a later archive plan must present (US06-02). Neither endpoint moves or
removes a single library file.
"""
from __future__ import annotations
from fastapi import APIRouter, Request
from fastapi.responses import JSONResponse
from pydantic import BaseModel
from photo_pipeline.services.archives import ArchiveError, ArchiveService
router = APIRouter(tags=["archives"])
# Which failures are the caller's request (422) and which are a missing thing (404).
NOT_FOUND_CODES = {"unknown_location"}
class RegisterLocationRequest(BaseModel):
name: str
root: str
class PreflightRequest(BaseModel):
location_id: str
# ``None`` means every album; an explicit list scopes the check.
albums: list[str] | None = None
def _service(request: Request) -> ArchiveService:
return ArchiveService(request.app.state.session_factory, config=request.app.state.config)
def _error(error: ArchiveError) -> JSONResponse:
status = 404 if error.code in NOT_FOUND_CODES else 422
return JSONResponse(
status_code=status, content={"error": {"code": error.code, "message": str(error)}}
)
@router.post("/archive-locations", status_code=201)
def register_location(body: RegisterLocationRequest, request: Request):
try:
return _service(request).register(body.name, body.root)
except ArchiveError as error:
return _error(error)
@router.get("/archive-locations")
def list_locations(request: Request) -> dict:
return {"locations": _service(request).locations()}
@router.post("/archive-preflight")
def preflight(body: PreflightRequest, request: Request):
try:
return _service(request).preflight(body.location_id, body.albums)
except ArchiveError as error:
return _error(error)