Documentation
¶
Overview ¶
Package versioncheck reports whether a newer GoModel release exists.
It reads a plain-text manifest on a daily schedule and on the first dashboard visit of each day. The request carries the running version, the distribution name, an anonymous install identifier, and the dashboard's own hostname; it never carries API keys, provider credentials, model names, prompts, or usage data.
Every outbound request is jittered so gateways started together — a Helm rollout, a restarted docker-compose stack — do not query in lockstep.
Index ¶
- Constants
- func DueToday(value string, now time.Time) bool
- func InstallID() string
- func IsNewer(current, latest string) bool
- func LeaksQueryInCleartext(raw string) bool
- func NewVisit(id string, now time.Time) string
- func SafeURL(raw string) string
- func SplitVisit(value string) (date, id string)
- type Beacon
- type Checker
- type Config
- type Status
Constants ¶
const CookieMaxAge = 31536000
CookieMaxAge keeps a browser's id stable for a year.
const CookieName = "gomodel_version_check"
CookieName is the browser cookie holding the visit marker. Its value is YYYY-MM-DD-{id}: the day this browser last checked, plus a random id generated on the first visit. Dashboard JavaScript reads the date half to decide whether today's check has already happened, so the cookie is deliberately not HttpOnly.
const DefaultURL = "https://gomodel.enterpilot.io/version"
DefaultURL is the public release manifest served by the GoModel website. The channel file ("core.txt" or "pro.txt") is appended to it.
Variables ¶
This section is empty.
Functions ¶
func DueToday ¶
DueToday reports whether a browser presenting this cookie value has yet to check in on the given day.
func InstallID ¶
func InstallID() string
InstallID returns a stable, anonymous identifier for this deployment, creating one on first use. It is a random UUID: it encodes nothing about the host, the operator, or the configuration, and only ever leaves the process on an update check.
A read-only or unwritable data directory is not an error; the caller gets a process-lifetime identifier instead.
func IsNewer ¶
IsNewer reports whether latest is a later release than current.
It is deliberately conservative: an unparseable or non-release local version ("dev", a bare commit) never reports an update, and build metadata is ignored, so a Pro build stamped "1.0.0+core.0.1.81" compares as 1.0.0. Within one release number a prerelease ranks below the final release ("1.0.0-rc1" < "1.0.0"), matching semantic versioning.
func LeaksQueryInCleartext ¶
LeaksQueryInCleartext reports whether a configured manifest URL would put its query string on the wire unencrypted. A private mirror may authenticate with a query token, and over plain HTTP that token is readable by anything on the path — redacting it from logs does not help there.
Reported rather than rejected: the URL is a deliberate operator choice, an internal mirror on a trusted network is a legitimate setup, and refusing to start the gateway over a non-essential update check would be a worse outcome than telling the operator what they have configured.
func NewVisit ¶
NewVisit builds a cookie value for today, reusing id when the browser already has one and minting a fresh one otherwise.
The day is UTC on both sides of the cookie: the dashboard reads the same value back, and a browser in a different timezone to the gateway would otherwise disagree about when a new day starts.
func SafeURL ¶
safeURL identifies the manifest host for errors and logs without quoting anything an operator may have embedded in the configured URL. A private mirror can carry a secret in userinfo, in the query, or in the path itself, so only the scheme and host survive.
func SplitVisit ¶
SplitVisit separates a cookie value into its date and id halves. An empty or malformed value yields empty strings, which callers treat as a first visit.
The id must be exactly the canonical UUID NewVisit generates. /version is unauthenticated and the id is echoed into an outbound request header and back into Set-Cookie, so an unvalidated one would let any caller put text of their choosing into both. Anything else is discarded and replaced with a fresh id, which is also the right answer for a cookie corrupted in transit.
Types ¶
type Beacon ¶
type Beacon struct {
UserAgent string
AcceptLanguage string
ClientHints map[string]string
Visit string
}
Beacon carries the allowlisted slice of a dashboard visit that travels with an update check.
type Checker ¶
type Checker struct {
// contains filtered or unexported fields
}
Checker owns the cached manifest result and the request budget.
func New ¶
New builds a Checker for the given distribution. It never returns an error: a disabled or misconfigured check degrades to reporting the local version.
func (*Checker) Refresh ¶
Refresh fetches the manifest and updates the cache. It returns the current status even when the request is throttled, out of budget, or fails, so callers can always answer with the local version.
type Config ¶
type Config struct {
Enabled bool
URL string
App string
Version string
InstallID string
Interval time.Duration
Timeout time.Duration
MaxDailyChecks int
// Client overrides the HTTP client, for tests.
Client *http.Client
// Now overrides the clock, for tests.
Now func() time.Time
}
Config configures a Checker. Zero values fall back to package defaults.
type Status ¶
type Status struct {
App string `json:"app"`
Version string `json:"version"`
Latest string `json:"latest,omitempty"`
UpdateAvailable bool `json:"update_available"`
CheckedAt string `json:"checked_at,omitempty"`
Enabled bool `json:"enabled"`
}
Status is the snapshot the /version endpoint serves. It is safe to expose: it contains only release metadata.