Publish documentation / publish (push) Successful in 1m27s
Add PostgreSQL-backed memory, editable evidence with source review and activation, and human-approved archive repairs across the harness, API, and UI. Include migrations, deployment support, regression coverage, and validation documentation. Refresh permissions from validated session roles so existing administrator logins can access newly deployed archive management features.
370 lines
13 KiB
TypeScript
370 lines
13 KiB
TypeScript
import { execFile } from "node:child_process";
|
|
import { createHash } from "node:crypto";
|
|
import {
|
|
existsSync,
|
|
mkdtempSync,
|
|
mkdirSync,
|
|
readFileSync,
|
|
rmSync,
|
|
statSync,
|
|
symlinkSync,
|
|
writeFileSync,
|
|
} from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { promisify } from "node:util";
|
|
import { afterEach, expect, test, vi } from "vitest";
|
|
import { parse } from "yaml";
|
|
import { WorkspaceRegistry } from "../src/workspaces/registry.js";
|
|
import {
|
|
buildCanonicalEffectiveConfig,
|
|
canonicalEffectiveConfigJson,
|
|
effectiveConfigIdentity,
|
|
} from "../src/workspaces/effective-config.js";
|
|
import type { WorkspaceRegistryConfig } from "../src/workspaces/types.js";
|
|
import {
|
|
publishDeterministicRuntimeConfigLease,
|
|
renderActiveWorkspaceRuntime,
|
|
renderWorkspaceRuntimeFromSnapshotPath,
|
|
} from "../src/workspaces/runtime-config-lease.js";
|
|
import { WorkspaceSecretStore } from "../src/workspaces/secret-store.js";
|
|
|
|
const runFile = promisify(execFile);
|
|
const roots: string[] = [];
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllEnvs();
|
|
roots.splice(0).forEach((root) => rmSync(root, { recursive: true, force: true }));
|
|
});
|
|
|
|
async function git(cwd: string, args: string[]): Promise<string> {
|
|
return (await runFile("git", args, { cwd })).stdout.trim();
|
|
}
|
|
|
|
async function fixture() {
|
|
const root = mkdtempSync(join(tmpdir(), "tht-runtime-lease-"));
|
|
roots.push(root);
|
|
const remote = join(root, "remote.git");
|
|
const source = join(root, "source");
|
|
const registryRoot = join(root, "registry");
|
|
const secretRoot = join(root, "secrets");
|
|
const dataRoot = join(root, "data");
|
|
const harnessDir = join(root, "harness");
|
|
mkdirSync(harnessDir, { recursive: true });
|
|
mkdirSync(join(harnessDir, "config"), { recursive: true });
|
|
writeFileSync(join(harnessDir, "config", "tht.yaml"), `session_storage:
|
|
mode: local
|
|
profile: server
|
|
`);
|
|
|
|
await git(root, ["init", "--bare", "--initial-branch=main", remote]);
|
|
mkdirSync(source);
|
|
await git(source, ["init", "--initial-branch=main"]);
|
|
await git(source, ["config", "user.name", "Runtime Lease Test"]);
|
|
await git(source, ["config", "user.email", "runtime-lease@example.invalid"]);
|
|
writeFileSync(join(source, "thoth-workspaces.yaml"), `schema_version: 1
|
|
workspaces: [{id: psd-clinical, name: Runtime Lease}]
|
|
`);
|
|
mkdirSync(join(source, "psd-clinical", "evidence"), { recursive: true });
|
|
writeFileSync(join(source, "psd-clinical", "workspace.yaml"), `workspace:
|
|
schema_version: 4
|
|
id: psd-clinical
|
|
name: Runtime Lease
|
|
language: en
|
|
evidence:
|
|
source:
|
|
type: filesystem
|
|
uri: psd-clinical/evidence
|
|
`);
|
|
writeFileSync(join(source, "psd-clinical", "evidence", "guide.md"), `# hello
|
|
`);
|
|
await git(source, ["add", "."]);
|
|
await git(source, ["commit", "-m", "Canonical workspace"]);
|
|
await git(source, ["remote", "add", "origin", remote]);
|
|
await git(source, ["push", "origin", "main"]);
|
|
|
|
mkdirSync(secretRoot);
|
|
mkdirSync(dataRoot);
|
|
|
|
const registryConfig: WorkspaceRegistryConfig = {
|
|
root: registryRoot,
|
|
remoteUrl: remote,
|
|
branch: "main",
|
|
gitAuthorName: "Runtime Lease Test",
|
|
gitAuthorEmail: "runtime-lease@example.invalid",
|
|
installationId: "test",
|
|
secretRoots: [secretRoot],
|
|
maxImportBytes: 1024 * 1024,
|
|
maxImportEntries: 16,
|
|
};
|
|
const registry = new WorkspaceRegistry(registryConfig);
|
|
await registry.bootstrap();
|
|
const revision = (await registry.list())[0];
|
|
const workspaceSecretStore = new WorkspaceSecretStore({
|
|
root: join(root, "vault"),
|
|
runtimeRoot: join(root, "runtime-secrets"),
|
|
installationId: "test",
|
|
});
|
|
workspaceSecretStore.putMany("psd-clinical", { "catalog.dwh.password": "secret" });
|
|
const catalogDatabase = {
|
|
id: "database-1",
|
|
workspaceId: "psd-clinical",
|
|
engine: "postgres" as const,
|
|
databaseName: "analytics",
|
|
schema: "mart",
|
|
binding: {
|
|
transport: "postgres_direct" as const,
|
|
host: "warehouse.internal",
|
|
port: 5432,
|
|
username: "reader",
|
|
},
|
|
version: 1,
|
|
createdAt: "2026-01-01T00:00:00Z",
|
|
updatedAt: "2026-01-01T00:00:00Z",
|
|
connectionStatus: "reachable" as const,
|
|
metadataContentRevision: 1,
|
|
preprocessingStatus: "failed" as const,
|
|
};
|
|
|
|
return {
|
|
dataRoot,
|
|
harnessDir,
|
|
source,
|
|
registry,
|
|
registryConfig,
|
|
revision,
|
|
workspaceSecretStore,
|
|
catalogDatabase,
|
|
};
|
|
}
|
|
|
|
const semanticRuntime = {
|
|
internalQdrantUrl: "http://qdrant:6333",
|
|
internalEmbeddingUrl: "http://embedding:11434",
|
|
internalEmbeddingModel: "qwen3-embedding:0.6b",
|
|
internalEmbeddingDimensions: 1024,
|
|
};
|
|
|
|
test("active workspace rendering is byte-identical to direct snapshot rendering", async () => {
|
|
const f = await fixture();
|
|
const direct = renderWorkspaceRuntimeFromSnapshotPath({
|
|
snapshotPath: f.revision.snapshotPath,
|
|
harnessDir: f.harnessDir,
|
|
configPath: "config/tht.yaml",
|
|
dataRoot: f.dataRoot,
|
|
secretRoots: f.registryConfig.secretRoots,
|
|
semanticRuntime,
|
|
catalogDatabase: f.catalogDatabase,
|
|
workspaceSecretStore: f.workspaceSecretStore,
|
|
});
|
|
const active = await renderActiveWorkspaceRuntime({
|
|
workspaceId: "psd-clinical",
|
|
registry: f.registry,
|
|
registryConfig: f.registryConfig,
|
|
harnessDir: f.harnessDir,
|
|
configPath: "config/tht.yaml",
|
|
dataRoot: f.dataRoot,
|
|
secretRoots: f.registryConfig.secretRoots,
|
|
semanticRuntime,
|
|
catalogDatabase: f.catalogDatabase,
|
|
workspaceSecretStore: f.workspaceSecretStore,
|
|
});
|
|
|
|
expect(active.renderedConfig).toBe(direct.renderedConfig);
|
|
expect(active.workspaceRevision).toBe(f.revision.commit);
|
|
expect(active.descriptorBlob).toMatch(/^sha256:[0-9a-f]{64}$/);
|
|
expect(active.catalogBlob).toMatch(/^sha256:[0-9a-f]{64}$/);
|
|
});
|
|
|
|
test("deterministic operator leases are keyed by logical identity and stable across calls", async () => {
|
|
const f = await fixture();
|
|
const first = await publishDeterministicRuntimeConfigLease({
|
|
workspaceId: "psd-clinical",
|
|
registry: f.registry,
|
|
registryConfig: f.registryConfig,
|
|
harnessDir: f.harnessDir,
|
|
configPath: "config/tht.yaml",
|
|
dataRoot: f.dataRoot,
|
|
secretRoots: f.registryConfig.secretRoots,
|
|
semanticRuntime,
|
|
catalogDatabase: f.catalogDatabase,
|
|
workspaceSecretStore: f.workspaceSecretStore,
|
|
});
|
|
const second = await publishDeterministicRuntimeConfigLease({
|
|
workspaceId: "psd-clinical",
|
|
registry: f.registry,
|
|
registryConfig: f.registryConfig,
|
|
harnessDir: f.harnessDir,
|
|
configPath: "config/tht.yaml",
|
|
dataRoot: f.dataRoot,
|
|
secretRoots: f.registryConfig.secretRoots,
|
|
semanticRuntime,
|
|
catalogDatabase: f.catalogDatabase,
|
|
workspaceSecretStore: f.workspaceSecretStore,
|
|
});
|
|
|
|
const suffix = createHash("sha256").update(first.inputFingerprint + "\n" + readFileSync(first.path, "utf8")).digest("hex").slice(0, 16);
|
|
expect(second.path).toBe(first.path);
|
|
expect(first.path).toBe(join(
|
|
f.dataRoot,
|
|
"sessions",
|
|
"psd-clinical",
|
|
"preprocessing",
|
|
"runtime-config",
|
|
`${f.revision.commit}-${suffix}.yaml`,
|
|
));
|
|
expect(statSync(first.path).mode & 0o777).toBe(0o400);
|
|
expect(statSync(first.manifestPath).mode & 0o777).toBe(0o600);
|
|
expect(readFileSync(first.path, "utf8")).toContain("collection_lifecycle: require_existing");
|
|
expect(readFileSync(first.path, "utf8")).toContain("memory:");
|
|
expect(existsSync(first.manifestPath)).toBe(true);
|
|
expect(first.effectiveConfigIdentity).toMatch(/^workspace:\/\/psd-clinical@v1:[0-9a-f]{64}$/);
|
|
expect(first.configFingerprint).toMatch(/^sha256:[0-9a-f]{64}$/);
|
|
expect(first.inputFingerprint).toMatch(/^sha256:[0-9a-f]{64}$/);
|
|
expect(first.inputFingerprint).not.toBe(first.configFingerprint);
|
|
const manifest = JSON.parse(readFileSync(first.manifestPath, "utf8"));
|
|
expect(manifest).toMatchObject({
|
|
schemaVersion: 1,
|
|
workspaceId: "psd-clinical",
|
|
workspaceRevision: f.revision.commit,
|
|
descriptorBlob: first.descriptorBlob,
|
|
catalogBlob: first.catalogBlob,
|
|
configDigest: first.configDigest,
|
|
bindingDigest: first.bindingDigest,
|
|
effectiveConfigIdentity: first.effectiveConfigIdentity,
|
|
configFingerprint: first.configFingerprint,
|
|
inputFingerprint: first.inputFingerprint,
|
|
path: first.path,
|
|
});
|
|
|
|
const changedDatabase = {
|
|
...f.catalogDatabase,
|
|
binding: { ...f.catalogDatabase.binding, host: "warehouse-two.internal" },
|
|
version: 2,
|
|
};
|
|
const changed = await publishDeterministicRuntimeConfigLease({
|
|
workspaceId: "psd-clinical",
|
|
registry: f.registry,
|
|
registryConfig: f.registryConfig,
|
|
harnessDir: f.harnessDir,
|
|
configPath: "config/tht.yaml",
|
|
dataRoot: f.dataRoot,
|
|
secretRoots: f.registryConfig.secretRoots,
|
|
semanticRuntime,
|
|
catalogDatabase: changedDatabase,
|
|
workspaceSecretStore: f.workspaceSecretStore,
|
|
});
|
|
expect(changed.path).not.toBe(first.path);
|
|
expect(changed.inputFingerprint).not.toBe(first.inputFingerprint);
|
|
expect(changed.configFingerprint).not.toBe(first.configFingerprint);
|
|
expect(readFileSync(changed.path, "utf8")).toContain("warehouse-two.internal");
|
|
});
|
|
|
|
test("runtime rendering rejects untrusted snapshot paths and symlinks", async () => {
|
|
const f = await fixture();
|
|
const outside = join(f.dataRoot, "outside.yaml");
|
|
writeFileSync(outside, readFileSync(f.revision.snapshotPath, "utf8"));
|
|
const symlink = join(f.dataRoot, "alias.yaml");
|
|
symlinkSync(f.revision.snapshotPath, symlink);
|
|
|
|
expect(() => renderWorkspaceRuntimeFromSnapshotPath({
|
|
snapshotPath: outside,
|
|
harnessDir: f.harnessDir,
|
|
configPath: "config/tht.yaml",
|
|
dataRoot: f.dataRoot,
|
|
secretRoots: f.registryConfig.secretRoots,
|
|
semanticRuntime,
|
|
catalogDatabase: f.catalogDatabase,
|
|
workspaceSecretStore: f.workspaceSecretStore,
|
|
})).toThrow(/trusted runtime snapshot/i);
|
|
expect(() => renderWorkspaceRuntimeFromSnapshotPath({
|
|
snapshotPath: symlink,
|
|
harnessDir: f.harnessDir,
|
|
configPath: "config/tht.yaml",
|
|
dataRoot: f.dataRoot,
|
|
secretRoots: f.registryConfig.secretRoots,
|
|
semanticRuntime,
|
|
catalogDatabase: f.catalogDatabase,
|
|
workspaceSecretStore: f.workspaceSecretStore,
|
|
})).toThrow(/trusted runtime snapshot/i);
|
|
});
|
|
|
|
|
|
test("operator lease and session snapshot produce byte-identical effective DWH bindings", async () => {
|
|
const f = await fixture();
|
|
const session = renderWorkspaceRuntimeFromSnapshotPath({
|
|
snapshotPath: f.revision.snapshotPath,
|
|
harnessDir: f.harnessDir,
|
|
configPath: "config/tht.yaml",
|
|
dataRoot: f.dataRoot,
|
|
secretRoots: f.registryConfig.secretRoots,
|
|
semanticRuntime,
|
|
catalogDatabase: f.catalogDatabase,
|
|
workspaceSecretStore: f.workspaceSecretStore,
|
|
});
|
|
const lease = await publishDeterministicRuntimeConfigLease({
|
|
workspaceId: "psd-clinical",
|
|
registry: f.registry,
|
|
registryConfig: f.registryConfig,
|
|
harnessDir: f.harnessDir,
|
|
configPath: "config/tht.yaml",
|
|
dataRoot: f.dataRoot,
|
|
secretRoots: f.registryConfig.secretRoots,
|
|
semanticRuntime,
|
|
catalogDatabase: f.catalogDatabase,
|
|
workspaceSecretStore: f.workspaceSecretStore,
|
|
});
|
|
|
|
const sessionCanonical = canonicalEffectiveConfigJson(buildCanonicalEffectiveConfig(parse(session.renderedConfig)));
|
|
const operatorCanonical = canonicalEffectiveConfigJson(lease.effectiveConfig);
|
|
expect(operatorCanonical).toBe(sessionCanonical);
|
|
expect(lease.effectiveConfigIdentity).toBe(
|
|
effectiveConfigIdentity("psd-clinical", parse(session.renderedConfig)),
|
|
);
|
|
});
|
|
|
|
test("a content-only Evidence commit keeps the same effective config identity with a new revision lease", async () => {
|
|
const f = await fixture();
|
|
const firstLease = await publishDeterministicRuntimeConfigLease({
|
|
workspaceId: "psd-clinical",
|
|
registry: f.registry,
|
|
registryConfig: f.registryConfig,
|
|
harnessDir: f.harnessDir,
|
|
configPath: "config/tht.yaml",
|
|
dataRoot: f.dataRoot,
|
|
secretRoots: f.registryConfig.secretRoots,
|
|
semanticRuntime,
|
|
catalogDatabase: f.catalogDatabase,
|
|
workspaceSecretStore: f.workspaceSecretStore,
|
|
});
|
|
const firstIdentity = firstLease.effectiveConfigIdentity;
|
|
|
|
writeFileSync(
|
|
join(f.source, "psd-clinical", "evidence", "guide.md"),
|
|
"# updated content only\n",
|
|
);
|
|
await git(f.source, ["add", "psd-clinical/evidence/guide.md"]);
|
|
await git(f.source, ["commit", "-m", "Evidence content only"]);
|
|
await git(f.source, ["push", "origin", "main"]);
|
|
await f.registry.pull();
|
|
const current = (await f.registry.list())[0];
|
|
|
|
const secondLease = await publishDeterministicRuntimeConfigLease({
|
|
workspaceId: "psd-clinical",
|
|
registry: f.registry,
|
|
registryConfig: f.registryConfig,
|
|
harnessDir: f.harnessDir,
|
|
configPath: "config/tht.yaml",
|
|
dataRoot: f.dataRoot,
|
|
secretRoots: f.registryConfig.secretRoots,
|
|
semanticRuntime,
|
|
catalogDatabase: f.catalogDatabase,
|
|
workspaceSecretStore: f.workspaceSecretStore,
|
|
});
|
|
|
|
expect(secondLease.workspaceRevision).toBe(current.commit);
|
|
expect(secondLease.workspaceRevision).not.toBe(firstLease.workspaceRevision);
|
|
expect(secondLease.effectiveConfigIdentity).toBe(firstIdentity);
|
|
expect(secondLease.path).not.toBe(firstLease.path);
|
|
});
|