Description
Split from #4981 (mega-issue). The reporter needs maintenance windows on schedules humans actually agree to:
- 1st Tuesday of each month
- Last Friday of each month
- Every Tuesday and Thursday
Today neither maintenance implementation can express these, and the newer one is worse than the legacy one:
- Config-policy Maintenance tab (
config_policy_maintenance_settings, the intended path): recurrence is once|daily|weekly|monthly with only a time of day. The resolver hardcodes weekly = Sunday and monthly = the 1st (featureConfigResolver.ts ~L2169-2186, windowStart.setDate(windowStart.getDate() - windowStart.getDay()), setDate(1)). A tech cannot pick which weekday or day of month at all. The MaintenanceTab.tsx UI has no day picker.
- Legacy standalone
maintenance_windows (routes marked deprecated): recurrenceRule supports daysOfWeek[] (multiple weekdays work) and dayOfMonth, but no nth-weekday / last-weekday; custom recurrence falls back to weekly (routes/maintenance.ts ~L256-259).
Without this, the reporter's workaround is one policy per client per server role, or a UDF-driven script that builds Windows scheduled tasks (see #4330).
Proposed Fix
Extend the config-policy maintenance recurrence model (and the shared validator) with:
weekly: daysOfWeek: number[] (multi-select)
monthly: either dayOfMonth or { ordinal: 1|2|3|4|'last', weekday }
- keep
once / daily as-is
Update isInMaintenanceWindow() to honour the new fields (currently Sunday/1st are baked in), the MaintenanceTab day pickers, maintenanceRebootWorker (reads the same window), and the effective-config display. Migration should backfill existing weekly rows to daysOfWeek: [0] and monthly rows to dayOfMonth: 1 so behaviour is unchanged.
Depends on nothing; #5235 (window ordering) and #5236 (post-window verification) are separate issues.
Affected Files
apps/api/src/db/schema/configurationPolicies.ts (~L215-233 configPolicyMaintenanceSettings)
apps/api/src/services/featureConfigResolver.ts (~L2028-2190 isInMaintenanceWindow)
apps/web/src/components/configurationPolicies/featureTabs/MaintenanceTab.tsx
apps/api/src/jobs/maintenanceRebootWorker.ts
packages/shared/src/validators/ (maintenance settings schema)
Reported By
stressedout9064 on Discord (#feature-suggestions, 2026-09-04) — split from #4981. Related: #4330 (UDF-driven reboot schedules, same underlying need).
Description
Split from #4981 (mega-issue). The reporter needs maintenance windows on schedules humans actually agree to:
Today neither maintenance implementation can express these, and the newer one is worse than the legacy one:
config_policy_maintenance_settings, the intended path):recurrenceisonce|daily|weekly|monthlywith only a time of day. The resolver hardcodes weekly = Sunday and monthly = the 1st (featureConfigResolver.ts~L2169-2186,windowStart.setDate(windowStart.getDate() - windowStart.getDay()),setDate(1)). A tech cannot pick which weekday or day of month at all. TheMaintenanceTab.tsxUI has no day picker.maintenance_windows(routes marked deprecated):recurrenceRulesupportsdaysOfWeek[](multiple weekdays work) anddayOfMonth, but no nth-weekday / last-weekday;customrecurrence falls back to weekly (routes/maintenance.ts~L256-259).Without this, the reporter's workaround is one policy per client per server role, or a UDF-driven script that builds Windows scheduled tasks (see #4330).
Proposed Fix
Extend the config-policy maintenance recurrence model (and the shared validator) with:
weekly:daysOfWeek: number[](multi-select)monthly: eitherdayOfMonthor{ ordinal: 1|2|3|4|'last', weekday }once/dailyas-isUpdate
isInMaintenanceWindow()to honour the new fields (currently Sunday/1st are baked in), theMaintenanceTabday pickers,maintenanceRebootWorker(reads the same window), and the effective-config display. Migration should backfill existing weekly rows todaysOfWeek: [0]and monthly rows todayOfMonth: 1so behaviour is unchanged.Depends on nothing; #5235 (window ordering) and #5236 (post-window verification) are separate issues.
Affected Files
apps/api/src/db/schema/configurationPolicies.ts(~L215-233configPolicyMaintenanceSettings)apps/api/src/services/featureConfigResolver.ts(~L2028-2190isInMaintenanceWindow)apps/web/src/components/configurationPolicies/featureTabs/MaintenanceTab.tsxapps/api/src/jobs/maintenanceRebootWorker.tspackages/shared/src/validators/(maintenance settings schema)Reported By
stressedout9064 on Discord (#feature-suggestions, 2026-09-04) — split from #4981. Related: #4330 (UDF-driven reboot schedules, same underlying need).