From 4735edfafcf5f9771f3442704075c19498d06af9 Mon Sep 17 00:00:00 2001 From: Anso Date: Sun, 24 May 2026 15:40:33 -0400 Subject: [PATCH] chore(stacks): explicit stack:read RBAC on list endpoints (#1187) GET /api/stacks and GET /api/stacks/statuses previously relied on the global authGate for protection without declaring their own permission. Every other endpoint in this router uses requirePermission(); the two list endpoints were silent. Add the explicit gate so: 1. The permission model is uniformly declared (audit-readability). 2. A future role (or per-stack Admiral scoped grant) without stack:read is correctly rejected without an extra code change. 3. The list endpoint behavior stays in sync with checkPermission semantics that the rest of the stack router already obeys. Runtime is observably unchanged for every existing role: admin, node-admin, deployer, viewer, and auditor all hold stack:read per ROLE_PERMISSIONS, so the new gate is a no-op for current users. No new test added because no role currently fails the gate; the existing stack suite (65 tests, all admin-role) exercises both endpoints and stays green. --- backend/src/routes/stacks.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/routes/stacks.ts b/backend/src/routes/stacks.ts index 50b995a3..b01e7fe5 100644 --- a/backend/src/routes/stacks.ts +++ b/backend/src/routes/stacks.ts @@ -195,6 +195,7 @@ stacksRouter.param('stackName', (req, res, next, stackName) => { }); stacksRouter.get('/', async (req: Request, res: Response) => { + if (!requirePermission(req, res, 'stack:read')) return; try { const stacks = await FileSystemService.getInstance(req.nodeId).getStacks(); res.json(stacks); @@ -204,6 +205,7 @@ stacksRouter.get('/', async (req: Request, res: Response) => { }); stacksRouter.get('/statuses', async (req: Request, res: Response) => { + if (!requirePermission(req, res, 'stack:read')) return; try { const result = await CacheService.getInstance().getOrFetch( `stack-statuses:${req.nodeId}`,