Architecture
The constraint that shaped everything: whoever runs this is a development team, not an ops team. So the server is one binary that runs its own migrations on boot, serves its own dashboard, and writes APKs to a directory. Postgres is the only thing to install alongside it.
What it does
Build distribution
- › Upload an APK with an environment and tags
- › Package, version and min SDK parsed from the file itself
- › A project locks to its first APK's package name
- › Download and install straight from the phone
What's new, first
- › Home screen answers: is there anything new for me?
- › New builds across followed projects, newest first
- › Per-project notification subscriptions
- › Push the moment a build lands
Many organizations, one app
- › Join as many servers as you work with
- › Separate sign-in, projects and settings per instance
- › Switch instances in a tap
- › Nothing shared between them
Joining in seconds
- › Scan the invite QR from the dashboard
- › Open an invite link
- › Or sign in with a server URL
- › Invites are single-use and expire
Access control
- › Admin, developer and tester roles
- › Groups grant project access
- › Every access change lands in the audit feed
- › Activity feed of who shipped what
APK verification
- › Check an APK before trusting it
- › Hash and manifest read on the phone
- › Only the hash, package and version leave the device
- › Server answers: match, suspicious or unknown
Organizing builds
- › Environments with a colour ramp
- › Free-form tags with admin-chosen colours
- › Filter build lists by environment
- › Changelogs rendered from sanitized Markdown
Self-hosted by design
- › Your builds, users, database and storage
- › Single binary plus Postgres, or Docker Compose
- › Firebase service-account key encrypted at rest
- › No vendor holds your APKs
Designed to be read
- › Carbon & Signal palette — colour carries meaning only
- › Contrast, not hue, marks what is tappable
- › Every pair clears WCAG AA, pinned by the dashboard's tests
- › The same tokens on Android and web
Worth knowing
- Argon2 password hashing, JWT access and refresh tokens, AES-GCM at rest for the Firebase service-account key
- No google-services.json: each organization brings its own Firebase project, and the app builds one Firebase instance per server at runtime
- A hand-written parser for the binary AndroidManifest, in Rust on the server and again in Kotlin on the phone
- Download links are HMAC-signed and expire after five minutes
- The dashboard is compiled into the server binary, so an install is one file and a database
- OpenAPI document generated from the router with utoipa, and dumped by the CLI
- Contrast test suite parses the real CSS and asserts every shipped colour pair against WCAG
- Rust integration tests against a real Postgres, a Playwright smoke test for the dashboard, JVM and instrumented tests for the app