v2.1.0 — Headwater
One self-hosted API for Google Maps, News, Trends and Autocomplete, plus YouTube
transcripts. This release renames the project, fixes several bugs that failed
silently, and moves the image to Python 3.14 on Debian 13.
Breaking
The project is now headwater. The old Docker Hub repository
rainmanjam/social-flood has been deleted, and Docker Hub does not redirect
a renamed or deleted repository. Any docker pull rainmanjam/social-flood in a
compose file, script or CI job stops working immediately.
- image: rainmanjam/social-flood:latest
+ image: rainmanjam/headwater:2.1.0The GitHub repository moved to rainmanjam/headwater; GitHub does redirect, so
existing git remotes keep working. No API path, parameter or response field
changed — only the name.
Maps now rejects impossible requests up front. A max_results/timeout
combination that cannot finish returns 400 with the count you can afford,
instead of timing out minutes later. max_results is capped at 45.
Fixed — bugs that returned success while doing nothing
These are the reason for the release. Each one looked healthy from the outside.
- Record storage never reached Redis.
RecordStorecalled
manager.is_available()on what is a@property, so every call raised
'bool' object is not callable, was swallowed, and silently fell back to
in-memory storage. Maps jobs, monitors and webhooks were lost on restart and
invisible to sibling workers./health/detailednow reports
record_storage_durable, and startup asserts it, so this cannot recur quietly. - The Redis health check tested nothing. It called a
_get_redis_client()
method that does not exist. It now pings the real client. - A broken import crashed every News search, hidden behind the cache.
- Google News ignored the proxy. GNews takes a
{"http": ..., "https": ...}
mapping, not a bare URL string.
Security
- Proxy credentials are no longer logged. A proxy URL carries
user:pass@
inline; two code paths wrote it to the transcript and application logs.
Credentials are masked at every call site now. - NLTK removed, which removes PYSEC-2026-2026 rather than suppressing it.
Article extraction still returns title, authors, date and full text;summary
andkeywordsare nownull, withnlp_available: falseto say so plainly. - Debian security updates are applied at image build.
Proxying is now per host
ENABLE_PROXY was global, which forced one decision for every upstream. The
upstreams disagree: Reddit needs a proxy, YouTube is refused by some providers at
the tunnel, and Google Maps loads through a plain GET but a full browser
navigation through a datacentre proxy never settles.
ENABLE_PROXY=true
PROXY_URLS=http://user:pass@proxy.example.com:8080
NO_PROXY_HOSTS=youtube.com,youtu.be,ytimg.com,google.comNO_PROXY_HOSTS matches on a dot boundary, so youtube.com does not also match
notyoutube.com.example.
Performance
- Google News search: ~80s → ~3s. GNews was launching a whole Chromium
instance per article to resolve redirect URLs. It now decodes them directly. - Maps searches are cached for an hour. The blocking path had no cache at
all, and Maps costs roughly 12 seconds per result. - Trends reference data is cached for a day.
/geo(3,681 locations) and
/categories(1,133) change on the order of months.
API
/geois served from the native Trends endpoint rather than a scrape.POST /batch-get-transcriptsaccepts a JSON body, up to 50 video ids.- Trends endpoints stop passing
Noneinto trendspy, so its own defaults apply. - Exhausted Google Trends quota returns 502, not an empty
200— a quiet
week and a broken scraper should never look the same.
Image and supply chain
- Python 3.14 on Debian 13 (trixie), pinned by digest.
- Multi-arch:
linux/amd64andlinux/arm64. - SBOM and provenance attestations attached, plus a cosign signature.
- Full OCI metadata — source, revision, version, licence, base image.
Docs
The README is rewritten against what the API actually exposes, with real
responses rather than invented ones, and all 29 markdown files were audited
against the code.
Images
docker pull rainmanjam/headwater:2.1.0
docker pull ghcr.io/rainmanjam/headwater:2.1.0Digest: sha256:ab46c57ed6ce94a5f3d24c0e2c16f067749c5c743356a07e46c879d85b127c7c
Verify the signature
cosign verify \
--certificate-identity-regexp 'https://github.com/rainmanjam/headwater/.github/workflows/release.yml@.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/rainmanjam/headwater@sha256:ab46c57ed6ce94a5f3d24c0e2c16f067749c5c743356a07e46c879d85b127c7cFull commit log: v2.0.0...v2.1.0