From 7bc798c0696c79e00b282ac854500ca1e48ae103 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Mar 2026 09:51:36 +0100 Subject: [PATCH] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Patrik Oldsberg --- docs/backend-system/core-services/actions-registry.md | 9 +++++++-- .../actionsRegistry/DefaultActionsRegistryService.ts | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/backend-system/core-services/actions-registry.md b/docs/backend-system/core-services/actions-registry.md index 23e8c2bff8..b2ebcc1d04 100644 --- a/docs/backend-system/core-services/actions-registry.md +++ b/docs/backend-system/core-services/actions-registry.md @@ -160,9 +160,14 @@ export const myPlugin = createBackendPlugin({ ## Permissions -Actions can optionally declare a `visibilityPermission` to control visibility and access through the Backstage permissions framework. When a permission is set, the action is only visible in listings and accessible by users who are authorized. +Actions can optionally declare a `visibilityPermission` to control visibility and access through the Backstage permissions framework. This permission is evaluated without any resource context and is intended for unconditional (non-resource) permissions only. When such a permission is set, the action is only visible in listings and accessible by users who are authorized. -When accessed via the Actions Service or the `/.backstage/actions/v1/...` HTTP endpoints, actions that are denied by the permission policy are filtered from list results and return a `404 Not Found` on invocation, as if they don't exist. +When accessed via the Actions Service or the `/.backstage/actions/v1/...` HTTP endpoints, actions that are not authorized by the permission policy are filtered from list results and return a `404 Not Found` on invocation, as if they don't exist. In particular: + +- `ALLOW` decisions make the action visible and invokable. +- `DENY` and `CONDITIONAL` decisions are both treated as not authorized, so the action is hidden from listings and returns `404 Not Found` when invoked. + +Because `visibilityPermission` is evaluated without resource context, resource-based or otherwise conditional permissions (that may normally return `CONDITIONAL` decisions) are not supported here and will effectively behave as denied. Permissions declared on actions are automatically registered with the `PermissionsRegistryService` so they appear in the permission policy system. diff --git a/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts b/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts index f4d9acca06..a2109ec1bf 100644 --- a/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts +++ b/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts @@ -154,7 +154,7 @@ export class DefaultActionsRegistryService implements ActionsRegistryService { [{ permission: action.visibilityPermission }], { credentials }, ); - if (decision.result === AuthorizeResult.DENY) { + if (decision.result !== AuthorizeResult.ALLOW) { throw new NotFoundError( `Action "${req.params.actionId}" not found`, ); @@ -233,7 +233,7 @@ export class DefaultActionsRegistryService implements ActionsRegistryService { const deniedIds = new Set( permissionedEntries - .filter((_, index) => decisions[index].result === AuthorizeResult.DENY) + .filter((_, index) => decisions[index].result !== AuthorizeResult.ALLOW) .map(([id]) => id), );