fix: retain snapshots for removed workspaces

This commit is contained in:
2026-08-04 08:52:11 +02:00
parent 8b046f9fb2
commit 3b23cf3714
4 changed files with 116 additions and 3 deletions
+16 -3
View File
@@ -72,6 +72,15 @@ export function sessionRoutes(
return typeof runner.withPrincipal === "function" ? runner.withPrincipal(principal) : runner;
};
/** Include retained historical descriptors so removed workspaces remain resumable. */
const sessionRevisions = async () => {
const registry = d.workspaceRegistry as Partial<WorkspaceRegistry>;
if (typeof registry.listRetainedSnapshots === "function") {
return await registry.listRetainedSnapshots();
}
return await d.workspaceRegistry.list();
};
const isNotFound = (error: unknown) =>
/not found|non trovata|inesistente|404/i.test(error instanceof Error ? error.message : String(error));
@@ -107,7 +116,7 @@ export function sessionRoutes(
};
let revisions: Awaited<ReturnType<typeof d.workspaceRegistry.list>>;
try {
revisions = await d.workspaceRegistry.list();
revisions = await sessionRevisions();
} catch (registryError) {
// Sessions created before revision pinning still live under the installation's legacy
// default config. Keep that compatibility path available when a fresh installation has
@@ -394,11 +403,15 @@ export function sessionRoutes(
// Admin RLS is deliberately disabled for a normal 'mine' listing.
const scopedPrincipal = scope === "mine" ? { ...principal, isAdmin: false } : principal;
const runner = runnerFor(scopedPrincipal);
const revisions = await d.workspaceRegistry.list();
const revisions = await sessionRevisions();
const lists = await Promise.all(revisions
.filter((revision) => revision.state === "operational")
.map((revision) => runner.sessionList(revision.snapshotPath) as Promise<SessionRow[]>));
const list = lists.flat();
const sessions = new Map<string, SessionRow>();
for (const row of lists.flat()) {
if (!sessions.has(row.id)) sessions.set(row.id, row);
}
const list = [...sessions.values()];
// Only an administrator-visible complete list (or the single local principal) is safe
// input for retention. A remote per-user view can never discard another principal's pin.
const reconcileSnapshotRetention = (d.workspaceRegistry as Partial<WorkspaceRegistry>).reconcileSnapshotRetention;