refactor: remove legacy workspace runtime branches

This commit is contained in:
2026-08-10 21:28:08 +02:00
parent f102629cee
commit c2f9b03973
14 changed files with 906 additions and 2691 deletions
+37 -65
View File
@@ -1,15 +1,12 @@
import { constants, realpathSync, statSync, accessSync } from "node:fs"; import { constants, realpathSync, statSync, accessSync } from "node:fs";
import { isAbsolute, relative } from "node:path"; import { isAbsolute, relative } from "node:path";
import { buildInstallationContract, type InstallationRole, type InstallationSuffix } from "./contracts.js"; import { buildInstallationContract, type InstallationSuffix } from "./contracts.js";
import { import {
DWH_TRANSPORTS, DWH_TRANSPORTS,
VECTOR_TRANSPORTS,
validateWorkspaceDescriptor, validateWorkspaceDescriptor,
type DwhTransport, type DwhTransport,
type VectorTransport,
type WorkspaceDescriptor, type WorkspaceDescriptor,
} from "./schema.js"; } from "./schema.js";
import type { DeprecatedV2Descriptor } from "./deprecated-v2-descriptor.js";
export interface ResolvedEvidenceBinding { export interface ResolvedEvidenceBinding {
values: Record<string, string>; values: Record<string, string>;
@@ -18,42 +15,26 @@ export interface ResolvedEvidenceBinding {
export interface RuntimeBindings { export interface RuntimeBindings {
dwh: ResolvedBinding; dwh: ResolvedBinding;
vector: ResolvedBinding;
vectorWriter: ResolvedBinding;
embedding: ResolvedBinding;
evidence: ResolvedEvidenceBinding; evidence: ResolvedEvidenceBinding;
} }
export interface ResolvedBinding { export interface ResolvedBinding {
transport: DwhTransport | VectorTransport; transport: DwhTransport;
values: Record<string, string>; values: Record<string, string>;
missing: string[]; missing: string[];
} }
const REQUIRED_SUFFIXES: Record<"DWH" | "VECTOR", Record<string, readonly InstallationSuffix[]>> = { const REQUIRED_SUFFIXES: Record<DwhTransport, readonly InstallationSuffix[]> = {
DWH: { postgres_direct: ["HOST", "PORT", "USER", "PASSWORD_FILE"],
postgres_direct: ["HOST", "PORT", "USER", "PASSWORD_FILE"], rest_api: ["BASE_URL", "API_KEY_FILE"],
rest_api: ["BASE_URL", "API_KEY_FILE"], ssh_tunnel: [
ssh_tunnel: [ "USER", "PASSWORD_FILE", "SSH_HOST", "SSH_PORT", "SSH_USER",
"USER", "PASSWORD_FILE", "SSH_HOST", "SSH_PORT", "SSH_USER", "SSH_PRIVATE_KEY_FILE", "SSH_KNOWN_HOSTS_FILE", "SSH_TARGET_HOST", "SSH_TARGET_PORT",
"SSH_PRIVATE_KEY_FILE", "SSH_KNOWN_HOSTS_FILE", "SSH_TARGET_HOST", "SSH_TARGET_PORT", ],
],
},
VECTOR: {
pgvector_direct: ["HOST", "PORT", "USER", "PASSWORD_FILE"],
rest_api: ["BASE_URL", "API_KEY_FILE"],
ssh_tunnel: [
"USER", "PASSWORD_FILE", "SSH_HOST", "SSH_PORT", "SSH_USER",
"SSH_PRIVATE_KEY_FILE", "SSH_KNOWN_HOSTS_FILE", "SSH_TARGET_HOST", "SSH_TARGET_PORT",
],
},
}; };
const EMBEDDING_REQUIRED_SUFFIXES: readonly InstallationSuffix[] = ["BASE_URL"]; function isTransport(value: string | undefined): value is DwhTransport {
return value !== undefined && (DWH_TRANSPORTS as readonly string[]).includes(value);
function isTransport(value: string | undefined): value is DwhTransport | VectorTransport {
return value !== undefined
&& ([...DWH_TRANSPORTS, ...VECTOR_TRANSPORTS] as readonly string[]).includes(value);
} }
function isInside(path: string, root: string): boolean { function isInside(path: string, root: string): boolean {
@@ -76,18 +57,23 @@ function safeSecretFilePath(path: string, secretRoots: readonly string[]): strin
} }
} }
function requireSupportedDescriptor(workspace: unknown): void {
if (typeof workspace !== "object" || workspace === null) {
throw new Error("Workspace bindings support only workspace schema version 3");
}
const metadata = Reflect.get(workspace, "workspace");
if (typeof metadata !== "object" || metadata === null
|| Reflect.get(metadata, "schema_version") !== 3) {
throw new Error("Workspace bindings support only workspace schema version 3");
}
}
function requiredSuffixes( function requiredSuffixes(
workspace: WorkspaceDescriptor, workspace: WorkspaceDescriptor,
role: Exclude<InstallationRole, "EVIDENCE">, transport: DwhTransport,
transport: DwhTransport | VectorTransport,
): readonly InstallationSuffix[] { ): readonly InstallationSuffix[] {
if (role === "EMBEDDING") return EMBEDDING_REQUIRED_SUFFIXES; const required = REQUIRED_SUFFIXES[transport];
if (role === "VECTOR_WRITER") return ["API_KEY_FILE"]; return transport === "rest_api" && workspace.diagnostics?.dwh_rest?.auth === "none"
const required = REQUIRED_SUFFIXES[role][transport] ?? [];
const diagnostic = role === "DWH"
? workspace.diagnostics?.dwh_rest
: (workspace as unknown as DeprecatedV2Descriptor).diagnostics?.vector_rest?.metadata;
return transport === "rest_api" && diagnostic?.auth === "none"
? required.filter((suffix) => suffix !== "API_KEY_FILE") ? required.filter((suffix) => suffix !== "API_KEY_FILE")
: required; : required;
} }
@@ -98,37 +84,29 @@ function requiredSuffixes(
*/ */
export function resolveBinding( export function resolveBinding(
workspace: WorkspaceDescriptor, workspace: WorkspaceDescriptor,
role: Exclude<InstallationRole, "EVIDENCE">, role: "DWH",
env: NodeJS.ProcessEnv, env: NodeJS.ProcessEnv,
secretRoots: readonly string[], secretRoots: readonly string[],
): ResolvedBinding { ): ResolvedBinding {
requireSupportedDescriptor(workspace);
const descriptor = validateWorkspaceDescriptor(workspace); const descriptor = validateWorkspaceDescriptor(workspace);
if (descriptor.workspace.schema_version === 3 && role !== "DWH") {
return { transport: "rest_api", values: {}, missing: [] };
}
const contract = buildInstallationContract(descriptor); const contract = buildInstallationContract(descriptor);
const legacy = descriptor as unknown as DeprecatedV2Descriptor;
const variables = contract.variables.filter((variable) => variable.role === role); const variables = contract.variables.filter((variable) => variable.role === role);
const transportVariable = variables.find((variable) => variable.suffix === "TRANSPORT"); const transportVariable = variables.find((variable) => variable.suffix === "TRANSPORT");
const supported = role === "DWH" const supported = descriptor.dwh.supported_transports;
? descriptor.dwh.supported_transports
: role === "VECTOR"
? legacy.semantic_index.vector_store.supported_transports
: ["rest_api"] as const;
const selectedValue = transportVariable ? env[transportVariable.name] : undefined; const selectedValue = transportVariable ? env[transportVariable.name] : undefined;
const selectedTransport = isTransport(selectedValue) ? selectedValue : supported[0]; const selectedTransport = isTransport(selectedValue) ? selectedValue : supported[0];
const missing: string[] = []; const missing: string[] = [];
if (transportVariable && (!isTransport(selectedValue) || !supported.includes(selectedTransport as never))) { if (transportVariable && (!isTransport(selectedValue) || !supported.includes(selectedTransport))) {
missing.push(transportVariable.name); missing.push(transportVariable.name);
} }
const required = new Set(requiredSuffixes(descriptor, role, selectedTransport)); const required = new Set(requiredSuffixes(descriptor, selectedTransport));
const values: Record<string, string> = {}; const values: Record<string, string> = {};
for (const variable of variables) { for (const variable of variables) {
if (variable.suffix === "TRANSPORT") continue; if (variable.suffix === "TRANSPORT") continue;
if (variable.transports && !variable.transports.includes(selectedTransport as never)) continue; if (variable.transports && !variable.transports.includes(selectedTransport)) continue;
const value = env[variable.name]; const value = env[variable.name];
const present = value !== undefined && value.trim() !== ""; const present = value !== undefined && value.trim() !== "";
@@ -149,12 +127,13 @@ export function resolveEvidenceBinding(
env: NodeJS.ProcessEnv, env: NodeJS.ProcessEnv,
secretRoots: readonly string[], secretRoots: readonly string[],
): ResolvedEvidenceBinding { ): ResolvedEvidenceBinding {
requireSupportedDescriptor(workspace);
const descriptor = validateWorkspaceDescriptor(workspace); const descriptor = validateWorkspaceDescriptor(workspace);
const variables = buildInstallationContract(descriptor).variables const variables = buildInstallationContract(descriptor).variables
.filter((variable) => variable.role === "EVIDENCE"); .filter((variable) => variable.role === "EVIDENCE");
if (variables.length === 0) return { values: {}, missing: [] }; if (variables.length === 0) return { values: {}, missing: [] };
const source = "evidence" in descriptor ? descriptor.evidence?.source : undefined; const source = descriptor.evidence?.source;
const required = new Set<InstallationSuffix>( const required = new Set<InstallationSuffix>(
source?.type === "http" source?.type === "http"
? ["SIGNED_URLS_FILE"] ? ["SIGNED_URLS_FILE"]
@@ -176,29 +155,22 @@ export function resolveEvidenceBinding(
return { values, missing }; return { values, missing };
} }
/** Resolve all runtime roles together so optional writer credentials cannot be smuggled into reader bindings. */ /** Resolve the complete schema-v3 runtime binding set. */
export function resolveRuntimeBindings( export function resolveRuntimeBindings(
workspace: WorkspaceDescriptor, workspace: WorkspaceDescriptor,
env: NodeJS.ProcessEnv, env: NodeJS.ProcessEnv,
secretRoots: readonly string[], secretRoots: readonly string[],
): RuntimeBindings { ): RuntimeBindings {
requireSupportedDescriptor(workspace);
const descriptor = validateWorkspaceDescriptor(workspace); const descriptor = validateWorkspaceDescriptor(workspace);
return { return {
dwh: resolveBinding(descriptor, "DWH", env, secretRoots), dwh: resolveBinding(descriptor, "DWH", env, secretRoots),
vector: resolveBinding(descriptor, "VECTOR", env, secretRoots),
vectorWriter: resolveBinding(descriptor, "VECTOR_WRITER", env, secretRoots),
embedding: resolveBinding(descriptor, "EMBEDDING", env, secretRoots),
evidence: resolveEvidenceBinding(descriptor, env, secretRoots), evidence: resolveEvidenceBinding(descriptor, env, secretRoots),
}; };
} }
/** /** SSH bindings remain diagnostic-only until the session runtime owns a long-lived tunnel. */
* SSH bindings are currently probe-only: diagnostics owns a short-lived tunnel, while the
* session runtime has no tunnel owner. Keep activation fail-closed until that lifecycle exists.
*/
export function supportsSessionRuntime(bindings: RuntimeBindings): boolean { export function supportsSessionRuntime(bindings: RuntimeBindings): boolean {
return bindings.dwh.transport !== "ssh_tunnel" return bindings.dwh.transport !== "ssh_tunnel" && bindings.evidence.missing.length === 0;
&& bindings.vector.transport !== "ssh_tunnel"
&& bindings.evidence.missing.length === 0;
} }
+24 -35
View File
@@ -1,8 +1,7 @@
import { validateWorkspaceDescriptor } from "./schema.js"; import { validateWorkspaceDescriptor } from "./schema.js";
import type { DwhTransport, VectorTransport, WorkspaceDescriptor } from "./schema.js"; import type { DwhTransport, WorkspaceDescriptor } from "./schema.js";
import type { DeprecatedV2Descriptor } from "./deprecated-v2-descriptor.js";
export type InstallationRole = "DWH" | "VECTOR" | "VECTOR_WRITER" | "EMBEDDING" | "EVIDENCE"; export type InstallationRole = "DWH" | "EVIDENCE";
export type InstallationSuffix = export type InstallationSuffix =
| "TRANSPORT" | "TRANSPORT"
| "HOST" | "HOST"
@@ -24,7 +23,7 @@ export type InstallationSuffix =
| "SECRET_KEY_FILE" | "SECRET_KEY_FILE"
| "SESSION_TOKEN_FILE"; | "SESSION_TOKEN_FILE";
type ConnectorTransport = DwhTransport | VectorTransport; type ConnectorTransport = DwhTransport;
export interface InstallationVariable { export interface InstallationVariable {
name: string; name: string;
@@ -67,12 +66,6 @@ const SSH_SUFFIXES: readonly InstallationSuffix[] = [
"SSH_TARGET_PORT", "SSH_TARGET_PORT",
]; ];
const EMBEDDING_SUFFIXES: readonly InstallationSuffix[] = [
"BASE_URL",
"API_KEY_FILE",
"TLS_CA_FILE",
];
function namespaceFor(workspace: WorkspaceDescriptor): string { function namespaceFor(workspace: WorkspaceDescriptor): string {
return workspace.workspace.id.replaceAll("-", "_").toUpperCase(); return workspace.workspace.id.replaceAll("-", "_").toUpperCase();
} }
@@ -94,11 +87,10 @@ function createVariable(
function connectorVariables( function connectorVariables(
namespace: string, namespace: string,
role: "DWH" | "VECTOR", transports: readonly DwhTransport[],
transports: readonly ConnectorTransport[],
): InstallationVariable[] { ): InstallationVariable[] {
const suffixTransports = new Map<InstallationSuffix, ConnectorTransport[]>(); const suffixTransports = new Map<InstallationSuffix, DwhTransport[]>();
const add = (suffixes: readonly InstallationSuffix[], transport: ConnectorTransport) => { const add = (suffixes: readonly InstallationSuffix[], transport: DwhTransport) => {
for (const suffix of suffixes) { for (const suffix of suffixes) {
const applicable = suffixTransports.get(suffix) ?? []; const applicable = suffixTransports.get(suffix) ?? [];
applicable.push(transport); applicable.push(transport);
@@ -107,7 +99,7 @@ function connectorVariables(
}; };
for (const transport of transports) { for (const transport of transports) {
if (transport === "postgres_direct" || transport === "pgvector_direct") { if (transport === "postgres_direct") {
add(DIRECT_SUFFIXES, transport); add(DIRECT_SUFFIXES, transport);
} else if (transport === "rest_api") { } else if (transport === "rest_api") {
add(REST_SUFFIXES, transport); add(REST_SUFFIXES, transport);
@@ -117,9 +109,9 @@ function connectorVariables(
} }
return [ return [
createVariable(namespace, role, "TRANSPORT", transports), createVariable(namespace, "DWH", "TRANSPORT", transports),
...[...suffixTransports.entries()].map(([suffix, applicable]) => ( ...[...suffixTransports.entries()].map(([suffix, applicable]) => (
createVariable(namespace, role, suffix, applicable) createVariable(namespace, "DWH", suffix, applicable)
)), )),
]; ];
} }
@@ -143,30 +135,27 @@ function evidenceVariables(
return []; return [];
} }
function requireSupportedDescriptor(workspace: unknown): void {
if (typeof workspace !== "object" || workspace === null) {
throw new Error("Installation contract supports only workspace schema version 3");
}
const metadata = Reflect.get(workspace, "workspace");
if (typeof metadata !== "object" || metadata === null
|| Reflect.get(metadata, "schema_version") !== 3) {
throw new Error("Installation contract supports only workspace schema version 3");
}
}
export function buildInstallationContract(workspace: WorkspaceDescriptor): InstallationContract { export function buildInstallationContract(workspace: WorkspaceDescriptor): InstallationContract {
requireSupportedDescriptor(workspace);
const descriptor = validateWorkspaceDescriptor(workspace); const descriptor = validateWorkspaceDescriptor(workspace);
const namespace = namespaceFor(descriptor); const namespace = namespaceFor(descriptor);
const schemaVersion = Number(descriptor.workspace.schema_version);
const legacy = descriptor as unknown as DeprecatedV2Descriptor;
return { return {
workspaceId: descriptor.workspace.id, workspaceId: descriptor.workspace.id,
namespace, namespace,
variables: [ variables: [
...connectorVariables(namespace, "DWH", descriptor.dwh.supported_transports), ...connectorVariables(namespace, descriptor.dwh.supported_transports),
...(schemaVersion === 2
? connectorVariables(
namespace,
"VECTOR",
legacy.semantic_index.vector_store.supported_transports,
)
: []),
...(schemaVersion === 2 && legacy.semantic_index.vector_writer
? [createVariable(namespace, "VECTOR_WRITER", "API_KEY_FILE")]
: []),
...(schemaVersion === 2
? EMBEDDING_SUFFIXES.map((suffix) => createVariable(namespace, "EMBEDDING", suffix))
: []),
...evidenceVariables(namespace, descriptor), ...evidenceVariables(namespace, descriptor),
], ],
}; };
@@ -276,10 +265,10 @@ export function renderWorkspaceDocs(workspace: WorkspaceDescriptor): { envExampl
"", "",
"Use the following UI fields as installation bindings. Secret fields always contain file paths, never secret values.", "Use the following UI fields as installation bindings. Secret fields always contain file paths, never secret values.",
"", "",
...(["DWH", "VECTOR", "VECTOR_WRITER", "EMBEDDING", "EVIDENCE"] as const) ...(["DWH", "EVIDENCE"] as const)
.filter((role) => variablesByRole.has(role)) .filter((role) => variablesByRole.has(role))
.flatMap((role) => [ .flatMap((role) => [
`## ${role === "DWH" ? "Data warehouse" : role === "VECTOR" ? "Vector store" : role === "VECTOR_WRITER" ? "Vector writer" : role === "EMBEDDING" ? "Embedding service" : "Evidence"}`, `## ${role === "DWH" ? "Data warehouse" : "Evidence"}`,
"", "",
...(variablesByRole.get(role) ?? []).map((variable) => ( ...(variablesByRole.get(role) ?? []).map((variable) => (
`- \`${variable.name}\`${variable.transports ? ` (for: ${variable.transports.join(", ")})` : ""}` `- \`${variable.name}\`${variable.transports ? ` (for: ${variable.transports.join(", ")})` : ""}`
@@ -1,52 +0,0 @@
import type {
CanonicalDiagnostics,
DwhTransport,
VectorTransport,
} from "./schema.js";
/**
* Temporary compile-time shape for legacy runtime branches that will be removed separately.
* It is deliberately not part of the accepted workspace descriptor schema.
*/
export interface DeprecatedV2Descriptor {
workspace: {
schema_version: 2;
id: string;
name: string;
description?: string;
language: "en" | "it";
};
dwh: {
engine: "postgres";
database: string;
schema: string;
port?: number;
timeout_ms?: number;
supported_transports: DwhTransport[];
};
semantic_index: {
vector_store: {
engine: "pgvector";
database: string;
schema: string;
collection: string;
dimensions: number;
distance: "cosine" | "l2" | "inner_product";
port?: number;
timeout_ms?: number;
supported_transports: VectorTransport[];
};
vector_writer?: Record<string, never>;
embedding: {
provider: "ollama_compatible" | "openai_compatible";
model: string;
dimensions: number;
timeout_ms?: number;
};
};
llm_policy: {
default?: `${string}/${string}`;
allowed: `${string}/${string}`[];
};
diagnostics?: CanonicalDiagnostics;
}
File diff suppressed because it is too large Load Diff
+32 -3
View File
@@ -1,8 +1,37 @@
import { validateOperationalWorkspace, type WorkspaceV3 } from "./schema.js"; import {
import type { DeprecatedV2Descriptor } from "./deprecated-v2-descriptor.js"; validateOperationalWorkspace,
type CanonicalDiagnostics,
type DwhTransport,
type WorkspaceV3,
} from "./schema.js";
/** Legacy input exists only at the migration boundary and is never an accepted runtime descriptor. */
interface WorkspaceV2MigrationInput {
workspace: {
schema_version: 2;
id: string;
name: string;
description?: string;
language: "en" | "it";
};
dwh: {
engine: "postgres";
database: string;
schema: string;
port?: number;
timeout_ms?: number;
supported_transports: DwhTransport[];
};
semantic_index: unknown;
llm_policy: {
default?: `${string}/${string}`;
allowed: `${string}/${string}`[];
};
diagnostics?: CanonicalDiagnostics;
}
export function migrateWorkspaceV2ToV3( export function migrateWorkspaceV2ToV3(
legacy: DeprecatedV2Descriptor, legacy: WorkspaceV2MigrationInput,
collection: string, collection: string,
): WorkspaceV3 { ): WorkspaceV3 {
return validateOperationalWorkspace({ return validateOperationalWorkspace({
+57 -136
View File
@@ -1,12 +1,7 @@
import { basename, join } from "node:path"; import { basename, join } from "node:path";
import { stringify } from "yaml"; import { stringify } from "yaml";
import { buildInstallationContract } from "./contracts.js"; import { buildInstallationContract } from "./contracts.js";
import { import { validateWorkspaceDescriptor, type WorkspaceDescriptor } from "./schema.js";
validateWorkspaceDescriptor,
type WorkspaceDescriptor,
type WorkspaceV3,
} from "./schema.js";
import type { DeprecatedV2Descriptor } from "./deprecated-v2-descriptor.js";
import type { ResolvedBinding, ResolvedEvidenceBinding, RuntimeBindings } from "./bindings.js"; import type { ResolvedBinding, ResolvedEvidenceBinding, RuntimeBindings } from "./bindings.js";
export type { RuntimeBindings } from "./bindings.js"; export type { RuntimeBindings } from "./bindings.js";
@@ -45,10 +40,6 @@ const DEFAULT_SEMANTIC_RUNTIME: SemanticRuntimeConfig = {
internalEmbeddingDimensions: 1024, internalEmbeddingDimensions: 1024,
}; };
function seconds(timeoutMs: number | undefined): number | undefined {
return timeoutMs === undefined ? undefined : Math.max(1, Math.ceil(timeoutMs / 1_000));
}
function bindingValue(binding: ResolvedBinding, name: string): string | undefined { function bindingValue(binding: ResolvedBinding, name: string): string | undefined {
return binding.values[name]; return binding.values[name];
} }
@@ -59,7 +50,7 @@ function requireBinding(binding: ResolvedBinding, name: string): string {
return value; return value;
} }
function legacyDirectConnection( function directConnection(
binding: ResolvedBinding, binding: ResolvedBinding,
names: { host: string; port: string; user: string; passwordFile: string; tlsCaFile: string }, names: { host: string; port: string; user: string; passwordFile: string; tlsCaFile: string },
identity: { database: string; schema: string }, identity: { database: string; schema: string },
@@ -77,7 +68,7 @@ function legacyDirectConnection(
return connection; return connection;
} }
function legacyRestEndpoint( function restEndpoint(
binding: ResolvedBinding, binding: ResolvedBinding,
names: { baseUrl: string; apiKeyFile: string; tlsCaFile: string }, names: { baseUrl: string; apiKeyFile: string; tlsCaFile: string },
requiresCredential: boolean, requiresCredential: boolean,
@@ -115,7 +106,7 @@ function requireEvidenceBinding(binding: ResolvedEvidenceBinding, name: string):
} }
function renderEvidence( function renderEvidence(
workspace: WorkspaceV3, workspace: WorkspaceDescriptor,
binding: ResolvedEvidenceBinding, binding: ResolvedEvidenceBinding,
context: RuntimeRenderContext, context: RuntimeRenderContext,
bindingName: (suffix: string) => string, bindingName: (suffix: string) => string,
@@ -188,6 +179,7 @@ function renderEvidence(
}; };
} }
function placeholderConnection(identity: { database: string; schema: string }): Record<string, unknown> { function placeholderConnection(identity: { database: string; schema: string }): Record<string, unknown> {
return { return {
host: "localhost", host: "localhost",
@@ -200,7 +192,18 @@ function placeholderConnection(identity: { database: string; schema: string }):
}; };
} }
/** Render the compatibility fields consumed by the current Python harness. */ function requireSupportedDescriptor(workspace: unknown): void {
if (typeof workspace !== "object" || workspace === null) {
throw new Error("Runtime renderer supports only workspace schema version 3");
}
const metadata = Reflect.get(workspace, "workspace");
if (typeof metadata !== "object" || metadata === null
|| Reflect.get(metadata, "schema_version") !== 3) {
throw new Error("Runtime renderer supports only workspace schema version 3");
}
}
/** Render the schema-v3 compatibility fields consumed by the current Python harness. */
export function renderRuntimeConfig( export function renderRuntimeConfig(
workspace: WorkspaceDescriptor, workspace: WorkspaceDescriptor,
bindings: RuntimeBindings, bindings: RuntimeBindings,
@@ -209,119 +212,36 @@ export function renderRuntimeConfig(
installation: RuntimeInstallationOverlay = {}, installation: RuntimeInstallationOverlay = {},
semanticRuntime: SemanticRuntimeConfig = DEFAULT_SEMANTIC_RUNTIME, semanticRuntime: SemanticRuntimeConfig = DEFAULT_SEMANTIC_RUNTIME,
): string { ): string {
requireSupportedDescriptor(workspace);
const descriptor = validateWorkspaceDescriptor(workspace); const descriptor = validateWorkspaceDescriptor(workspace);
const contract = buildInstallationContract(descriptor); const contract = buildInstallationContract(descriptor);
const name = (role: "DWH" | "VECTOR" | "EMBEDDING" | "EVIDENCE", suffix: string) => { const name = (role: "DWH" | "EVIDENCE", suffix: string) => {
const variable = contract.variables.find((entry) => entry.role === role && entry.suffix === suffix); const variable = contract.variables.find((entry) => entry.role === role && entry.suffix === suffix);
if (!variable) throw new Error(`workspace contract is missing ${role}_${suffix}`); if (!variable) throw new Error(`workspace contract is missing ${role}_${suffix}`);
return variable.name; return variable.name;
}; };
if (Number(descriptor.workspace.schema_version) !== 2) { const renderedEvidence = descriptor.evidence === undefined
if (Number(descriptor.workspace.schema_version) === 1) { ? undefined
throw new Error("Workspace descriptor requires explicit migration to schema version 2"); : renderEvidence(
} descriptor,
const canonicalV3 = descriptor as WorkspaceV3; bindings.evidence,
const renderedEvidence = canonicalV3.evidence === undefined requireRuntimeRenderContext(identity),
? undefined (suffix) => name("EVIDENCE", suffix),
: renderEvidence( );
canonicalV3, if (bindings.dwh.missing.length > 0) {
bindings.evidence,
requireRuntimeRenderContext(identity),
(suffix) => name("EVIDENCE", suffix),
);
if (bindings.dwh.missing.length > 0) {
throw new Error("runtime configuration requires complete bindings");
}
const dwhRest = bindings.dwh.transport === "rest_api";
const dwhIdentity = { database: descriptor.dwh.database, schema: descriptor.dwh.schema };
const database = bindings.dwh.transport === "postgres_direct"
? { ...legacyDirectConnection(bindings.dwh, {
host: name("DWH", "HOST"),
port: name("DWH", "PORT"),
user: name("DWH", "USER"),
passwordFile: name("DWH", "PASSWORD_FILE"),
tlsCaFile: name("DWH", "TLS_CA_FILE"),
}, dwhIdentity), transport: "direct" }
: placeholderConnection(dwhIdentity);
const renderedV3: Record<string, unknown> = {
...(identity ? {
runtime_identity: {
workspace_id: identity.workspaceId,
workspace_revision: identity.workspaceRevision,
source_identity: `workspace://${identity.workspaceId}`,
},
} : {}),
...(installation.session_storage === undefined
? {} : { session_storage: installation.session_storage }),
...(installation.profile === undefined ? {} : { profile: installation.profile }),
language: descriptor.workspace.language,
database,
resources: {
vector: {
engine: "qdrant",
base_url: semanticRuntime.internalQdrantUrl,
collection: descriptor.semantic_index.vector_store.collection,
},
embeddings: {
provider: "ollama_internal",
base_url: semanticRuntime.internalEmbeddingUrl,
model: semanticRuntime.internalEmbeddingModel,
dimensions: semanticRuntime.internalEmbeddingDimensions,
},
},
roots: paths,
paths,
...(renderedEvidence ?? {}),
};
if (bindings.dwh.transport === "postgres_direct") {
renderedV3.dwh = { type: "postgres_direct", connection: database };
} else if (dwhRest) {
renderedV3.rest = legacyRestEndpoint(bindings.dwh, {
baseUrl: name("DWH", "BASE_URL"),
apiKeyFile: name("DWH", "API_KEY_FILE"),
tlsCaFile: name("DWH", "TLS_CA_FILE"),
}, descriptor.diagnostics?.dwh_rest?.auth !== "none");
renderedV3.database = placeholderConnection(dwhIdentity);
renderedV3.dwh = { type: "thoth_rest", database: dwhIdentity, endpoint: renderedV3.rest };
} else {
throw new Error("ssh_tunnel runtime configuration requires a diagnostic tunnel");
}
return stringify(renderedV3, { lineWidth: 0, sortMapEntries: false });
}
const canonical = descriptor as unknown as DeprecatedV2Descriptor;
if ([...bindings.dwh.missing, ...bindings.vector.missing, ...bindings.embedding.missing].length > 0) {
throw new Error("runtime configuration requires complete bindings"); throw new Error("runtime configuration requires complete bindings");
} }
const dwhIdentity = { database: canonical.dwh.database, schema: canonical.dwh.schema }; const dwhIdentity = { database: descriptor.dwh.database, schema: descriptor.dwh.schema };
const vectorIdentity = { const database = bindings.dwh.transport === "postgres_direct"
database: canonical.semantic_index.vector_store.database ?? canonical.dwh.database, ? { ...directConnection(bindings.dwh, {
schema: canonical.semantic_index.vector_store.schema ?? canonical.dwh.schema, host: name("DWH", "HOST"),
}; port: name("DWH", "PORT"),
const dwhDirect = bindings.dwh.transport === "postgres_direct"; user: name("DWH", "USER"),
const vectorDirect = bindings.vector.transport === "pgvector_direct"; passwordFile: name("DWH", "PASSWORD_FILE"),
const database = dwhDirect tlsCaFile: name("DWH", "TLS_CA_FILE"),
? { ...legacyDirectConnection(bindings.dwh, {
host: name("DWH", "HOST"), port: name("DWH", "PORT"), user: name("DWH", "USER"),
passwordFile: name("DWH", "PASSWORD_FILE"), tlsCaFile: name("DWH", "TLS_CA_FILE"),
}, dwhIdentity), transport: "direct" } }, dwhIdentity), transport: "direct" }
: placeholderConnection(dwhIdentity); : placeholderConnection(dwhIdentity);
const vectorDb = vectorDirect
? legacyDirectConnection(bindings.vector, {
host: name("VECTOR", "HOST"), port: name("VECTOR", "PORT"), user: name("VECTOR", "USER"),
passwordFile: name("VECTOR", "PASSWORD_FILE"), tlsCaFile: name("VECTOR", "TLS_CA_FILE"),
}, vectorIdentity)
: placeholderConnection(vectorIdentity);
const embedding: Record<string, unknown> = {
base_url: requireBinding(bindings.embedding, name("EMBEDDING", "BASE_URL")),
model: canonical.semantic_index.embedding.model,
dim: canonical.semantic_index.embedding.dimensions,
};
const embeddingTimeout = seconds(canonical.semantic_index.embedding.timeout_ms);
if (embeddingTimeout !== undefined) embedding.timeout = embeddingTimeout;
const rendered: Record<string, unknown> = { const rendered: Record<string, unknown> = {
...(identity ? { ...(identity ? {
runtime_identity: { runtime_identity: {
@@ -333,37 +253,38 @@ export function renderRuntimeConfig(
...(installation.session_storage === undefined ...(installation.session_storage === undefined
? {} : { session_storage: installation.session_storage }), ? {} : { session_storage: installation.session_storage }),
...(installation.profile === undefined ? {} : { profile: installation.profile }), ...(installation.profile === undefined ? {} : { profile: installation.profile }),
language: canonical.workspace.language, language: descriptor.workspace.language,
database, database,
vector_db: vectorDb, resources: {
embeddings: embedding, vector: {
engine: "qdrant",
base_url: semanticRuntime.internalQdrantUrl,
collection: descriptor.semantic_index.vector_store.collection,
},
embeddings: {
provider: "ollama_internal",
base_url: semanticRuntime.internalEmbeddingUrl,
model: semanticRuntime.internalEmbeddingModel,
dimensions: semanticRuntime.internalEmbeddingDimensions,
},
},
roots: paths, roots: paths,
paths, paths,
...(renderedEvidence ?? {}),
}; };
if (dwhDirect) { if (bindings.dwh.transport === "postgres_direct") {
rendered.dwh = { type: "postgres_direct", connection: database }; rendered.dwh = { type: "postgres_direct", connection: database };
} else if (bindings.dwh.transport === "rest_api") { } else if (bindings.dwh.transport === "rest_api") {
const rest = legacyRestEndpoint(bindings.dwh, { const rest = restEndpoint(bindings.dwh, {
baseUrl: name("DWH", "BASE_URL"), apiKeyFile: name("DWH", "API_KEY_FILE"), baseUrl: name("DWH", "BASE_URL"),
apiKeyFile: name("DWH", "API_KEY_FILE"),
tlsCaFile: name("DWH", "TLS_CA_FILE"), tlsCaFile: name("DWH", "TLS_CA_FILE"),
}, canonical.diagnostics?.dwh_rest?.auth !== "none"); }, descriptor.diagnostics?.dwh_rest?.auth !== "none");
rendered.rest = rest; rendered.rest = rest;
rendered.database = placeholderConnection(dwhIdentity);
rendered.dwh = { type: "thoth_rest", database: dwhIdentity, endpoint: rest }; rendered.dwh = { type: "thoth_rest", database: dwhIdentity, endpoint: rest };
} else { } else {
throw new Error("ssh_tunnel runtime configuration requires a diagnostic tunnel"); throw new Error("ssh_tunnel runtime configuration requires a diagnostic tunnel");
} }
if (vectorDirect) {
rendered.vectors = { type: "pgvector_direct", connection: vectorDb };
} else if (bindings.vector.transport === "rest_api") {
const vectorRest = legacyRestEndpoint(bindings.vector, {
baseUrl: name("VECTOR", "BASE_URL"), apiKeyFile: name("VECTOR", "API_KEY_FILE"),
tlsCaFile: name("VECTOR", "TLS_CA_FILE"),
}, canonical.diagnostics?.vector_rest?.metadata.auth !== "none");
rendered.vector_rest = vectorRest;
rendered.vectors = { type: "thoth_vector_http", reader: vectorRest };
} else {
throw new Error("ssh_tunnel runtime configuration requires a diagnostic tunnel");
}
return stringify(rendered, { lineWidth: 0, sortMapEntries: false }); return stringify(rendered, { lineWidth: 0, sortMapEntries: false });
} }
+4 -5
View File
@@ -287,11 +287,10 @@ test("runs diagnostics for a schema v3 workspace without external semantic bindi
expect(testResult.statusCode).toBe(200); expect(testResult.statusCode).toBe(200);
expect(testResult.json()).toMatchObject({ activatable: true, diagnostics: [] }); expect(testResult.json()).toMatchObject({ activatable: true, diagnostics: [] });
expect(diagnose).toHaveBeenCalledWith(workspace, expect.objectContaining({ expect(diagnose).toHaveBeenCalledWith(workspace, {
vector: expect.objectContaining({ missing: [], values: {} }), dwh: expect.objectContaining({ transport: "postgres_direct" }),
vectorWriter: expect.objectContaining({ missing: [], values: {} }), evidence: { missing: [], values: {} },
embedding: expect.objectContaining({ missing: [], values: {} }), }, { writeProbe: false });
}), { writeProbe: false });
}); });
test("reports missing Evidence binding through the real test route without changing registry revision", async () => { test("reports missing Evidence binding through the real test route without changing registry revision", async () => {
@@ -55,18 +55,6 @@ function evidenceWorkspace(source: string, policy = ""): string {
${source}${policy}`; ${source}${policy}`;
} }
const migrationRequiredWorkspace = canonicalWorkspace
.replace("schema_version: 3", "schema_version: 2")
.replace(
" engine: qdrant\n collection: psd-clinical",
" engine: pgvector\n database: analytics\n schema: vectors\n collection: documents",
)
.replace(" dimensions: 1024", " dimensions: 768")
.replace(" distance: cosine", " distance: cosine\n supported_transports: [rest_api]")
.replace(" provider: ollama_internal", " provider: ollama_compatible")
.replace(" model: qwen3-embedding:0.6b", " model: nomic-embed-text")
.replace(" dimensions: 1024", " dimensions: 768");
afterEach(() => { afterEach(() => {
vi.unstubAllEnvs(); vi.unstubAllEnvs();
roots.splice(0).forEach((root) => rmSync(root, { recursive: true, force: true })); roots.splice(0).forEach((root) => rmSync(root, { recursive: true, force: true }));
@@ -377,15 +365,6 @@ test("static S3 Evidence resolves only configured secret-root file paths", async
} }
}); });
test("ThtRunner refuses to render a migration-required registry snapshot", async () => {
const f = await fixture(migrationRequiredWorkspace);
const runner = runnerFor(f);
expect(() => runner.acquireWorkspaceRuntime(f.revision.snapshotPath)).toThrow(
"Workspace descriptor requires explicit migration to schema version 3",
);
});
test("local GET sessions mine uses the real canonical handoff and returns an empty inventory", async () => { test("local GET sessions mine uses the real canonical handoff and returns an empty inventory", async () => {
const f = await fixture(); const f = await fixture();
const app = buildApp(loadConfig({ const app = buildApp(loadConfig({
+38 -217
View File
@@ -12,32 +12,6 @@ import {
import { supportsSessionRuntime } from "../src/workspaces/bindings.js"; import { supportsSessionRuntime } from "../src/workspaces/bindings.js";
import { parseWorkspaceYaml } from "../src/workspaces/schema.js"; import { parseWorkspaceYaml } from "../src/workspaces/schema.js";
const workspace = parseWorkspaceYaml(`workspace:
schema_version: 2
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: pgvector
database: postgres
schema: vectors
collection: clinical_documents
dimensions: 768
distance: cosine
supported_transports: [pgvector_direct, rest_api]
embedding:
provider: ollama_compatible
model: nomic-embed-text-v2-moe
dimensions: 768
llm_policy:
allowed: [zai/glm-5.2]
`);
const workspaceV3 = parseWorkspaceYaml(`workspace: const workspaceV3 = parseWorkspaceYaml(`workspace:
schema_version: 3 schema_version: 3
id: psd-clinical id: psd-clinical
@@ -47,7 +21,7 @@ dwh:
engine: postgres engine: postgres
database: postgres database: postgres
schema: datawarehouse schema: datawarehouse
supported_transports: [postgres_direct, rest_api] supported_transports: [postgres_direct, rest_api, ssh_tunnel]
semantic_index: semantic_index:
vector_store: vector_store:
engine: qdrant engine: qdrant
@@ -59,6 +33,7 @@ semantic_index:
model: qwen3-embedding:0.6b model: qwen3-embedding:0.6b
dimensions: 1024 dimensions: 1024
llm_policy: llm_policy:
default: zai/glm-5.2
allowed: [zai/glm-5.2] allowed: [zai/glm-5.2]
`); `);
const paths: RuntimePaths = { const paths: RuntimePaths = {
@@ -72,31 +47,6 @@ const semanticRuntime: SemanticRuntimeConfig = {
internalEmbeddingModel: "qwen3-embedding:0.6b", internalEmbeddingModel: "qwen3-embedding:0.6b",
internalEmbeddingDimensions: 1024, internalEmbeddingDimensions: 1024,
}; };
const legacyWorkspace = parseWorkspaceYaml(`workspace:
schema_version: 1
id: psd-clinical
name: Policlinico San Donato
language: it
dwh:
engine: postgres
database: postgres
schema: datawarehouse
supported_transports: [postgres_direct]
semantic_index:
vector_store:
engine: pgvector
collection: clinical_documents
dimensions: 768
distance: cosine
supported_transports: [pgvector_direct]
embedding:
provider: ollama_compatible
model: nomic-embed-text-v2-moe
dimensions: 768
llm_policy:
allowed: [zai/glm-5.2]
`);
const directBindings: RuntimeBindings = { const directBindings: RuntimeBindings = {
dwh: { dwh: {
transport: "postgres_direct", transport: "postgres_direct",
@@ -109,44 +59,13 @@ const directBindings: RuntimeBindings = {
THT_WS_PSD_CLINICAL_DWH_TLS_CA_FILE: "/run/secrets/dwh-ca.pem", THT_WS_PSD_CLINICAL_DWH_TLS_CA_FILE: "/run/secrets/dwh-ca.pem",
}, },
}, },
vector: {
transport: "pgvector_direct",
missing: [],
values: {
THT_WS_PSD_CLINICAL_VECTOR_HOST: "vector.internal",
THT_WS_PSD_CLINICAL_VECTOR_PORT: "5432",
THT_WS_PSD_CLINICAL_VECTOR_USER: "vector_reader",
THT_WS_PSD_CLINICAL_VECTOR_PASSWORD_FILE: "/run/secrets/vector-password",
THT_WS_PSD_CLINICAL_VECTOR_TLS_CA_FILE: "/run/secrets/vector-ca.pem",
},
},
vectorWriter: { transport: "rest_api", missing: [], values: {} },
embedding: {
transport: "rest_api",
missing: [],
values: { THT_WS_PSD_CLINICAL_EMBEDDING_BASE_URL: "http://embedding.internal:11434" },
},
evidence: { missing: [], values: {} }, evidence: { missing: [], values: {} },
}; };
test("runtime support stays fail-closed for either SSH connector", () => { test("renders only the schema-v3 internal Qdrant and Ollama runtime shape", () => {
expect(supportsSessionRuntime(directBindings)).toBe(true); const rendered = parse(renderRuntimeConfig(workspaceV3, directBindings, paths, {
expect(supportsSessionRuntime({ workspaceId: "psd-clinical", workspaceRevision: "a".repeat(40),
...directBindings, }, {}, semanticRuntime));
dwh: { ...directBindings.dwh, transport: "ssh_tunnel" },
})).toBe(false);
expect(supportsSessionRuntime({
...directBindings,
vector: { ...directBindings.vector, transport: "ssh_tunnel" },
})).toBe(false);
});
test("renders a direct PostgreSQL binding to the legacy harness shape", () => {
const yaml = renderRuntimeConfig(workspace, directBindings, paths, {
workspaceId: "psd-clinical",
workspaceRevision: "a".repeat(40),
});
const rendered = parse(yaml);
expect(rendered).toMatchObject({ expect(rendered).toMatchObject({
runtime_identity: { runtime_identity: {
@@ -156,151 +75,53 @@ test("renders a direct PostgreSQL binding to the legacy harness shape", () => {
}, },
language: "it", language: "it",
database: { database: {
host: "dwh.internal", host: "dwh.internal", port: 5432, database: "postgres", schema: "datawarehouse",
port: 5432, user: "thoth_reader", password_file: "/run/secrets/dwh-password",
database: "postgres", ssl_ca_file: "/run/secrets/dwh-ca.pem", transport: "direct",
schema: "datawarehouse",
user: "thoth_reader",
password_file: "/run/secrets/dwh-password",
ssl_ca_file: "/run/secrets/dwh-ca.pem",
transport: "direct",
}, },
vector_db: { dwh: { type: "postgres_direct" },
host: "vector.internal", resources: {
database: "postgres", vector: { engine: "qdrant", base_url: "http://qdrant:6333", collection: "psd-clinical" },
schema: "vectors", embeddings: {
password_file: "/run/secrets/vector-password", provider: "ollama_internal", base_url: "http://embedding:11434",
ssl_ca_file: "/run/secrets/vector-ca.pem", model: "qwen3-embedding:0.6b", dimensions: 1024,
}, },
embeddings: {
base_url: "http://embedding.internal:11434",
model: "nomic-embed-text-v2-moe",
dim: 768,
}, },
paths, paths,
}); });
expect(yaml).toContain("type: postgres_direct"); expect(rendered).not.toHaveProperty("vector_db");
expect(yaml).toContain("schema: datawarehouse");
});
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);
const rendered = parse(renderRuntimeConfig(workspaceV3, directBindings, paths, undefined, {}, semanticRuntime));
expect(rendered.resources).toMatchObject({
vector: {
engine: "qdrant",
base_url: "http://qdrant:6333",
collection: "psd-clinical",
},
embeddings: {
provider: "ollama_internal",
base_url: "http://embedding:11434",
model: "qwen3-embedding:0.6b",
dimensions: 1024,
},
});
expect(rendered).not.toHaveProperty("embeddings"); expect(rendered).not.toHaveProperty("embeddings");
expect(rendered).not.toHaveProperty("vector_rest");
}); });
test("schema v3 runtime rendering never exposes external semantic endpoints from bindings", () => { test("renders schema-v3 DWH REST without exposing secret contents", () => {
const rendered = parse(renderRuntimeConfig(workspaceV3, { const rendered = parse(renderRuntimeConfig(workspaceV3, {
...directBindings,
vector: {
transport: "rest_api",
missing: [],
values: {
THT_WS_PSD_CLINICAL_VECTOR_BASE_URL: "https://vector.example.test",
THT_WS_PSD_CLINICAL_VECTOR_API_KEY_FILE: "/run/secrets/vector-api-key",
},
},
embedding: {
transport: "rest_api",
missing: [],
values: {
THT_WS_PSD_CLINICAL_EMBEDDING_BASE_URL: "https://embedding.example.test",
},
},
}, paths, undefined, {}, semanticRuntime));
expect(rendered.resources.vector).toMatchObject({
engine: "qdrant",
base_url: "http://qdrant:6333",
collection: "psd-clinical",
});
expect(rendered.resources.embeddings).toMatchObject({
provider: "ollama_internal",
base_url: "http://embedding:11434",
model: "qwen3-embedding:0.6b",
dimensions: 1024,
});
expect(rendered).not.toHaveProperty("embeddings");
expect(JSON.stringify(rendered)).not.toContain("vector.example.test");
expect(JSON.stringify(rendered)).not.toContain("embedding.example.test");
});
test("omits direct TLS fields when binding validation did not retain a file path", () => {
const dwhValues = { ...directBindings.dwh.values };
const vectorValues = { ...directBindings.vector.values };
delete dwhValues.THT_WS_PSD_CLINICAL_DWH_TLS_CA_FILE;
delete vectorValues.THT_WS_PSD_CLINICAL_VECTOR_TLS_CA_FILE;
const yaml = renderRuntimeConfig(workspace, {
...directBindings,
dwh: { dwh: {
...directBindings.dwh, transport: "rest_api", missing: [], values: {
values: dwhValues,
},
vector: {
...directBindings.vector,
values: vectorValues,
},
}, paths);
const rendered = parse(yaml);
expect(rendered.database).not.toHaveProperty("ssl_ca_file");
expect(rendered.vector_db).not.toHaveProperty("ssl_ca_file");
});
test("renders REST bindings through the legacy rest sections without secret values", () => {
const yaml = renderRuntimeConfig(workspace, {
...directBindings,
dwh: {
transport: "rest_api",
missing: [],
values: {
THT_WS_PSD_CLINICAL_DWH_BASE_URL: "https://dwh.example.test", THT_WS_PSD_CLINICAL_DWH_BASE_URL: "https://dwh.example.test",
THT_WS_PSD_CLINICAL_DWH_API_KEY_FILE: "/run/secrets/dwh-api-key", THT_WS_PSD_CLINICAL_DWH_API_KEY_FILE: "/run/secrets/dwh-api-key",
THT_WS_PSD_CLINICAL_DWH_TLS_CA_FILE: "/run/secrets/ca.pem",
}, },
}, },
vector: { evidence: { missing: [], values: {} },
transport: "rest_api", }, paths));
missing: [],
values: {
THT_WS_PSD_CLINICAL_VECTOR_BASE_URL: "https://vector.example.test",
THT_WS_PSD_CLINICAL_VECTOR_API_KEY_FILE: "/run/secrets/vector-api-key",
},
},
}, paths);
const rendered = parse(yaml);
expect(rendered).toMatchObject({ expect(rendered.rest).toEqual({
database: { transport: "rest", schema: "datawarehouse" }, base_url: "https://dwh.example.test", api_key_file: "/run/secrets/dwh-api-key",
rest: {
base_url: "https://dwh.example.test",
api_key_file: "/run/secrets/dwh-api-key",
ssl_ca_file: "/run/secrets/ca.pem",
},
vector_rest: {
base_url: "https://vector.example.test",
api_key_file: "/run/secrets/vector-api-key",
},
}); });
expect(yaml).not.toContain("\n api_key: "); expect(rendered.dwh).toMatchObject({
type: "thoth_rest", database: { database: "postgres", schema: "datawarehouse" },
});
expect(JSON.stringify(rendered)).not.toContain("api_key:");
});
test("runtime support is fail-closed for DWH SSH and incomplete Evidence", () => {
expect(supportsSessionRuntime(directBindings)).toBe(true);
expect(supportsSessionRuntime({
...directBindings, dwh: { ...directBindings.dwh, transport: "ssh_tunnel" },
})).toBe(false);
expect(supportsSessionRuntime({
...directBindings, evidence: { values: {}, missing: ["EVIDENCE_FILE"] },
})).toBe(false);
}); });
const evidenceSecretRoots: string[] = []; const evidenceSecretRoots: string[] = [];
+73 -188
View File
@@ -1,36 +1,14 @@
import { chmodSync, mkdirSync, mkdtempSync, realpathSync, rmSync, symlinkSync, writeFileSync } from "node:fs"; import {
chmodSync, mkdirSync, mkdtempSync, realpathSync, rmSync, symlinkSync, writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os"; import { tmpdir } from "node:os";
import { join } from "node:path"; import { join } from "node:path";
import { afterEach, expect, test } from "vitest"; import { afterEach, expect, test } from "vitest";
import { resolveBinding, resolveEvidenceBinding, resolveRuntimeBindings, supportsSessionRuntime } from "../src/workspaces/bindings.js"; import {
resolveBinding, resolveEvidenceBinding, resolveRuntimeBindings, supportsSessionRuntime,
} from "../src/workspaces/bindings.js";
import { parseWorkspaceYaml } from "../src/workspaces/schema.js"; import { parseWorkspaceYaml } from "../src/workspaces/schema.js";
const workspace = parseWorkspaceYaml(`workspace:
schema_version: 2
id: psd-clinical
name: Policlinico San Donato
language: it
dwh:
engine: postgres
database: postgres
schema: datawarehouse
supported_transports: [postgres_direct, rest_api, ssh_tunnel]
semantic_index:
vector_store:
engine: pgvector
database: postgres
schema: vectors
collection: clinical_documents
dimensions: 768
distance: cosine
supported_transports: [pgvector_direct, rest_api, ssh_tunnel]
embedding:
provider: ollama_compatible
model: nomic-embed-text-v2-moe
dimensions: 768
llm_policy:
allowed: [zai/glm-5.2]
`);
const workspaceV3 = parseWorkspaceYaml(`workspace: const workspaceV3 = parseWorkspaceYaml(`workspace:
schema_version: 3 schema_version: 3
id: psd-clinical id: psd-clinical
@@ -40,19 +18,11 @@ dwh:
engine: postgres engine: postgres
database: postgres database: postgres
schema: datawarehouse schema: datawarehouse
supported_transports: [postgres_direct, rest_api] supported_transports: [postgres_direct, rest_api, ssh_tunnel]
semantic_index: semantic_index:
vector_store: vector_store: { engine: qdrant, collection: psd-clinical, dimensions: 1024, distance: cosine }
engine: qdrant embedding: { provider: ollama_internal, model: qwen3-embedding:0.6b, dimensions: 1024 }
collection: psd-clinical llm_policy: { allowed: [zai/glm-5.2] }
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[] = []; const temporaryRoots: string[] = [];
@@ -70,80 +40,13 @@ function secretPath(name: string): { root: string; path: string } {
return { root: secrets, path }; return { root: secrets, path };
} }
test("marks a portable workspace non-activatable when its local REST key file is absent", () => { test("resolves schema-v3 direct DWH bindings from the stable namespace", () => {
const result = resolveBinding(workspace, "DWH", {
THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "rest_api",
THT_WS_PSD_CLINICAL_DWH_BASE_URL: "https://dwh.example.test",
}, ["/run/secrets"]);
expect(result.missing).toContain("THT_WS_PSD_CLINICAL_DWH_API_KEY_FILE");
});
test("does not require a REST secret file when its declared diagnostic uses auth none", () => {
const unauthenticatedWorkspace = parseWorkspaceYaml(`workspace:
schema_version: 2
id: psd-clinical
name: Policlinico San Donato
language: it
dwh:
engine: postgres
database: postgres
schema: datawarehouse
supported_transports: [rest_api]
semantic_index:
vector_store:
engine: pgvector
database: postgres
schema: vectors
collection: clinical_documents
dimensions: 768
distance: cosine
supported_transports: [rest_api]
embedding:
provider: ollama_compatible
model: nomic-embed-text-v2-moe
dimensions: 768
diagnostics:
dwh_rest:
method: POST
path: /rpc/ping
auth: none
response: { database: database, schema: schema }
vector_rest:
metadata:
method: GET
path: /vector/metadata
auth: none
response: { collection: collection, dimensions: dimensions, distance: distance }
embedding:
method: GET
path: /models
auth: none
response: { model: model, dimensions: dimensions }
llm_policy:
allowed: [zai/glm-5.2]
`);
const bindings = resolveRuntimeBindings(unauthenticatedWorkspace, {
THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "rest_api",
THT_WS_PSD_CLINICAL_DWH_BASE_URL: "https://dwh.example.test",
THT_WS_PSD_CLINICAL_VECTOR_TRANSPORT: "rest_api",
THT_WS_PSD_CLINICAL_VECTOR_BASE_URL: "https://vector.example.test",
THT_WS_PSD_CLINICAL_EMBEDDING_BASE_URL: "https://embedding.example.test",
}, ["/run/secrets"]);
expect(bindings.dwh.missing).toEqual([]);
expect(bindings.vector.missing).toEqual([]);
expect(bindings.embedding.missing).toEqual([]);
});
test("resolves direct bindings from the stable workspace namespace", () => {
const password = secretPath("dwh-password"); const password = secretPath("dwh-password");
const result = resolveBinding(workspace, "DWH", { const result = resolveBinding(workspaceV3, "DWH", {
THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "postgres_direct", THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "postgres_direct",
THT_WS_PSD_CLINICAL_DWH_HOST: "dwh.internal", THT_WS_PSD_CLINICAL_DWH_HOST: "dwh.internal",
THT_WS_PSD_CLINICAL_DWH_PORT: "5432", THT_WS_PSD_CLINICAL_DWH_PORT: "5432",
THT_WS_PSD_CLINICAL_DWH_USER: "thoth_reader", THT_WS_PSD_CLINICAL_DWH_USER: "reader",
THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE: password.path, THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE: password.path,
}, [password.root]); }, [password.root]);
@@ -158,82 +61,72 @@ test("resolves direct bindings from the stable workspace namespace", () => {
}); });
}); });
test("reports only a FILE variable name when a secret path is outside the configured roots", () => { test("requires schema-v3 REST credentials unless the DWH diagnostic declares auth none", () => {
expect(resolveBinding(workspaceV3, "DWH", {
THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "rest_api",
THT_WS_PSD_CLINICAL_DWH_BASE_URL: "https://dwh.example.test",
}, []).missing).toContain("THT_WS_PSD_CLINICAL_DWH_API_KEY_FILE");
const noAuth = parseWorkspaceYaml(`workspace:
schema_version: 3
id: psd-clinical
name: No auth
language: en
dwh:
engine: postgres
database: postgres
schema: public
supported_transports: [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 }
diagnostics:
dwh_rest:
method: GET
path: /health
auth: none
response: { database: database, schema: schema }
llm_policy: { allowed: [zai/glm-5.2] }
`);
expect(resolveBinding(noAuth, "DWH", {
THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "rest_api",
THT_WS_PSD_CLINICAL_DWH_BASE_URL: "https://dwh.example.test",
}, []).missing).toEqual([]);
});
test("rejects unsupported transports and secret paths outside configured roots", () => {
const outside = secretPath("outside-password"); const outside = secretPath("outside-password");
const allowed = secretPath("allowed-password"); const allowed = secretPath("allowed-password");
const result = resolveBinding(workspace, "DWH", { const directOnly = parseWorkspaceYaml(`workspace:
schema_version: 3
id: psd-clinical
name: Direct only
language: en
dwh:
engine: postgres
database: postgres
schema: public
supported_transports: [postgres_direct]
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] }
`);
expect(resolveBinding(directOnly, "DWH", {
THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "rest_api",
}, []).missing).toContain("THT_WS_PSD_CLINICAL_DWH_TRANSPORT");
const result = resolveBinding(workspaceV3, "DWH", {
THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "postgres_direct", THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "postgres_direct",
THT_WS_PSD_CLINICAL_DWH_HOST: "dwh.internal", THT_WS_PSD_CLINICAL_DWH_HOST: "dwh.internal",
THT_WS_PSD_CLINICAL_DWH_PORT: "5432", THT_WS_PSD_CLINICAL_DWH_PORT: "5432",
THT_WS_PSD_CLINICAL_DWH_USER: "thoth_reader", THT_WS_PSD_CLINICAL_DWH_USER: "reader",
THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE: outside.path, THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE: outside.path,
}, [allowed.root]); }, [allowed.root]);
expect(result.missing).toContain("THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE");
expect(result.missing).toEqual(["THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE"]); expect(JSON.stringify(result)).not.toContain(outside.path);
expect(result.missing.join("\n")).not.toContain(outside.path);
}); });
test("reports an invalid optional secret file instead of silently dropping it", () => { test("runtime bindings contain only DWH and Evidence roles", () => {
const password = secretPath("dwh-password");
const result = resolveBinding(workspace, "DWH", {
THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "postgres_direct",
THT_WS_PSD_CLINICAL_DWH_HOST: "dwh.internal",
THT_WS_PSD_CLINICAL_DWH_PORT: "5432",
THT_WS_PSD_CLINICAL_DWH_USER: "thoth_reader",
THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE: password.path,
THT_WS_PSD_CLINICAL_DWH_TLS_CA_FILE: "relative-ca.pem",
}, [password.root]);
expect(result.missing).toContain("THT_WS_PSD_CLINICAL_DWH_TLS_CA_FILE");
expect(result.values).not.toHaveProperty("THT_WS_PSD_CLINICAL_DWH_TLS_CA_FILE");
});
test("rejects a selected transport that the canonical workspace does not support", () => {
const directOnly = {
...workspace,
dwh: { ...workspace.dwh, supported_transports: ["postgres_direct"] },
};
const result = resolveBinding(directOnly, "DWH", {
THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "rest_api",
}, ["/run/secrets"]);
expect(result).toMatchObject({
transport: "rest_api",
missing: ["THT_WS_PSD_CLINICAL_DWH_TRANSPORT"],
});
});
test("never treats a vector reader credential as the optional writer binding", () => {
const readerKey = secretPath("vector-reader-key");
const writerWorkspace = {
...workspace,
semantic_index: { ...workspace.semantic_index, vector_writer: {} },
};
const resolveWriter = () => resolveBinding(writerWorkspace, "VECTOR_WRITER" as never, {
THT_WS_PSD_CLINICAL_VECTOR_API_KEY_FILE: readerKey.path,
}, [readerKey.root]);
expect(resolveWriter).not.toThrow();
expect(resolveWriter()).toMatchObject({
missing: ["THT_WS_PSD_CLINICAL_VECTOR_WRITER_API_KEY_FILE"],
values: {},
});
});
test("fails closed for v3 external semantic bindings", () => {
expect(() => resolveBinding(workspaceV3, "VECTOR", {}, ["/run/secrets"]))
.not.toThrow();
expect(() => resolveBinding(workspaceV3, "EMBEDDING", {}, ["/run/secrets"]))
.not.toThrow();
expect(() => resolveRuntimeBindings(workspaceV3, {
THT_WS_PSD_CLINICAL_VECTOR_TRANSPORT: "rest_api",
THT_WS_PSD_CLINICAL_VECTOR_BASE_URL: "https://vector.example.test",
THT_WS_PSD_CLINICAL_EMBEDDING_BASE_URL: "https://embedding.example.test",
THT_WS_PSD_CLINICAL_VECTOR_API_KEY_FILE: "/run/secrets/vector-api-key",
}, ["/run/secrets"])).not.toThrow();
});
test("schema v3 ignores external semantic binding variables and reports only DWH requirements", () => {
const password = secretPath("dwh-password"); const password = secretPath("dwh-password");
const bindings = resolveRuntimeBindings(workspaceV3, { const bindings = resolveRuntimeBindings(workspaceV3, {
THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "postgres_direct", THT_WS_PSD_CLINICAL_DWH_TRANSPORT: "postgres_direct",
@@ -241,21 +134,13 @@ test("schema v3 ignores external semantic binding variables and reports only DWH
THT_WS_PSD_CLINICAL_DWH_PORT: "5432", THT_WS_PSD_CLINICAL_DWH_PORT: "5432",
THT_WS_PSD_CLINICAL_DWH_USER: "reader", THT_WS_PSD_CLINICAL_DWH_USER: "reader",
THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE: password.path, THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE: password.path,
THT_WS_PSD_CLINICAL_VECTOR_TRANSPORT: "rest_api", THT_WS_PSD_CLINICAL_VECTOR_BASE_URL: "https://ignored.example.test",
THT_WS_PSD_CLINICAL_VECTOR_BASE_URL: "https://vector.example.test",
THT_WS_PSD_CLINICAL_VECTOR_API_KEY_FILE: "/run/secrets/vector-api-key",
THT_WS_PSD_CLINICAL_EMBEDDING_BASE_URL: "https://embedding.example.test",
THT_WS_PSD_CLINICAL_EMBEDDING_API_KEY_FILE: "/run/secrets/embedding-api-key",
}, [password.root]); }, [password.root]);
expect(Object.keys(bindings)).toEqual(["dwh", "evidence"]);
expect(bindings.dwh.missing).toEqual([]); expect(bindings.dwh.missing).toEqual([]);
expect(bindings.vector.missing).toEqual([]); expect(supportsSessionRuntime(bindings)).toBe(true);
expect(bindings.embedding.missing).toEqual([]);
expect(bindings.vector.values).toEqual({});
expect(bindings.embedding.values).toEqual({});
}); });
function withEvidence(source: Record<string, unknown>) { function withEvidence(source: Record<string, unknown>) {
return parseWorkspaceYaml(`workspace: return parseWorkspaceYaml(`workspace:
schema_version: 3 schema_version: 3
+23 -281
View File
@@ -1,46 +1,10 @@
import { expect, test } from "vitest"; import { expect, test } from "vitest";
import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os"; import { tmpdir } from "node:os";
import { join } from "node:path"; import { join } from "node:path";
import { fileURLToPath } from "node:url";
import { parse } from "yaml";
import { buildInstallationContract, renderWorkspaceDocs } from "../src/workspaces/contracts.js"; import { buildInstallationContract, renderWorkspaceDocs } from "../src/workspaces/contracts.js";
import { type CanonicalWorkspace, parseWorkspaceYaml } from "../src/workspaces/schema.js"; import { type CanonicalWorkspace, parseWorkspaceYaml } from "../src/workspaces/schema.js";
import { renderRuntimeConfig, type RuntimeBindings } from "../src/workspaces/runtime-renderer.js";
const validWorkspace = parseWorkspaceYaml(`workspace:
schema_version: 2
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: pgvector
database: postgres
schema: vectors
collection: clinical_documents
dimensions: 768
distance: cosine
supported_transports:
- pgvector_direct
- rest_api
embedding:
provider: ollama_compatible
model: nomic-embed-text-v2-moe
dimensions: 768
llm_policy:
default: zai/glm-5.2
allowed:
- zai/glm-5.2
- openai/gpt-5
`);
const workspaceV3 = parseWorkspaceYaml(`workspace: const workspaceV3 = parseWorkspaceYaml(`workspace:
schema_version: 3 schema_version: 3
id: psd-clinical id: psd-clinical
@@ -50,270 +14,48 @@ dwh:
engine: postgres engine: postgres
database: postgres database: postgres
schema: datawarehouse schema: datawarehouse
supported_transports: [postgres_direct, rest_api] supported_transports: [postgres_direct, rest_api, ssh_tunnel]
semantic_index: semantic_index:
vector_store: vector_store: { engine: qdrant, collection: psd-clinical, dimensions: 1024, distance: cosine }
engine: qdrant embedding: { provider: ollama_internal, model: qwen3-embedding:0.6b, dimensions: 1024 }
collection: psd-clinical
dimensions: 1024
distance: cosine
embedding:
provider: ollama_internal
model: qwen3-embedding:0.6b
dimensions: 1024
llm_policy: llm_policy:
allowed: [zai/glm-5.2] allowed: [zai/glm-5.2]
`); `);
test("generates stable FILE-based secret requirements from an immutable ID", () => { test("schema-v3 installation contracts expose only DWH bindings and no semantic variables", () => {
const contract = buildInstallationContract(validWorkspace);
expect(contract.variables.map((variable) => variable.name))
.toContain("THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE");
expect(contract.variables.filter((variable) => variable.secret).every((variable) => (
variable.name.endsWith("_FILE")
))).toBe(true);
expect(renderWorkspaceDocs(validWorkspace).envExample).not.toContain("secret-value");
});
test("derives variable names from fixed role and suffix metadata", () => {
const contract = buildInstallationContract(validWorkspace);
const password = contract.variables.find((variable) => (
variable.role === "DWH" && variable.suffix === "PASSWORD_FILE"
));
expect(password).toMatchObject({
name: "THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE",
role: "DWH",
suffix: "PASSWORD_FILE",
secret: true,
});
});
test("renders English UI headings and workspace-language Italian prose", () => {
const docs = renderWorkspaceDocs(validWorkspace);
expect(docs.markdown).toContain("# Installation requirements");
expect(docs.markdown).toContain("Configurazione dell'installazione");
expect(docs.markdown).not.toContain("## Vector writer");
expect(docs.envExample).toContain("THT_WS_PSD_CLINICAL_VECTOR_TRANSPORT=");
});
test("schema v3 installation contracts expose only DWH bindings and no semantic variables", () => {
const contract = buildInstallationContract(workspaceV3); const contract = buildInstallationContract(workspaceV3);
const names = contract.variables.map((variable) => variable.name); const names = contract.variables.map((variable) => variable.name);
const docs = renderWorkspaceDocs(workspaceV3); const docs = renderWorkspaceDocs(workspaceV3);
expect(contract.workspaceId).toBe("psd-clinical");
expect(contract.namespace).toBe("PSD_CLINICAL");
expect(contract.variables.every((variable) => variable.role === "DWH")).toBe(true); expect(contract.variables.every((variable) => variable.role === "DWH")).toBe(true);
expect(names).toContain("THT_WS_PSD_CLINICAL_DWH_TRANSPORT"); expect(names).toContain("THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE");
expect(names.some((name) => /_VECTOR_|_EMBEDDING_/.test(name))).toBe(false); expect(names.some((name) => /_VECTOR_|_EMBEDDING_/.test(name))).toBe(false);
expect(docs.envExample).not.toContain("_VECTOR_"); expect(docs.envExample).not.toContain("_VECTOR_");
expect(docs.envExample).not.toContain("_EMBEDDING_"); expect(docs.markdown).toContain("Configurazione dell'installazione");
expect(docs.markdown).not.toContain("Vector store"); expect(docs.markdown).not.toContain("Vector store");
expect(docs.markdown).not.toContain("Embedding service"); expect(docs.markdown).not.toContain("Embedding service");
}); });
test("renders the vector store identity and creates writer credentials only when declared", () => { test.each([
const writerWorkspace = parseWorkspaceYaml(`workspace: ["postgres_direct", "HOST", "BASE_URL"],
schema_version: 2 ["rest_api", "BASE_URL", "HOST"],
id: psd-clinical ["ssh_tunnel", "SSH_PRIVATE_KEY_FILE", "BASE_URL"],
name: Policlinico San Donato ] as const)("documents only the DWH fields for %s", (transport, included, excluded) => {
language: it const descriptor = parseWorkspaceYaml(renderWorkspaceWithoutEvidence()
dwh: .replace("[postgres_direct]", `[${transport}]`));
engine: postgres const variables = buildInstallationContract(descriptor).variables;
database: warehouse expect(variables.find(({ suffix }) => suffix === included)?.transports).toEqual([transport]);
schema: datawarehouse expect(variables.some(({ suffix }) => suffix === excluded)).toBe(false);
supported_transports: [postgres_direct, rest_api] expect(variables.filter(({ secret }) => secret).every(({ name }) => name.endsWith("_FILE")))
semantic_index: .toBe(true);
vector_store:
engine: pgvector
database: vector_database
schema: vectors
collection: clinical_documents
dimensions: 768
distance: cosine
supported_transports: [pgvector_direct, rest_api]
vector_writer: {}
embedding:
provider: ollama_compatible
model: nomic-embed-text-v2-moe
dimensions: 768
diagnostics:
dwh_rest:
method: POST
path: /rpc/ping
auth: bearer
response:
database: database
schema: schema
vector_rest:
metadata:
method: GET
path: /metadata
auth: bearer
response:
collection: collection
dimensions: dimensions
distance: distance
embedding:
method: GET
path: /models
auth: none
response:
model: model
dimensions: dimensions
llm_policy:
allowed: [zai/glm-5.2]
`);
const bindings: RuntimeBindings = {
dwh: {
transport: "postgres_direct",
missing: [],
values: {
THT_WS_PSD_CLINICAL_DWH_HOST: "dwh.internal",
THT_WS_PSD_CLINICAL_DWH_PORT: "5432",
THT_WS_PSD_CLINICAL_DWH_USER: "reader",
THT_WS_PSD_CLINICAL_DWH_PASSWORD_FILE: "/run/secrets/dwh",
},
},
vector: {
transport: "pgvector_direct",
missing: [],
values: {
THT_WS_PSD_CLINICAL_VECTOR_HOST: "vector.internal",
THT_WS_PSD_CLINICAL_VECTOR_PORT: "5432",
THT_WS_PSD_CLINICAL_VECTOR_USER: "vector-reader",
THT_WS_PSD_CLINICAL_VECTOR_PASSWORD_FILE: "/run/secrets/vector-reader",
},
},
vectorWriter: { transport: "rest_api", missing: [], values: {} },
embedding: {
transport: "rest_api",
missing: [],
values: { THT_WS_PSD_CLINICAL_EMBEDDING_BASE_URL: "https://embedding.internal" },
},
evidence: { missing: [], values: {} },
};
const writerVariables = buildInstallationContract(writerWorkspace).variables
.filter((variable) => variable.role === "VECTOR_WRITER");
expect(writerVariables).toEqual([expect.objectContaining({
name: "THT_WS_PSD_CLINICAL_VECTOR_WRITER_API_KEY_FILE",
role: "VECTOR_WRITER",
secret: true,
})]);
expect(buildInstallationContract(validWorkspace).variables.some((variable) => (
variable.role === "VECTOR_WRITER"
))).toBe(false);
expect(parse(renderRuntimeConfig(writerWorkspace, bindings, {
sessions: "/data/sessions",
artifacts: "/data/artifacts",
indexes: "/data/indexes",
})).vector_db).toMatchObject({ database: "vector_database", schema: "vectors" });
});
test("renders legacy writer secret-file bindings without reintroducing them to the active protocol", () => {
const writerVariable = "THT_WS_PSD_CLINICAL_VECTOR_WRITER_API_KEY_FILE";
const generated = renderWorkspaceDocs(parseWorkspaceYaml(`workspace:
schema_version: 2
id: psd-clinical
name: Policlinico San Donato
language: it
dwh:
engine: postgres
database: warehouse
schema: datawarehouse
supported_transports: [postgres_direct]
semantic_index:
vector_store:
engine: pgvector
database: vector_database
schema: vectors
collection: clinical_documents
dimensions: 768
distance: cosine
supported_transports: [rest_api]
vector_writer: {}
embedding:
provider: ollama_compatible
model: nomic-embed-text-v2-moe
dimensions: 768
llm_policy:
allowed: [zai/glm-5.2]
`));
const protocolPath = fileURLToPath(new URL("../../docs/workspace-diagnostic-protocol.md", import.meta.url));
expect(generated.markdown).toContain(`\`${writerVariable}\``);
expect(generated.envExample).toContain(`${writerVariable}=`);
expect(existsSync(protocolPath)).toBe(true);
if (existsSync(protocolPath)) {
expect(readFileSync(protocolPath, "utf8")).not.toContain(writerVariable);
expect(readFileSync(protocolPath, "utf8")).toContain("There are no supported `THT_WS_<NAMESPACE>_VECTOR_*`");
}
});
function withTransports(
dwhTransport: CanonicalWorkspace["dwh"]["supported_transports"][number],
vectorTransport: CanonicalWorkspace["semantic_index"]["vector_store"]["supported_transports"][number],
): CanonicalWorkspace {
return {
...validWorkspace,
dwh: { ...validWorkspace.dwh, supported_transports: [dwhTransport] },
semantic_index: {
...validWorkspace.semantic_index,
vector_store: {
...validWorkspace.semantic_index.vector_store,
supported_transports: [vectorTransport],
},
},
};
}
test("emits only direct connector bindings for direct transports", () => {
const variables = buildInstallationContract(withTransports("postgres_direct", "pgvector_direct")).variables;
for (const role of ["DWH", "VECTOR"] as const) {
const names = variables.filter((variable) => variable.role === role).map((variable) => variable.name);
expect(names).toContain(`THT_WS_PSD_CLINICAL_${role}_HOST`);
expect(names).toContain(`THT_WS_PSD_CLINICAL_${role}_PASSWORD_FILE`);
expect(names).not.toContain(`THT_WS_PSD_CLINICAL_${role}_BASE_URL`);
expect(names).not.toContain(`THT_WS_PSD_CLINICAL_${role}_API_KEY_FILE`);
expect(names.some((name) => name.includes("_SSH_"))).toBe(false);
}
});
test("emits only REST connector bindings for REST transports", () => {
const variables = buildInstallationContract(withTransports("rest_api", "rest_api")).variables;
for (const role of ["DWH", "VECTOR"] as const) {
const names = variables.filter((variable) => variable.role === role).map((variable) => variable.name);
expect(names).toContain(`THT_WS_PSD_CLINICAL_${role}_BASE_URL`);
expect(names).toContain(`THT_WS_PSD_CLINICAL_${role}_API_KEY_FILE`);
expect(names).not.toContain(`THT_WS_PSD_CLINICAL_${role}_HOST`);
expect(names).not.toContain(`THT_WS_PSD_CLINICAL_${role}_PASSWORD_FILE`);
expect(names.some((name) => name.includes("_SSH_"))).toBe(false);
}
});
test("emits SSH bindings only for SSH-tunnel transports", () => {
const variables = buildInstallationContract(withTransports("ssh_tunnel", "ssh_tunnel")).variables;
for (const role of ["DWH", "VECTOR"] as const) {
const roleVariables = variables.filter((variable) => variable.role === role);
expect(roleVariables.map((variable) => variable.name))
.toContain(`THT_WS_PSD_CLINICAL_${role}_SSH_PRIVATE_KEY_FILE`);
expect(roleVariables.find((variable) => variable.suffix === "SSH_HOST")?.transports)
.toEqual(["ssh_tunnel"]);
expect(roleVariables.map((variable) => variable.name))
.not.toContain(`THT_WS_PSD_CLINICAL_${role}_BASE_URL`);
}
}); });
test("validates public contract and documentation inputs at runtime", () => { test("validates public contract and documentation inputs at runtime", () => {
const unsafeWorkspace = { const unsafeWorkspace = {
...validWorkspace, ...workspaceV3,
workspace: { ...validWorkspace.workspace, id: "psd\nclinical" }, workspace: { ...workspaceV3.workspace, id: "psd\nclinical" },
} as CanonicalWorkspace; } as CanonicalWorkspace;
expect(() => buildInstallationContract(unsafeWorkspace)).toThrow(/id/i); expect(() => buildInstallationContract(unsafeWorkspace)).toThrow(/id/i);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,70 @@
import { expect, test, vi } from "vitest";
import { buildInstallationContract } from "../src/workspaces/contracts.js";
import {
createProductionWorkspaceDiagnoser,
createWorkspaceDiagnoser,
type DiagnosticAdapters,
} from "../src/workspaces/diagnostics.js";
import {
resolveBinding,
resolveEvidenceBinding,
resolveRuntimeBindings,
} from "../src/workspaces/bindings.js";
import { renderRuntimeConfig, type RuntimeBindings } from "../src/workspaces/runtime-renderer.js";
const unsupportedWorkspace = {
workspace: { schema_version: 2, id: "legacy-workspace", name: "Legacy", language: "en" },
dwh: {
engine: "postgres", database: "warehouse", schema: "public",
supported_transports: ["postgres_direct"],
},
semantic_index: {
vector_store: {
engine: "pgvector", database: "warehouse", schema: "vectors",
collection: "documents", dimensions: 768, distance: "cosine",
supported_transports: ["pgvector_direct"],
},
embedding: { provider: "ollama_compatible", model: "legacy", dimensions: 768 },
},
llm_policy: { allowed: ["zai/glm-5.2"] },
};
const bindings: RuntimeBindings = {
dwh: { transport: "postgres_direct", values: {}, missing: [] },
evidence: { values: {}, missing: [] },
};
const adapters: DiagnosticAdapters = {
probeConnector: vi.fn(),
inspectQdrant: vi.fn(),
probeEmbedding: vi.fn(),
};
test("renderer rejects callers that bypass the schema-v3 type contract", () => {
expect(() => renderRuntimeConfig(unsupportedWorkspace as never, bindings, {
sessions: "/data/sessions", artifacts: "/data/artifacts", indexes: "/data/indexes",
})).toThrow("Runtime renderer supports only workspace schema version 3");
});
test("installation contract rejects callers that bypass the schema-v3 type contract", () => {
expect(() => buildInstallationContract(unsupportedWorkspace as never))
.toThrow("Installation contract supports only workspace schema version 3");
});
test("binding entry points reject callers that bypass the schema-v3 type contract", () => {
expect(() => resolveBinding(unsupportedWorkspace as never, "DWH", {}, []))
.toThrow("Workspace bindings support only workspace schema version 3");
expect(() => resolveEvidenceBinding(unsupportedWorkspace as never, {}, []))
.toThrow("Workspace bindings support only workspace schema version 3");
expect(() => resolveRuntimeBindings(unsupportedWorkspace as never, {}, []))
.toThrow("Workspace bindings support only workspace schema version 3");
});
test("diagnoser factories reject callers that bypass the schema-v3 type contract", async () => {
await expect(createWorkspaceDiagnoser(adapters)(unsupportedWorkspace as never, bindings, {
writeProbe: false,
})).rejects.toThrow("Workspace diagnoser supports only workspace schema version 3");
await expect(createProductionWorkspaceDiagnoser(5_000, adapters)(
unsupportedWorkspace as never, bindings, { writeProbe: false },
)).rejects.toThrow("Workspace diagnoser supports only workspace schema version 3");
});
-36
View File
@@ -548,39 +548,3 @@ test.each([
type: "filesystem", uri: "workspace-content/psd-clinical/evidence", type: "filesystem", uri: "workspace-content/psd-clinical/evidence",
}, { ...explicitPolicy, [field]: value }), new RegExp(field, "i")); }, { ...explicitPolicy, [field]: value }), new RegExp(field, "i"));
}); });
test("rejects evidence on strict schema v1 and v2 descriptors", () => {
for (const schemaVersion of [1, 2]) {
const yaml = validYaml
.replace("schema_version: 3", `schema_version: ${schemaVersion}`)
.replace(`semantic_index:
vector_store:
engine: qdrant
collection: psd-clinical
dimensions: 1024
distance: cosine
embedding:
provider: ollama_internal
model: qwen3-embedding:0.6b
dimensions: 1024`, `semantic_index:
vector_store:
engine: pgvector
database: postgres
schema: vectors
collection: documents
dimensions: 1024
distance: cosine
supported_transports:
- pgvector_direct
embedding:
provider: ollama_compatible
model: evidence-test
dimensions: 1024`)
+ `evidence:
source:
type: filesystem
uri: workspace-content/psd-clinical/evidence
`;
expect(() => parseWorkspaceYaml(yaml)).toThrow(/evidence|unrecognized/i);
}
});