import { afterEach, describe, expect, it } from "vitest" ;
import { withTempDir } from "../test-helpers/temp-dir.js" ;
import {
findLatestTaskForRelatedSessionKeyForOwner,
findTaskByRunIdForOwner,
getTaskByIdForOwner,
resolveTaskForLookupTokenForOwner,
} from "./task-owner-access.js" ;
import { createTaskRecord, resetTaskRegistryForTests } from "./task-registry.js" ;
const ORIGINAL_STATE_DIR = process.env.OPENCLAW_STATE_DIR;
afterEach(() => {
resetTaskRegistryForTests({ persist: false });
if (ORIGINAL_STATE_DIR == null ) {
delete process.env.OPENCLAW_STATE_DIR;
} else {
process.env.OPENCLAW_STATE_DIR = ORIGINAL_STATE_DIR;
}
});
async function withTaskRegistryTempDir<T>(run: () => Promise<T> | T): Promise<T> {
return await withTempDir({ prefix: "openclaw-task-owner-access-" }, async (root) => {
const previousStateDir = process.env.OPENCLAW_STATE_DIR;
process.env.OPENCLAW_STATE_DIR = root;
resetTaskRegistryForTests({ persist: false });
try {
return await run();
} finally {
resetTaskRegistryForTests({ persist: false });
if (previousStateDir == null ) {
delete process.env.OPENCLAW_STATE_DIR;
} else {
process.env.OPENCLAW_STATE_DIR = previousStateDir;
}
}
});
}
describe("task owner access" , () => {
it("returns owner-scoped tasks for owner and child-session lookups" , async () => {
await withTaskRegistryTempDir(() => {
const task = createTaskRecord({
runtime: "subagent" ,
ownerKey: "agent:main:main" ,
scopeKind: "session" ,
childSessionKey: "agent:main:subagent:child-1" ,
runId: "owner-visible-run" ,
task: "Owner visible task" ,
status: "running" ,
});
expect(
findLatestTaskForRelatedSessionKeyForOwner({
relatedSessionKey: "agent:main:subagent:child-1" ,
callerOwnerKey: "agent:main:main" ,
})?.taskId,
).toBe(task.taskId);
expect(
findTaskByRunIdForOwner({
runId: "owner-visible-run" ,
callerOwnerKey: "agent:main:main" ,
})?.taskId,
).toBe(task.taskId);
});
});
it("denies cross-owner task reads" , async () => {
await withTaskRegistryTempDir(() => {
const task = createTaskRecord({
runtime: "acp" ,
ownerKey: "agent:main:main" ,
scopeKind: "session" ,
childSessionKey: "agent:main:acp:child-1" ,
runId: "owner-hidden-run" ,
task: "Hidden task" ,
status: "queued" ,
});
expect(
getTaskByIdForOwner({
taskId: task.taskId,
callerOwnerKey: "agent:main:subagent:other-parent" ,
}),
).toBeUndefined();
expect(
findTaskByRunIdForOwner({
runId: "owner-hidden-run" ,
callerOwnerKey: "agent:main:subagent:other-parent" ,
}),
).toBeUndefined();
expect(
resolveTaskForLookupTokenForOwner({
token: "agent:main:acp:child-1" ,
callerOwnerKey: "agent:main:subagent:other-parent" ,
}),
).toBeUndefined();
});
});
it("requires an exact owner-key match" , async () => {
await withTaskRegistryTempDir(() => {
const task = createTaskRecord({
runtime: "acp" ,
ownerKey: "agent:main:MixedCase" ,
scopeKind: "session" ,
runId: "case-sensitive-owner-run" ,
task: "Case-sensitive owner" ,
status: "queued" ,
});
expect(
getTaskByIdForOwner({
taskId: task.taskId,
callerOwnerKey: "agent:main:mixedcase" ,
}),
).toBeUndefined();
});
});
it("does not expose system-owned tasks through owner-scoped readers" , async () => {
await withTaskRegistryTempDir(() => {
const task = createTaskRecord({
runtime: "cron" ,
ownerKey: "system:cron:nightly" ,
scopeKind: "system" ,
requesterSessionKey: "system:cron:nightly" ,
childSessionKey: "agent:main:cron:nightly" ,
runId: "system-task-run" ,
task: "Nightly cron" ,
status: "running" ,
deliveryStatus: "not_applicable" ,
});
expect(
getTaskByIdForOwner({
taskId: task.taskId,
callerOwnerKey: "agent:main:main" ,
}),
).toBeUndefined();
expect(
resolveTaskForLookupTokenForOwner({
token: "system-task-run" ,
callerOwnerKey: "agent:main:main" ,
}),
).toBeUndefined();
});
});
});
Messung V0.5 in Prozent C=100 H=100 G=100
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-09)
¤
*© Formatika GbR, Deutschland