Files
verdande/docs/beacon.md
T
kristianwindandClaude Opus 5 6154e6b247 feat(udgaver): urd — noter-udgaven siger sit eget navn
Verdande og Urd er to af nornerne i Völuspá, og digtet har dem skære
mærker i træ: *skáru á skíði*. Verdande er det der bliver; Urd er det der
blev, og blev gemt. En instans startet uden opgaveruterne er et andet
produkt for den der bruger den, så den siger et andet navn.

Navnet læses fra udgaven i ÉT sted — Config.ProductName/ProductSlug —
frem for at stå skrevet i teksterne. Frontend-bygget er byte-identisk i
begge udgaver; serveren omdøber de to filer, browseren læser før noget
JavaScript kører.

Der er to titler, og det blev først klart, da e2e-prøven sagde det:
skallens <title>, som serveren omdøber, og rutens egen i <svelte:head>,
som appen sætter bagefter og som overskriver den første. Go-prøven var
grøn over de bytes, serveren sendte, mens fanen sagde "Noter · verdande".
Begge prøver spørger nu om begge.

Omdøbningen er ankret på hele strenge frem for på ordet "verdande", fordi
app.html også indeholder localStorage.getItem('verdande:theme'). Omdøbes
præfikset der og ikke i resten af appen, bliver temaet sat fra én nøgle og
læst fra en anden, og det eneste symptom er det hvide blink, det
indlejrede script findes for at undgå. Tre plantede fejl bekræfter, at det
er de rigtige prøver, der fanger det: et flyttet anker i app.html, en bred
søg-erstat, og en applyRebrands uden fejlretur.

Mailen var det vigtigste sted. appName var et felt med en værdi og ingen
læser, og kommentaren ved siden af sagde, at det stod i hver besked — de
tre steder havde ordet skrevet ud i stedet. En invitation fra en
urd-instans går til et andet menneskes indbakke.

Også omdøbt: web-manifestet (og sendt som application/manifest+json — Go
kender ikke .webmanifest og sniffer den til text/plain, hvorefter
browseren ignorerer manifestet uden at sige noget, og installationsknappen
bare ikke er der), mærket i menuen (ᚢ uruz frem for ᚹ wunjo),
opstartsloggen, passkey-promptens visningsnavn, ICS-kalendernavnet og
udseendet, der er opkaldt efter programmet.

Ikonet er IKKE med: icon.svg er stadig ᚹ, og de tre PNG'er genereres fra
den. Det rører binære, genererede filer og hører i sin egen ændring.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-07 01:11:25 +02:00

78 lines
3.8 KiB
Markdown

# The install count
verdande reports that it exists — and so does urd, which is the same program in
its [notes edition](editions.md). 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 — and not which of the two editions is running, so the count does not
tell the two apart either. 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.