feat: add canonical workspace schema

This commit is contained in:
2026-08-03 21:31:07 +02:00
parent 6434c9c4e1
commit 92cb0545be
4 changed files with 414 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
import { expect, test } from "vitest";
import { buildInstallationContract, renderWorkspaceDocs } from "../src/workspaces/contracts.js";
import { parseWorkspaceYaml } from "../src/workspaces/schema.js";
const validWorkspace = 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
- rest_api
semantic_index:
vector_store:
engine: pgvector
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
`);
test("generates stable FILE-based secret requirements from an immutable ID", () => {
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.envExample).toContain("THT_WS_PSD_CLINICAL_VECTOR_TRANSPORT=");
});
+62
View File
@@ -0,0 +1,62 @@
import { expect, test } from "vitest";
import { parseWorkspaceYaml, serializeWorkspaceYaml } from "../src/workspaces/schema.js";
export const validYaml = `workspace:
schema_version: 1
id: psd-clinical
name: Policlinico San Donato
description: Clinical data warehouse workspace
language: it
dwh:
engine: postgres
database: postgres
schema: datawarehouse
supported_transports:
- postgres_direct
- rest_api
- ssh_tunnel
semantic_index:
vector_store:
engine: pgvector
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:
default: zai/glm-5.2
allowed:
- zai/glm-5.2
- openai/gpt-5
`;
test("rejects a workspace whose embedding dimensions differ from its collection", () => {
expect(() => parseWorkspaceYaml(validYaml.replace("dimensions: 768", "dimensions: 1536")))
.toThrow(/dimensions/i);
});
test("rejects an LLM default outside its allowlist", () => {
expect(() => parseWorkspaceYaml(validYaml.replace("- zai/glm-5.2", "- openai/gpt-5")))
.toThrow(/allowlist/i);
});
test("rejects unknown keys and invalid immutable IDs", () => {
expect(() => parseWorkspaceYaml(validYaml.replace(" language: it", " language: it\n label: PSD")))
.toThrow(/unrecognized key/i);
expect(() => parseWorkspaceYaml(validYaml.replace("id: psd-clinical", "id: PSD")))
.toThrow(/id/i);
});
test("serializes canonical YAML that parses back to the same workspace", () => {
const workspace = parseWorkspaceYaml(validYaml);
const serialized = serializeWorkspaceYaml(workspace);
expect(serializeWorkspaceYaml(parseWorkspaceYaml(serialized))).toBe(serialized);
expect(parseWorkspaceYaml(serialized)).toEqual(workspace);
});