Complete temporal detection safety gate
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-18 00:53:00 +02:00
parent fc42ea9af5
commit 9146981802
16 changed files with 689 additions and 23 deletions
+22 -4
View File
@@ -1,6 +1,8 @@
from __future__ import annotations
import logging
import re
import time
import uuid
from contextlib import asynccontextmanager
@@ -13,11 +15,13 @@ from app.api.routes import analysis, areas, assistant, datasets, demo, detection
from app.core.config import get_settings
from app.core.errors import AppError
from app.core.logging import configure_logging
from app.core.request_context import reset_request_id, set_request_id
from app.db.session import SessionLocal
from app.services.runtime_reconciliation_service import RuntimeReconciliationService
logger = logging.getLogger("geointel")
SAFE_REQUEST_ID = re.compile(r"^[A-Za-z0-9._:-]{1,128}$")
def _to_error_payload(
@@ -91,11 +95,25 @@ def create_app() -> FastAPI:
@app.middleware("http")
async def request_identity(request: Request, call_next):
request_id = request.headers.get("x-request-id") or str(uuid.uuid4())
supplied_request_id = request.headers.get("x-request-id", "")
request_id = supplied_request_id if SAFE_REQUEST_ID.fullmatch(supplied_request_id) else str(uuid.uuid4())
request.state.request_id = request_id
response = await call_next(request)
response.headers["x-request-id"] = request_id
return response
token = set_request_id(request_id)
started_at = time.perf_counter()
try:
response = await call_next(request)
response.headers["x-request-id"] = request_id
logger.info(
"request_complete request_id=%s method=%s path=%s status=%s duration_ms=%.1f",
request_id,
request.method,
request.url.path,
response.status_code,
(time.perf_counter() - started_at) * 1000,
)
return response
finally:
reset_request_id(token)
@app.exception_handler(AppError)
async def app_error(request: Request, exc: AppError): # noqa: ARG001