* Allow empty LDAP Application DN value and password in General settings form
* fix(ui): use LDAP app_dn, app_dn_password with empty string instead of enforcing non-empty values
* feat: add LOG_FORMAT env var with JSON formatter for early logging
Introduce LOG_FORMAT environment variable (set to "json" to enable).
When active, logging.basicConfig() uses a JSONFormatter that outputs
single-line JSON objects with fields: ts, level, msg, caller, error,
stacktrace. This covers all log messages emitted during module imports
before Loguru's start_logger() takes over.
* feat: add JSON sink for Loguru when LOG_FORMAT=json
Add _json_sink() as a Loguru sink function that writes single-line JSON
to stdout. In start_logger(), conditionally use the JSON sink instead of
the plain-text stdout_format when LOG_FORMAT is set to "json".
* feat: suppress ASCII banner and fix alembic logging in JSON mode
- Wrap the ASCII art banner print in main.py with a LOG_FORMAT != "json"
guard so JSON output stays machine-parseable.
- Skip alembic's fileConfig() call in migrations/env.py when
LOG_FORMAT=json to prevent it from replacing the JSON log handlers
installed during early startup.
* fix(ui): remove select-none from move and pdf menu items to allow highlighting
* fix(ui): explicitly disable dragging and text selection inside dropdown menus globally
fix: model fallback routing for all model types and default model selection
Backend: When ENABLE_CUSTOM_MODEL_FALLBACK is active and a custom model's
base model is unavailable, the fallback now swaps the model and form data
to the configured default model directly. This ensures routing uses the
fallback model's type (pipe, Ollama, or OpenAI) instead of the original
model's type, which previously caused "Model not found" errors when the
fallback was a different backend type.
Frontend: Fixed default model selection in new chat initialization where
the admin-configured default models were always overwritten by the first
available model. The first-available fallback now only triggers when the
configured defaults don't resolve to valid available models.
This commit adds aria-labels to the text inputs and textareas that previously lacked them, applies role=switch to inputs, and adds accessible titles to floating quick actions.
This commit adds aria-labels to the search inputs, select fields, action buttons, and close buttons on modals across the admin users layout and the site changelog modal for improved screen reader support.
fix: reset taskIds and messageQueue on new chat
Fixes a bug where clicking "New Chat" after sending a message would
silently drop subsequent messages. The initNewChat function reset most
chat state but did not clear taskIds or messageQueue, causing
submitPrompt to queue messages indefinitely instead of sending them.
Adds critical accessibility fixes across various app components:
- auth/+page: provide alt text for logo, turn on screenReader support for password input, add aria-required, hide decorative SVGs from AT
- AppSidebar: wrap navigation icons in a <nav> structure, provide ARIA labels for Home and Chat icons
- s/[id]/+page: convert structural divs into semantically accurate h1 heading and time element, wrap message display in main region
- OnBoarding: replace flawed aria-labelledby with direct aria-label on start button
- NotificationToast: provide role='status' and aria-live='polite' for proper screen reader broadcasting
- ChangelogModal: add required heading semantics for structure
- AddFilesPlaceholder: provide heading element role for standalone text content
- ImportModal: provide aria-label for close button
Addresses WCAG 4.1.3, 1.1.1, 3.3.2, and 1.3.1.
Add aria-hidden='true' to 112 SVG icon components in src/lib/components/icons/ that were missing this attribute. Decorative icons that convey no semantic meaning should be hidden from the accessibility tree to prevent screen readers from attempting to read meaningless SVG markup (WCAG 1.1.1 Non-text Content, WCAG 4.1.2 Name, Role, Value).
The remaining 60 icon files already had aria-hidden='true' set. All 172 icon components now consistently declare aria-hidden='true' on their root svg element.