fix: harden task3 qdrant compatibility boundaries
This commit is contained in:
+33
-11
@@ -550,17 +550,8 @@ def load_config(path: Path) -> Config:
|
||||
_validate_internal_embedding_contract(expanded, path)
|
||||
_validate_internal_vector_contract(expanded, path)
|
||||
translated, used_legacy = translate_legacy_config(expanded)
|
||||
_validate_vector_resource_consistency(expanded, translated, path)
|
||||
vectors = translated.get("vectors")
|
||||
resource_vector = expanded.get("resources", {}).get("vector") if isinstance(
|
||||
expanded.get("resources"), dict
|
||||
) else None
|
||||
if (
|
||||
isinstance(vectors, dict)
|
||||
and vectors.get("type") == "qdrant"
|
||||
and isinstance(resource_vector, dict)
|
||||
and "collection_lifecycle" in resource_vector
|
||||
):
|
||||
vectors["collection_lifecycle"] = resource_vector["collection_lifecycle"]
|
||||
# runtime_identity is the registry marker. The lifecycle is an internal
|
||||
# runtime policy, never a descriptor-controlled option.
|
||||
if (
|
||||
@@ -673,6 +664,37 @@ def _validate_internal_embedding_contract(raw: dict[str, Any], path: Path) -> No
|
||||
)
|
||||
|
||||
|
||||
def _normalize_qdrant_base_url(value: str) -> str:
|
||||
parsed = urlparse(value)
|
||||
hostname = (parsed.hostname or "").lower()
|
||||
try:
|
||||
port = parsed.port
|
||||
except ValueError:
|
||||
port = None
|
||||
host = f"[{hostname}]" if ":" in hostname and not hostname.startswith("[") else hostname
|
||||
netloc = f"{host}:{port}" if port is not None else host
|
||||
return f"{parsed.scheme.lower()}://{netloc}{parsed.path.rstrip('/') or '/'}"
|
||||
|
||||
|
||||
def _validate_vector_resource_consistency(raw: dict[str, Any], translated: dict[str, Any], path: Path) -> None:
|
||||
"""Reject divergent top-level and compatibility Qdrant resource views."""
|
||||
resources = raw.get("resources")
|
||||
resource = resources.get("vector") if isinstance(resources, dict) else None
|
||||
vectors = translated.get("vectors")
|
||||
if not isinstance(resource, dict) or not isinstance(vectors, dict):
|
||||
return
|
||||
if vectors.get("type") != "qdrant" or resource.get("engine") != "qdrant":
|
||||
raise ConfigError(
|
||||
f"Configurazione non valida in {path}: vectors and resources.vector must both describe qdrant"
|
||||
)
|
||||
if _normalize_qdrant_base_url(vectors.get("base_url", "")) != _normalize_qdrant_base_url(
|
||||
resource.get("base_url", "")
|
||||
) or vectors.get("collection") != resource.get("collection"):
|
||||
raise ConfigError(
|
||||
f"Configurazione non valida in {path}: vectors and resources.vector disagree"
|
||||
)
|
||||
|
||||
|
||||
def _validate_internal_vector_contract(raw: dict[str, Any], path: Path) -> None:
|
||||
resources = raw.get("resources")
|
||||
if not isinstance(resources, dict):
|
||||
@@ -684,7 +706,7 @@ def _validate_internal_vector_contract(raw: dict[str, Any], path: Path) -> None:
|
||||
engine = vector.get("engine")
|
||||
base_url = vector.get("base_url")
|
||||
collection = vector.get("collection")
|
||||
allowed = {"engine", "base_url", "collection", "collection_lifecycle"}
|
||||
allowed = {"engine", "base_url", "collection"}
|
||||
unexpected = sorted(set(vector) - allowed)
|
||||
if unexpected:
|
||||
raise ConfigError(
|
||||
|
||||
Reference in New Issue
Block a user