Android OTA archive: collected device getprop + resolved firmware metadata,
served to the app via cdn.jsdelivr.net. See the design in
android-ota-finder/docs/server.md.
Paths are lowercased; {group} = ro.product.manufacturer (falling back to
ro.product.brand), so e.g. SBM801FJ lives under sharp/, not sbm/.
OTA/Google/{group}/{model}/
index.json # {firmware:[...], builds:[...]} (regenerated by Actions)
getprop/{sha1(fingerprint)}.json # submitted by the app via the Worker
firmware/{sha1(postBuild)}.json # resolved by Actions (one per OTA)
The chain links by fingerprint, the only id present in both the device props
(ro.build.fingerprint) and OTA metadata (pre-build/post-build) — so it works
even when ro.build.date.utc is missing. A firmware's identity is its postBuild
(the build it installs); preBuild is just the build it updates from. Each firmware
records otaType (full | incremental, from metadata pre-build presence).
https://cdn.jsdelivr.net/gh/mouseos/ota-archive@main/OTA/Google/{group}/{model}/index.json
The app fetches this once and walks the chain in memory: match the device fingerprint
against firmware[].preBuild, follow postBuild → next.
worker/— Cloudflare Worker, write-onlyPOST /v1/getprop(commits getprop by fingerprint hash under the manufacturer group).scripts/— Python run by Actions:resolve.py(fingerprint-linked checkin chain with ro.product.device fallback + HTTP-Range metadata, writes firmware by postBuild hash + otaType),regen_index.py(per-model index.json),list_pending.py,ia_upload.py(archive.org).checkin*.py/*_pb2.pyare the android-checkin reference protobufs..github/workflows/pipeline.yml— cron (6h): resolve → regen index → commit → purge jsDelivr; then a matrix job uploads pending firmware to archive.org. The web site (mouseos/ota-archive-web) polls this repo on its own schedule — there is no cross-repo trigger (GITHUB_TOKEN gets 403 on other repos) — and the verify job fails visibly if the published web snapshot is older than 30 hours.
cd worker
npm install
npx wrangler login # browser auth (human)
npx wrangler secret put GH_TOKEN # paste a fine-grained PAT (Contents: R/W on this repo)
# optional rate limit:
# npx wrangler kv namespace create RL # then uncomment kv_namespaces in wrangler.toml
npx wrangler deploy # -> https://ota-getprop.<sub>.workers.dev/v1/getpropPut that endpoint URL into the app.
IA_ACCESS_KEY,IA_SECRET_KEY— from https://archive.org/account/s3.php- (
GITHUB_TOKENis automatic; the workflow already haspermissions: contents: write.)
Create an account; generate S3 keys (above). One item per device —
ota-google-{group}-{model} — with each firmware stored inside under its
original package filename.
- Set the Worker endpoint URL.
- Read timestamps.json / firmware.json from the jsDelivr URLs above.
No credentials are needed for Google checkin (anonymous) or jsDelivr.