fix: tighten internal semantic compose contracts
This commit is contained in:
@@ -40,6 +40,8 @@ for (const service of [qdrant, embedding, modelInit]) {
|
||||
}
|
||||
if ((qdrant.expose || []).join(",") !== "6333") throw new Error("qdrant must expose only 6333");
|
||||
if ((embedding.expose || []).join(",") !== "11434") throw new Error("embedding must expose only 11434");
|
||||
if (!qdrant.healthcheck) throw new Error("qdrant must define a healthcheck");
|
||||
if (!embedding.healthcheck) throw new Error("embedding must define a healthcheck");
|
||||
if (qdrant.image !== "qdrant/qdrant:v1.18.2@sha256:75eab8c4ba42096724fdcfde8b4de0b5713d529dde32f285a1f86fdcb2c9e50c") {
|
||||
throw new Error("qdrant image must be pinned by version and digest");
|
||||
}
|
||||
@@ -72,6 +74,9 @@ if (depends.qdrant?.condition !== "service_healthy") {
|
||||
if (depends["embedding-model-init"]?.condition !== "service_completed_successfully") {
|
||||
throw new Error("core must wait for embedding-model-init success");
|
||||
}
|
||||
if (modelInit.depends_on?.embedding?.condition !== "service_healthy") {
|
||||
throw new Error("embedding-model-init must wait for embedding health");
|
||||
}
|
||||
if (JSON.stringify(embedding).includes('"devices"')) {
|
||||
throw new Error("base embedding service must stay CPU-only");
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ TASK13_ROOT="$root"
|
||||
TASK13_TMP="$fixture"
|
||||
TASK13_RUN_ID="fixture-$profile"
|
||||
TASK13_PROJECT="thothii-task13-$profile"
|
||||
TASK13_PROFILE="$profile"
|
||||
TASK13_CORE_IMAGE="task13-core-$profile:fixture"
|
||||
TASK13_FRONTEND_IMAGE="task13-frontend-$profile:fixture"
|
||||
TASK13_SECRET_VALUE="task13-runtime-secret-$profile"
|
||||
@@ -36,6 +37,7 @@ TASK13_PI_SETTINGS="$fixture/settings.json"
|
||||
TASK13_LLM_SERVER="$fixture/fake-llm.mjs"
|
||||
TASK13_LLM_CONTAINER="$TASK13_PROJECT-llm"
|
||||
TASK13_REMOTE="$fixture/remote.git"
|
||||
TASK13_CURRENT_IMAGE_OVERRIDE="$fixture/current-image.yaml"
|
||||
mkdir -p "$TASK13_REMOTE"
|
||||
|
||||
workspace="$fixture/task13-smoke.yaml"
|
||||
@@ -94,6 +96,7 @@ fi
|
||||
rendered="$fixture/rendered.json"
|
||||
docker compose --project-name "$TASK13_PROJECT" --project-directory "$root" \
|
||||
--env-file "$TASK13_ENV_FILE" "${compose_files[@]}" config --format json >"$rendered"
|
||||
task13_assert_rendered_contract
|
||||
tsx_loader="$root/backend/node_modules/tsx/dist/loader.mjs"
|
||||
checker=(node --import "$tsx_loader" "$root/scripts/task13-runtime-fixture-check.ts")
|
||||
[[ -f "$tsx_loader" ]] || {
|
||||
|
||||
@@ -75,12 +75,17 @@ for (const serviceName of ["qdrant", "embedding", "embedding-model-init"]) {
|
||||
}
|
||||
if ((config.services.qdrant.expose || []).join(",") !== "6333") throw new Error("qdrant must expose only 6333");
|
||||
if ((config.services.embedding.expose || []).join(",") !== "11434") throw new Error("embedding must expose only 11434");
|
||||
if (!config.services.qdrant.healthcheck) throw new Error("qdrant must define a healthcheck");
|
||||
if (!config.services.embedding.healthcheck) throw new Error("embedding must define a healthcheck");
|
||||
if (config.services.core.depends_on?.qdrant?.condition !== "service_healthy") {
|
||||
throw new Error("core must wait for qdrant health");
|
||||
}
|
||||
if (config.services.core.depends_on?.["embedding-model-init"]?.condition !== "service_completed_successfully") {
|
||||
throw new Error("core must wait for embedding-model-init success");
|
||||
}
|
||||
if (config.services["embedding-model-init"].depends_on?.embedding?.condition !== "service_healthy") {
|
||||
throw new Error("embedding-model-init must wait for embedding health");
|
||||
}
|
||||
if (JSON.stringify(config.services.embedding).includes('"devices"')) {
|
||||
throw new Error("base embedding service must stay CPU-only");
|
||||
}
|
||||
@@ -190,6 +195,10 @@ if (config.services.core.depends_on?.qdrant?.condition !== "service_healthy") {
|
||||
if (config.services.core.depends_on?.["embedding-model-init"]?.condition !== "service_completed_successfully") {
|
||||
throw new Error("core must wait for embedding-model-init success");
|
||||
}
|
||||
if (!config.services.embedding.healthcheck) throw new Error("embedding must define a healthcheck");
|
||||
if (config.services["embedding-model-init"].depends_on?.embedding?.condition !== "service_healthy") {
|
||||
throw new Error("embedding-model-init must wait for embedding health");
|
||||
}
|
||||
if (/docker\.sock|\/var\/run\/docker|docker[-_]?daemon/i.test(JSON.stringify(config.services))) {
|
||||
throw new Error("Compose must not mount the Docker socket or daemon");
|
||||
}
|
||||
|
||||
@@ -518,7 +518,8 @@ task13_build_thothctl() {
|
||||
task13_assert_rendered_contract() {
|
||||
local services rendered
|
||||
services="$(task13_compose config --services | sort)"
|
||||
[[ "$services" == $'core\nfrontend' ]] || task13_fail "rendered stack is not exactly core and frontend"
|
||||
[[ "$services" == $'core\nembedding\nembedding-model-init\nfrontend\nqdrant' ]] \
|
||||
|| task13_fail "rendered stack is not the mandatory internal semantic topology"
|
||||
rendered="$TASK13_TMP/rendered-compose.yaml"
|
||||
task13_compose config >"$rendered"
|
||||
if grep -Eqi 'docker\.sock|/var/run/docker' "$rendered"; then
|
||||
@@ -527,9 +528,14 @@ task13_assert_rendered_contract() {
|
||||
if grep -Fq "$TASK13_SECRET_VALUE" "$rendered"; then
|
||||
task13_fail "rendered Compose exposed the fixture secret"
|
||||
fi
|
||||
for endpoint in THT_DWH_REST_URL THT_VEC_REST_URL THT_OLLAMA_URL THT_LLM_URL; do
|
||||
for endpoint in THT_DWH_REST_URL THT_LLM_URL \
|
||||
THT_INTERNAL_QDRANT_URL THT_INTERNAL_EMBEDDING_URL \
|
||||
THT_INTERNAL_EMBEDDING_MODEL THT_INTERNAL_EMBEDDING_DIMENSIONS; do
|
||||
grep -Fq "$endpoint" "$rendered" || task13_fail "rendered Compose lacks $endpoint"
|
||||
done
|
||||
if grep -Eq 'THT_VEC_REST_URL|THT_VEC_WRITE_REST_URL|THT_OLLAMA_URL' "$rendered"; then
|
||||
task13_fail "rendered Compose still exposes retired external semantic bindings"
|
||||
fi
|
||||
}
|
||||
|
||||
task13_start_stack() {
|
||||
|
||||
Reference in New Issue
Block a user