Skip to content

Fix multiple UI UX issues - #3062

Open
Piumal1999 wants to merge 19 commits into
wso2:mainfrom
Piumal1999:rb-bug-fixes
Open

Fix multiple UI UX issues#3062
Piumal1999 wants to merge 19 commits into
wso2:mainfrom
Piumal1999:rb-bug-fixes

Conversation

@Piumal1999

Copy link
Copy Markdown
Contributor

Purpose

Explain why this feature or fix is required. Describe the underlying problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc.

Goals

Describe what solutions this feature or fix introduces to address the problems outlined above.

Approach

Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI. Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here.

User stories

Summary of user stories addressed by this change>

Documentation

Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact

Automation tests

  • Unit tests

    Code coverage information

  • Integration tests

    Details about the test cases and coverage

Security checks

Samples

Provide high-level details about the samples related to this feature

Related PRs

List any other related PRs

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The API Portal removes static service API-key authentication, adds role-mode authorization integration tests, improves page and Markdown error status handling, supports unlabeled views, updates immutable resource handles, and changes Cypress setup to session-based authentication.

Changes

API Portal authentication and integration coverage

Layer / File(s) Summary
Session authentication and service API-key removal
portals/api-portal/src/middlewares/*, portals/api-portal/it/test-config.toml, portals/api-portal/it/ui/cypress/*, portals/api-portal/it/rest-api/organizations/*
Static service API-key authentication and configuration were removed. Cypress and REST integration requests now use session cookies and CSRF tokens.
Role-mode authorization fixtures and tests
portals/api-portal/it/configs/*, portals/api-portal/it/docker-compose.test*, portals/api-portal/it/rest-api/auth/*, portals/api-portal/it/README.md
A role-authorized portal instance, role mappings, isolated storage, and authorization tests were added.
Content rendering and status-aware responses
portals/api-portal/src/utils/util.js, portals/api-portal/src/controllers/*, portals/api-portal/src/defaultContent/pages/*, portals/api-portal/it/rest-api/ai-discovery/*
Page errors preserve supported status codes. Markdown endpoints return status-aware responses. API catalog grouping and MCP links were corrected.
View, organization, and resource management contracts
portals/api-portal/docs/api-portal-openapi-spec-v0.9.yaml, portals/api-portal/src/services/*, portals/api-portal/src/dao/*, portals/api-portal/src/scripts/settings-*, portals/api-portal/src/pages/settings/*
Views accept omitted labels. Organization references can be cleared. API, label, and webhook handles are immutable during edits.
Portal copy and key-management UI
portals/api-portal/src/pages/application/*, portals/api-portal/src/scripts/oauth2-key-generation.js, portals/api-portal/src/pages/login-page/*, portals/api-portal/docs/consume-an-api/*
Key-management text now uses “Remove keys”. Login branding and OAuth2 removal guidance were updated.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: lasanthas, krishanx92, renuka-fernando

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description contains only the unfilled template and provides no purpose, goals, approach, testing, security, documentation, or environment details. Complete each required section with specific details about the changes, affected issues, tests, security checks, documentation, and test environment.
Docstring Coverage ⚠️ Warning Docstring coverage is 44.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately identifies the pull request as addressing multiple user-interface and user-experience issues, although it does not mention non-UI changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
portals/api-portal/src/middlewares/authMiddleware.js (2)

400-412: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the stale "org resolved from header" comment.

The comment on line 400 says the mTLS branch resolves the org "from the organization request header." The function it calls, resolvePortalOrg (documented at lines 246-253), does the opposite: the header no longer selects the organization, it is only checked for a mismatch. Update the line 400 comment to match the documented behavior of resolvePortalOrg, or a future reader will misunderstand how org selection works for mTLS credentials.

📝 Proposed fix
-        // 4. mTLS — org resolved from the `organization` request header
+        // 4. mTLS — org resolved from the portal's configured organization;
+        //    the `organization` header, if present, is only checked for a mismatch.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/api-portal/src/middlewares/authMiddleware.js` around lines 400 - 412,
Update the comment immediately above the mTLS branch in the authentication
middleware to state that resolvePortalOrg validates the organization header for
mismatches rather than selecting the organization from it; leave the
resolvePortalOrg call and authentication behavior unchanged.

465-479: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Correct the apiKeyAuth docstring — it inverts the actual acceptance rule.

The docstring says this handler "Accepts any preauthorized non-OAuth mode (mTLS, role-mode session)." That does not match req.auth?.preauthorized:

  • Role-mode sessions set preauthorized: !isRoleMode(), which is false in role mode (line 347) — they are rejected, not accepted, contradicting "role-mode session" in the doc.
  • Scope-mode IDP sessions have mode: 'oauth2' and preauthorized: true — they are accepted, contradicting "non-OAuth mode" in the doc.

This handler is currently unreachable (no operation declares apiKeyAuth), so there is no live exposure. Still, fix the wording now so a future engineer who adds security: [apiKeyAuth] to an operation does not rely on an incorrect mental model of which sessions pass.

📝 Proposed fix
- * Accepts any preauthorized non-OAuth mode (mTLS, role-mode session).
+ * Accepts any mode with req.auth.preauthorized === true — currently mTLS,
+ * and scope-mode OAuth2 sessions (preauthorized is false for role-mode
+ * sessions, platform-jwt sessions, and bearer tokens).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/api-portal/src/middlewares/authMiddleware.js` around lines 465 - 479,
Correct the apiKeyAuth docstring to state that the handler accepts requests only
when req.auth?.preauthorized is true, including scope-mode OAuth2 sessions, and
does not accept role-mode sessions when they set it false. Remove the inaccurate
“non-OAuth” and “role-mode session” wording while preserving the surrounding
credential-store and scope-check guidance.
🧹 Nitpick comments (1)
portals/api-portal/it/rest-api/views-and-labels/views.spec.js (1)

63-67: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Verify persistence for an explicit empty label array.

The test checks only 201 for labels: []. It does not prove that the stored view has an empty label set. Fetch /views/${id} and assert fetched.body.labels is [], as in the omitted-label test.

Proposed test assertion
         expect(res.status).toBe(201);
+        const fetched = await client.as('admin').get(`/views/${id}`);
+        expect(fetched.status).toBe(200);
+        expect(fetched.body.labels).toEqual([]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/api-portal/it/rest-api/views-and-labels/views.spec.js` around lines
63 - 67, Update the creates-a-view-with-an-empty-label-array test around
uniqueHandle and the POST request to fetch /views/${id} after confirming
creation, then assert the fetched response’s body.labels is an empty array,
matching the omitted-label persistence test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@portals/api-portal/src/controllers/apiContentController.js`:
- Around line 1139-1143: Update sendMarkdownError to set the response
Content-Type to the caller’s success media type before sending either the 404 or
500 markdown body, passing that media type into the helper if necessary and
updating its callers accordingly.

In `@portals/api-portal/src/controllers/customContentController.js`:
- Line 105: Update the locally generated missing-page errors in the controller
to include a 404 status before they are passed to next(error), ensuring
pageErrorStatus(error) maps both missing-file branches to HTTP 404 instead of
500.

In `@portals/api-portal/src/pages/application/partials/manage-keys-km-card.hbs`:
- Around line 65-74: Update the removal messaging in the manage-keys footer and
the related confirmation flows in confirmAndRemoveKeys and
oauth2-key-generation.js to accurately describe the DELETE route: it removes
only the portal’s local OAuth client_id mapping, while external OAuth clients
and already-issued tokens remain active. Remove wording that claims credentials
are deleted or tokens are revoked, and synchronize any related documentation
with this behavior.

In `@portals/api-portal/src/styles/settings-layout.css`:
- Around line 612-615: Update the .cfg-form-input[readonly]:focus rule to retain
a clearly visible keyboard-focus indicator instead of removing all focus
styling. Add or preserve a distinct outline, border, or shadow that contrasts
with the base read-only input appearance.

---

Outside diff comments:
In `@portals/api-portal/src/middlewares/authMiddleware.js`:
- Around line 400-412: Update the comment immediately above the mTLS branch in
the authentication middleware to state that resolvePortalOrg validates the
organization header for mismatches rather than selecting the organization from
it; leave the resolvePortalOrg call and authentication behavior unchanged.
- Around line 465-479: Correct the apiKeyAuth docstring to state that the
handler accepts requests only when req.auth?.preauthorized is true, including
scope-mode OAuth2 sessions, and does not accept role-mode sessions when they set
it false. Remove the inaccurate “non-OAuth” and “role-mode session” wording
while preserving the surrounding credential-store and scope-check guidance.

---

Nitpick comments:
In `@portals/api-portal/it/rest-api/views-and-labels/views.spec.js`:
- Around line 63-67: Update the creates-a-view-with-an-empty-label-array test
around uniqueHandle and the POST request to fetch /views/${id} after confirming
creation, then assert the fetched response’s body.labels is an empty array,
matching the omitted-label persistence test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c30c0454-113e-4dee-90a7-548a1c8afd22

📥 Commits

Reviewing files that changed from the base of the PR and between 29f710c and b690361.

⛔ Files ignored due to path filters (2)
  • portals/api-portal/src/defaultContent/images/api-portal-logo-white.png is excluded by !**/*.png
  • portals/api-portal/src/defaultContent/images/api-portal-logo-white.svg is excluded by !**/*.svg
📒 Files selected for processing (54)
  • portals/api-portal/configs/config-template.toml
  • portals/api-portal/docs/api-portal-openapi-spec-v0.9.yaml
  • portals/api-portal/docs/consume-an-api/consume-with-oauth2.md
  • portals/api-portal/it/README.md
  • portals/api-portal/it/configs/portal-roles-role-mode-it.yaml
  • portals/api-portal/it/docker-compose.test.postgres.yaml
  • portals/api-portal/it/docker-compose.test.yaml
  • portals/api-portal/it/rest-api/ai-discovery/apis-md.spec.js
  • portals/api-portal/it/rest-api/auth/role-mode-authorization.spec.js
  • portals/api-portal/it/rest-api/organizations/single-org-isolation.spec.js
  • portals/api-portal/it/rest-api/support/fixtures.js
  • portals/api-portal/it/rest-api/views-and-labels/views.spec.js
  • portals/api-portal/it/test-config.toml
  • portals/api-portal/it/ui/cypress/e2e/001-basic/001-portal-access.cy.js
  • portals/api-portal/it/ui/cypress/e2e/002-apis/001-api-listing.cy.js
  • portals/api-portal/it/ui/cypress/e2e/002-apis/002-rest-api-details.cy.js
  • portals/api-portal/it/ui/cypress/e2e/003-mcp-servers/001-mcp-listing.cy.js
  • portals/api-portal/it/ui/cypress/e2e/applications/application-flows.cy.js
  • portals/api-portal/it/ui/cypress/e2e/settings/001-views-labels.cy.js
  • portals/api-portal/it/ui/cypress/e2e/settings/002-key-managers.cy.js
  • portals/api-portal/it/ui/cypress/support/commands/portal.js
  • portals/api-portal/it/ui/cypress/support/commands/seed.js
  • portals/api-portal/src/config/configDefaults.js
  • portals/api-portal/src/controllers/apiContentController.js
  • portals/api-portal/src/controllers/apiKeysOverviewController.js
  • portals/api-portal/src/controllers/apiWorkflowsController.js
  • portals/api-portal/src/controllers/applicationsContentController.js
  • portals/api-portal/src/controllers/customContentController.js
  • portals/api-portal/src/controllers/orgContentController.js
  • portals/api-portal/src/controllers/subscriptionsContentController.js
  • portals/api-portal/src/dao/organizationDao.js
  • portals/api-portal/src/defaultContent/pages/apis/partials/apis-md.hbs
  • portals/api-portal/src/defaultContent/pages/docs/page.hbs
  • portals/api-portal/src/defaultContent/pages/mcp-landing/page.hbs
  • portals/api-portal/src/defaultContent/pages/mcps/partials/mcps-md.hbs
  • portals/api-portal/src/middlewares/authMiddleware.js
  • portals/api-portal/src/middlewares/csrfProtection.js
  • portals/api-portal/src/middlewares/ensureAuthenticated.js
  • portals/api-portal/src/middlewares/registerPartials.js
  • portals/api-portal/src/pages/application/partials/manage-keys-km-card.hbs
  • portals/api-portal/src/pages/login-page/layout.hbs
  • portals/api-portal/src/pages/settings/partials/cfg-apis-panel.hbs
  • portals/api-portal/src/pages/settings/partials/cfg-labels-panel.hbs
  • portals/api-portal/src/pages/settings/partials/cfg-modals.hbs
  • portals/api-portal/src/pages/settings/partials/cfg-webhook-form.hbs
  • portals/api-portal/src/pages/settings/partials/cfg-webhooks-panel.hbs
  • portals/api-portal/src/scripts/oauth2-key-generation.js
  • portals/api-portal/src/scripts/settings-apis.js
  • portals/api-portal/src/scripts/settings-labels.js
  • portals/api-portal/src/scripts/settings-organization.js
  • portals/api-portal/src/scripts/settings-webhooks.js
  • portals/api-portal/src/services/apiMetadataService.js
  • portals/api-portal/src/styles/settings-layout.css
  • portals/api-portal/src/utils/util.js
💤 Files with no reviewable changes (3)
  • portals/api-portal/src/config/configDefaults.js
  • portals/api-portal/configs/config-template.toml
  • portals/api-portal/src/middlewares/ensureAuthenticated.js

Comment on lines +1139 to +1143
function sendMarkdownError(res, error, failureMessage) {
if (util.pageErrorStatus(error) === 404) {
return res.status(404).send('# Not Found\n\nThe requested resource does not exist.');
}
return res.status(500).send(`# Error\n\n${failureMessage}`);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 3 \
  'function sendMarkdownError|sendMarkdownError\(|Content-Type.*text/(markdown|plain)' \
  portals/api-portal

Repository: wso2/api-platform

Length of output: 10952


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf 'Relevant helper and callers:\n'
sed -n '1128,1148p;1250,1272p;1332,1348p;1356,1372p;1404,1427p;1448,1468p;1560,1580p' portals/api-portal/src/controllers/apiContentController.js

printf '\nResponse ContentType headers around sendMarkdownError call sites:\n'
python3 - <<'PY'
from pathlib import Path
p = Path('portals/api-portal/src/controllers/apiContentController.js')
lines = p.read_text().splitlines()
for name_start, name_end in [
    ('sendMarkdownError', 1148),
    ('apiContentDetailMarkdown', 1272),
    ('portalIndexMarkdown', 1348),
    ('portalIndexMarkdownPreview', 1372),
    ('apisMarkdown', 1428),
    ('mcpsMarkdown', 1469),
    ('documentMarkdown', 1580),
]:
    print(f'-- {name_start} --')
    for i in range(name_start, name_end + 1):
        if 'setHeader' in lines[i-1] or 'sendMarkdownError' in lines[i-1] or 'Content-Type' in lines[i-1]:
            print(f'{i}: {lines[i-1]}')
PY

printf '\nCheck if a Content-Type has already been sent before sendMarkdownError in each block by simulating Express response setHeader semantics across line range:\n'
python3 - <<'PY'
from pathlib import Path
p = Path('portals/api-portal/src/controllers/apiContentController.js')
lines = p.read_text().splitlines()
callers = [
    ('apiContentDetailMarkdown', 1250, 1270),
    ('portalIndexMarkdown', 1334, 1346),
    ('portalIndexMarkdownPreview', 1358, 1370),
    ('apisMarkdown', 1410, 1426),
    ('mcpsMarkdown', 1450, 1466),
    ('documentMarkdown', 1564, 1578),
]
for name, start, end in callers:
    header_set_before_error = any(i < end and 'Content-Type' in (lines[i-1] if i <= len(lines) else '') for i in range(start, end + 1))
    calls = [i for i in range(start, end + 1) if 'sendMarkdownError' in lines[i-1]]
    print(f'{name}: header_set_before_error={header_set_before_error}, calls={calls}')
PY

Repository: wso2/api-platform

Length of output: 6311


🌐 Web query:

Express.js response.send string default Content-Type text/html

💡 Result:

In Express.js, when you pass a string to the res.send method, the framework automatically sets the Content-Type response header to text/html [1][2][3]. Furthermore, Express also appends a charset parameter of utf-8 to this header, resulting in a final Content-Type value of text/html; charset=utf-8 [4]. This behavior is designed to ensure proper character encoding handling, as Express defaults to UTF-8 for string responses [5]. If you wish to override this default, you can explicitly set the Content-Type header using methods like res.set or res.type before calling res.send [1][2]. For example: res.set('Content-Type', 'text/plain'); res.send('Your string here'); If you need to send a response without Express automatically setting or modifying the Content-Type or charset, you can bypass the convenience logic of res.send by using the lower-level res.write and res.end methods instead [6].

Citations:


Set the response media type in sendMarkdownError.

sendMarkdownError returns markdown/plain bodies through res.send, and Express defaults string bodies to text/html; charset=utf-8. Use the caller’s success media type in error responses, either by passing the media type into this helper or by setting the header before each call.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/api-portal/src/controllers/apiContentController.js` around lines 1139
- 1143, Update sendMarkdownError to set the response Content-Type to the
caller’s success media type before sending either the 404 or 500 markdown body,
passing that media type into the helper if necessary and updating its callers
accordingly.

filePath: req.params.filePath,
});
error.status = 500;
error.status = pageErrorStatus(error);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Set 404 status on locally generated missing-page errors.

At Lines 79 and 81, the controller throws plain Error objects when the page file is missing. pageErrorStatus(error) only preserves error.statusCode or error.status, so these requests still return HTTP 500 instead of HTTP 404.

Set status: 404 on both errors before calling next(error).

Proposed fix
-                    throw new Error(`Manage keys page not found. This route should be handled by the application controller.`);
+                    throw Object.assign(new Error(`Manage keys page not found. This route should be handled by the application controller.`), { status: 404 });
...
-                throw new Error(`Content page not found at ${resolvedPagePath}`);
+                throw Object.assign(new Error(`Content page not found at ${resolvedPagePath}`), { status: 404 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/api-portal/src/controllers/customContentController.js` at line 105,
Update the locally generated missing-page errors in the controller to include a
404 status before they are passed to next(error), ensuring
pageErrorStatus(error) maps both missing-file branches to HTTP 404 instead of
500.

Comment on lines +65 to +74
{{!-- Remove-keys footer — part of Credentials tab --}}
<div class="mk-km-footer" id="keyActionsContainer-{{keyType}}">
<span class="mk-secret-note">
<i class="bi bi-info-circle"></i>
Revoking removes all credentials. Tokens already issued remain valid until they expire.
Removing deletes all credentials. Tokens already issued remain valid until they expire.
</span>
<div class="mk-footer-actions">
<button class="mk-btn-danger"
onclick="confirmAndRevokeKeys('{{appId}}', '{{keys.keyMappingId}}', '{{keyType}}')">
<i class="bi bi-trash3"></i> Revoke keys
onclick="confirmAndRemoveKeys('{{appId}}', '{{keys.keyMappingId}}', '{{keyType}}')">
<i class="bi bi-trash3"></i> Remove keys

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 12 \
  'oauth-keys|removeApplicationKeys|Remove Application Keys|remove this client ID' .

Repository: wso2/api-platform

Length of output: 31522


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Locate and inspect the relevant implementation and route handling without running repository code.
printf 'Files:\n'
git ls-files | rg 'appDao|oauthKey|oauth-key|application-keys|apiPortalController|consume-with-oauth2' || true

printf '\nRelevant implementations:\n'
for f in $(git ls-files | rg 'appDao|oauthKey|oauth-key|application-keys|apiPortalController' | head -20); do
  echo '--- $f ---'
  wc -l "$f"
  rg -n -C 8 'deleteOAuth|revokeOAuth|removeOAuth|OAuth|oauth-keys|keyMappingId|client_id|local|external|token|credentials' "$f" || true
done

printf '\nRoute/server registration references:\n'
rg -n -C 5 'oauth-keys|/applications/.*/oauth-keys|revokeOAuthKeys|appDao|removeApplicationKeys' .

Repository: wso2/api-platform

Length of output: 50375


Align the removal message with the route contract.

DELETE /applications/{applicationId}/oauth-keys/{keyMappingId} removes the portal’s local OAuth client_id mapping and returns Application key mapping removed successfully; it does not delete the external OAuth client or revoke already-issued tokens. Update portals/api-portal/src/pages/application/partials/manage-keys-km-card.hbs:69, portals/api-portal/src/scripts/warning.js:108, portals/api-portal/src/scripts/oauth2-key-generation.js:66, and related docs so the UI does not say credentials are revoked or deleted.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/api-portal/src/pages/application/partials/manage-keys-km-card.hbs`
around lines 65 - 74, Update the removal messaging in the manage-keys footer and
the related confirmation flows in confirmAndRemoveKeys and
oauth2-key-generation.js to accurately describe the DELETE route: it removes
only the portal’s local OAuth client_id mapping, while external OAuth clients
and already-issued tokens remain active. Remove wording that claims credentials
are deleted or tokens are revoked, and synchronize any related documentation
with this behavior.

Comment on lines +612 to +615
.cfg-form-input[readonly]:focus {
border-color: var(--border-strong);
box-shadow: none;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep a visible focus indicator for read-only inputs.

Read-only inputs remain keyboard-focusable. Lines 612-615 remove the border and shadow supplied by the normal focus rule, while the base input style also removes the browser outline. A keyboard user can tab to a handle without a visible focus state. Preserve a focus outline or add a distinct focus style.

Proposed focus style
 .cfg-form-input[readonly]:focus {
-  border-color: var(--border-strong);
-  box-shadow: none;
+  border-color: var(--primary);
+  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.cfg-form-input[readonly]:focus {
border-color: var(--border-strong);
box-shadow: none;
}
.cfg-form-input[readonly]:focus {
border-color: var(--primary);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/api-portal/src/styles/settings-layout.css` around lines 612 - 615,
Update the .cfg-form-input[readonly]:focus rule to retain a clearly visible
keyboard-focus indicator instead of removing all focus styling. Add or preserve
a distinct outline, border, or shadow that contrasts with the base read-only
input appearance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant