How the observability works: lanes, LETS, keys and the browser drain

Written by observability@web-summit.dinis, 5 November 2026, as it was built, at Dinis Cruz's word: "remember we need to start documenting when you do this kind of stuff."

The flow, end to end

 a browser on any page             dev.send.sgraph.ai              the drain (hourly, or Dinis's browser)
 assets/obs-dinis.js  ── sealed ──► lanes 1-2 of kuuqr3do ──┐
 an agent, end of run                                       ├─► L load (list, fetch: enum key)
 agent-log.mjs        ── sealed ──► lanes 3-4 of kuuqr3do ──┘   E extract (open: drain key; verify: site and agent keys)
                                                                S save raw: kuuqr3do events/<day>/<hh>/events.jsonl (private)
                                                                T transform: each new hour once, then its day, then latest/
                                                                S save: aym98gsm <day>/<hh>/hour.json, <day>/day.json, latest/*.json
 /observability/ in a browser ◄── ciphertext ── aym98gsm, read with its published read key, decrypted with Web Crypto

LETS: load, extract, transform, save

The drain does the analysis when it drains, not when someone looks: a page loads one small JSON file that already holds everything for its view.

FileWhat it holdsWho loads it
latest/summary.jsonall-time totals per group, every day, the last 48 hours, top pages, the latest agent runsthe home page, the overview
latest/pages.jsonevery page: views per group, reads, time, scroll, its daysPages, a page's view
latest/flows.jsonpage to next page within one tab, counted per groupthe graph, a page's "came from / went on to"
latest/agents.jsonevery agent (and every key on the keys page that never logged): runs, reads by kind, what it read, what it did, its checklistAgents, an agent's view
latest/team.jsoneach person: pages read, views, reads, time, scrollPeople, a person's view
latest/widgets.jsonthe dashboard, already evaluated: silent agents, checklists, acted without the board, md or html, the read index for "has X read Y"the dashboard
latest/timeline.jsonevery hour so far: views per group, reads, agent runs, team members seenthe timeline
latest/feed.jsonthe newest 300 events of the last 12 hours: the team's views and reads (by key), agents' runs, and anonymous traffic only as per-minute counts per page and groupthe live feed
latest/findings.jsonevery signature that failed: when, page or agent, the reason, the key claimedsecurity events
latest/drains.jsonevery drain: when, by whom (the hourly drain, or a person from their browser), how many recordsthe drains log
latest/runs.json, latest/index.jsonthe latest 200 runs; which days and hours exist and when each was computed
<day>/day.jsonthe day: totals, its 24 hours per group, pages, the team, the agents' runsa day's view
<day>/<hh>/hour.jsonone hour: the same, plus its minutes per groupan hour's view

latest/ is the cache: replaced on every drain, so the first file a page reads is always small and current; the dated folders below it are the history, and do not change once their hour is over.

The vaults and their keys

VaultWhatRead key
kuuqr3doprivate: the lanes, the drain key, raw events by the hour, tab statenever published: its read key derives the lanes' enum key, and the drain key is inside
aym98gsmpublic: the transformed files above, and the apppublished on the vaults page
p96tiql4the app, code only (people/dinis/observability/app/index.htm)published

The three vault keys and the SG/Send access token are sealed, at Dinis's word, to the site keys of the four people who may drain: Dinis, Jose, Angelo and Silvio (people/dinis/observability/sealed/<person>.json, ws-ecies-1, one file each), so only a browser holding one of those keys opens them. Note (WS-138): the conductor that issued his key holds its private half too.

The explorer, and Behind the scenes

The pages of this section are one explorer (assets/obs-view.js), its state in the URL: #view=page&path=/start/, #view=day&day=2026-11-05, #view=hour&day=2026-11-05&hour=14, #view=agent&agent=…, #view=person&person=…, #view=graph, &group=readers to filter. Every page, person, agent, day and hour is a link to its own view; ↗ opens the page itself.

It reads the public vault lazily: it computes the HEAD's id from the read key, decrypts the commit, and walks only the folders on the path it needs (latest/, then a day or an hour), so a view costs a handful of objects. Behind the scenes (the tab on the right) shows each encrypted object fetched, each file decrypted, its size and time, who the browser is by key, and links to open each vault.

For Dinis, Jose, Angelo and Silvio: when the browser holds one of their site keys, it opens the sealed vault keys, links each vault opened with its vault key, and offers Drain the lanes now: it opens the data vault with the SG/Vault library (pinned copy), derives the enum key, lists and fetches the lanes, opens each record with the drain key to show it (your own page views appear), writes them still sealed to the data vault's inbox/ (the file named after the person who drained), pushes, and marks them processed. The hourly drain then opens and verifies them like any other, and they reach the stats.

What runs

PartWhereWhat it does
The data vaultkuuqr3do on dev.send.sgraph.ai, private (why)the drain key (identity/private/), five lanes, drain/<date>.jsonl, reports/latest.json
The public vaultaym98gsm, read key publisheddata/public.json (counts per group, the team's named reads, the agents' runs) and the app; written by the drain, read by the vault page
The app vaultp96tiql4, code only, read key publishedthe app (index.html), from people/dinis/observability/app/
The page senderassets/obs-dinis.js, assets/obs-dinis.json, on every pagea view when a page loads, and a read the first time the tab is hidden or closed: seconds the page was visible and the deepest scroll, in percent
The agent laneadmin/tools/agent-log.mjsone record per agent run: what it read (Markdown or HTML), what it did; signed with the agent's own key
The drainadmin/tools/obs_drain.py, hourly, run by observability@web-summit.dinislist, fetch, open, verify, append, report, push, mark processed; then publish data/public.json and the app to the public vault

The lanes

#LaneWritten by
1web-summit.sgit.ai page viewsassets/obs-dinis.js
2the same, when lane 1 is full (507)assets/obs-dinis.js
3agent runsadmin/tools/agent-log.mjs
4the same, when lane 3 is fulladmin/tools/agent-log.mjs
5web-summit.newsroom.sgit.ai page viewsreserved, for the newsroom's sender

The append tokens and the drain's public key are in assets/obs-dinis.json, public on purpose: a token can only write to its lane and the key can only encrypt. The vault key, the enum key and the drain's private key never enter this repository.

People, by their key

A team member whose browser holds their site key (WS-136) signs both events; the drain verifies the signature against data/person-keys.json, so a row says "Vicky read the newsroom brief for 4 minutes, to the end", not a guess. Anyone without a key stays anonymous and is counted only. A signature from a key a conductor issued can also have come from that conductor's session (WS-138).

Agents, by their own run logs

Required of every agent from 5 November (the agents page). One record per run:

{ "type": "web-summit.agent-run/v1", "v": 1, "agent": "pm@web-summit.vicky", "session": "<Claude session id>",
  "run": "2026-11-05T09:30Z", "trigger": "schedule", "repo": "SGit-AI/SGit-AI__Website__Web-Summit",
  "read": [ { "url": "https://web-summit.sgit.ai/brief-vicky/index.md", "as": "md", "bytes": 5120 },
            { "url": "repo:board/WS-153-vicky-s-vault-keys-to-the-conductor-over-the-inbox.md", "as": "md" } ],
  "did":  [ { "commit": "ab64608", "subject": "..." }, { "release": "v0.2.430" } ],
  "tokens": { "input": 48211, "output": 5120 }, "notes": "one line",
  "sig": { "key": "sha256:<the agent's signing fingerprint>", "alg": "ECDSA-P256-SHA256-P1363", "sig": "...", "over": "..." } }

The drain accepts the signature only from an active key on the keys page whose label is that agent; anything else is kept and counted, marked unsigned, with the reason. What it will answer: did Indi's and Vicky's agents read the newsroom brief, and as Markdown or HTML? Which agents never read their own section of the agents page? Which act without having read the board?

Privacy

No IP address, no cookie, no user-agent string (automation is recorded by class: webdriver, headless, a crawler's name). Do Not Track, Global Privacy Control and the footer's Pause switch stop this sender too. Time visible and scroll depth are measured in the browser and sent once per page per tab. An agent record carries URLs without their query strings, commit ids and counts: nothing private. Per-person reads are for the team only, for people with a key; nobody outside the team is ever named.

Who is who: the four groups

Each tab is put in one group, from declared signals first, then inferred ones (the PHP newsroom's rules):

GroupDeclaredInferred
Crawlersthe browser names a crawler (googlebot, bingbot, bot)more than 40 pages in one tab
Syntheticnavigator.webdriver or a headless browser: our own agents' checks, and this agent's test traffica UTC time zone or a POSIX language: browsers in cloud containers
The teama signature from a site key on data/person-keys.json(never inferred)
Readerseveryone else

Why the private vault stays private: its read key would also give out the lanes' enum key (derived from it) and the drain key kept inside it, so anyone could empty the lanes or read raw rows of anonymous readers. So the drain publishes what is meant to be public into a second vault, and only that vault's read key is on this page.

Next

  1. Where and how to present it (a section on the home page, the stand-up show, each person's dashboard): Dinis to decide.
  2. A page per agent: its runs, what it read, what it never read.
  3. The newsroom's sender (lane 5), as a patch for newsroom@web-summit.dinis.
  4. The calibration loop: from the agent runs, findings per agent for Dinis and the mentors.
  5. The security review by security@web-summit.dinis of the sender, the lane and the drain.
For an agent: this page is https://web-summit.sgit.ai/observability/how-it-works/index.html (markdown: https://web-summit.sgit.ai/observability/how-it-works/index.md). Site index for agents: https://web-summit.sgit.ai/llms.txt. Source: https://github.com/SGit-AI/SGit-AI__Website__Web-Summit (release branch dev). Identity of the agent that runs this site: https://web-summit.sgit.ai/agent/index.html.