docs: add P1.1 workspace directory plan

This commit is contained in:
2026-08-11 14:22:28 +02:00
parent 66f44b054f
commit 7356d6794b
4 changed files with 1662 additions and 0 deletions
+75
View File
@@ -0,0 +1,75 @@
import { parseAllDocuments } from "yaml";
import { z } from "zod";
import type { WorkspaceDescriptor } from "./schema.js";
export const CATALOG_PATH = "thoth-workspaces.yaml";
export interface WorkspaceCatalogEntry {
id: string;
name: string;
description?: string;
}
export interface WorkspaceCatalog {
schema_version: 1;
workspaces: WorkspaceCatalogEntry[];
}
const workspaceId = z.string().trim().regex(/^[a-z][a-z0-9-]{2,62}$/, {
message: "workspace id must match ^[a-z][a-z0-9-]{2,62}$",
}).refine((value) => value !== "workspace-docs", {
message: "workspace id is reserved",
});
const catalogEntry = z.object({
id: workspaceId,
name: z.string().trim().min(1),
description: z.string().trim().min(1).optional(),
}).strict();
const catalogSchema = z.object({
schema_version: z.literal(1),
workspaces: z.array(catalogEntry),
}).strict().superRefine((catalog, context) => {
const seen = new Set<string>();
catalog.workspaces.forEach((entry, index) => {
if (seen.has(entry.id)) {
context.addIssue({
code: "custom",
path: ["workspaces", index, "id"],
message: "workspace id is duplicated in the catalog",
});
}
seen.add(entry.id);
});
});
function safeCatalogError(): Error {
return new Error("Workspace catalog is invalid");
}
export function parseWorkspaceCatalogYaml(source: string): WorkspaceCatalog {
try {
const documents = parseAllDocuments(source, { uniqueKeys: true });
if (documents.length !== 1) throw safeCatalogError();
const document = documents[0];
if (document.errors.length > 0 || document.warnings.length > 0) throw safeCatalogError();
return catalogSchema.parse(document.toJSON()) as WorkspaceCatalog;
} catch (error) {
if (error instanceof Error && error.message === "Workspace catalog is invalid") throw error;
throw safeCatalogError();
}
}
export function assertCatalogMatchesDescriptor(
entry: WorkspaceCatalogEntry,
workspace: WorkspaceDescriptor,
): void {
if (
entry.id !== workspace.workspace.id
|| entry.name !== workspace.workspace.name
|| entry.description !== workspace.workspace.description
) {
throw new Error("Workspace catalog metadata does not match descriptor");
}
}
+82
View File
@@ -0,0 +1,82 @@
import { expect, test } from "vitest";
import { parseWorkspaceYaml } from "../src/workspaces/schema.js";
import {
CATALOG_PATH,
assertCatalogMatchesDescriptor,
parseWorkspaceCatalogYaml,
} from "../src/workspaces/catalog.js";
const descriptor = parseWorkspaceYaml(`workspace:
schema_version: 3
id: psd
name: Policlinico San Donato
description: Clinical warehouse
language: it
dwh:
engine: postgres
database: postgres
schema: datawarehouse
supported_transports: [rest_api]
semantic_index:
vector_store: { engine: qdrant, collection: psd, dimensions: 1024, distance: cosine }
embedding: { provider: ollama_internal, model: qwen3-embedding:0.6b, dimensions: 1024 }
llm_policy: { allowed: [zai/glm-5.2] }
`);
test("parses the strict ordered root catalog", () => {
expect(CATALOG_PATH).toBe("thoth-workspaces.yaml");
expect(parseWorkspaceCatalogYaml(`schema_version: 1
workspaces:
- id: psd
name: Policlinico San Donato
description: Clinical warehouse
- id: research
name: Research
`)).toEqual({
schema_version: 1,
workspaces: [
{ id: "psd", name: "Policlinico San Donato", description: "Clinical warehouse" },
{ id: "research", name: "Research" },
],
});
});
test("preserves optional description absence and trims metadata", () => {
expect(parseWorkspaceCatalogYaml(`schema_version: 1
workspaces:
- id: psd
name: " PSD "
`)).toEqual({ schema_version: 1, workspaces: [{ id: "psd", name: "PSD" }] });
});
test.each([
["duplicate IDs", `schema_version: 1\nworkspaces: [{id: psd, name: One}, {id: psd, name: Two}]`],
["invalid ID", `schema_version: 1\nworkspaces: [{id: PSD, name: One}]`],
["reserved ID", `schema_version: 1\nworkspaces: [{id: workspace-docs, name: One}]`],
["unknown key", `schema_version: 1\nworkspaces: [{id: psd, name: One, secret: CANARY}]`],
["duplicate YAML key", `schema_version: 1\nworkspaces:\n - id: psd\n id: research\n name: One`],
["multiple documents", `schema_version: 1\nworkspaces: []\n---\nschema_version: 1\nworkspaces: []`],
])("rejects %s without exposing unsafe input", (_name, source) => {
expect(() => parseWorkspaceCatalogYaml(source)).toThrow(/catalog|workspace|id|YAML/i);
try { parseWorkspaceCatalogYaml(source); } catch (error) {
expect(String(error)).not.toContain("CANARY");
}
});
test("rejects catalog metadata that differs from its descriptor", () => {
expect(() => assertCatalogMatchesDescriptor(
{ id: "psd", name: "Other", description: "Clinical warehouse" }, descriptor,
)).toThrow(/catalog|metadata/i);
expect(() => assertCatalogMatchesDescriptor(
{ id: "psd", name: "Policlinico San Donato" }, descriptor,
)).toThrow(/catalog|metadata/i);
expect(() => assertCatalogMatchesDescriptor(
{ id: "other", name: "Policlinico San Donato", description: "Clinical warehouse" }, descriptor,
)).toThrow(/catalog|metadata/i);
});
test("accepts exact catalog metadata", () => {
expect(() => assertCatalogMatchesDescriptor(
{ id: "psd", name: "Policlinico San Donato", description: "Clinical warehouse" }, descriptor,
)).not.toThrow();
});