mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-29 04:25:52 +01:00
Verify private task denial contracts with current master
Preserve existing PR history and verified downstream privacy rules. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
commit
7b0755dac2
5 files changed
+14
-13
No files matched your search
@@ -190,8 +190,9 @@ const support = await getEmbeddedPostgresTestSupport();
|
||||
{ projectId: f.projectId, assigneeAgentId: null, assigneeUserId: "board-user" },
|
||||
]) {
|
||||
const result = await create(path, fields);
|
||||
expect(result.status, JSON.stringify(result.body)).toBe(403);
|
||||
expect(result.body.error).toMatch(/outside.*boundary|cannot assign work to board users|different company/i);
|
||||
const hiddenProject = fields.projectId !== f.projectId && path.startsWith("/api/companies/");
|
||||
expect(result.status, JSON.stringify(result.body)).toBe(hiddenProject ? 404 : 403);
|
||||
expect(result.body.error).toMatch(hiddenProject ? /^Project not found$/ : /outside.*boundary|cannot assign work to board users|different company/i);
|
||||
}
|
||||
}
|
||||
const after = await server.db.select({ id: issues.id }).from(issues).where(eq(issues.companyId, f.companyId));
|
||||
@@ -232,7 +233,10 @@ const support = await getEmbeddedPostgresTestSupport();
|
||||
body: JSON.stringify({ title: "Root cannot escape into another project", parentId: f.issueId,
|
||||
projectId: outside.id, assigneeAgentId: f.agentId, status: "backlog" }),
|
||||
});
|
||||
expect(response.status, JSON.stringify(await response.json())).toBe(403);
|
||||
const denied = await response.json();
|
||||
const hiddenProject = path.startsWith("/api/companies/");
|
||||
expect(response.status, JSON.stringify(denied)).toBe(hiddenProject ? 404 : 403);
|
||||
expect(denied.error).toMatch(hiddenProject ? /^Project not found$/ : /outside.*boundary/i);
|
||||
}
|
||||
await expect(call(f, "create_task", { title: "Native root cannot escape", projectId: outside.id,
|
||||
idempotencyKey: "root-outside", status: "backlog" })).rejects.toThrow(/outside.*boundary/);
|
||||
|
||||
@@ -1734,7 +1734,7 @@ describeEmbeddedPostgres(
|
||||
const before = await snapshot(db);
|
||||
const res = await attempt.req();
|
||||
expect(res.status, `${attempt.id}: ${JSON.stringify(res.body)}`).toBe(
|
||||
["LT approvals", "LT-15/16", "LT-19", "LT-26 child", "LT-26 company issue", "LT-26 interaction", "LT-06 resume", "LT-06 blocker mutation"].includes(attempt.id) ? 403 : 404,
|
||||
["LT approvals", "LT-15/16", "LT-19", "LT-26 child", "LT-26 child with unauthorized assignee", "LT-26 company issue", "LT-26 interaction", "LT-06 resume", "LT-06 blocker mutation"].includes(attempt.id) ? 403 : 404,
|
||||
);
|
||||
expectNoCanary(res.body, ...forbiddenMarkers);
|
||||
const after = await snapshot(db);
|
||||
|
||||
@@ -265,6 +265,7 @@ describeEmbeddedPostgres("gateway connector invocation telemetry", () => {
|
||||
}, 30_000);
|
||||
|
||||
afterEach(async () => {
|
||||
vi.useRealTimers();
|
||||
track.mockClear();
|
||||
failLogActivityForAction.current = null;
|
||||
await db.delete(activityLog);
|
||||
@@ -379,6 +380,9 @@ describeEmbeddedPostgres("gateway connector invocation telemetry", () => {
|
||||
}, 30_000);
|
||||
|
||||
it("emits one denied event for a policy block and one rate_limited event past the limit", async () => {
|
||||
// Both calls must land in the same policy window, even across a minute boundary.
|
||||
vi.useFakeTimers({ toFake: ["Date"] });
|
||||
vi.setSystemTime(new Date("2026-10-06T12:00:30Z"));
|
||||
const f = await fixture();
|
||||
await db.insert(toolPolicies).values({
|
||||
companyId: f.company.id,
|
||||
|
||||
Reference in new issue
Block a user