mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-14 06:16:20 -06:00
There is no way to answer "how many screens run ScreenTinker?". The product is
self-hostable by design, so most installs are invisible to us on purpose — and
should stay that way. This asks once, and reports only if the operator says yes.
The entire payload is three fields:
{ instance_id, version, screen_count }
instance_id is a random UUID minted on first use and kept in app_settings. It
carries nothing about the install; its only job is to let two reports from the
same server be recognised as one server, so a count is a count rather than a sum
of duplicates. That makes a report pseudonymous rather than anonymous, and the
wording shown to operators says so rather than claiming otherwise.
The payload is short on purpose. Every field added costs participation, and
participation is the only thing that makes the resulting number worth quoting.
Player-platform counts were considered and left out: release assets are already
published per platform, so GitHub's per-asset download counts answer "where should
effort go" at zero privacy cost and without asking anyone for anything.
Verifiability is the feature, not the copy. Settings shows the ACTUAL payload this
server would send, generated live from its own data, plus what it last really sent
and when. The payload is built in one function so a reviewer can check it at a
glance, and the test fails if a field is ever added.
Both answers persist. Declining is remembered as 'off' rather than falling back to
'unasked', so the prompt cannot return after an update — re-prompting is how
telemetry earns its reputation and gets patched out.
Collector side is inert unless TELEMETRY_COLLECTOR=1, so a normal install never
exposes the endpoint. Reports upsert on instance_id rather than appending, so an
install reporting daily occupies one row rather than 365 a year. The source IP is
never read or stored — receiving one is unavoidable, logging it would quietly turn
a pseudonymous report into an identifiable one.
Tests pin the negative promises, which are the ones that rot silently: sends
nothing before consent, sends nothing after a decline, payload is exactly three
keys, id survives a restart, a failed send never records a phantom report. Screen
count excludes unpaired provisioning rows, which would otherwise overstate the one
number this exists to state honestly.
docs/telemetry.md documents the payload, what is not sent, how to verify it, and
that any published total is a floor rather than a basis for extrapolation.
1657/1657 pass.
78 lines
3.4 KiB
Markdown
78 lines
3.4 KiB
Markdown
# Install statistics
|
|
|
|
ScreenTinker can optionally report how many screens an install runs. It is **off until you turn it
|
|
on**, and this page documents the whole of it.
|
|
|
|
---
|
|
|
|
## What is sent
|
|
|
|
Three fields. This is the complete payload:
|
|
|
|
```json
|
|
{
|
|
"instance_id": "9f2c1b6e-4a17-4c8e-9d3b-27a5e0f81c44",
|
|
"version": "1.9.34",
|
|
"screen_count": 42
|
|
}
|
|
```
|
|
|
|
| Field | What it is |
|
|
|---|---|
|
|
| `instance_id` | A random UUID generated by your server on first use and kept in its own database. It carries no information about you — its only job is to let two reports from the same server be recognised as the same server, so a count is a count rather than a sum of duplicates. |
|
|
| `version` | The ScreenTinker version this server is running. |
|
|
| `screen_count` | How many displays have been paired with this server. |
|
|
|
|
## What is not sent
|
|
|
|
No hostnames, IP addresses or domains. No organization, workspace or user names. No email
|
|
addresses and no user count. No device names, locations or serial numbers. No content, filenames,
|
|
playlists or schedules. No logs and no configuration.
|
|
|
|
The request is sent over HTTPS, and the receiving service does not record the source address.
|
|
|
|
## Verifying that
|
|
|
|
Rather than take the above on trust:
|
|
|
|
- **In the product** — Settings → Install statistics shows the exact payload your server would
|
|
send, generated live from your own data, plus what it last actually sent and when.
|
|
- **In the source** — the payload is built in one function, `payload()` in
|
|
[`server/lib/telemetry.js`](../server/lib/telemetry.js). Every field that leaves your server
|
|
is in that object literal. `server/test/telemetry.test.js` fails if a field is added.
|
|
- **On the wire** — the destination is a single `POST`, overridable with `TELEMETRY_ENDPOINT`, so
|
|
you can point it at your own collector and read exactly what arrives.
|
|
|
|
## Turning it on or off
|
|
|
|
You are asked once, on the dashboard, if you are a platform administrator. Both answers are
|
|
remembered, so declining is permanent and you will not be asked again after an update.
|
|
|
|
To change your mind at any time: **Settings → Install statistics**.
|
|
|
|
Reports are sent at most once a day. Nothing is queued or retried — if your server is offline or
|
|
the request fails, that day is simply skipped.
|
|
|
|
## Why we ask
|
|
|
|
ScreenTinker is self-hostable, so most installs are invisible to us by design, and that is how it
|
|
should stay. The cost is that we genuinely cannot answer "how many screens run this?" — a question
|
|
that matters for arguing the project is worth continuing to build, and for deciding which players
|
|
deserve the next round of work.
|
|
|
|
Sharing is a small, specific way to help with that. Declining is a completely reasonable answer and
|
|
changes nothing about how the product works.
|
|
|
|
> **A note on honesty.** Because sharing is opt-in, any total we publish is a **floor** — "at least
|
|
> N screens" — never an estimate of the whole install base. Instances that opt in are not a random
|
|
> sample of those that don't, so the number is not something to extrapolate from, and we won't.
|
|
|
|
## Running your own collector
|
|
|
|
Set `TELEMETRY_COLLECTOR=1` and this server accepts reports at `POST /api/telemetry/report`,
|
|
storing them in a `telemetry_reports` table keyed by `instance_id`. The endpoint is inert unless
|
|
that variable is set, so a normal install never exposes it.
|
|
|
|
Reports are upserted rather than appended — one row per install holding its latest report, not a
|
|
growing event log.
|