controller v0.271.0: automatic app updates — the update leg after the off-site copy, the backup gate waits, the switch (09 6.4 part 7; R-680, R-678, R-643)
gates / gates (push) Successful in 24s
gates / gates (push) Successful in 24s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -188,6 +188,12 @@ type Settings struct {
|
||||
// offsets; overrides yaml when a valid value is present (mirrors PasswordHash precedence).
|
||||
BackupWindowStart string `json:"backup_window_start,omitempty"`
|
||||
|
||||
// AppUpdate (v0.271.0, `09` §3 decision 12) — the per-box switch for AUTOMATIC app updates. The key
|
||||
// is `app_update.unattended`; ABSENT MEANS ON (the operator's ruling: on by default), so a box that
|
||||
// never saved the switch, and every box upgraded from before v0.271.0, updates its apps by itself.
|
||||
// Only an explicit false turns it off. NOT `self_update.auto_update` — that is the controller's own.
|
||||
AppUpdate *AppUpdateSettings `json:"app_update,omitempty"`
|
||||
|
||||
// Storage paths registry
|
||||
StoragePaths []StoragePath `json:"storage_paths,omitempty"`
|
||||
|
||||
@@ -886,6 +892,36 @@ func (s *Settings) SetBackupWindowStart(start string) error {
|
||||
return s.save()
|
||||
}
|
||||
|
||||
// AppUpdateSettings is settings.json's `app_update` object (v0.271.0).
|
||||
type AppUpdateSettings struct {
|
||||
// Unattended nil = the default, ON (decision 12). Pinned by TestAppUpdateUnattended_DefaultOn.
|
||||
Unattended *bool `json:"unattended,omitempty"`
|
||||
}
|
||||
|
||||
// GetAppUpdateUnattended reports whether this box may update its apps by itself (decision 12).
|
||||
// Absent = ON.
|
||||
func (s *Settings) GetAppUpdateUnattended() bool {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
if s.AppUpdate == nil || s.AppUpdate.Unattended == nil {
|
||||
return true
|
||||
}
|
||||
return *s.AppUpdate.Unattended
|
||||
}
|
||||
|
||||
// SetAppUpdateUnattended stores the household's choice and saves. It takes effect at the leg's next
|
||||
// start (and before its next step, if a leg is running) — the leg reads it each time.
|
||||
func (s *Settings) SetAppUpdateUnattended(on bool) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.AppUpdate == nil {
|
||||
s.AppUpdate = &AppUpdateSettings{}
|
||||
}
|
||||
v := on
|
||||
s.AppUpdate.Unattended = &v
|
||||
return s.save()
|
||||
}
|
||||
|
||||
// SetConfigLanguage records the language controller.yaml says this box should start in.
|
||||
//
|
||||
// Called once at startup and again after each config pull. It never touches s.Language: a
|
||||
|
||||
Reference in New Issue
Block a user