fix: read active workspace state beneath the operator registry root

This commit is contained in:
2026-08-11 19:18:02 +02:00
parent 436d8d2720
commit fe49f5b6d8
2 changed files with 15 additions and 5 deletions
@@ -129,7 +129,8 @@ export class WorkspacePreprocessingService {
{ kind: "runtime_config", digest: runtime.configLease.configDigest }, { kind: "runtime_config", digest: runtime.configLease.configDigest },
], ],
}); });
} catch { } catch (error) {
const detail = error instanceof Error ? error.message : String(error);
return { return {
schemaVersion: 1, schemaVersion: 1,
status: "failed", status: "failed",
@@ -139,6 +140,7 @@ export class WorkspacePreprocessingService {
descriptorBlob: "", descriptorBlob: "",
operation: "inspect", operation: "inspect",
completedStages: [], completedStages: [],
warnings: detail.length > 0 ? [detail.slice(0, 512)] : undefined,
}; };
} }
} }
+12 -4
View File
@@ -337,12 +337,20 @@ export async function renderActiveWorkspaceRuntime(options: {
secretRoots: readonly string[]; secretRoots: readonly string[];
semanticRuntime: SemanticRuntimeConfig; semanticRuntime: SemanticRuntimeConfig;
}): Promise<ActiveRenderedWorkspaceRuntime> { }): Promise<ActiveRenderedWorkspaceRuntime> {
const { revision } = await options.registry.read(options.workspaceId); // The persisted active state may reference host-side snapshot paths (written by another
// process or installation). Read the active state directly and resolve the immutable snapshot
// beneath this process's own configured registry root, so the path is correct inside the
// maintenance container and on the host. This deliberately bypasses WorkspaceRegistry.read,
// whose integrity check would fail on host-side paths inside the container.
const activePath = join(options.registryConfig.root, "state", "active.json");
const active = JSON.parse(await readFileAsync(activePath, "utf8")) as {
head: string;
revisions?: Array<{ id: string; commit: string; blob: string }>;
};
const revision = (active.revisions ?? []).find((entry) => entry.id === options.workspaceId);
if (!revision) throw new Error("workspace is not active");
const repository = new GitWorkspaceRepository(options.registryConfig); const repository = new GitWorkspaceRepository(options.registryConfig);
await repository.ensureLayout(); await repository.ensureLayout();
// The persisted active state may reference host-side snapshot paths (written by another
// process or installation). The operator always resolves the immutable snapshot beneath its
// own configured registry root so the path is correct inside the container and on the host.
const snapshotPath = options.registry.snapshotPath(revision.commit, revision.id); const snapshotPath = options.registry.snapshotPath(revision.commit, revision.id);
const workspace = parseWorkspaceYaml(await readFileAsync(snapshotPath, "utf8")); const workspace = parseWorkspaceYaml(await readFileAsync(snapshotPath, "utf8"));
const rendered = renderWorkspaceRuntimeFromWorkspace({ const rendered = renderWorkspaceRuntimeFromWorkspace({