Separate local parsing from model indexing, bind review decisions to immutable manifests, persist vectors behind active profiles, and expose retrieval, chat, evaluation, and document workflows through the React workbench. Constraint: Live Bailian authentication currently fails for all three configured capabilities Rejected: Direct upload-to-embedding flow | bypasses local review and manifest binding Confidence: high Scope-risk: broad Directive: Keep private-data deployment blocked until authentication, RBAC, and separate database roles land Tested: make verify; fresh and replay Docker document smoke; worker recovery smoke; frozen synthetic evaluation; migration 0003-0004 roundtrip Not-tested: Successful live Bailian calls, OCR, real multi-user authorization
This commit is contained in:
@@ -34,6 +34,7 @@ class Settings(BaseSettings):
|
||||
|
||||
upload_root: Path = Path("/data/uploads")
|
||||
max_upload_mb: int = Field(default=100, ge=1, le=2048)
|
||||
document_namespace_mode: Literal["fake", "bailian"] = "fake"
|
||||
|
||||
model_gateway_base_url: str = "http://model-gateway:8000"
|
||||
model_gateway_token_file: Path = Path("/run/secrets/model_gateway_api_token")
|
||||
@@ -65,7 +66,7 @@ class Settings(BaseSettings):
|
||||
model_timeout_seconds: float = Field(default=90, gt=0, le=600)
|
||||
model_max_retries: int = Field(default=3, ge=0, le=10)
|
||||
model_max_concurrency: int = Field(default=4, ge=1, le=100)
|
||||
worker_capabilities: str = "document_parse,embedding,rerank,evaluation"
|
||||
worker_capabilities: str = "document_parse"
|
||||
|
||||
@field_validator(
|
||||
"bailian_openai_base_url",
|
||||
|
||||
@@ -13,6 +13,8 @@ DEMO_FAKE_EMBEDDING_MODEL = "fake-feature-hash-v1"
|
||||
IDENTITY_NAMESPACE = uuid.UUID("eef85571-1f64-4a09-86d7-53fd329c3eb2")
|
||||
KNOWLEDGE_BASE_ID = uuid.uuid5(IDENTITY_NAMESPACE, "synthetic-demo-knowledge-base")
|
||||
ACCESS_SCOPE_ID = uuid.uuid5(IDENTITY_NAMESPACE, "synthetic-demo-public-scope")
|
||||
BAILIAN_KNOWLEDGE_BASE_ID = uuid.uuid5(IDENTITY_NAMESPACE, "synthetic-bailian-knowledge-base")
|
||||
BAILIAN_ACCESS_SCOPE_ID = uuid.uuid5(IDENTITY_NAMESPACE, "synthetic-bailian-public-scope")
|
||||
|
||||
|
||||
def offline_embedding_profile_hash(dimension: int) -> str:
|
||||
|
||||
@@ -6,6 +6,7 @@ from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from fastapi import Request
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
PROBLEM_MEDIA_TYPE = "application/problem+json"
|
||||
@@ -60,3 +61,35 @@ def api_problem_handler(request: Request, exc: ApiProblem) -> JSONResponse:
|
||||
trace_id=trace_id,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def request_validation_problem_handler(
|
||||
request: Request,
|
||||
exc: RequestValidationError,
|
||||
) -> JSONResponse:
|
||||
"""Return bounded validation metadata without echoing rejected input values."""
|
||||
|
||||
trace_id = str(getattr(request.state, "trace_id", "unavailable"))
|
||||
field_errors: list[dict[str, str]] = []
|
||||
for error in exc.errors():
|
||||
location = error.get("loc", ())
|
||||
field = ".".join(str(part) for part in location if str(part) not in {"body", "query"})
|
||||
error_type = error.get("type")
|
||||
field_errors.append(
|
||||
{
|
||||
"field": field[:240] or "request",
|
||||
"code": str(error_type)[:120] if error_type else "invalid_value",
|
||||
}
|
||||
)
|
||||
return JSONResponse(
|
||||
status_code=422,
|
||||
media_type=PROBLEM_MEDIA_TYPE,
|
||||
content=problem_payload(
|
||||
status=422,
|
||||
code="REQUEST_VALIDATION_FAILED",
|
||||
title="Request validation failed",
|
||||
detail="One or more request fields did not satisfy the public API contract.",
|
||||
trace_id=trace_id,
|
||||
field_errors=field_errors[:50],
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user