API-dokumentationen har fulgt med hele vejen — der er en prøve, der fejler, hvis en rute ikke står i openapi.yaml, og den fangede mig fire gange i går. Brugervejledningen har ikke fulgt med, og det er den, folk læser. Nyt: en side om beskeder — hvad der udløser en, hvorfor gentagne rettelser bliver slået sammen, push pr. apparat og mærket på ikonet. En om at åbne links i en anden browser, som mest af alt handler om, hvad en webside ikke kan: hverken se hvilke browsere der findes eller vælge mellem dem. Og en om tællingen af installationer, som ikke stod nogen steder overhovedet — en melding, der er slået til som udgangspunkt, har en pligt til at være skrevet ned, også når ingen har spurgt. Rettet: AI-siden beskrev to funktioner, hvor der nu er syv, og listen over hvad der sendes hvorhen var derfor forkert som en påstand om noget privat. Noter-siden manglede deling med en e-mailadresse og hvad `@Sofie` gør. Mail-siden manglede den anden vej ind i indbakken. Konfigurationen sagde stadig, at versionstjekket kun kunne se efter. Og tagbeskeden når nu frem. Den ER annonceringen — skrevet på produktets eget sprog til dem, der bruger det — og udgivelsen på GitHub blev fyldt med en autogenereret liste over commit-overskrifter i stedet, som er skrevet til dem, der læser koden. Nu står teksten øverst og listen under den. Linjen med linket til udgivelsen selv tages af: en side, der linker til sig selv, hjælper ingen. Dokumentationen bygges nu også på en PR. `mkdocs build --strict` fejler på et link til en side, der ikke findes, og at bygge først efter merge er at få det at vide på main. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
76 lines
3.6 KiB
Markdown
76 lines
3.6 KiB
Markdown
# The install count
|
|
|
|
verdande reports that it exists. Two values, once a day:
|
|
|
|
```json
|
|
{
|
|
"instance_id": "01a0806d-3601-7000-ad76-057f1f684881",
|
|
"version": "v0.44.1"
|
|
}
|
|
```
|
|
|
|
That is the whole message. No IP is stored by the collector, no hostname, no
|
|
domain, no account, no counts of anything you have made, nothing about what you
|
|
use it for. The payload is small enough to be printed in full on the settings page,
|
|
and it is printed there — a promise about telemetry is worth exactly as much as
|
|
your ability to check it.
|
|
|
|
## On by default, off in one click
|
|
|
|
The alternative that was considered first was compulsory, and the argument against
|
|
it is practical rather than principled: it cannot be enforced. The domain can be
|
|
blocked, the binary can be patched, and a fork removes it in its first commit. So
|
|
mandatory buys nothing over on-by-default while costing the trust the rest of this
|
|
program works for.
|
|
|
|
Which is why the first administrator to sign in is **told, unprompted**, with the
|
|
real id, the real version and the real address in front of them, and two buttons.
|
|
On by default is only defensible if it is said out loud without being asked; a
|
|
settings page where it is stated fully is not the same thing, because that page is
|
|
opened by people who already suspect there is something to read.
|
|
|
|
**Settings → Data** afterwards: one switch. An explicit "off" survives upgrades.
|
|
|
|
!!! note "This disagrees with the update check, on purpose"
|
|
|
|
`VERDANDE_UPDATE_CHECK` is off unless you ask for it, and its reasoning is that
|
|
a self-hosted app reaching out unbidden has broken the deal its operator made by
|
|
self-hosting. That is the same situation as this one, and the two defaults do
|
|
not agree. The case for treating them differently: the update check reveals an
|
|
instance to a third party (GitHub) and returns something you can act on, while
|
|
this returns nothing and goes to the project. Whether that is a distinction or
|
|
an excuse is a judgement call, and it was made deliberately.
|
|
|
|
## What the collector cannot see, and what it can
|
|
|
|
A request has a source address whether or not anybody writes it down. The collector
|
|
stores none and logs none, and the code is arranged so the address never reaches a
|
|
function that could — the table has nowhere to put one. But the request passes
|
|
through a reverse proxy and a tunnel on the way, and those keep their own logs.
|
|
"We send no IP" would be a half-truth; what is true is that nothing here records
|
|
one.
|
|
|
|
The ping is not authenticated either, so anybody can post a made-up id and inflate
|
|
the count. That is an accepted trade: a token would have to ship inside every
|
|
install anyway.
|
|
|
|
## Running your own count
|
|
|
|
Somebody running a fleet points **Settings → Data → Modtagerens adresse** at their
|
|
own instance, and ticks **Denne instans er tælleren** there. Until that is ticked,
|
|
`POST /api/v1/beacon` answers **404** rather than accepting quietly — an instance
|
|
nobody made a collector must not become a bucket anyone can post into.
|
|
|
|
The collector's page then shows totals, active in 7 and 30 days, and a breakdown by
|
|
version. Publishing that number at `/api/v1/beacon/count` is a second, separate
|
|
opt-in, and it has a floor under it (25 by default): a number that *falls* cannot be
|
|
published as a fact — a bad release, a DNS change that quietly stops the pings, or
|
|
lost rows all look like "fewer people use this now" — and a small number mostly says
|
|
how little it takes to move it.
|
|
|
|
## When it cannot reach
|
|
|
|
The reason is written down and shown on the settings page. A beacon that cannot
|
|
reach its collector otherwise fails in complete silence: it tries again tomorrow,
|
|
the page says "last sent" with a date that quietly gets older, and nobody notices.
|