Skip to content

feat(admin): operator notifications dashboard UI - #787

Open
Ferryx349 wants to merge 4 commits into
mainfrom
feat/admin-notifications-ui
Open

Ferryx349 wants to merge 4 commits into
mainfrom
feat/admin-notifications-ui

Conversation

@Ferryx349

Copy link
Copy Markdown
Collaborator

Description

This PR adds the Operator Notifications section to the admin dashboard, on top of the notifications API in #784.

  • New Notifications view: enable/disable, event toggles, retry/retention fields
  • Targets: add/remove HTTP (and type selector for discord/slack/telegram), masked secrets after save
  • Save configuration / Reload wired to GET / PATCH /admin/notifications
  • Test per target → POST /admin/notifications/test
  • Delivery history table → GET /admin/notifications/deliveries with status/event filters, refresh, and load more
    Stack: base branch feat/admin-notifications-api (feat(admin): add GET/PATCH /admin/notifications API #784), not main.

Related Issue

Closes:- #761

Motivation and Context

How Has This Been Tested?

  • Log in to /admin, open Notifications
  • Enable operator notifications, Add target → HTTP, paste https://webhook.site/<uuid> (no #!/view/...), Save configuration
  • Test → green success; webhook.site shows POST JSON
  • Refresh log → row appears (after feat(admin): add GET/PATCH /admin/notifications API #784 follow-ups for test/outbox logging, or after a real settings.changed delivery)
  • Reload → settings load with *** for webhook URL; save again without changing URL still works
  • Toggle an event, save → no red error banner

Screenshots (if appropriate):

Screenshot 2026-09-25 at 16 39 49

Video Demontration :- https://github.com/user-attachments/assets/0f82a097-ef14-409e-b954-b989ee974028

Types of changes

  • Non-functional change (docs, style, minor refactor)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my code changes.
  • I added a changeset, or this is docs-only and I added an empty changeset.
  • All new and existing tests passed.

Expose operator notification config with secret redaction, validated PATCH
updates, delivery log filters, and relay-named test messages. Closes #760.
Reject persisting redacted placeholders on new targets, add PATCH
controller coverage, reload settings in the maintenance worker, and
record test deliveries in the delivery log.
Add Notifications admin view for targets, event toggles, save/reload,
test delivery, and delivery history on top of the notifications API.
@changeset-bot

changeset-bot Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e1adfca

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
nostream Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@greptile-apps

greptile-apps Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 3/5

[High risk] Adds admin API and UI for operator notification configuration.

The PR should not merge until target creation works on supported HTTP dashboards and test results remain accurate when delivery logging fails.

Findings

  1. P1 Add target fails over HTTP ▶
  2. P1 Log failure masks successful delivery ▶
  3. P2 History stops at 200 entries ▶
  4. P2 Unsaved targets cannot be tested ▶
  5. P2 Target IDs break card markup ▶
Summary

Adds an operator-notifications admin view and GET/PATCH configuration API, with target testing, delivery-history filters, and test-delivery logging.

  • Notification settings are merged with existing configuration and returned with secrets redacted.
  • The dashboard adds target controls, event toggles, retry and retention fields, and delivery-history controls.
  • Review findings concern target creation on HTTP dashboards, test-result accuracy when logging fails, and limitations in the new UI.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  UI[Admin Notifications view] -->|GET / PATCH| API[Notifications settings API]
  API --> CFG[Settings file]
  API --> OUT[Notification outbox]
  UI -->|POST test with target ID| TEST[Test controller]
  TEST --> SEND[Target delivery]
  SEND --> LOG[Delivery log]
  UI -->|GET deliveries with filters and limit| LOGAPI[Delivery-history API]
  LOGAPI --> LOG
Loading

Reviews (1) · Last reviewed commit: "feat(admin): operator notifications dash..."

elements.success.classList.remove('d-none')
}

const defaultEvents = () => ({

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Add target fails over HTTP

If an operator opens the dashboard over HTTP from a non-localhost host, crypto.randomUUID() is unavailable outside a secure browser context. Clicking Add target then throws before creating a card, so the operator cannot configure a new target.

Comment on lines +110 to +124
try {
await deliverToTarget(target, envelope)
await this.deliveryLogRepository.append({
outboxId: null,
eventType,
targetId: target.id,
targetType: target.type,
status: NotificationDeliveryStatus.SUCCESS,
attemptNumber: 1,
errorSnippet: null,
})
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
logger.error('test delivery failed for %s: %s', maskTargetForLog(target), message)
await this.deliveryLogRepository.append({

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Log failure masks successful delivery

If the webhook succeeds but writing its delivery-log entry fails, the shared try block treats the log error as a delivery failure and tries to write a second log entry. The test endpoint then reports failure even though the notification arrived.

Comment on lines +414 to +416
elements.logMore?.addEventListener('click', () => {
logLimit = Math.min(logLimit + 25, 200)
void loadDeliveryLog(false)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 History stops at 200 entries

Load more stops increasing the limit at 200, and the API has no offset or cursor. Once there are more than 200 deliveries, operators cannot browse older entries through this table, even if those entries are still within the retention period.

Comment on lines +190 to +192
card.querySelector('[data-action="test-target"]')?.addEventListener('click', () => {
void testTarget(target.id, card)
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Unsaved targets cannot be tested

A new target immediately has a Test button, but the request sends only its ID and the endpoint looks up that ID in saved settings. Testing a newly added card therefore returns “Unknown notification target” instead of testing the details on the card. Disable Test until the target is saved, or support testing pending details.

Comment on lines +143 to +144
<label class="visually-hidden" for="target-type-${target.id}">Target type</label>
<select id="target-type-${target.id}" data-target-field="type" class="form-select form-select-sm console-input notifications-target-type">

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Target IDs break card markup

Saved target IDs need only be nonempty, but this card inserts them directly into HTML attributes. An ID containing a quote or markup can break labels and controls or add unwanted elements. The delivery table also inserts stored fields through innerHTML. Build these elements with DOM APIs and assign dynamic values as text or attributes.

@coveralls

Copy link
Copy Markdown
Collaborator

Coverage Status

coverage: 72.876% (+0.4%) from 72.459% — feat/admin-notifications-ui into main

This branch has not been deployed

No deployments
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.

2 participants