Make the governed RAG evidence path executable end to end
Some checks failed
verify / verify (push) Has been cancelled

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:
2026-07-13 05:58:11 +08:00
parent 75592af33a
commit ecdb10c37a
111 changed files with 25457 additions and 152 deletions

View File

@@ -0,0 +1,89 @@
"""Worker handler wiring for governed document embedding jobs."""
from __future__ import annotations
import uuid
from collections.abc import Mapping, Sequence
from app.adapters.fake import FakeEmbeddingProvider
from app.adapters.model_gateway import ModelGatewayAdapter
from app.core.config import Settings
from app.persistence.indexing import PostgresIndexingRepository
from app.persistence.job_queue import BackgroundJob
from app.ports.model_providers import EmbeddingResult
from app.services.indexing import DocumentIndexingService
from app.worker import JobHandler
class InvalidIndexingJobError(RuntimeError):
"""A safe job-envelope failure that never includes payload content."""
def __init__(self) -> None:
super().__init__("EMBED_DOCUMENT job envelope is invalid")
class _WorkerGatewayEmbeddingProvider:
"""Open the internal gateway only for real provider batches.
Synthetic profiles are routed to ``FakeEmbeddingProvider`` by the service,
so they never read a gateway token or create model-network traffic.
"""
def __init__(self, settings: Settings) -> None:
if settings.model_gateway_caller != "worker":
raise ValueError("indexing handlers require MODEL_GATEWAY_CALLER=worker")
self._settings = settings
async def embed_documents(self, texts: Sequence[str]) -> EmbeddingResult:
async with ModelGatewayAdapter.from_settings(self._settings) as gateway:
return await gateway.embed_documents(texts)
async def embed_query(self, text: str) -> EmbeddingResult:
async with ModelGatewayAdapter.from_settings(self._settings) as gateway:
return await gateway.embed_query(text)
def build_embed_document_handler(service: DocumentIndexingService) -> JobHandler:
"""Build a testable handler around one configured indexing service."""
async def handle(job: BackgroundJob) -> None:
document_version_id = _document_version_id(job)
await service.index_document_version(
lease=job.lease,
document_version_id=document_version_id,
trace_id=job.id,
)
return handle
def build_indexing_handlers(settings: Settings) -> Mapping[str, JobHandler]:
"""Return production handler registration without loading cloud credentials eagerly."""
if settings.model_gateway_caller != "worker":
raise ValueError("indexing handlers require MODEL_GATEWAY_CALLER=worker")
service = DocumentIndexingService(
repository=PostgresIndexingRepository(settings),
embedding_provider=_WorkerGatewayEmbeddingProvider(settings),
synthetic_embedding_provider=FakeEmbeddingProvider(settings.embedding_dimension),
)
return {"EMBED_DOCUMENT": build_embed_document_handler(service)}
def _document_version_id(job: BackgroundJob) -> uuid.UUID:
raw_version_id = job.payload.get("document_version_id")
if (
job.job_type != "EMBED_DOCUMENT"
or job.required_capability != "embedding"
or job.resource_type != "document_version"
or job.lease.job_id != job.id
or not isinstance(raw_version_id, str)
):
raise InvalidIndexingJobError
try:
document_version_id = uuid.UUID(raw_version_id)
except (AttributeError, ValueError):
raise InvalidIndexingJobError from None
if str(document_version_id) != raw_version_id or document_version_id != job.resource_id:
raise InvalidIndexingJobError
return document_version_id