You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Migrate to TypeScript 7.0 RC (Go-based tsgo compiler):
Updated peer dependency to typescript: ^7.0.1-rc
Updated @typescript/native-preview to 7.0.0-dev.20260701.1
Updated tsconfig.json, migration docs, and instruction files
Patches esModuleInterop default and other TS 7.0 defaults
✨ Features
HDIdle per-disk model (Lab Mode feature): Replaced the global HDIdle
enable/disable toggle with a fully per-disk configuration model gated behind
Lab Mode (experimental_lab_mode=true). Key changes:
Per-disk enable/disable: each physical disk has its own HDIdle record
(enabled: yes|custom|no); the service runs automatically when ≥1 disk is
enabled. The five global Settings.hdidle_* fields have been removed.
Dashboard suggestion badge: HDDs that have not yet been configured show
an inline "Enable HDIdle?" badge in the disk I/O table (visible only in Lab
Mode). The badge provides Ignore (persists suggestion_ignored=true)
and Enable (navigates to the per-disk card in the Volumes page).
Non-rotational guard: enabling HDIdle on an SSD/NVMe or a device with
unknown rotational type opens a confirm dialog; accepting persists force_enabled=true so the warning does not repeat. The backend returns
HTTP 409 if the flag is missing, preventing accidental spindowns of SSDs.
Rotational detection: Disk.is_rotational tri-state (HDD/SSD/unknown)
is now derived from /sys/block/<dev>/queue/rotational (sysfs primary) with
SMART rotation_rate as fallback. Unknown (e.g. USB enclosures) returns nil — treated as non-rotational for safety.
Ignore-suggestion endpoint: POST /api/disk/{id}/hdidle/ignore-suggestion
persists the badge dismissal per disk.
Adaptive polling: the monitor goroutine polls every 60s when ≥1 disk is
spun-up and slows to 5min when all monitored disks are already spun-down.
The goroutine is never started when zero disks are enabled.
readOnly threading: the per-disk settings card now correctly propagates
the readOnly flag from VolumeDetailsPanel.
mDNS Registration: Added optional mDNS registration of the SRAT service for local network discovery. When enabled, the backend registers a _srat._tcp service with the system mDNS responder, advertising the service name, port, and metadata. This allows compatible clients to discover the SRAT service on the local network without manual configuration. The feature is controlled by a new MDNSRegistration boolean setting in the advanced settings section.
🐛 Bug Fixes
HDIdle service permanently broken after first Stop(): Stop() no longer
leaves stopChan non-nil after close. Subsequent Start() calls now succeed
(idempotent). Fixes a latent bug where the service refused to restart after
any config PUT.
Nested mutex deadlock in GetDeviceStatus, GetProcessStatus, and observeDiskActivity: calls to IsRunning() under an existing lock now read stopChan directly to avoid the deadlock inherent in re-acquiring an RWMutex that is not guaranteed reentrant.
GetDeviceConfig returned HTTP 500 when service disabled: the guard !s.config.Enabled → ErrorHDIdleNotSupported has been removed. The config
endpoint is now always available for inspection/configuration regardless of
whether the monitor goroutine is running.
disk_id injected unsanitised into file path: hdidle_handler.go was
naïvely prefixing every disk_id with /dev/disk/by-id/ without validation.
Replaced by HDIdleServiceInterface.ResolveDevicePath() which probes three
candidate paths (absolute /dev/…, by-id, kernel name) and rejects inputs
containing path-traversal characters.
🔄 Breaking Changes
Settings.hdidle_enabled, hdidle_default_idle_time, hdidle_default_command_type, hdidle_default_power_condition, and hdidle_ignore_spin_down_detection have
been removed from the API and the DB (migration 00017 drops the
corresponding rows from the properties table).
POST /api/hdidle/start and POST /api/hdidle/stop have been removed.
The service lifecycle is now fully automatic (driven by the per-disk records).
PATCH /api/disk/{id}/hdidle/config has been removed (it was a dead spec
entry with no handler).
🏗 Chore
DB migration 00017 (drop_global_hdidle_properties): deletes the five
obsolete global HDIdle property rows. Down migration re-seeds them with their
original defaults for dev/test rollback.
events.PowerEvent now carries a Kind PowerEventKind discriminant field
(config or status) so subscribers can branch without comparing zero-values.
Two new dto.HDIdleDevice fields (SuggestionIgnored, ForceEnabled) and
matching GORM/generated-layer/converter updates. Schema columns are added by
GORM AutoMigrate on the next startup — no manual migration needed.
openapi.json is not regenerated in this branch — it requires a working
Go toolchain and go run ./cmd/srat-openapi. CI must run go run ./cmd/srat-openapi -dir=backend/docs and cd frontend && bun run gen:api before merging to keep generated artifacts in
sync. Three hand-edited generated files (config_to_dto_conv_gen.go, dto_to_dbom_conv_gen.go, g/hdidle_device_config.go) are aligned with their
source directives — a go generate ./... run will produce the same output.
🔧 Maintenance
Multi-variant server release: Release archives now ship three srat-server variants — srat-server-static (fully static, zero shared-library dependencies), srat-server-musl (dynamic linked against musl libc, built via Zig), and srat-server-glib (dynamic linked against glibc, built via CGO). The srat-server entry in the archive is a symlink that defaults to srat-server-static; the upgrade process automatically updates it to the best available variant for the running system (musl → glibc → static). srat-openapi is no longer included in release archives. srat-cli is always statically linked.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Changelog
🔧 Chore
tsgocompiler):typescript: ^7.0.1-rc@typescript/native-previewto7.0.0-dev.20260701.1tsconfig.json, migration docs, and instruction filesesModuleInteropdefault and other TS 7.0 defaults✨ Features
enable/disable toggle with a fully per-disk configuration model gated behind
Lab Mode (
experimental_lab_mode=true). Key changes:(
enabled: yes|custom|no); the service runs automatically when ≥1 disk isenabled. The five global
Settings.hdidle_*fields have been removed.an inline "Enable HDIdle?" badge in the disk I/O table (visible only in Lab
Mode). The badge provides Ignore (persists
suggestion_ignored=true)and Enable (navigates to the per-disk card in the Volumes page).
unknown rotational type opens a confirm dialog; accepting persists
force_enabled=trueso the warning does not repeat. The backend returnsHTTP 409 if the flag is missing, preventing accidental spindowns of SSDs.
Disk.is_rotationaltri-state (HDD/SSD/unknown)is now derived from
/sys/block/<dev>/queue/rotational(sysfs primary) withSMART
rotation_rateas fallback. Unknown (e.g. USB enclosures) returnsnil— treated as non-rotational for safety.POST /api/disk/{id}/hdidle/ignore-suggestionpersists the badge dismissal per disk.
spun-up and slows to 5min when all monitored disks are already spun-down.
The goroutine is never started when zero disks are enabled.
the
readOnlyflag fromVolumeDetailsPanel._srat._tcpservice with the system mDNS responder, advertising the service name, port, and metadata. This allows compatible clients to discover the SRAT service on the local network without manual configuration. The feature is controlled by a newMDNSRegistrationboolean setting in the advanced settings section.🐛 Bug Fixes
Stop()no longerleaves
stopChannon-nil after close. SubsequentStart()calls now succeed(idempotent). Fixes a latent bug where the service refused to restart after
any config PUT.
GetDeviceStatus,GetProcessStatus, andobserveDiskActivity: calls toIsRunning()under an existing lock now readstopChandirectly to avoid the deadlock inherent in re-acquiring anRWMutexthat is not guaranteed reentrant.GetDeviceConfigreturned HTTP 500 when service disabled: the guard!s.config.Enabled → ErrorHDIdleNotSupportedhas been removed. The configendpoint is now always available for inspection/configuration regardless of
whether the monitor goroutine is running.
disk_idinjected unsanitised into file path:hdidle_handler.gowasnaïvely prefixing every
disk_idwith/dev/disk/by-id/without validation.Replaced by
HDIdleServiceInterface.ResolveDevicePath()which probes threecandidate paths (absolute
/dev/…, by-id, kernel name) and rejects inputscontaining path-traversal characters.
🔄 Breaking Changes
Settings.hdidle_enabled,hdidle_default_idle_time,hdidle_default_command_type,hdidle_default_power_condition, andhdidle_ignore_spin_down_detectionhavebeen removed from the API and the DB (migration 00017 drops the
corresponding rows from the
propertiestable).POST /api/hdidle/startandPOST /api/hdidle/stophave been removed.The service lifecycle is now fully automatic (driven by the per-disk records).
PATCH /api/disk/{id}/hdidle/confighas been removed (it was a dead specentry with no handler).
🏗 Chore
00017(drop_global_hdidle_properties): deletes the fiveobsolete global HDIdle property rows. Down migration re-seeds them with their
original defaults for dev/test rollback.
events.PowerEventnow carries aKind PowerEventKinddiscriminant field(
configorstatus) so subscribers can branch without comparing zero-values.dto.HDIdleDevicefields (SuggestionIgnored,ForceEnabled) andmatching GORM/generated-layer/converter updates. Schema columns are added by
GORM
AutoMigrateon the next startup — no manual migration needed.openapi.jsonis not regenerated in this branch — it requires a workingGo toolchain and
go run ./cmd/srat-openapi. CI must rungo run ./cmd/srat-openapi -dir=backend/docsandcd frontend && bun run gen:apibefore merging to keep generated artifacts insync. Three hand-edited generated files (
config_to_dto_conv_gen.go,dto_to_dbom_conv_gen.go,g/hdidle_device_config.go) are aligned with theirsource directives — a
go generate ./...run will produce the same output.🔧 Maintenance
srat-servervariants —srat-server-static(fully static, zero shared-library dependencies),srat-server-musl(dynamic linked against musl libc, built via Zig), andsrat-server-glib(dynamic linked against glibc, built via CGO). Thesrat-serverentry in the archive is a symlink that defaults tosrat-server-static; the upgrade process automatically updates it to the best available variant for the running system (musl → glibc → static).srat-openapiis no longer included in release archives.srat-cliis always statically linked.What's Changed
maxLength:128toSharedResource.Nameby @opencode-agent[bot] in AddedmaxLength:128toSharedResource.Name#734New Contributors
maxLength:128toSharedResource.Name#734Full Changelog: 2026.5.0-rc9...2026.7.0-rc11
This discussion was created from the release Release 2026.7.0-rc11.
Beta Was this translation helpful? Give feedback.
All reactions