The executor loaded every agent secret in a Space and injected decrypted values into shell environment variables for any member's bot run. Restore agentSecretScopeForRun scoping accidentally dropped in 0a8a831. Add an executor test that fails when findMany is scoped only by spaceId. Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
This commit is contained in:
parent
04528a93e3
commit
ff11f1d151
@ -12,6 +12,7 @@ import {
|
|||||||
toolCompletionAuditPayload,
|
toolCompletionAuditPayload,
|
||||||
toolCompletionFromResult,
|
toolCompletionFromResult,
|
||||||
} from "./executor.js";
|
} from "./executor.js";
|
||||||
|
import { agentSecretScopeForRun } from "./agent-environment.js";
|
||||||
import { missingTurnImagesInstruction, settleSteeringAttachmentLoads } from "./executor-attachments.js";
|
import { missingTurnImagesInstruction, settleSteeringAttachmentLoads } from "./executor-attachments.js";
|
||||||
import { threadContextForRun } from "./executor-completion.js";
|
import { threadContextForRun } from "./executor-completion.js";
|
||||||
import { serializeModelSecret } from "./pi-oauth.js";
|
import { serializeModelSecret } from "./pi-oauth.js";
|
||||||
@ -1253,6 +1254,94 @@ description: Prepare standup notes
|
|||||||
expect(runtimeRun).not.toHaveBeenCalled();
|
expect(runtimeRun).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("scopes agent secrets to the run owner when loading the environment", async () => {
|
||||||
|
const agentSecretFindMany = vi.fn(async () => []);
|
||||||
|
const run = {
|
||||||
|
id: "run-1",
|
||||||
|
botId: "bot-1",
|
||||||
|
threadId: "thread-1",
|
||||||
|
taskId: "task-1",
|
||||||
|
userId: "member-user",
|
||||||
|
spaceId: "shared-ws",
|
||||||
|
status: "queued",
|
||||||
|
trigger: "user",
|
||||||
|
routineId: null,
|
||||||
|
sourceMessageId: null,
|
||||||
|
checkpoint: null,
|
||||||
|
leaseFence: 0,
|
||||||
|
};
|
||||||
|
const botLookup = vi.fn(async (args: { select?: { computerId?: boolean } }) =>
|
||||||
|
args.select?.computerId
|
||||||
|
? { computerId: "computer-1", computerSwitching: false }
|
||||||
|
: {
|
||||||
|
id: "bot-1",
|
||||||
|
name: "Assistant",
|
||||||
|
modelProvider: null,
|
||||||
|
modelId: null,
|
||||||
|
thinkingLevel: null,
|
||||||
|
memoryScope: "isolated",
|
||||||
|
computer: { id: "computer-1", scope: "private" },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const prisma = {
|
||||||
|
run: {
|
||||||
|
findUnique: vi.fn(async () => run),
|
||||||
|
findUniqueOrThrow: vi.fn(async () => ({ status: "leased", startedAt: null })),
|
||||||
|
updateMany: vi.fn(async () => ({ count: 1 })),
|
||||||
|
},
|
||||||
|
bot: { findUniqueOrThrow: botLookup },
|
||||||
|
computer: {
|
||||||
|
findUniqueOrThrow: vi.fn(async () => ({ scope: "private", state: "running" })),
|
||||||
|
},
|
||||||
|
attempt: {
|
||||||
|
create: vi.fn(async () => ({ id: "attempt-1" })),
|
||||||
|
updateMany: vi.fn(async () => ({ count: 1 })),
|
||||||
|
},
|
||||||
|
thread: {
|
||||||
|
findUniqueOrThrow: vi.fn(async () => ({
|
||||||
|
id: "thread-1",
|
||||||
|
groupId: null,
|
||||||
|
historyCompactionSummary: null,
|
||||||
|
historyCompactedUpToSeq: null,
|
||||||
|
historyCompactionGeneration: 0,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
message: { findMany: vi.fn(async () => []) },
|
||||||
|
task: { findUniqueOrThrow: vi.fn(async () => ({ id: "task-1", prompt: "hello" })) },
|
||||||
|
connection: { findMany: vi.fn(async () => []) },
|
||||||
|
spaceModelPreference: { findFirst: vi.fn(async () => null) },
|
||||||
|
userModelCredential: { findFirst: vi.fn(async () => null) },
|
||||||
|
deploymentSettings: { findUnique: vi.fn(async () => null) },
|
||||||
|
taughtSkill: { findMany: vi.fn(async () => []) },
|
||||||
|
agentSecret: { findMany: agentSecretFindMany },
|
||||||
|
agentSkill: { findMany: vi.fn(async () => []) },
|
||||||
|
scratchpadItem: { findMany: vi.fn(async () => []) },
|
||||||
|
} as unknown as PrismaClient;
|
||||||
|
const executor = createRunExecutor({
|
||||||
|
prisma,
|
||||||
|
runtime: {
|
||||||
|
describe: () => ({ capabilities: { scripted: false } }),
|
||||||
|
run: vi.fn(),
|
||||||
|
},
|
||||||
|
memoryProviders: { resolve: vi.fn(async () => null) },
|
||||||
|
memory: { read: vi.fn(async () => ({ documents: [] })) },
|
||||||
|
events: {
|
||||||
|
append: vi.fn(async () => undefined),
|
||||||
|
finalizeRun: vi.fn(async () => ({ continuationRunId: null })),
|
||||||
|
},
|
||||||
|
jobs: { enqueue: vi.fn(async () => undefined) },
|
||||||
|
secrets: [],
|
||||||
|
} as unknown as Parameters<typeof createRunExecutor>[0]);
|
||||||
|
|
||||||
|
await executor.continueRun("run-1", "worker-1");
|
||||||
|
|
||||||
|
expect(agentSecretFindMany).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
where: agentSecretScopeForRun("shared-ws", "member-user"),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("resolves a per-bot model override with that provider’s credential", async () => {
|
it("resolves a per-bot model override with that provider’s credential", async () => {
|
||||||
const findFirst = vi.fn(
|
const findFirst = vi.fn(
|
||||||
async (args: { where: { credential?: { provider?: string }; isDefault?: boolean } }) => {
|
async (args: { where: { credential?: { provider?: string }; isDefault?: boolean } }) => {
|
||||||
|
|||||||
@ -108,6 +108,7 @@ import {
|
|||||||
respondAgentConnection,
|
respondAgentConnection,
|
||||||
} from "./agent-connections.js";
|
} from "./agent-connections.js";
|
||||||
import {
|
import {
|
||||||
|
agentSecretScopeForRun,
|
||||||
decryptAgentEnvironment,
|
decryptAgentEnvironment,
|
||||||
formatAgentEnvironmentInstruction,
|
formatAgentEnvironmentInstruction,
|
||||||
redactAgentCommandResult,
|
redactAgentCommandResult,
|
||||||
@ -1026,7 +1027,7 @@ export function createRunExecutor(deps: ExecutorDeps) {
|
|||||||
userId: run.userId,
|
userId: run.userId,
|
||||||
}),
|
}),
|
||||||
deps.prisma.agentSecret.findMany({
|
deps.prisma.agentSecret.findMany({
|
||||||
where: { spaceId: run.spaceId },
|
where: agentSecretScopeForRun(run.spaceId, run.userId),
|
||||||
select: {
|
select: {
|
||||||
name: true,
|
name: true,
|
||||||
secret: { select: { id: true, ciphertext: true } },
|
secret: { select: { id: true, ciphertext: true } },
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user