diff --git a/addons/core/translations/actions/en-us.yaml b/addons/core/translations/actions/en-us.yaml
index 97f396c438..5bd43c30d7 100644
--- a/addons/core/translations/actions/en-us.yaml
+++ b/addons/core/translations/actions/en-us.yaml
@@ -23,6 +23,7 @@ retry: Retry
play: Play
pause: Pause
resume: Resume
+export: Export
get-topic-help: Get help for this topic
copy-to-clipboard: Copy to Clipboard
copy-error-detail-to-clipboard: Copy error detail to clipboard
diff --git a/addons/core/translations/resources/en-us.yaml b/addons/core/translations/resources/en-us.yaml
index 61043b6c8f..d7f673b19d 100644
--- a/addons/core/translations/resources/en-us.yaml
+++ b/addons/core/translations/resources/en-us.yaml
@@ -660,6 +660,9 @@ role:
read-only-user:
name: Read-Only User
description: Can view but not modify any resources
+ edit-grants:
+ title: Edit Grants
+ description: Modify existing grant strings or add new grant strings to this role.
scope:
title: Scope
title_plural: Scopes
diff --git a/ui/admin/app/components/form/role/edit-grants/index.hbs b/ui/admin/app/components/form/role/edit-grants/index.hbs
new file mode 100644
index 0000000000..809766cb09
--- /dev/null
+++ b/ui/admin/app/components/form/role/edit-grants/index.hbs
@@ -0,0 +1,31 @@
+{{!
+ Copyright IBM Corp. 2021, 2026
+ SPDX-License-Identifier: BUSL-1.1
+}}
+
+
+ {{! TODO: Add responsive options to @colspan once we upgrade to HDS v6.0.0}}
+
+
+ {{! TODO: Add grants code editor. }}
+
+
+
+ {{! TODO: Add string options and actions. }}
+
+
+
+
+ <:actions>
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/admin/app/components/roles/role/actions/index.hbs b/ui/admin/app/components/roles/role/actions/index.hbs
index d9323602e2..c65403ea97 100644
--- a/ui/admin/app/components/roles/role/actions/index.hbs
+++ b/ui/admin/app/components/roles/role/actions/index.hbs
@@ -45,6 +45,12 @@
>
{{t 'resources.role.grant-templates.actions.add-grant-templates'}}
+
+ {{t 'resources.role.edit-grants.title'}}
+
{{/if}}
{{#if perms.canDelete}}
{{#if
diff --git a/ui/admin/app/router.js b/ui/admin/app/router.js
index e1fd337143..ad707865cd 100644
--- a/ui/admin/app/router.js
+++ b/ui/admin/app/router.js
@@ -58,6 +58,7 @@ Router.map(function () {
this.route('manage-custom-scopes');
this.route('manage-org-projects', { path: ':org_id' });
});
+ this.route('edit-grants');
});
this.route('new');
});
diff --git a/ui/admin/app/routes/scopes/scope/roles/role/edit-grants.js b/ui/admin/app/routes/scopes/scope/roles/role/edit-grants.js
new file mode 100644
index 0000000000..74dc74dcb3
--- /dev/null
+++ b/ui/admin/app/routes/scopes/scope/roles/role/edit-grants.js
@@ -0,0 +1,8 @@
+/**
+ * Copyright IBM Corp. 2021, 2026
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import Route from '@ember/routing/route';
+
+export default class ScopesScopeRolesRoleEditGrantsRoute extends Route {}
diff --git a/ui/admin/app/templates/scopes/scope/roles/role/edit-grants.hbs b/ui/admin/app/templates/scopes/scope/roles/role/edit-grants.hbs
new file mode 100644
index 0000000000..b2ff25c2ab
--- /dev/null
+++ b/ui/admin/app/templates/scopes/scope/roles/role/edit-grants.hbs
@@ -0,0 +1,34 @@
+{{!
+ Copyright IBM Corp. 2021, 2026
+ SPDX-License-Identifier: BUSL-1.1
+}}
+
+{{page-title (t 'resources.role.edit-grants.title')}}
+
+
+
+
+
+
+
+
+
+
+ {{t 'resources.role.edit-grants.title'}}
+ {{! TODO: Add correct doc link once it's created}}
+ {{! }}
+
+
+ {{t 'resources.role.edit-grants.description'}}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/admin/tests/acceptance/roles/edit-grants-test.js b/ui/admin/tests/acceptance/roles/edit-grants-test.js
new file mode 100644
index 0000000000..d625f264af
--- /dev/null
+++ b/ui/admin/tests/acceptance/roles/edit-grants-test.js
@@ -0,0 +1,79 @@
+/**
+ * Copyright IBM Corp. 2021, 2026
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import { module, test } from 'qunit';
+import { visit, click, currentURL } from '@ember/test-helpers';
+import { setupApplicationTest } from 'admin/tests/helpers';
+import * as selectors from './selectors';
+import { setRunOptions } from 'ember-a11y-testing/test-support';
+
+module('Acceptance | roles/edit grants', function (hooks) {
+ setupApplicationTest(hooks);
+
+ const instances = {
+ scopes: {
+ global: null,
+ },
+ role: null,
+ };
+
+ const urls = {
+ role: null,
+ editGrants: null,
+ };
+
+ hooks.beforeEach(async function () {
+ instances.scopes.global = this.server.schema.scopes.find('global');
+ instances.role = this.server.create('role', {
+ scope: instances.scopes.global,
+ });
+ urls.role = `/scopes/global/roles/${instances.role.id}`;
+ urls.editGrants = `${urls.role}/edit-grants`;
+ });
+
+ test('can navigate to edit grants for roles with proper authorization', async function (assert) {
+ setRunOptions({
+ rules: {
+ 'color-contrast': {
+ // [ember-a11y-ignore]: axe rule "color-contrast" automatically ignored on 2026-02-27
+ enabled: false,
+ },
+ },
+ });
+
+ await visit(urls.role);
+
+ assert.true(instances.role.authorized_actions.includes('set-grants'));
+
+ await click(selectors.MANAGE_DROPDOWN_ROLES);
+ await click(selectors.MANAGE_DROPDOWN_EDIT_GRANTS);
+
+ assert.strictEqual(currentURL(), urls.editGrants);
+ });
+
+ test('cannot navigate to edit grants for roles without proper authorization', async function (assert) {
+ setRunOptions({
+ rules: {
+ 'color-contrast': {
+ // [ember-a11y-ignore]: axe rule "color-contrast" automatically ignored on 2026-02-27
+ enabled: false,
+ },
+ },
+ });
+
+ instances.role.authorized_actions =
+ instances.role.authorized_actions.filter(
+ (action) => action !== 'set-grants',
+ );
+ await visit(urls.role);
+
+ assert.false(instances.role.authorized_actions.includes('set-grants'));
+
+ await click(selectors.MANAGE_DROPDOWN_ROLES);
+
+ assert.dom(selectors.MANAGE_DROPDOWN_EDIT_GRANTS).doesNotExist();
+ assert.strictEqual(currentURL(), urls.role);
+ });
+});
diff --git a/ui/admin/tests/acceptance/roles/selectors.js b/ui/admin/tests/acceptance/roles/selectors.js
index 033c34aa26..dc50628e6d 100644
--- a/ui/admin/tests/acceptance/roles/selectors.js
+++ b/ui/admin/tests/acceptance/roles/selectors.js
@@ -16,6 +16,7 @@ export const MANAGE_DROPDOWN_ADD_PRINCIPALS =
'[data-test-manage-role-principals]';
export const MANAGE_DROPDOWN_ADD_GRANT_TEMPLATES =
'[data-test-manage-role-grant-templates]';
+export const MANAGE_DROPDOWN_EDIT_GRANTS = '[data-test-manage-dropdown-grants]';
export const ROLE_BADGE = (id) =>
`tbody [data-test-role-row="${id}"] td:nth-child(2) .hds-badge__text`;
diff --git a/ui/admin/tests/unit/routes/scopes/scope/roles/role/edit-grants-test.js b/ui/admin/tests/unit/routes/scopes/scope/roles/role/edit-grants-test.js
new file mode 100644
index 0000000000..d1bb72470b
--- /dev/null
+++ b/ui/admin/tests/unit/routes/scopes/scope/roles/role/edit-grants-test.js
@@ -0,0 +1,16 @@
+/**
+ * Copyright IBM Corp. 2021, 2026
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Route | scopes/scope/roles/role/edit-grants', function (hooks) {
+ setupTest(hooks);
+
+ test('it exists', function (assert) {
+ let route = this.owner.lookup('route:scopes/scope/roles/role/edit-grants');
+ assert.ok(route);
+ });
+});