feat(version): add self-hosted update check endpoint #193

Merged
nrupard merged 2 commits from feat/pms-238-self-hosted-version-check into main 2026-06-12 17:11:32 +02:00
Owner

Self-hosted operators can opt in to an update check by setting MOKOSH_UPDATE_CHECK_URL to a JSON manifest endpoint that publishes the latest released version. The new GET /api/v1/version/check handler fetches that manifest, compares the advertised version against the running build with a dependency-free semver-core comparison, and reports disabled / up_to_date / update_available / error. When the env var is unset the check reports disabled and makes no outbound request, so a stock install stays fully offline.

The probe config and its reqwest::Client are cached in a OnceLock with a sanitised display URL, mirroring the existing /ready Infisical probe so repeated polling reuses one connection pool and never echoes embedded credentials in error strings. A failed remote check returns 502 Bad Gateway; disabled and successful checks return 200 with Cache-Control: no-store.

#PMS-238

Self-hosted operators can opt in to an update check by setting MOKOSH_UPDATE_CHECK_URL to a JSON manifest endpoint that publishes the latest released version. The new GET /api/v1/version/check handler fetches that manifest, compares the advertised version against the running build with a dependency-free semver-core comparison, and reports disabled / up_to_date / update_available / error. When the env var is unset the check reports disabled and makes no outbound request, so a stock install stays fully offline. The probe config and its reqwest::Client are cached in a OnceLock with a sanitised display URL, mirroring the existing /ready Infisical probe so repeated polling reuses one connection pool and never echoes embedded credentials in error strings. A failed remote check returns 502 Bad Gateway; disabled and successful checks return 200 with Cache-Control: no-store. #PMS-238
feat(version): add self-hosted update check endpoint
All checks were successful
E2E (staging) / Playwright against staging (pull_request) Successful in 47s
Check / fmt + clippy + compile + tests (pull_request) Successful in 2m30s
Build OCI container / Build and push mokosh-api image (push) Successful in 3m42s
e08a3ad764
Self-hosted operators can opt in to an update check by setting MOKOSH_UPDATE_CHECK_URL to a JSON manifest endpoint that publishes the latest released version. The new GET /api/v1/version/check handler fetches that manifest, compares the advertised version against the running build with a dependency-free semver-core comparison, and reports disabled / up_to_date / update_available / error. When the env var is unset the check reports disabled and makes no outbound request, so a stock install stays fully offline.

The probe config and its reqwest::Client are cached in a OnceLock with a sanitised display URL, mirroring the existing /ready Infisical probe so repeated polling reuses one connection pool and never echoes embedded credentials in error strings. A failed remote check returns 502 Bad Gateway; disabled and successful checks return 200 with Cache-Control: no-store.

#PMS-238
feat(version): cache update-check result with a TTL
All checks were successful
E2E (staging) / Playwright against staging (pull_request) Successful in 46s
Create release / Create release from merged PR (pull_request) Has been skipped
Check / fmt + clippy + compile + tests (pull_request) Successful in 2m27s
Build OCI container / Build and push mokosh-api image (push) Successful in 3m58s
551db74819
The /version/check endpoint is unauthenticated and triggers an outbound manifest fetch on every call, so a caller (or an attacker) could amplify each hit into one upstream request and hold a connection for the 5s timeout. Cache the result behind a Mutex<Option<CachedResult>>: successful checks are reused for 15 minutes, errors for 60 seconds so a transient upstream outage recovers on the next poll instead of being pinned for the full success window. Steady-state polling now collapses to one upstream request per window.

The network path is split into fetch_update_check so run_update_check owns the cache policy; the lock is taken only for the lookup/store, never held across the await. The disabled branch makes no request and is not cached.

#PMS-238

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nrupard deleted branch feat/pms-238-self-hosted-version-check 2026-06-12 17:11:32 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!193
No description provided.