2 Commits
Author SHA1 Message Date
Jake WriterandClaude Opus 5.5 73f81b2543 fix(pythonlib): write downloaded files beside their destination, not via mkdtemp (#829)
The fpgen model was staged in tempfile.mkdtemp() and os.replace'd into
fpgen's data directory, and an extracted GeoIP database was unpacked in
tempfile.TemporaryDirectory() and shutil.move'd into the cache. Since
Python 3.13, mkdtemp() on Windows creates an owner-only directory, and a
file moved out of it on the same volume keeps that ACL. So a model or
database installed from an elevated shell (or over SSH, which is elevated)
could not be read by the same user unelevated, or by any other account:
the launch failed with "fpgen's model directory is not writable by this
user", though the failure was a read. Found on Windows 11 with
camoufox 0.5.7b5 under Python 3.14.

Add pkgman.write_atomic(): write a temporary file beside the destination,
so it takes the directory's permissions, then os.replace it into place.
The model's members are all verified before any is written, as before.
The permission error now names the file and says how to recover from a
model another account installed.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 00:00:23 +00:00
f36390a19e feat(geoip): make GeoIP AIO the default source, deprecate GeoLite2 (#820)
The default GeoIP source was MaxMind GeoLite2 via sapics/ip-location-db,
whose URLs kept serving the 2026-06-17 build after that project moved to
GitHub Releases (found in #815). GeoIP AIO (daijro/geoip-all-in-one)
resolves timezones more accurately on real proxy IPs and is rebuilt weekly.

- repos.yml: AIO is the default; GeoLite2 is `deprecated: true`, with the
  Releases URLs from #815 so it still works when picked by name.
- A cache holding a deprecated source it was not explicitly given
  (`camoufox set --geoip` or the GUI) moves to the default and drops the
  old database. An explicit choice is kept, with a FutureWarning.
- needs_update() reads the database's build date instead of the file age:
  refresh once the build is over 8 days old, re-checking at most daily,
  and warn when a fresh download is over 30 days old (a frozen source).
- get_geolocation(geoip_db=...) now reads that source's own database
  rather than the active one's, and no longer makes it the active one.
- tests/test_geoip_sources.py (from #815) downloads every non-deprecated
  source and fails when its build is stale; tests.yml installs the geoip
  extra so it runs, and so gates every release.
- TypeScript twin updated to match; goldens answer in both layouts.

Co-authored-by: lp177 <57773165+lp177@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:02:52 +00:00