Fix admin update check and badge
The updates cache methods used value receivers, so periodic re-checks
updated a throwaway copy and the shared cache never changed after
startup. The Updates page could then report a stale "last checked"
time and an update for the currently installed version, while other
admin tabs showed no badge at all.
- Uses pointer receivers and lock all reads of the cache
- Refreshes the cache in the background from any admin page, not just Updates, so the badge stays current
- Clears the error after a check succeeds, add a request timeout, reject non-200 responses and invalid version body
- Strips the git-describe suffix so dev builds compare as their release
- Formats the "last checked" timestamp in UTC