// cloud_version.go — t103 daemon 雲端版本偵測。 // 每輪 GET {cypher_url}/health 取 bundle_version,比對最低相容日期, // 過舊時 status.json 記錄,托盤顯示更新入口。 package main import ( "encoding/json" "io" "net/http" "strings" "time" ) // minCloudBuilt 是雲端最低相容建置日期(YYYY-MM-DD)。 // 雲端契約變更(新 API/schema 上線)時手動升此常數;daemon 下一輪自動偵測並提示更新。 const minCloudBuilt = "2026-07-28" // fetchCloudVersion 可在測試中替換為 stub,避免真實網路呼叫拖慢測試。 var fetchCloudVersion = fetchBundleVersion // fetchBundleVersion GET {cypherURL}/health 取 bundle_version。 // 5s timeout;失敗(逾時、連不上、非 JSON)靜默回 ("", false)——呼叫端不判定過舊。 func fetchBundleVersion(cypherURL string) (version string, ok bool) { client := &http.Client{Timeout: 5 * time.Second} resp, err := client.Get(strings.TrimSuffix(cypherURL, "/") + "/health") if err != nil { return "", false } defer resp.Body.Close() var payload struct { BundleVersion string `json:"bundle_version"` } if err := json.NewDecoder(io.LimitReader(resp.Body, 4096)).Decode(&payload); err != nil { return "", false } return payload.BundleVersion, true } // cloudVersionStale 判斷雲端是否需要更新。 // checkOK=false(/health 不可達)回 false(靜默不判定)。 // bundle_version 空(老實例)或日期部分 < minCloudBuilt 回 true。 func cloudVersionStale(version string, checkOK bool) bool { if !checkOK { return false } if version == "" { return true } // bundle_version 格式:YYYY-MM-DD+(或純 YYYY-MM-DD) date := strings.SplitN(version, "+", 2)[0] return date < minCloudBuilt }