Security-review follow-ups on the OIDC flows.
IPv6 loopback redirect_uri in dynamic client registration (RFC 8252):
- valid_redirect_uri? compared URI#host, which returns the bracketed "[::1]"
for IPv6 literals, so http://[::1]:PORT/... was always rejected. Compare
#hostname (unbracketed) instead, unblocking IPv6-only native clients.
Extract redirect_authorize_error (removes 12 copies of the boilerplate):
- The authorize/consent flows built the error redirect by hand ~a dozen times
(error_uri = "...?error=..."; += "&error_description=#{CGI.escape ...}"; +=
state; redirect_to). One helper now composes the query, and — unlike every
copy — appends "&error=..." when the redirect_uri already has a query string
instead of a malformed second "?".
Extract token-endpoint helpers (removes ~80 duplicated lines):
- authenticate_token_client: the identical client-auth preamble shared by the
authorization-code, refresh, and device-code grants.
- render_token_triple: the access + refresh + id_token mint and RFC 6749 §5.1
response shared by the authorization-code and device-code grants.
Single source of truth for scope descriptions:
- New OidcHelper#scope_description + shared shared/_scope_list partial, used by
both the browser consent screen and the device authorization screen; drops the
scope_labels hash and the hard-coded per-scope blocks that would have drifted.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Q4ATZHoMCWqvSpE2yYoie
Bumps dependencies (jwt 3.2.0, puma 8.0.2, net-imap 0.6.4.1 and others
via bundle update) to resolve bundler-audit advisories, and applies
standardrb autofixes so the lint job passes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The previous <picture media="(prefers-color-scheme: dark)"> only fires
when the OS is in dark mode. Clinch toggles dark mode with a class on
<html> via dark_mode_controller and Tailwind's @custom-variant dark
(&:where(.dark, .dark *)), so the picture source never swapped when
users clicked the in-app theme toggle. Render both <img> tags and
use Tailwind's dark:hidden / hidden dark:block so the swap follows
whatever strategy Tailwind is configured for.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When an application has no icon attached, render a deterministic
monogram SVG instead of the generic picture-frame placeholder. Initials
are picked from capital letters in the name (ShelfLife -> SL); fall
back to the first two letters when fewer than two capitals exist
(Audiobookshelf -> AU). Background colour is hashed from the name for
stable per-app identity across visits.
Adds an optional second icon attachment, icon_dark, alongside the main
icon. When present, render a <picture> with a prefers-color-scheme:
dark source so the browser swaps automatically; when absent, the main
icon is used in both modes. The SVG sanitization, content-type fix,
and size/format validation now run over both attachments uniformly.
Bumps to 0.14.0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously the copy-pasteable env-var block only appeared right after
creating an app or regenerating credentials. Operators had no easy way
back to it, so they had to reconstruct OIDC_DISCOVERY_URL etc. from
memory.
Adds a collapsed <details> disclosure inside the OIDC Configuration
card with the same env vars (placeholder for the secret, which can't
be re-shown). Extracts the env-line construction into an
oidc_env_lines helper so the flash panel and the persistent display
share one source of truth.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Uses Tailwind v4 class-based dark mode with a Stimulus controller for
toggling. Respects prefers-color-scheme as default, prevents FOUC with
an inline script, and persists the user's choice in localStorage. All
views updated with dark: variants for backgrounds, text, borders,
badges, buttons, and form inputs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Switch from SolidQueue to async job processor for simpler background job handling
- Remove SolidQueue gem and related configuration files
- Add letter_opener gem for development email preview
- Fix invitation email template issues (invitation_login_token method and route helper)
- Configure SMTP settings via environment variables in application.rb
- Add email delivery configuration banner on admin users page
- Improve admin users page with inline action buttons and SMTP configuration warnings
- Update development and production environments to use async processor
- Add helper methods to detect SMTP configuration and filter out localhost settings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>