Because these overrides were underspecified (ie didn't apply to third
party component css), and because the webgui currently doesn't use css
layering, exclusions have been made in the webgui's
default-base.css so they apply broadly, rendering these overrides incorrect and unnecessary.
…ownloaded as part of the upgrade
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved cleanup of temporary plugin configuration files during update
cancellation operations.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Add startup budget tracking to prevent silent hangs during API boot
- Add timeout wrappers around startup operations with graceful
degradation
- Add detailed logging for startup progress and failures
## Background
A user reported being unable to start their array on v7.2-beta.1 due to
the API failing to start. The root cause was a leftover
`dynamix.my.servers` folder from a previously uninstalled Connect
plugin. The API would hang during startup with no error messages, and
PM2 would eventually kill it after 15 seconds with no diagnostic
information.
**Original syslog:**
```
Aug 2 11:55:48 Vault root: Starting Unraid API service...
Aug 2 11:55:48 Vault root: Backup file not found at '/boot/config/plugins/dynamix.my.servers/node_modules-for-v4.12.0.tar.xz'. Skipping restore.
Aug 2 11:55:52 Vault root: Starting the Unraid API
[API never completes - PM2 times out waiting for 'ready' signal]
```
## Solution
### Startup Budget Tracking
Instead of fixed timeouts per operation (which could exceed PM2's
15-second limit in aggregate), we now track a total startup budget:
- **Total budget:** 13 seconds (2 seconds before PM2's 15-second kill
timeout)
- **Bootstrap reserve:** 8 seconds reserved for NestJS bootstrap
- **Per-operation max:** 2 seconds for pre-bootstrap operations
The `StartupBudget` class dynamically calculates timeouts based on
remaining time, ensuring we never exceed PM2's limit and always provide
clear timeout messages.
### Graceful Degradation
Non-critical operations now fail gracefully with warnings instead of
crashing:
- `loadStateFiles()` - continues with default state
- `loadRegistrationKey()` - continues without registration key
- `loadDynamixConfig()` - continues with default config
- `StateManager` - continues without file watching
- `setupRegistrationKeyWatch()` - continues without key watching
Critical operations still fail fast:
- Config directory creation
- NestJS server bootstrap
### Improved Logging
Each startup phase now logs its completion, making it easy to identify
where hangs occur:
```
Config directory ready
Emhttp state loaded
Registration key loaded
Dynamix config loaded
State manager initialized
Registration key watch active
Bootstrapping NestJS server (budget: 11234ms)...
Startup complete in 1766ms
```
## Test plan
- [x] Verify API starts normally with all startup logs visible
- [x] Verify startup completes within PM2's 15-second timeout
- [ ] Test with missing/corrupted config files to verify graceful
degradation
- [ ] Verify timeout messages appear before PM2 kills the process
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Fixed GraphQL registration state not updating when license keys are
installed/upgraded
- Root cause: /boot/config is on FAT32 which doesn't support inotify -
the file watcher was silently failing
## Changes
- Enable polling for key file watcher (required for FAT32 filesystem)
- Add retry logic to reload var.ini after key changes to handle emhttpd
update timing variation
## Test plan
- Unit tests for retry logic (will run in CI)
- Manual test on Unraid: install/upgrade license key, verify GraphQL
returns updated state within ~8 seconds
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Tests**
* Added a comprehensive test suite covering retry behavior, exponential
backoff timing, and various registration-change scenarios.
* **Refactor**
* Switched registration key monitoring to a polling-based watcher with
an exponential-backoff retry for config reloads; added event logging and
improved retry/stopping behavior to make state updates more reliable and
observable.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Enhanced remote access configuration handling to gracefully manage
missing or undefined parameter values.
* Improved overall system stability through safer default handling of
optional settings that may not be present.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Localization**
* Updated translations across 24 languages including Arabic, Bengali,
German, Spanish, French, Japanese, Korean, Portuguese, and Russian for
OS update eligibility messages, driver update status notifications, and
license/trial key expiration messaging to improve international user
experience.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Removed translation function calls from the UI components for reboot
type text, replacing them with direct references to the computed
properties.
- Enhanced ineligible update messages by integrating localization for
various conditions, ensuring clearer user feedback regarding update
eligibility.
- Added new localization strings for ineligible update scenarios in the
English locale file.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added new localization keys for OS update eligibility, reboot labels,
changelog link, and expanded uptime/trial expiry messages.
* **Bug Fixes**
* Restored translated strings and added locale-aware release date
formatting for update/ineligible messaging and badges.
* **Theme & UI**
* Streamlined theme initialization and server-driven theme application;
removed legacy CSS-variable persistence and adjusted dark/banner
behavior.
* **Tests**
* Added i18n and date/locale formatting tests and improved
local-storage-like test mocks.
* **Chores**
* Removed an auto-registered global component and strengthened
script/theme initialization and CSS-variable validation.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- rely on the existing Pinia persisted state instead of manual
localStorage hydration
- reapply CSS variables after persisted hydration so custom header
colors show immediately
## Testing
- Not run (not requested)
------
[Codex
Task](https://chatgpt.com/codex/tasks/task_e_691e5a1d052c8323973847eb5833fbb9)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Plugin configuration now lives in a single API configuration object
for consistent handling.
* Connection plugin wiring simplified so the connect plugin is always
provided without runtime fallbacks.
* **Chores**
* Startup now automatically removes stale connect-plugin entries from
saved config when the plugin is absent, improving startup reliability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- remove the REST API log download helper and associated service wiring
- drop the Download API Logs UI component and related registrations and
test references
- update tests and type declarations to reflect the removal
## Testing
- Not run (not requested)
------
[Codex
Task](https://chatgpt.com/codex/tasks/task_e_691ce360f8f88323888ad6ef49f32b45)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Removed Features**
* Removed the API logs download feature — the UI download component and
the corresponding public API endpoint are no longer available.
* **Chores**
* Cleaned up related tests, component registrations, and unused
integration/dependency wiring tied to the removed logs feature.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Changed theme class names from `.theme-*` to `.Theme--*` for consistency.
- Updated scoping logic to prevent scoping of `.Theme--` classes, ensuring they remain global.
- Enhanced theme store logic to check for existing `.Theme--` classes before applying new theme classes, preventing conflicts.
- Adjusted class cleaning logic to retain `.Theme--` classes when necessary.
Hopefully fixes release please over-scoping its changelog generation
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated CI/CD workflow configuration to enable full repository history
retrieval during build processes, improving the reliability of version
control operations in automated deployments.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Expanded localization support with comprehensive validation error
messages across 22 languages including Arabic, Chinese, French, German,
Hindi, Japanese, Portuguese, Russian, Spanish, and others.
* Enhanced form validation messaging for API key management, OIDC
provider configuration, SSO setup, and related settings to provide
localized guidance for users fixing errors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Style**
* Enhanced header banner styling: centered, non-repeating cover images
with layered gradient overlays and adjusted user-profile banner
positioning for improved layout.
* **Bug Fixes**
* Banner display logic updated so "image" is treated like "yes" for
showing banner images.
* **Tests**
* Added unit tests covering banner/theme display behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Per-package CPU power and temperature displayed in hardware info
(total and per-package values).
* CPU package topology (cores/threads per package) included in CPU info.
* Real-time per-package CPU telemetry exposed via a new system metrics
subscription.
* **Chores**
* Added an automated deployment script and npm deploy script for the
shared package.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Simon Fairweather <simon.n.fairweather@gmail.com>
Co-authored-by: Simon Fairweather <simon.n.fairweather@gmail.com>
Co-authored-by: SimonFair <39065407+SimonFair@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
## Summary
- install the pinia-plugin-persistedstate integration directly inside
the theme store and hydrate cached themes before applying CSS variables
- fall back to the active/global Pinia instance while ensuring persisted
state is only wired once per store instance
- update the theme store tests to reset the shared Pinia state between
runs and rely on the plugin-backed persistence
## Testing
- pnpm --filter web test __test__/store/theme.test.ts
------
[Codex
Task](https://chatgpt.com/codex/tasks/task_e_69156c5e8de48323841f7dbfdadec51d)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Theme preferences now persist across sessions and are restored on
return.
* **Behavior Change**
* Theme switching may now update the URL/address bar to reflect the
selected theme.
* **Chores**
* Added a persistence integration to enable storing/restoring theme
data.
* **Tests**
* Updated/added tests covering hydration from storage and persistence of
server-provided themes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Mitigates an edge case where the connect api plugin does not uninstall
itself when Unraid version < 7.2.0, resulting in retention of undesired
connect functionality on stock unraid after upgrading to 7.2.0+.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* App now detects Connect plugin availability at startup and falls back
gracefully with a no-op mode and a logged warning if the plugin is
absent.
* Added an environment option to skip the plugin availability check when
needed.
* Export behavior adjusted so the application uses the appropriate
module based on plugin presence.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added --bypass-npm and --npm flags, support for passing plugin names
as command args, and a restart option; CLI params now merge with
interactive prompts.
* **Bug Fixes**
* Vendor archive rebuild is performed only when actual uninstalls occur.
* Restart behavior uses resolved options for consistent restarts.
* Removal can run as "config-only" without running package operations.
* **Tests**
* Expanded tests for bypass scenarios, prompt flows, config-only
removals, and removal control flow.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a language switcher widget to all test pages for convenient
locale selection.
* Displays supported language options in a dropdown menu with extensive
multi-language support.
* Persists user's locale preference across page reloads.
* **Tests**
* Enhanced test utilities with improved multi-locale support and locale
switching capabilities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- also adds util for reading ini configs synchronously
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Added safe mode support to prevent plugin loading when enabled,
returning an empty plugin list in safe mode.
* **Tests**
* Added comprehensive test coverage for safe mode functionality and
state file loading mechanisms.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Chores**
* Streamlined the remote access update workflow by removing an
unnecessary step previously executed during remote access configuration
changes, resulting in a more efficient update process.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Resolves#1767
plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/include/UpdateFlashBackup.php:415
still reads the API version from _var($mystatus,'version'), but commit
441e1805c removed the code that populates $mystatus (the parse of
/var/local/emhttp/myservers.cfg). As a result $mystatus is undefined, so
we now send api_version= to the flash activation endpoint. The PHP
runtime also emits “Undefined variable: mystatus” / “Trying to access
array offset on value of type null” notices before headers are written.
Those notices corrupt the JSON response, the keyserver rejects the
request because the api_version is missing, and the flash backup state
file is never updated—so the web GUI stays stuck at “Loading”.
Because the status request always invokes UpdateFlashBackup.php, every
page load trips the same failure path, leaving
/var/local/emhttp/flashbackup.ini with loading=Loading. The frontend
only listens for /sub/flashbackup events, so until that INI file is
rewritten the spinner never clears and the enable button never becomes
active.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* UI now initializes flash backup status on page load so backup controls
reflect current server state immediately.
* Backup state saves now publish remote updates, improving
synchronization of backup status.
* **Bug Fixes**
* Improved API version handling for flash backup operations: sends
version when available and falls back gracefully when unknown.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
so the parser does not treat them as comments.
This surfaces a new bug: `#`'s in notification subject or descriptions
are treated as comments, and content following a `#` will not be
displayed in queries from the api, unless the values are explicitly
quoted as strings:
```
subject=Warning #1 OS # ❌ Truncates after "Warning"
subject=\#1 OS # ❌ Backslash escape doesn't work
subject="Warning #1 OS" # ✅ Double quotes work!
subject='Warning #1 OS' # ✅ Single quotes work!
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Version 4.25.3
* **Improvements**
* Enhanced notification system with improved handling of special
characters and HTML-formatted content in messages.
* Better text rendering accuracy across all notification types.
* **Chores**
* Updated application dependencies.
* Version bumped to 4.25.3.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Replace the eslint prettier plugin (which profiling revealed to be the
bottleneck) with separate `prettier` invocations. This yielded a 73 second reduction (89%) in the environment described below.
Before:
```
pnpm --filter web lint:fix 81.79s user 1.85s system 110% cpu 1:15.81 total
```
After:
```
pnpm --filter web lint:fix 8.83s user 0.93s system 170% cpu 5.737 total
```
System specs (Nov 5 2025):
```
OS: macOS Sequoia 15.6.1 (24G90) arm64
Host: MacBook Air (15-inch, M2, 2023)
Kernel: Darwin 24.6.0
Uptime: 44 days, 5 hours, 22 mins
Packages: 52 (nix-default), 195 (brew), 4 (brew-cask)
Shell: zsh 5.9
CPU: Apple M2 (8) @ 3.50 GHz
GPU: Apple M2 (10) @ 1.40 GHz [Integrated]
Memory: 19.51 GiB / 24.00 GiB (81%)
Swap: 4.83 GiB / 6.00 GiB (80%)
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Separated code formatting and linting tools into independent workflows
for improved developer efficiency
* Updated development tool configuration to streamline the linting and
formatting process
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Localization**
* Added proper Arabic translation for server action status messages
* Added proper French translation for server action status messages
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
On FAT32, `fs.stat()` updates accesstime, which means file reads are
also writes, which means we can't use `usePoll` without degrading users'
flash drives.
To keep file reads lazy without a larger refactor, I override
`getters.dynamix()` as the entrypoint to re-read the boot drive's
dynamix config.
Consecutive calls to `getters.dynamix()` are a common access pattern,
which means we have to memoize to avoid many redundant file reads, so I
used a TTL cache with a 250ms lifetime, hoping to scope config files to
each request.
`getters.dynamix()` is also used synchonously, so bit the bullet and
switched away from async reads for simplicity, considering that most
reads will be occurring from memory, even during cache misses.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a TTL memoized loader utility with exported types.
* Added a public function to load Dynamix configuration at startup.
* **Refactor**
* Startup now uses the deterministic, cached config loader; runtime
file-watch for Dynamix config removed.
* Simplified config state handling and load-status reporting for more
predictable startup behavior.
* **Tests**
* Added tests for TTL caching, eviction, keying, and conditional
caching.
* **Chores**
* Bumped package versions and updated changelog.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated release notes extraction workflow to improve handling of
version headers in generated release notes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Automated release-notes generation with layered fallbacks (use
provided notes, extract from changelog, generate from previous release,
call provider APIs, or default message).
* New version-validation step to ensure package versions are consistent
before publishing.
* **Chores**
* Moved release-notes logic into a reusable workflow and rewired the
manual release process to consume its outputs for more consistent
releases.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Adds a workflow to create or override (github) releases with a release
produced from a specific git ref. Refactors the main build process into
a workflow call for reusability.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Consolidated multi-target build pipeline for API, UI library, and web
app with unified artifact publishing, improved caching, and simplified
downstream wiring.
* **New Features**
* Added a manual, parameterized release workflow to create/update draft
releases with optional prerelease tagging and generated release notes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* New Features
* Expanded and refined translations across the UI for Arabic, Bengali,
Catalan, Czech, Danish, German, Spanish, French, Hindi, Croatian,
Hungarian, Italian, Japanese, Korean, Latvian, Dutch, Norwegian, Polish,
Portuguese, Romanian, Russian, Swedish, Ukrainian, and Chinese.
* Updated labels, titles, and descriptions for API key management,
OIDC/SSO configuration, buttons, and restrictions to native-language
equivalents.
* Improves readability and consistency in localized interfaces; no
functional changes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Refactor**
* Consolidated URL resolution and handling logic for improved
consistency across the application
* Enhanced GraphQL endpoint configuration with better fallback
mechanisms for more reliable connections
* Optimized platform command execution through improved default
parameter handling
* **Chores**
* Infrastructure configuration updates and maintenance
<!-- end of auto-generated comment: release notes by coderabbit.ai -->