fix(updates): tag Window JSON so the persisted maintenance window round-trips
The admin API persists the auto-update maintenance window as lowercase
JSON {"start","end"} (platform_settings key "update_window"), but
updates.Window had no json tags, so it marshaled/unmarshaled with
capitalized keys. The natural decode the update runner will use --
json.Unmarshal(stored, &updates.Window{}) -- would therefore miss every
key and silently yield the zero Window. That fails closed (a zero window
Contains nothing, so notify-only, never a rogue apply), so it is safe but
a latent silent-zero trap for the not-yet-built runner.
Add json:"start"/json:"end" to updates.Window so the obvious decode is
correct by construction; value time.Time treats a stored null as a no-op,
so a cleared/never-set window still decodes to the zero Window. Nothing
in the package serialized Window before, so this changes no existing
behavior.
Guarded by a cross-package contract test in internal/api that marshals
the real api.updateWindow DTO and unmarshals it into updates.Window --
asserting the interval survives (Contains(mid) is true) and that an empty
window decodes to the fail-closed zero Window -- so the two shapes cannot
drift apart silently.
This commit is contained in:
2 files changed
+65
-2
No files matched your search
@@ -34,9 +34,14 @@ const (
|
||||
// on top. A zero Window (both ends zero) is "unset" and Contains always returns
|
||||
// false, so a Scheduled component with no window set can never auto-apply — it holds
|
||||
// at notify until a human actually schedules a time.
|
||||
// The json tags are load-bearing across a package boundary: the maintenance window
|
||||
// is persisted by internal/api (platform_settings key "update_window") as lowercase
|
||||
// {"start","end"}, and the update runner reads those bytes back into a Window. With
|
||||
// value (not pointer) time.Time, a stored null unmarshals as a no-op, so a cleared
|
||||
// or never-set window decodes to the zero Window — Contains false, fails closed.
|
||||
type Window struct {
|
||||
Start time.Time
|
||||
End time.Time
|
||||
Start time.Time `json:"start"`
|
||||
End time.Time `json:"end"`
|
||||
}
|
||||
|
||||
// Contains reports whether now is inside the window. An unset (zero) or inverted
|
||||
|
||||
Reference in new issue
Block a user