diff --git a/server/src/routes/authz.ts b/server/src/routes/authz.ts index ec6c49621dc..e24567bc085 100644 --- a/server/src/routes/authz.ts +++ b/server/src/routes/authz.ts @@ -31,6 +31,12 @@ export function assertBoardOrgAccess(req: Request) { throw forbidden("Company membership or instance admin access required"); } +export function assertBoardOrAgent(req: Request) { + if (req.actor.type !== "board" && req.actor.type !== "agent") { + throw forbidden("Board or agent access required"); + } +} + export function assertInstanceAdmin(req: Request) { assertBoard(req); if (req.actor.source === "local_implicit" || req.actor.isInstanceAdmin) { diff --git a/server/src/routes/plugins.ts b/server/src/routes/plugins.ts index c3f6265f0af..1c01bbba890 100644 --- a/server/src/routes/plugins.ts +++ b/server/src/routes/plugins.ts @@ -11,8 +11,9 @@ * - Retrieving UI slot contributions for frontend rendering * - Discovering and executing plugin-contributed agent tools * - * All routes require board-level authentication, and sensitive instance-wide + * Most routes require board-level authentication, and sensitive instance-wide * mutations such as install/upgrade require instance-admin privileges. + * Plugin tool discovery and execution routes allow both board and agent access. * * @module server/routes/plugins * @see doc/plugins/PLUGIN_SPEC.md for the full plugin specification @@ -60,6 +61,7 @@ import { JsonRpcCallError, PLUGIN_RPC_ERROR_CODES } from "@paperclipai/plugin-sd import { assertAuthenticated, assertBoard, + assertBoardOrAgent, assertBoardOrgAccess, assertCompanyAccess, assertInstanceAdmin, @@ -878,7 +880,7 @@ export function pluginRoutes( * Errors: 501 if tool dispatcher is not configured */ router.get("/plugins/tools", async (req, res) => { - assertBoardOrgAccess(req); + assertBoardOrAgent(req); if (!toolDeps) { res.status(501).json({ error: "Plugin tool dispatch is not enabled" }); @@ -912,7 +914,7 @@ export function pluginRoutes( * - 502 if the plugin worker is unavailable or the RPC call fails */ router.post("/plugins/tools/execute", async (req, res) => { - assertBoardOrgAccess(req); + assertBoardOrAgent(req); if (!toolDeps) { res.status(501).json({ error: "Plugin tool dispatch is not enabled" });