controller v0.94.0: pull-based config-refresh (re-pull + self-restart on config_version change)

PushResponse.ConfigVersion from the report ACK; ConfigRefresher reconciles vs.
the last-applied version (settings.applied_config_version) and on a change calls
bootstrap.RefreshConfig (re-pull controller.yaml + re-merge local_api) then
GracefulSelfRestart. First-run records baseline (no restart); unchanged = no-op
(no storm); failed pull keeps config + retries. Companion to hub v0.26.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HxLA1mZurFq9kt8hneFeCs
This commit is contained in:
2026-06-30 21:49:47 +02:00
parent 464b14f029
commit 419d3d0b4e
9 changed files with 432 additions and 0 deletions
+21
View File
@@ -53,6 +53,11 @@ type Settings struct {
HubVerifiedAt string `json:"hub_verified_at,omitempty"` // RFC3339
HubLastCheck string `json:"hub_last_check,omitempty"` // RFC3339
// AppliedConfigVersion is the hub config_version this controller has last pulled + applied
// (v0.26.0 pull-based config-refresh). 0 = none recorded yet → the first report ACK records the
// baseline without restarting. A change vs. the ACK triggers a re-pull + self-restart.
AppliedConfigVersion int `json:"applied_config_version,omitempty"`
// Recovery credentials (saved from setup wizard input)
RetrievalPassword string `json:"retrieval_password,omitempty"`
@@ -1110,6 +1115,22 @@ func (s *Settings) SetHubVerified(verified bool, at time.Time) error {
return s.save()
}
// GetAppliedConfigVersion returns the last-applied hub config_version (0 = none recorded yet).
func (s *Settings) GetAppliedConfigVersion() int {
s.mu.RLock()
defer s.mu.RUnlock()
return s.AppliedConfigVersion
}
// SetAppliedConfigVersion persists the config_version this controller has pulled + applied. Recorded
// BEFORE a config-refresh self-restart so the restarted process sees it applied and does not loop.
func (s *Settings) SetAppliedConfigVersion(v int) error {
s.mu.Lock()
defer s.mu.Unlock()
s.AppliedConfigVersion = v
return s.save()
}
// SetHubLastCheck updates the last Hub check timestamp without changing verification status.
// GetLastGuestBootID returns the persisted last-seen guest boot-id ("" if never recorded).
func (s *Settings) GetLastGuestBootID() string {