Conversation
Fixes target#3549 Adds free-form, user-authored comments to alerts, recording who said what and when. Any signed-in user may comment on any alert. Comments capture triage context that does not belong in the system-generated event log: what someone tried, what they found, who they handed it to. The event log stays a record of what GoAlert did. Cleanup is handled by the database rather than by another job. Alert cleanup is a plain `DELETE FROM alerts`, so a foreign key with ON DELETE CASCADE removes an alert's comments along with it. This is deliberately unlike alert_logs, which has no foreign key to alerts and therefore needs its own separate cleanup pass to avoid orphans. TestAlertCommentsCleanupCascade runs the real cleanup job and then asserts against the alert_comments table directly, since after the alert is gone the comments are unreachable through the API either way. The author FK is ON DELETE SET NULL rather than CASCADE: deleting a user must not erase the comment history on an alert. The text and timestamp survive and only the attribution is lost, which the UI renders as "Deleted user". Bodies render through the existing Markdown component, the same one alert details use, so links are clickable and formatting works without adding a dependency. That does not weaken sanitization: React escapes interpolated text, the component never enables rehype-raw so raw HTML is displayed rather than mounted, and its allowElement hook runs hrefs through safeURL. A Cypress case posts an <img onerror> payload and asserts no img element is created. Users may delete their own comments; admins may delete any. A delete that matches nothing reports "comment not found" rather than distinguishing missing from not-yours, so comment IDs cannot be probed. Tests: 5 smoke tests in test/smoke/alertcomments_test.go covering create/list, validation, delete permissions, cascade-on-cleanup and author-deletion retention, plus 5 Cypress cases. Signed-off-by: Jake Remitz <jremitz@simondata.com>
|
Very useful feature, hope we can have this in a near future :prey: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
make checkto catch common errors. Fixed any that came up.Description:
Adds free-form comments on alerts, recording who wrote what and when. Any signed-in user can comment on any alert.
The motivation is that triage context currently has nowhere to live. The alert log is a record of what GoAlert did — created, escalated, notified — so there is no place for a person to note what they tried, what they found, or who they handed it to. That context ends up in chat and is lost once the alert closes.
Comments are deliberately inert with respect to alerting: commenting requires no authorization beyond being a user, and never changes alert state, escalation, or notification routing.
Design notes
Cleanup is handled by a foreign key rather than a new job:
Alert cleanup is a plain
DELETE FROM alerts, so comments are removed along with their alert and cannot accumulate. This is deliberately unlikealert_logs, which has no foreign key toalertsand therefore needs its own separate cleanup pass to avoid orphans.The author FK is
ON DELETE SET NULLrather thanCASCADE, so deleting a user does not erase an alert's comment history — the text and timestamp survive, and only the attribution is lost (rendered as "Deleted user").Bodies render through the existing
Markdowncomponent, the same one alert details use, so links are clickable and formatting works without adding a dependency.Which issue(s) this PR fixes:
Fixes #3549
Out of Scope:
POSTDataAlert/POSTDataAlertStatus). Happy to add this if wanted — it seemed better raised separately, since that payload is a public contract and a comment does not currently trigger a status notification.Describe any introduced user-facing changes:
A "Comments" card on the alert details page, between the escalation policy and the event log. It lists existing comments — author, relative timestamp, body — and provides a box to add one. It carries the same "Full Timestamps" toggle as the event log, sharing that preference with it.
Comments are capped at 4096 characters, enforced both in Go and by a
CHECKconstraint.Describe any introduced API changes:
All additive.
Alert.commentsis batched through a dataloader to avoid an N+1 when listing alerts.New migration
20260728115032-add-alert-comments.sqlcreates thealert_commentstable. Noengine_processing_versionschange — no engine behavior is affected, so old and new nodes coexist during a rolling deploy. TheDownmigration drops only what it added.Additional Info:
Tests —
test/smoke/alertcomments_test.go(5 smoke tests):alert_commentstable directly via SQL, since once the alert is deleted the comments are unreachable through the API whether or not they were actually removedPlus 5 Cypress cases in
web/src/cypress/e2e/alerts.cy.tscovering add, markdown rendering, link rendering, the timestamp toggle, and empty-comment rejection.On sanitization: comment bodies are untrusted input, so to be explicit about why rendering Markdown is safe here — React escapes interpolated text, the
Markdowncomponent does not enablerehype-raw(so raw HTML is displayed rather than mounted), and itsallowElementhook runs hrefs throughsafeURL. One of the Cypress cases posts an<img onerror>payload and asserts noimgelement is created.Note on
make check:golangci-linthas nodarwin/arm64release asset, so I ran the pinned version (v2.12.2) in a container against this branch — 0 issues.make check-jspasses. Three pre-existing Jest failures inweb/src/app/utilandweb/src/app/schedulesare locale-formatting assertions in files this branch does not touch.