feat: run bounded workspace connector diagnostics
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
import { expect, test, vi } from "vitest";
|
||||
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import {
|
||||
createConcreteDiagnosticAdapters,
|
||||
createProductionWorkspaceDiagnoser,
|
||||
createWorkspaceDiagnoser,
|
||||
type DiagnosticAdapters,
|
||||
@@ -35,6 +39,64 @@ semantic_index:
|
||||
timeout_ms: 8000
|
||||
llm_policy:
|
||||
allowed: [zai/glm-5.2]
|
||||
diagnostics:
|
||||
dwh_rest:
|
||||
method: POST
|
||||
path: /rpc/ping
|
||||
auth: bearer
|
||||
response: { database: database, schema: schema }
|
||||
vector_rest:
|
||||
metadata:
|
||||
method: GET
|
||||
path: /vector/metadata
|
||||
auth: bearer
|
||||
response: { collection: collection, dimensions: dimensions, distance: distance }
|
||||
reversible_probe:
|
||||
method: POST
|
||||
path: /vector/diagnostic-probe
|
||||
auth: bearer
|
||||
`);
|
||||
|
||||
const writerWorkspace = parseWorkspaceYaml(`workspace:
|
||||
schema_version: 2
|
||||
id: psd-clinical
|
||||
name: Policlinico San Donato
|
||||
language: it
|
||||
dwh:
|
||||
engine: postgres
|
||||
database: warehouse
|
||||
schema: datawarehouse
|
||||
timeout_ms: 8000
|
||||
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
|
||||
timeout_ms: 8000
|
||||
supported_transports: [pgvector_direct, rest_api, ssh_tunnel]
|
||||
vector_writer: {}
|
||||
embedding:
|
||||
provider: ollama_compatible
|
||||
model: nomic-embed-text-v2-moe
|
||||
dimensions: 768
|
||||
timeout_ms: 8000
|
||||
llm_policy:
|
||||
allowed: [zai/glm-5.2]
|
||||
diagnostics:
|
||||
vector_rest:
|
||||
metadata:
|
||||
method: GET
|
||||
path: /vector/metadata
|
||||
auth: bearer
|
||||
response: { collection: collection, dimensions: dimensions, distance: distance }
|
||||
reversible_probe:
|
||||
method: POST
|
||||
path: /vector/diagnostic-probe
|
||||
auth: bearer
|
||||
`);
|
||||
|
||||
const bindings: RuntimeBindings = {
|
||||
@@ -71,6 +133,19 @@ const bindings: RuntimeBindings = {
|
||||
},
|
||||
};
|
||||
|
||||
const writerBindings: RuntimeBindings = {
|
||||
...bindings,
|
||||
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-reader-key",
|
||||
THT_WS_PSD_CLINICAL_VECTOR_WRITER_API_KEY_FILE: "/run/secrets/vector-writer-key",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function successfulAdapters(overrides: Partial<DiagnosticAdapters> = {}): DiagnosticAdapters {
|
||||
return {
|
||||
probeConnector: vi.fn(async (request) => ({
|
||||
@@ -216,10 +291,45 @@ test("uses a loopback-only SSH tunnel for the bounded connector probe", async ()
|
||||
}));
|
||||
});
|
||||
|
||||
test("passes the declared vector database and schema to direct diagnostics", async () => {
|
||||
const adapters = successfulAdapters();
|
||||
|
||||
await diagnose(adapters)(workspace, bindings, { writeProbe: false });
|
||||
|
||||
expect(adapters.probeConnector).toHaveBeenCalledWith(expect.objectContaining({
|
||||
role: "vector",
|
||||
resource: { database: "postgres", schema: "vectors", collection: "clinical_documents" },
|
||||
}));
|
||||
});
|
||||
|
||||
test("uses strict known-host SSH arguments and always closes the temporary tunnel", async () => {
|
||||
const directory = await mkdtemp(join(tmpdir(), "thothii-diagnostic-"));
|
||||
const privateKeyFile = join(directory, "ssh-key");
|
||||
await writeFile(privateKeyFile, "test-key\n", { mode: 0o600 });
|
||||
const close = vi.fn(async () => undefined);
|
||||
const start = vi.fn(async () => ({ tunnel: { host: "127.0.0.1" as const, port: 45432 }, close }));
|
||||
|
||||
try {
|
||||
const adapter = createConcreteDiagnosticAdapters({ sshProcess: { start } });
|
||||
await adapter.withSshTunnel({
|
||||
sshHost: "bastion.example.test", sshPort: 22, sshUser: "tunnel", privateKeyFile,
|
||||
knownHostsFile: "/run/secrets/known-hosts", targetHost: "vector.internal", targetPort: 5432,
|
||||
localHost: "127.0.0.1", localPort: 0, timeoutMs: 5000, signal: new AbortController().signal,
|
||||
}, async () => undefined);
|
||||
|
||||
expect(start).toHaveBeenCalledWith(expect.any(Object), expect.arrayContaining([
|
||||
"StrictHostKeyChecking=yes", "UserKnownHostsFile=/run/secrets/known-hosts", "-i", privateKeyFile,
|
||||
]));
|
||||
expect(close).toHaveBeenCalledOnce();
|
||||
} finally {
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("requires a matching embedding model vector and removes its unique write probe", async () => {
|
||||
const adapters = successfulAdapters();
|
||||
|
||||
const result = await diagnose(adapters)(workspace, bindings, { writeProbe: true });
|
||||
const result = await diagnose(adapters)(writerWorkspace, writerBindings, { writeProbe: true });
|
||||
|
||||
expect(result.activatable).toBe(true);
|
||||
expect(adapters.probeEmbedding).toHaveBeenCalledWith(expect.objectContaining({
|
||||
@@ -237,6 +347,62 @@ test("requires a matching embedding model vector and removes its unique write pr
|
||||
}));
|
||||
});
|
||||
|
||||
test("keeps a reader-only workspace activatable without a vector write probe", async () => {
|
||||
const adapters = successfulAdapters();
|
||||
|
||||
const result = await diagnose(adapters)(workspace, bindings, { writeProbe: true });
|
||||
|
||||
expect(result.activatable).toBe(true);
|
||||
expect(adapters.writeDiagnosticRecord).not.toHaveBeenCalled();
|
||||
expect(adapters.removeDiagnosticRecord).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("does not substitute the reader credential for a declared vector writer", async () => {
|
||||
const adapters = successfulAdapters();
|
||||
|
||||
const result = await diagnose(adapters)(writerWorkspace, bindings, { writeProbe: true });
|
||||
|
||||
expect(result.activatable).toBe(true);
|
||||
expect(adapters.writeDiagnosticRecord).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("uses the declared POST DWH ping endpoint without exposing its local credential", async () => {
|
||||
const directory = await mkdtemp(join(tmpdir(), "thothii-diagnostic-"));
|
||||
const credentialFile = join(directory, "dwh-api-key");
|
||||
await writeFile(credentialFile, "local-secret\n", { mode: 0o600 });
|
||||
const fetchSpy = vi.fn(async () => new Response(JSON.stringify({ database: "warehouse", schema: "datawarehouse" }), {
|
||||
status: 200,
|
||||
headers: { "content-type": "application/json" },
|
||||
}));
|
||||
vi.stubGlobal("fetch", fetchSpy);
|
||||
|
||||
try {
|
||||
const result = await createConcreteDiagnosticAdapters().probeConnector({
|
||||
role: "dwh",
|
||||
transport: "rest_api",
|
||||
baseUrl: "https://dwh.example.test",
|
||||
credentialFile,
|
||||
resource: { database: "warehouse", schema: "datawarehouse" },
|
||||
diagnostic: {
|
||||
method: "POST", path: "/rpc/ping", auth: "bearer",
|
||||
response: { database: "database", schema: "schema" },
|
||||
},
|
||||
timeoutMs: 5000,
|
||||
signal: new AbortController().signal,
|
||||
});
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledWith("https://dwh.example.test/rpc/ping", expect.objectContaining({
|
||||
method: "POST",
|
||||
redirect: "error",
|
||||
}));
|
||||
expect(result).toMatchObject({ authenticated: true, resource: { database: "warehouse", schema: "datawarehouse" } });
|
||||
expect(JSON.stringify(result)).not.toContain("local-secret");
|
||||
} finally {
|
||||
vi.unstubAllGlobals();
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("constructs the production diagnoser with the configured timeout and injected adapters", async () => {
|
||||
const adapters = successfulAdapters();
|
||||
|
||||
@@ -256,7 +422,7 @@ test("retries bounded cleanup after a write-probe removal times out", async () =
|
||||
const diagnoseWithShortTimeout = createWorkspaceDiagnoser(adapters, { timeoutMs: 10 });
|
||||
|
||||
const startedAt = Date.now();
|
||||
const result = await diagnoseWithShortTimeout(workspace, bindings, { writeProbe: true });
|
||||
const result = await diagnoseWithShortTimeout(writerWorkspace, writerBindings, { writeProbe: true });
|
||||
|
||||
expect(Date.now() - startedAt).toBeLessThan(250);
|
||||
expect(adapters.writeDiagnosticRecord).toHaveBeenCalledTimes(1);
|
||||
|
||||
Reference in New Issue
Block a user