2026-10-22 · 2026-10-22__telemetry-over-an-append-lane.md
Who reads this site: anonymous telemetry over an append lane
Status: accepted and being built. Brief by Dinis Cruz (editor), spoken on 22 October 2026; written up by dev@php.newsroom. Build brief, the kind an agent executes.
The ask, in the editor's words
Add logging using an append lane. Capture who is visiting the website, which pages they see, and where they come from. All of it from the front end: there is no back end. Not the IP address: the region (London, Surrey) and the country, which the browser can get from a lookup service. Keep it in a separate vault, and share that vault's key with the editor. Write this as an article brief in the admin section first, then implement it.
What exists to build on
- sgit.ai's build brief "Telemetry from a published vault" and the append-lane API: a write-only channel gated by a token, a blind
{"ok": true}response, no account needed to send, lanes outside the commit tree. The routes are on dev.send.sgraph.ai only. - The newsroom's own reading meter already encrypts a reader's share in the browser to a published public key (sgit's hybrid envelope v2: AES-256-GCM wrapped with RSA-OAEP-SHA256) and posts it to a lane. The same forty lines of Web Crypto carry an event.
- The CLI has
sgit pki keygen / export / encrypt / decryptand no lane commands, so draining is HTTP: list with the enum key, fetch, decrypt locally, mark processed.
The design
1. A separate, private telemetry vault (id 84wr8mib) holds the key pair, the drained events and the daily reports. Its vault key, the enum key and the key pair's passphrase stay with the editor and the drainer; none of them is in this repository.
2. The site publishes, in data/telemetry.json, the three things a visitor's browser needs and may hold: the telemetry vault id, the append token and the recipient public key. The append token is write-only and the write response is blind, so a visitor who reads it out of the page can add rows and learn nothing. This is the one credential shape that survives publication.
3. On every page, assets/telemetry.js mints a random session id in memory, asks a geolocation service for the visitor's country, region and city (the service sees the IP; the event does not carry it), builds one event, encrypts it to the public key and posts it to the lane. It never blocks the page, fails silently, and rate-limits itself to one event per page per session.
4. admin/build/telemetry_drain.py lists the lane with the enum key, fetches pending files, decrypts them with the private key, writes them as JSON lines into the telemetry vault under drain/<date>/, marks them processed, and computes reports/<date>.json: counts by page, country, region, referrer host and site version. The site's admin section publishes the counts, never the rows.
5. A visible notice on every page says that anonymous usage events are sent and what they contain, because opening a page on this site now phones home, and the estate's rule is to say so where it happens.
The event
{ "v": 1, "site": "php.oct.2026.newsroom.sgit.ai", "ver": "0.2.3", "ts": "2026-10-22T12:00:00Z",
"sid": "8 random hex", "path": "/code/index.html", "ref": "news.ycombinator.com",
"country": "GB", "region": "England", "city": "London", "lang": "en-GB", "screen": "desktop",
"tz": "Europe/London" }
No IP, no user agent string, no cookie, no name. ref is the referrer's host only. city is whatever the lookup returns, which is the ISP's idea of a city, not a location.
What it cannot do, said up front
- It cannot prove anything. Every visitor holds the token and the public key, so any row can be forged and the lane can be flooded (1000 pending files per token, then 507). Rows are claims; the reports say so.
- It cannot tell who. There is no identity; the session id is random and dies with the tab.
- It cannot see the server's view. dev.send.sgraph.ai sees lane activity, sizes, timing and the requesting IP; the geolocation service sees the IP too. "The content is encrypted" is true; "the traffic is invisible" is not.
- Readers with blockers will not appear. The counts are a floor.
Deliverables
data/telemetry.json(public lane descriptor),assets/telemetry.js, the notice in the footer, this brief.admin/build/telemetry_drain.py, run by whoever holds the telemetry vault key;admin/telemetry/index.htmlshowing the latest report.- The telemetry vault:
README.md,identity/(public bundle, passphrase-protected private key),drain/,reports/. - An end-to-end test: one event written from the CLI, listed with the enum key, fetched and decrypted, before the first page ships.
Open questions for the editor
- Which geolocation service to trust with visitors' IPs. The first release uses ipapi.co with ipwho.is as fallback; both are third parties and both see the IP. A Cloudflare-fronted site could use
/cdn-cgi/traceinstead and leak nothing to a third party. - Whether the reports should be public (counts only) or stay in the vault. The first release publishes counts.
- Whether the editor wants the city at all. Region and country answer the question asked; the city is noise from ISPs.