Cumulative release covering all work since v1.8.10. New features, major architectural improvements, and a security posture upgrade from B+ to A+.
New features
- Full Revamp UI on
/achievements— magazine hero, conic donut, asymmetric stats grid, chapter tabs, control-panel filter strip, ambient orb + film grain - Friends drawer Revamp — follows the same Classic/Revamp toggle as the achievements page
- "Offline — last watched X" — offline friends now mirror the online "Watching X" treatment
HideLastWatchedprivacy preference — opt out of the last-watched echo- HMAC-SHA256 webhook signing — outbound POSTs now include
X-AchievementBadges-SignatureandX-AchievementBadges-Timestampheaders when admin setsWebhookSigningSecret. Same envelope as Stripe / GitHub.
Backend efficiency
AchievementBadgeService.Save()andMessagingService.Save()debounced 1.5s — coalesces back-to-back writes from playback/messaging hot paths into one disk flushFriendsServiceLastWatchedlookups cached 90s with play-event invalidation (eliminates per-friend 50-item DB query on every friends-list call)AuditLogService.LogusesRemoveRangefor in-place FIFO trim;GetRecentdoes an O(limit) tail walk instead ofOrderByDescendingWriteIndenteddisabled on production stores (~50% smaller files)- Embedded resource cache in
client-scriptroute (no more re-streaming CSS/JS/JSON/PNG/MP3/SVG from the assembly on every request) Cache-Control: public, max-age=86400, immutableon assets, with version-only cache busting (browsers actually cache between page loads now)SidebarInjectionMiddlewaremarker fast-path (last-4KB scan) + injection log dropped from INF to Debug- Sidebar showcase poller backs off from 5s to 30s steady state after page settled
Security A+
- Default class-level rate limit (
user-60-per-min) on every controller route, with stricter overrides preserved on cooldown routes AdminAuditLogFilterwrites an entry on everyRequiresElevationaction- CSP,
X-Content-Type-Options,X-Frame-Options,Referrer-Policy,Permissions-Policyon the anonymous profile-card endpoint - New
Jellyfin.Plugin.AchievementBadges.Testsproject — 34 xUnit security regression tests coveringWebhookUrlValidatorandSvgSanitizer(SSRF, IPv6 SSRF, scheme rejection, malformed URL rejection, dangerous SVG element rejection, on-event-handler rejection, external DTD rejection, oversized payload rejection, external<use href>rejection) - GitHub Actions workflow
.github/workflows/security.ymlruns the tests +dotnet list package --vulnerable+gitleakson every push, PR, and weekly cron SECURITY.mdexpanded with full threat model, trust boundaries, defences-in-place inventory, continuous verification matrix, and disclosure SLA- Three medium-severity audit findings fixed:
GetActivityFeed+GetMessageThread+GetConvMessagesclamppage/limitto safe bounds;WebhookUrlValidatornow fails closed on DNS errors instead of allowing through
Verification
- 34/34 security regression tests pass
- Plugin starts clean on the live host with v1.9.0;