versioncheck

package
v0.1.83 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2026 License: MIT Imports: 17 Imported by: 0

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

View Source
const CookieMaxAge = 31536000

CookieMaxAge keeps a browser's id stable for a year.

View Source
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.

View Source
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

func DueToday(value string, now time.Time) bool

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

func IsNewer(current, latest string) bool

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

func LeaksQueryInCleartext(raw string) bool

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

func NewVisit(id string, now time.Time) string

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

func SafeURL(raw string) string

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

func SplitVisit(value string) (date, id string)

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.

func BeaconFromRequest

func BeaconFromRequest(r *http.Request, visit string) Beacon

BeaconFromRequest extracts the allowlisted fields of a dashboard request.

type Checker

type Checker struct {
	// contains filtered or unexported fields
}

Checker owns the cached manifest result and the request budget.

func New

func New(cfg Config) *Checker

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) Enabled

func (c *Checker) Enabled() bool

Enabled reports whether outbound checks are configured.

func (*Checker) Refresh

func (c *Checker) Refresh(ctx context.Context, beacon Beacon) (Status, error)

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.

func (*Checker) Run

func (c *Checker) Run(ctx context.Context)

Run performs the background schedule until ctx is cancelled. The first check waits a random slice of the interval (capped at ten minutes) so a fleet restarting together spreads its requests out.

func (*Checker) Status

func (c *Checker) Status() Status

Status returns the cached result without touching the network.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL