@username mentions: notification exists; rendered profile links missing in rendered bodies #440
Labels
No labels
actions
bug
cli
duplicate
enhancement
fork
forum
git storage
help wanted
insights
invalid
issues
moderation
oidc
ownership transfer
packages
pr/merge protection rules
projects
pull requests
question
releases
sponsorships
tags
webhooks
wiki
wontfix
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
crueber/walhub#440
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
@username mentions: server-side notification + rendered profile links
What's requested
Two linked behaviors for
@namementions in recorded issue comments/PR bodies (and review/thread comments), per the user's ask:@usernamein a recorded comment body or PR body triggers a server-side notification — the recipient's bell tray shows amentionedmessage with a deep link to the thread.@usernamein the thread body links to that user's profile page — everywhere prescribed (issue comments, PR bodies, review comments), valid handles only, with conservative boundaries (no matches inside code spans/fences, emails, or@@/a@btoken-adjacent forms).Evidence — part 1 (notification) EXISTS and is correct
internal/identity/mentions.go—identity.ParseMentions, the 06 §3 grammar: code-strip, word-boundary regex, 50-token cap, dedupe/sort.internal/issues/service.go:1174(emitMentioned, called from open/comment)internal/pulls/service.go:1020(PR opened body + comments)internal/review/review.go:316(submitted reviews + thread comments)internal/notify/emit.go—validPrincipalprofile probe (users/<p>/profile.json, 404 = dropped), team expansion capped at 100, silent drop of invalid mentions.web/src/pages/Notifications.jsx—reasonChiphot-stylesmentioned/team_mention;threadHrefdeep-links to/{repo}/issues/{num}or/{repo}/pull/{num}; SSE live-prepend + unread badge.Verified by execution: a throwaway probe test against the live tree returned
users=[bob@example.com] teams=[acme/backend]for a mixed body — parse and emit machinery is green.Evidence — part 2 (rendered profile links) DOES NOT EXIST
web/src/lib/render-md.jsis the single markdown pipeline (marked → DOMPurify). It implements issue/PR ref autolinks (#N, issue #340) but has zero mention handling —grep -i mention web/src/lib/render-md.jsis empty.web/src/pages/Mentions.jsx,CommentComposer.jsx); nothing links a rendered@nametoken to a profile.docs/features/06_notifications.md§3/§7 mandates parse/fan-out but never specifies rendered mention links;08_ui_sdk.mddoesn't either. This ticket is the spec amendment as well as the implementation.Architecture notes
ValidPrincipal,internal/identity/identity.go:136): usernames are the identity key since Forgejo #370; emails remain valid legacy spellings. The client-side rendered-link parser must match the same grammar — best shape is mirroringmentionTokininternal/identity/mentions.goas a pure, headless-testable function inweb/src/lib/(repo convention:render-md.jsnode-testable layers; the#Nautolink layer at line ~170 is the exact pattern to copy).render-md.js's marked→resolve layer (the ref-autolink stage): rewrite matched@tokentext to<a href="/{principal}">(profile page is route/:owner,web/src/index.jsx:86). Usernames are unambiguous; email-shaped tokens also link to/{principal}since/:ownerresolves both spellings (matchPrincipal).@org/teamtokens should NOT be linked (teams live under/:org/settings/...//:owner/teams/:slug— out of scope here unless trivial; planner's call, note it).[^A-Za-z0-9_@-]or start), trailing-punctuation trim like the server's.,;:!?")]}strip.a + hrefrelative — already in the DOMPurify allowlist, no config change (same reasoning as ref autolinks,render-md.jsheader).Acceptance criteria
web/src/lib/render-md.jsgains a mention-autolink pass beside the#Nref-autolink pass, mirroringidentity.ParseMentionsboundaries (code spans/fences/links skipped, same left-boundary + trailing-punct rules)@username(and legacy email principals) link to/{principal}in issue threads, PR threads, and review bodies (all consumers ofrenderBody)node --testheadless tests (valid/invalid handles, code-span skip, email vs username,@@,a@b.com, boundary cases) — table mirrorsinternal/identity/mentions_test.godocs/features/06_notifications.md§7 (and08_ui_sdk.mdrenderer row) gain the rendered-mention-link contractmentioned/team_mentionwith tray deep links (verified in evidence above)#Nbehavior byte-identical (existing tests stay green)User-requirement pin (from the filing request — verify all three are covered by this ticket's acceptance criteria)
@usernamein a recorded issue comment or PR body notifies that user — confirmed already implemented server-side (ParseMentions → notify emit); this ticket's job is to NOT regress it while adding rendering.@usernamelinks to/:usernamein rendered comments AND PR bodies — this is the core gap this ticket fixes.Also confirm the flagged decision points are answered or explicitly left to the planner: edit re-evaluation of mentions, self-mention behavior.
Fix ready for review: #443 (#443) — renderer + spec only, no server changes. linkifyMentions beside the ref pass (@user/@email → /{principal}; @org/team unlinked; decision (a)); 18/18 new tests green, refs byte-identical, vite build green. The 2 smoke.test.js failures are live-server probes failing identically on pristine main (left untouched).
Review: PR #443 (fix/issue-440) — @mention profile links
Verified in scratch worktree at
8b13c66(node_modules symlinked, worktree removed after; main worktree untouched, still clean). No browser used — node tests + reasoning only, per instructions.Test results
node --test web/test/unit/mentions-autolink.test.js: 18/18 passvite build: succeeds (2.24s)@@x,a@b.com,x@bob,@bob@x,@.bob,@..stay plain;@bob./(@bob),trim punct outside link; fences/code/existing-links/URLs skipped; barejane@example.comkeeps mailto with no profile link;@Amy@Example.COMfolds the marked mailto shape into/{principal};@BOB-> href/bob, displayBOB.The 10 checks
[^A-Za-z0-9_@-]/^, non-consuming = strictly better), trailing-punct set identical (.,;:!?"')]}}), skip set reuses the sameSKIP_RE(a/code/pre/script/style, render-md.js:225),validMentionUsernameis byte-for-byteauth.ValidUsernamesemantics (1..64, no leading dot, not.., post-lowercase charset).@org/team(next==="/") and@bob@x(next==="@"`) correctly stay plain.matchPrincipal(identity/users.go:101, case-insensitive both spellings)."<>and is escAttr'd; display text charset excludes<> &"', so no breakout (probed@bob"><img...>->href="/bob", payload stays inert text pre-sanitizer).One follow-up (NOT a blocker, do NOT fix in this branch)
Pre-existing server gap, predates this PR:
mentionTok(identity/mentions.go) matches only email-shaped ororg/teamtokens — a bare@bobnever parses server-side, so it renders as a link (correct per this ticket) but emits no notification. The issue's notify evidence only probed the email spelling (bob@example.com), and doc 06 §3 says@<principal>(which per ValidPrincipal includes bare usernames). So doc §3 > server impl. Fixing it means extendingmentionTok+ cap-counting semantics + Go tests — a scoped server change that violates this ticket's 'No server changes' rule. Recommend merging this PR as-is and filing a server-side follow-up (extendmentionTokbare-username alternative or narrow §3 to email+team).No pushes made — nothing in the branch needed fixing.
MERGE RECOMMENDATION: ready to merge.
Fixed by PR #443 (review clean — all 10 checks pass, mirror exact, #N byte-identical; bare-@username notify gap filed as #444), merged. Closing.