// Package status loads and manages the service status JSON. package status import ( "encoding/json" "os" "sync" "time" ) var mu sync.RWMutex // Service represents a single monitored service. type Service struct { Name string `json:"name"` Description string `json:"description"` URL string `json:"url,omitempty"` CheckURL string `json:"check_url,omitempty"` // HTTP URL probed automatically; empty = manual Status string `json:"status"` // "up", "degraded", "down", "unknown" Note string `json:"note,omitempty"` } // Page is the full status page data loaded from JSON. type Page struct { LastChecked time.Time `json:"last_checked"` Services []Service `json:"services"` } // Load reads and parses the status JSON from path. func Load(path string) (*Page, error) { mu.RLock() defer mu.RUnlock() return load(path) } func load(path string) (*Page, error) { raw, err := os.ReadFile(path) if err != nil { return nil, err } var p Page if err := json.Unmarshal(raw, &p); err != nil { return nil, err } return &p, nil } // Save writes the status page data back to path. func Save(path string, p *Page) error { mu.Lock() defer mu.Unlock() p.LastChecked = time.Now().UTC() raw, err := json.MarshalIndent(p, "", " ") if err != nil { return err } return os.WriteFile(path, raw, 0644) }