fix: fail closed v3 legacy semantic fallbacks

This commit is contained in:
2026-08-08 16:52:33 +02:00
parent 2f7f923c4d
commit ba1d7b0e78
10 changed files with 172 additions and 48 deletions
@@ -30,6 +30,29 @@ semantic_index:
llm_policy:
allowed: [zai/glm-5.2]
`);
const workspaceV3 = parseWorkspaceYaml(`workspace:
schema_version: 3
id: psd-clinical
name: Policlinico San Donato
language: it
dwh:
engine: postgres
database: postgres
schema: datawarehouse
supported_transports: [postgres_direct, rest_api]
semantic_index:
vector_store:
engine: qdrant
collection: psd-clinical
dimensions: 1024
distance: cosine
embedding:
provider: ollama_internal
model: qwen3-embedding:0.6b
dimensions: 1024
llm_policy:
allowed: [zai/glm-5.2]
`);
const paths: RuntimePaths = {
sessions: "/data/workspaces/psd-clinical/sessions",
artifacts: "/data/workspaces/psd-clinical/artifacts",
@@ -149,6 +172,12 @@ test("refuses to render a v1 descriptor until an explicit migration creates v2",
expect(() => renderRuntimeConfig(legacyWorkspace, directBindings, paths)).toThrow(/migrat/i);
});
test("fails closed for v3 runtime rendering and session support", () => {
expect(supportsSessionRuntime(directBindings)).toBe(true);
expect(() => renderRuntimeConfig(workspaceV3, directBindings, paths))
.toThrow(/unsupported|schema version 3|qdrant|ollama_internal/i);
});
test("omits direct TLS fields when binding validation did not retain a file path", () => {
const dwhValues = { ...directBindings.dwh.values };
const vectorValues = { ...directBindings.vector.values };
+32
View File
@@ -31,6 +31,29 @@ semantic_index:
llm_policy:
allowed: [zai/glm-5.2]
`);
const workspaceV3 = parseWorkspaceYaml(`workspace:
schema_version: 3
id: psd-clinical
name: Policlinico San Donato
language: it
dwh:
engine: postgres
database: postgres
schema: datawarehouse
supported_transports: [postgres_direct, rest_api]
semantic_index:
vector_store:
engine: qdrant
collection: psd-clinical
dimensions: 1024
distance: cosine
embedding:
provider: ollama_internal
model: qwen3-embedding:0.6b
dimensions: 1024
llm_policy:
allowed: [zai/glm-5.2]
`);
const temporaryRoots: string[] = [];
afterEach(() => {
@@ -196,3 +219,12 @@ test("never treats a vector reader credential as the optional writer binding", (
values: {},
});
});
test("fails closed for v3 external semantic bindings", () => {
expect(() => resolveBinding(workspaceV3, "VECTOR", {}, ["/run/secrets"]))
.toThrow(/unsupported|schema version 3|semantic/i);
expect(() => resolveBinding(workspaceV3, "EMBEDDING", {}, ["/run/secrets"]))
.toThrow(/unsupported|schema version 3|semantic/i);
expect(() => resolveRuntimeBindings(workspaceV3, {}, ["/run/secrets"]))
.toThrow(/unsupported|schema version 3|semantic/i);
});
+33
View File
@@ -39,6 +39,29 @@ llm_policy:
- zai/glm-5.2
- openai/gpt-5
`);
const workspaceV3 = parseWorkspaceYaml(`workspace:
schema_version: 3
id: psd-clinical
name: Policlinico San Donato
language: it
dwh:
engine: postgres
database: postgres
schema: datawarehouse
supported_transports: [postgres_direct, rest_api]
semantic_index:
vector_store:
engine: qdrant
collection: psd-clinical
dimensions: 1024
distance: cosine
embedding:
provider: ollama_internal
model: qwen3-embedding:0.6b
dimensions: 1024
llm_policy:
allowed: [zai/glm-5.2]
`);
test("generates stable FILE-based secret requirements from an immutable ID", () => {
const contract = buildInstallationContract(validWorkspace);
@@ -278,3 +301,13 @@ test("validates public contract and documentation inputs at runtime", () => {
expect(() => buildInstallationContract(unsafeWorkspace)).toThrow(/id/i);
expect(() => renderWorkspaceDocs(unsafeWorkspace)).toThrow(/id/i);
});
test("v3 installation contract omits external vector and embedding bindings", () => {
const contract = buildInstallationContract(workspaceV3);
const names = contract.variables.map((variable) => variable.name);
expect(names).toContain("THT_WS_PSD_CLINICAL_DWH_TRANSPORT");
expect(names.some((name) => name.includes("_VECTOR_"))).toBe(false);
expect(names.some((name) => name.includes("_EMBEDDING_"))).toBe(false);
expect(renderWorkspaceDocs(workspaceV3).markdown).not.toContain("Embedding service");
});
+12
View File
@@ -128,6 +128,18 @@ test("rejects unknown fields in schema v3 semantic identity", () => {
expect(() => parseWorkspaceYaml(withUnknownField)).toThrow(/unrecognized key/i);
});
test("rejects legacy semantic connector fields and diagnostics in schema v3", () => {
expect(() => parseWorkspaceYaml(validYaml.replace(
" collection: psd-clinical\n",
" collection: psd-clinical\n database: postgres\n",
))).toThrow(/unrecognized key|database/i);
expect(() => parseWorkspaceYaml(validYaml.replace(
"llm_policy:\n",
"diagnostics:\n vector_rest:\n metadata:\n method: GET\n path: /metadata\n auth: bearer\n response:\n collection: collection\n dimensions: dimensions\n distance: distance\nllm_policy:\n",
))).toThrow(/unrecognized key|vector_rest/i);
});
test("keeps v1 and v2 descriptors parseable but non-operational", () => {
const v1Yaml = `workspace:
schema_version: 1