fix: harden workspace schema contracts

This commit is contained in:
2026-08-03 21:40:58 +02:00
parent 92cb0545be
commit 5a654939a5
4 changed files with 152 additions and 16 deletions
+18 -2
View File
@@ -19,6 +19,8 @@ export interface CanonicalWorkspace {
engine: "postgres";
database: string;
schema: string;
port?: number;
timeout_ms?: number;
supported_transports: DwhTransport[];
};
semantic_index: {
@@ -27,12 +29,15 @@ export interface CanonicalWorkspace {
collection: string;
dimensions: number;
distance: "cosine" | "l2" | "inner_product";
port?: number;
timeout_ms?: number;
supported_transports: VectorTransport[];
};
embedding: {
provider: "ollama_compatible" | "openai_compatible";
model: string;
dimensions: number;
timeout_ms?: number;
};
};
llm_policy: {
@@ -48,6 +53,8 @@ const identifier = z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/, {
message: "database identifiers must start with a letter or underscore",
});
const dimensions = z.number().int().positive().max(32_768);
const port = z.number().int().min(1).max(65_535);
const timeoutMs = z.number().int().positive();
const modelReference = z.string().regex(/^[^/\s]+\/[^/\s]+$/, {
message: "model must use provider/model syntax",
});
@@ -70,6 +77,8 @@ const WorkspaceSchema = z.object({
engine: z.literal("postgres"),
database: identifier,
schema: identifier,
port: port.optional(),
timeout_ms: timeoutMs.optional(),
supported_transports: z.array(z.enum(DWH_TRANSPORTS)).min(1),
}).strict(),
semantic_index: z.object({
@@ -78,12 +87,15 @@ const WorkspaceSchema = z.object({
collection: identifier,
dimensions,
distance: z.enum(["cosine", "l2", "inner_product"]),
port: port.optional(),
timeout_ms: timeoutMs.optional(),
supported_transports: z.array(z.enum(VECTOR_TRANSPORTS)).min(1),
}).strict(),
embedding: z.object({
provider: z.enum(["ollama_compatible", "openai_compatible"]),
model: z.string().trim().min(1),
dimensions,
timeout_ms: timeoutMs.optional(),
}).strict(),
}).strict(),
llm_policy: z.object({
@@ -127,11 +139,15 @@ export function parseWorkspaceYaml(source: string): CanonicalWorkspace {
throw new Error(`Invalid workspace YAML: ${document.errors.map((error) => error.message).join("; ")}`);
}
return WorkspaceSchema.parse(document.toJSON()) as CanonicalWorkspace;
return validateCanonicalWorkspace(document.toJSON());
}
export function validateCanonicalWorkspace(workspace: unknown): CanonicalWorkspace {
return WorkspaceSchema.parse(workspace) as CanonicalWorkspace;
}
export function serializeWorkspaceYaml(workspace: CanonicalWorkspace): string {
const canonical = WorkspaceSchema.parse(workspace) as CanonicalWorkspace;
const canonical = validateCanonicalWorkspace(workspace);
return stringify(canonical, { lineWidth: 0, sortMapEntries: true });
}