fix: replace addressed registry lifecycle with capability owner

This commit is contained in:
2026-08-11 16:03:27 +02:00
parent ca37156a56
commit 56acb397be
7 changed files with 356 additions and 198 deletions
+25 -1
View File
@@ -1,6 +1,8 @@
import Fastify, { type FastifyInstance } from "fastify";
import cors from "@fastify/cors";
import { join } from "node:path";
import { mkdirSync, realpathSync } from "node:fs";
import { createHash } from "node:crypto";
import type { AppConfig } from "./config.js";
import { ThtRunner } from "./tht/tht-runner.js";
import { PiProcessManager } from "./pi/pi-process-manager.js";
@@ -18,6 +20,10 @@ import { loadSettings, type Settings } from "./settings/settings-store.js";
import { ReadinessManager } from "./runtime/readiness-manager.js";
import { MaintenanceBarrier } from "./runtime/maintenance-gate.js";
import { WorkspaceRegistry } from "./workspaces/registry.js";
import { GitWorkspaceRepository } from "./workspaces/git-repository.js";
import { WorkspaceFsAtV1 } from "./workspaces/workspace-fs-at.js";
import { VerifiedWorkspaceLockRootLeaseFactory } from "./workspaces/workspace-lock-root-lease.js";
import { CapabilityAwareRegistryPublicationLifecycleOwner, canonicalBootstrapRequestDigest } from "./workspaces/registry-publication.js";
import { createProductionWorkspaceDiagnoser } from "./workspaces/diagnostics.js";
import { workspaceRoutes, type WorkspaceDiagnoser } from "./routes/workspaces.js";
import { piManagementRoutes } from "./routes/pi-management.js";
@@ -39,6 +45,24 @@ export interface BuildAppDeps {
piManagement?: PiManagementService;
}
function createWorkspaceRegistry(config: AppConfig): WorkspaceRegistry {
const registryConfig = config.workspaceRegistry;
const repository = new GitWorkspaceRepository(registryConfig);
const sessionsRoot = join(registryConfig.root, "sessions");
mkdirSync(sessionsRoot, { recursive: true, mode: 0o700 });
const rootLeaseFactory = new VerifiedWorkspaceLockRootLeaseFactory({
workspaceFsAt: new WorkspaceFsAtV1(), installationId: registryConfig.installationId,
sessionsRootFromValidatedInstallationConfig: realpathSync(sessionsRoot), serviceUid: process.getuid?.() ?? 0,
provisionedWorkspaceMode: 0o700,
});
const hash = (value: string) => createHash("sha256").update(value).digest("hex");
const repositoryIdentity = { remote: registryConfig.remoteUrl ?? "", branch: registryConfig.branch, head: "", digest: hash(`${registryConfig.remoteUrl ?? ""}:${registryConfig.branch}`) };
const remoteIdentity = { remote: registryConfig.remoteUrl ?? "", head: "", digest: repositoryIdentity.digest };
const request = { kind: "bootstrap" as const, installation: { installationId: registryConfig.installationId, digest: hash(registryConfig.installationId) }, repository: repositoryIdentity, remote: remoteIdentity, workspaceIds: [] as string[] };
return new WorkspaceRegistry({ rootLeaseFactory, lifecycleOwner: new CapabilityAwareRegistryPublicationLifecycleOwner(), participants: [], synchronizers: [], repository,
installationIdentity: { operation: "registry_bootstrap", requestSha256: canonicalBootstrapRequestDigest(request) as never, installationIdentitySha256: request.installation.digest as never, repositoryIdentitySha256: repositoryIdentity.digest as never, remoteRefIdentitySha256: remoteIdentity.digest as never }, repositoryIdentity, remoteIdentity });
}
export function buildApp(config: AppConfig, deps?: BuildAppDeps): FastifyInstance {
const app = Fastify({ logger: { level: "warn" }, disableRequestLogging: true });
@@ -67,7 +91,7 @@ export function buildApp(config: AppConfig, deps?: BuildAppDeps): FastifyInstanc
});
const mgr = deps?.mgr ?? new PiProcessManager(config, deps?.spawnFn ? { spawnFn: deps.spawnFn } : undefined);
const hub = deps?.hub ?? new SseHub();
const workspaceRegistry = deps?.workspaceRegistry ?? new WorkspaceRegistry(config.workspaceRegistry);
const workspaceRegistry = deps?.workspaceRegistry ?? createWorkspaceRegistry(config);
const workspaceDiagnoser = deps?.workspaceDiagnoser
?? createProductionWorkspaceDiagnoser(config.workspaceDiagnosticTimeoutMs, undefined, {
internalQdrantUrl: config.internalQdrantUrl,