Fix same-directory workspace ownership

This commit is contained in:
Mohamed Boudra
2026-06-15 22:22:31 +07:00
parent a4d4d42873
commit ba9f7740a8
21 changed files with 599 additions and 139 deletions
@@ -110,6 +110,20 @@ it("lists subdirectory terminals when querying the workspace root", async () =>
expect(rootTerminals.map((terminal) => terminal.id)).toEqual([created.id]);
});
it("includes only stamped terminals in workspace-scoped queries", async () => {
manager = createTerminalManager();
const cwd = realpathSync(tmpdir());
const legacy = await manager.createTerminal({ cwd });
const owned = await manager.createTerminal({ cwd, workspaceId: "ws-owned" });
const sibling = await manager.createTerminal({ cwd, workspaceId: "ws-sibling" });
const scoped = await manager.getTerminals(cwd, { workspaceId: "ws-owned" });
const unscoped = await manager.getTerminals(cwd);
expect(scoped.map((terminal) => terminal.id)).toEqual([owned.id]);
expect(unscoped.map((terminal) => terminal.id)).toEqual([legacy.id, owned.id, sibling.id]);
});
it("creates additional terminal with auto-incrementing name", async () => {
manager = createTerminalManager();
const cwd = realpathSync(tmpdir());
@@ -296,14 +296,10 @@ export function createTerminalManager(
}
// When the query carries a workspaceId, two workspaces sharing a cwd must
// not see each other's terminals. Exclude sessions owned by a different
// workspace; keep sessions without an owner (COMPAT: created by clients
// that predate terminal workspace ownership).
// not see each other's terminals. A missing owner is not workspace
// membership; unscoped callers can still list those legacy terminals.
if (options?.workspaceId !== undefined) {
return sessions.filter(
(session) =>
session.workspaceId === undefined || session.workspaceId === options.workspaceId,
);
return sessions.filter((session) => session.workspaceId === options.workspaceId);
}
return sessions;
},
@@ -566,6 +566,57 @@ it("lists terminals locally without waiting on the worker", async () => {
expect(worker.sentMessages.some((message) => message.type === "getTerminals")).toBe(false);
});
it("includes only stamped terminals in workspace-scoped local reads", async () => {
const worker = new FakeTerminalWorker();
manager = createWorkerTerminalManager({
requestTimeoutMs: 5,
forkWorker: () => worker,
});
worker.emitWorkerMessage({
type: "terminalCreated",
terminal: {
id: "terminal-legacy",
name: "Legacy",
cwd: "/workspace",
activity: null,
},
state: createTerminalState(),
});
worker.emitWorkerMessage({
type: "terminalCreated",
terminal: {
id: "terminal-owned",
name: "Owned",
cwd: "/workspace",
workspaceId: "ws-owned",
activity: null,
},
state: createTerminalState(),
});
worker.emitWorkerMessage({
type: "terminalCreated",
terminal: {
id: "terminal-sibling",
name: "Sibling",
cwd: "/workspace",
workspaceId: "ws-sibling",
activity: null,
},
state: createTerminalState(),
});
const scoped = await manager.getTerminals("/workspace", { workspaceId: "ws-owned" });
const unscoped = await manager.getTerminals("/workspace");
expect(scoped.map((terminal) => terminal.id)).toEqual(["terminal-owned"]);
expect(unscoped.map((terminal) => terminal.id)).toEqual([
"terminal-legacy",
"terminal-owned",
"terminal-sibling",
]);
});
it("rejects non-absolute cwd in getTerminals", async () => {
const worker = new FakeTerminalWorker();
manager = createWorkerTerminalManager({
@@ -653,14 +653,10 @@ export function createWorkerTerminalManager(
}
// When the query carries a workspaceId, two workspaces sharing a cwd must
// not see each other's terminals. Exclude sessions owned by a different
// workspace; keep sessions without an owner (COMPAT: created by clients
// that predate terminal workspace ownership).
// not see each other's terminals. A missing owner is not workspace
// membership; unscoped callers can still list those legacy terminals.
if (options?.workspaceId !== undefined) {
return sessions.filter(
(session) =>
session.workspaceId === undefined || session.workspaceId === options.workspaceId,
);
return sessions.filter((session) => session.workspaceId === options.workspaceId);
}
return sessions;
},