* feat(alertmanager): migrate recurrence bounds to schedule level
Promote startTime/endTime from a planned maintenance's nested recurrence
up to the schedule level. For recurring maintenances the recurrence
bounds were the source of truth; the recurrence struct loses these
fields in the next step, so the values are moved while they can still be
read. The migration operates on raw JSON for that reason.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* refactor(alertmanager): drop start/end bounds from Recurrence
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* refactor: code cleanup
* fix: upcoming check for recurring maintenances
* fix: remove recurrence.startTime/endTime usages
* fix: use embedded timezone in start/end times
Accept times in any timezone, but always convert them to the selected
timezone. The conversion is required to correctly handle the recurring
maintenances for timezones where DST is involved.
* refactor: remove redundant code
* fix: make startTime a required field
* test: cover fixed schedule active window in IsActive
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* test: cover recurring schedule active window in IsActive
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore: add justification for unreachable code
* fix: don't let one corrupt maintenance abort the migration
* fix: don't let one corrupt maintenance break the list
ListPlannedMaintenance now reads the schedule as raw text and parses each
row individually, skipping and logging the bad ones so the rest survive.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix: tests to use UTC instead of utc
* fix: return proper errors from schedule.Unmarshal
* fix: copy schedule type to migration
* chore: move tz conversion to checkX methods
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Srikanth Chekuri <srikanth.chekuri92@gmail.com>