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
+23 -17
View File
@@ -1,4 +1,4 @@
import { validateCanonicalWorkspace } from "./schema.js";
import { validateWorkspaceDescriptor } from "./schema.js";
import type { DwhTransport, VectorTransport, WorkspaceDescriptor } from "./schema.js";
export type InstallationRole = "DWH" | "VECTOR" | "VECTOR_WRITER" | "EMBEDDING";
@@ -120,23 +120,29 @@ function connectorVariables(
}
export function buildInstallationContract(workspace: WorkspaceDescriptor): InstallationContract {
const canonical = validateCanonicalWorkspace(workspace);
const namespace = namespaceFor(canonical);
const descriptor = validateWorkspaceDescriptor(workspace);
const namespace = namespaceFor(descriptor);
return {
workspaceId: canonical.workspace.id,
workspaceId: descriptor.workspace.id,
namespace,
variables: [
...connectorVariables(namespace, "DWH", canonical.dwh.supported_transports),
...connectorVariables(
namespace,
"VECTOR",
canonical.semantic_index.vector_store.supported_transports ?? [],
),
...(canonical.semantic_index.vector_writer
...connectorVariables(namespace, "DWH", descriptor.dwh.supported_transports),
...(descriptor.workspace.schema_version === 2
? connectorVariables(
namespace,
"VECTOR",
"supported_transports" in descriptor.semantic_index.vector_store
? descriptor.semantic_index.vector_store.supported_transports
: [],
)
: []),
...(descriptor.workspace.schema_version === 2 && descriptor.semantic_index.vector_writer
? [createVariable(namespace, "VECTOR_WRITER", "API_KEY_FILE")]
: []),
...EMBEDDING_SUFFIXES.map((suffix) => createVariable(namespace, "EMBEDDING", suffix)),
...(descriptor.workspace.schema_version === 2
? EMBEDDING_SUFFIXES.map((suffix) => createVariable(namespace, "EMBEDDING", suffix))
: []),
],
};
}
@@ -148,8 +154,8 @@ function localizedIntroduction(workspace: WorkspaceDescriptor): string {
}
export function renderWorkspaceDocs(workspace: WorkspaceDescriptor): { envExample: string; markdown: string } {
const canonical = validateCanonicalWorkspace(workspace);
const contract = buildInstallationContract(canonical);
const descriptor = validateWorkspaceDescriptor(workspace);
const contract = buildInstallationContract(descriptor);
const variablesByRole = new Map<InstallationRole, InstallationVariable[]>();
for (const variable of contract.variables) {
const variables = variablesByRole.get(variable.role) ?? [];
@@ -158,7 +164,7 @@ export function renderWorkspaceDocs(workspace: WorkspaceDescriptor): { envExampl
}
const envExample = [
`# Generated installation bindings for ${canonical.workspace.id}`,
`# Generated installation bindings for ${descriptor.workspace.id}`,
"# Provide secret file paths only; never paste secret values here.",
...contract.variables.map((variable) => `${variable.name}=`),
"",
@@ -167,9 +173,9 @@ export function renderWorkspaceDocs(workspace: WorkspaceDescriptor): { envExampl
const markdown = [
"# Installation requirements",
"",
`**Workspace:** ${canonical.workspace.name}`,
`**Workspace:** ${descriptor.workspace.name}`,
"",
localizedIntroduction(canonical),
localizedIntroduction(descriptor),
"",
"Use the following UI fields as installation bindings. Secret fields always contain file paths, never secret values.",
"",