From 7c02f6eeb520f8f77a4c6dbc72f1b6dfb0da331c Mon Sep 17 00:00:00 2001 From: Anso Date: Sun, 2 Aug 2026 02:03:57 -0400 Subject: [PATCH] feat: add stack:read permission gate to Settings Labels section (#1747) The Labels section registry entry had no requiredPermission, leaving it visible to every authenticated operator. The backend already enforces stack:read on GET and stack:edit on write endpoints, and the frontend component already hides edit controls behind can('stack:edit'). Adding stack:read to the registry declares the contract explicitly. All five built-in roles hold stack:read, so this has no observable effect on current users. It becomes a functioning gate automatically if a future role or scoped user type is introduced without the permission. --- frontend/src/components/settings/__tests__/registry.test.ts | 1 + .../settings/__tests__/settingsVisibilityMatrix.test.ts | 1 + frontend/src/components/settings/registry.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/frontend/src/components/settings/__tests__/registry.test.ts b/frontend/src/components/settings/__tests__/registry.test.ts index 26990c97..2455bc79 100644 --- a/frontend/src/components/settings/__tests__/registry.test.ts +++ b/frontend/src/components/settings/__tests__/registry.test.ts @@ -156,6 +156,7 @@ describe('requiredPermission registry mapping', () => { expect(byId.get('developer')?.requiredPermission).toBe('system:settings'); expect(byId.get('data-retention')?.requiredPermission).toBe('system:settings'); expect(byId.get('image-updates')?.requiredPermission).toBe('system:settings'); + expect(byId.get('labels')?.requiredPermission).toBe('stack:read'); }); it('keeps adminOnly on identity, credentials, and emergency surfaces', () => { diff --git a/frontend/src/components/settings/__tests__/settingsVisibilityMatrix.test.ts b/frontend/src/components/settings/__tests__/settingsVisibilityMatrix.test.ts index 9037ed29..7ecd46c8 100644 --- a/frontend/src/components/settings/__tests__/settingsVisibilityMatrix.test.ts +++ b/frontend/src/components/settings/__tests__/settingsVisibilityMatrix.test.ts @@ -25,6 +25,7 @@ describe('settings section visibility by role', () => { 'registries', 'webhooks', 'nodes', + 'labels', ] as const; it('shows permission-gated sections only to roles that hold the permission', () => { diff --git a/frontend/src/components/settings/registry.ts b/frontend/src/components/settings/registry.ts index 366ecd8f..b1ba031f 100644 --- a/frontend/src/components/settings/registry.ts +++ b/frontend/src/components/settings/registry.ts @@ -267,6 +267,7 @@ export const SETTINGS_ITEMS: readonly SettingsItemMeta[] = [ keywords: ['labels', 'tags', 'palette', 'organisation'], tier: null, scope: 'node', + requiredPermission: 'stack:read', }, // Operations {