Releases: edbfi/obzorarr
Release list
v0.1.11
What's New
- Build version in sidebars — The dashboard and admin sidebars now display the running build version so you can confirm which release is deployed. (#76)
- Same-tab Plex OAuth redirect mode — Optional flow that keeps Plex sign-in in the current tab instead of a popup. Friendlier for password managers and automation. (#60)
Bug Fixes
Sign-in & sessions
- Logging out no longer 500s when you hit the URL directly; you're reliably redirected to the landing page from both admin and user areas.
- Plex PIN polling is no longer caught by the strict auth rate limiter, so sign-in completes cleanly on slow networks.
- Periodic re-check against Plex so revoked server access logs the user out promptly. (#49)
- Session re-checks are suspended during first-run onboarding to avoid spurious logouts.
Wrapped slideshow
- Fixed a race that could leave the slideshow on a blank slide after rapid navigation.
- The "Close" button on the wrapped page no longer strands you on about:blank; it falls back to the home page when there's no history to return to.
- Progress bar now uses your active theme color instead of always rendering red.
- Durations no longer show "9h 60m" — values roll over correctly to the next hour.
- Personal wrapped headings now say "Your Content Mix" instead of "YOU'S Content Mix".
- Tapping the very first pixel of the left edge now reliably goes to the previous slide instead of skipping forward.
- Your position in the slideshow is preserved in the URL (#slide=N) so refresh or back-forward keeps your place.
- Reduced-motion preferences are respected when animating progress.
- A personal wrapped page with no history now shows a clear empty state instead of misleading fun facts.
- Marathon-day stats are capped at 24 hours so duplicated history records can't produce impossible totals.
- Keyboard navigation on the final summary slide no longer accidentally activates buttons when mashing arrow keys.
Sharing & privacy
- When the server rejects a privacy setting (e.g. below the admin-enforced floor), the radio now snaps back visually and a toast explains why — no more silent resets.
- Privacy modes below the admin's floor render as visibly disabled with an inline explanation instead of looking available.
- Invalid or expired share links now show a message that actually explains expiry/invalidation instead of a bare "not found".
- Share modal is flicker-free and properly announces the selected option to screen readers.
- Private-OAuth denial pages now tell the viewer they need to sign in to Plex and be a member of this server.
Admin
- "Delete All History" and "Clear Cache" now surface a toast if the preflight check fails, instead of appearing to do nothing.
- "Clear All" on the Logs page now refreshes the table immediately — no reload required.
- Date-range filters and active filter pills on logs are now reactive, and streaming log entries honour the active filters.
- "Export JSON" on the logs page actually downloads a file now.
- Added the missing "Slides" link to the admin sidebar and a proper empty state on year selectors when no history exists.
- Cron schedule input validates as you type and blocks save on invalid expressions.
- "Next sync" no longer shows a stale time when the scheduler is paused.
- OpenAI API key can now be cleared from settings; empty save deletes the stored value.
- Custom slides render Markdown as HTML (previously shown raw) and the delete confirmation now includes the slide's title in an inline prompt instead of a native dialog.
- Toggling "Can control" on a user now respects the configured global default share mode rather than hardcoding public.
- Destructive actions (Clear All Logs, bulk user-control apply) use a consistent confirm dialog.
- Active admin tab is written to the URL so Settings pages are bookmarkable.
- Users table and logs actions have proper mobile styles.
Onboarding
- Fixed CSRF token handling that could block the onboarding footer form and stall navigation between steps. (#65, #66, #67)
- Added a Cancel button on the sync step so you can back out of a long import.
- The AI fun-facts step now accepts an OpenAI API key, base URL, model, and persona with a Test Connection button that verifies credentials before saving; admin settings mirror the same Test Connection, with an SSRF safeguard that refuses to forward the stored key to a different base URL. AI features default to off — you opt in explicitly. (#77)
- Hidden submit buttons use an accessible sr-only pattern instead of off-screen positioning.
Plex integration
- Servers identified by hostname URL are now matched using /identity machine identifier. (#74)
- Plex friend payloads with null fields no longer crash account sync; plain-host server URLs are recognised. (#73)
Errors & rate limiting
- New friendly error pages for 404 / 403 / 429 / 5xx.
- 429 responses now include a Retry-After header.
- Username lookup rejects whitespace-only input.
Security
- Plex auth tokens and OpenAI API keys are no longer embedded in the page load payload sent to the browser. Logins complete server-side; secrets stay on the server.
- CSP is tailored to the app (allows Plex thumbnails via plex.tv / *.plex.direct and Google Fonts; denies frame-ancestors).
- Early 403 / 404 responses from CSRF and request-filter handlers now carry the same security headers as normal responses, and use the same request-filter matchers in dev and production.
Maintenance
- Refactored the code-quality workflow into tiered jobs for faster CI. (#64)
- Thumbnail proxy now forwards ETag / Last-Modified and handles If-None-Match / If-Modified-Since for proper 304 caching.
- Cleaned up verification checks and test isolation. (#62)
- Updated Vite to v8, TypeScript to v6, Biome to 2.4.12, marked to v18, @lucide/svelte to v1, plus smaller bumps and config migrations.
Full changelog: 0.1.10...0.1.11
v0.1.10
Bug Fixes
- Prevent PRIVATE_LINK token leak in landing page lookup (#44)
- The
lookupUseraction previously retrieved or generated the secret share token and redirected unauthenticated visitors directly to the token URL, defeating PRIVATE_LINK mode by exposing the token to anyone who knew a username - Access control is now fully delegated to the wrapped page's
checkWrappedAccess, which correctly denies access when no token is present in the URL
- The
Full Changelog: 0.1.9...0.1.10
v0.1.9
Bug Fixes
- Onboarding security hardening (#42)
- Added admin authentication guard to the
/onboarding/completeendpoint, preventing unauthenticated or non-admin users from completing onboarding - Added step-ordering enforcement to prevent users from skipping ahead by navigating directly to later step URLs
- Added admin authentication guard to the
Dependency Updates
- Updated
@biomejs/biometo v2.4.4 - Updated
@lucide/svelteto ^0.575.0 - Updated
cronerto v10 - Updated
rollup-plugin-visualizerto v7 - Updated
@j178/prekto ^0.3.0
Other Changes
- Automated biome config migration for Renovate PRs
- Fixed Renovate auto-rebase after GitHub Actions bot commits
Full Changelog: 0.1.8...0.1.9
v0.1.8
v0.1.7
Bug Fix
Fixed username lookup redirect for private-link share mode
Resolved an issue where users entering their Plex username on the landing page would receive a 404 error when the share mode was set to private-link.
Problem: The username lookup feature was redirecting all users to the standard user ID URL format (/wrapped/{year}/u/{userId}), which requires either authentication or public sharing mode. This caused lookups to fail for users with private-link mode enabled, as that mode requires a token-based URL.
Solution: The landing page now checks the effective share mode after resolving a username and redirects to the appropriate URL:
- For
private-linkmode: redirects to the token-based URL - For other modes: redirects to the standard user ID URL
v0.1.6
Security Enhancements
-
CSRF protection middleware (#13)
- Added comprehensive CSRF protection for form submissions
- Validates Origin and Host headers for state-changing requests
-
CSRF configuration step in onboarding (#20)
- New setup step guides users through CSRF domain configuration
-
CSRF warning banner for unconfigured users (#21)
- Warning banner displayed in admin panel when CSRF protection is not configured
New Features
-
Environment variable precedence for settings (#14)
- Settings can now be configured via environment variables
- Environment values take precedence over database-stored settings
-
Upgraded default AI model to gpt-5-mini for improved fun facts generation
-
Pre-commit hooks with prek (#15)
- Added automated code quality checks before commits
- CI workflow validates hook configuration (#17)
Bug Fixes
-
Toggle switch visibility improvements (#25)
- Enhanced contrast and theme button alignment in UI
-
Admin logs page stability (#19)
- Added defensive checks for filter handling
-
Year navigation edge case
- Fixed undefined array access when navigating between years
Performance
- Optimized startup performance (#16)
- Settings conflict cleanup now runs once at startup instead of per-request
Other Changes
- Streamlined Plex settings form (#18)
- Expanded test coverage across settings, funfacts, and core modules (#22, #23, #24)
- Documentation updates and corrections
Full Changelog: 0.1.5...0.1.6
v0.1.5
🎆 Happy New Year! Wishing everyone a wonderful 2026 filled with great movies, binge-worthy shows, and plenty of time to enjoy them!
New Features
- Year navigation for Wrapped presentations (#12)
- Switch between years with available viewing data via new navigation controls
- Glass morphism styled controls in bottom-left corner
- Full keyboard accessibility (Enter/Space) with ARIA labels
- Supports reduced-motion preferences
Bug Fixes
- Safari popup blocker workaround (#11)
- Added redirect-based fallback when Plex OAuth popup is blocked
- Affects Safari on macOS and iOS where popups after async calls are blocked
- Modal offers redirect-based authentication as an alternative
- Works for both landing page login and onboarding flow
Full Changelog: 0.1.4...0.1.5
v0.1.4
Security
- Hardened application against common attack vectors (#10)
- Added request filtering to block vulnerability scanner probes (
.env,.git,wp-*,phpmyadmin, etc.) - Implemented global rate limiting with route-specific configurations (auth: 10/5min, API: 30/min, default: 60/min)
- Added security headers:
X-Frame-Options,HSTS,X-Content-Type-Options - Fixed cookie secure flag for production environments
- Removed GET logout endpoint to prevent CSRF attacks
- Sanitized error messages in onboarding endpoints
- Added request filtering to block vulnerability scanner probes (
Full Changelog: v0.1.3...v0.1.4
v0.1.3
Security Fixes
This release addresses two security vulnerabilities:
Authorization Bypass (High Severity)
- Fixed an authorization bypass in the user wrapped page (
/wrapped/[year]/u/[identifier]) that allowed unauthorized access when using numeric user IDs instead of share tokens - Unauthorized access now properly returns 403/404 responses
Stored XSS Prevention (Critical Severity)
- Added HTML sanitization for custom slide markdown content using
sanitize-html - All markdown output is now sanitized before rendering to prevent script injection
- Implemented strict allowlist for safe HTML tags, attributes, and URL schemes
- Added MIME type validation for data URIs in images
Dependency Updates
- Updated
unocssfrom 66.5.11 to 66.5.12 - Updated
svelte-adapter-bunfrom 1.0.0 to 1.0.1
Breaking Changes
- Custom slides will no longer allow arbitrary HTML; content is sanitized according to a strict allowlist of safe tags and attributes
v0.1.2
Bug Fixes
- Plex resource schema validation: Updated Plex API resource schema fields to allow nullable values. Fields such as
product,productVersion,platform,platformVersion,device,createdAt,lastSeenAt,provides, andpublicAddresscan now properly handle null responses from the Plex API, resolving validation errors that occurred with certain server configurations.

