From 33bb33b7cf2556aff448997345fbea8a03420324 Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Sat, 29 Aug 2026 01:17:52 -0500 Subject: [PATCH] =?UTF-8?q?page:=20strata=20redesign=20=E2=80=94=20namespa?= =?UTF-8?q?ce=20layers,=20reader=20line,=20ask-the-tail=20duckdb-wasm=20pa?= =?UTF-8?q?nel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rows are namespaces whose height follows log(events); click splits one into its collections (fetched on demand); find pins any authority; more layers grows the top-N. The tail panel lists a namespace's public parquet partitions via /api/partitions and runs SQL over them in the browser. Era bands keyed on the bootstrap end date, not witnessed spans. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01B927dNwNKNYsbQdUoNJwHS --- src/index.ts | 18 +- src/page.html | 602 +++++++++++++++++++++++++++----------------------- 2 files changed, 347 insertions(+), 273 deletions(-) diff --git a/src/index.ts b/src/index.ts index 9902e0a..339c4f9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -288,6 +288,20 @@ async function collections(url: URL, env: Env): Promise { return json({ collections: results }, 200, { "cache-control": "public, max-age=300" }); } +const PUBLIC_BASE = "https://pub-735e1688181b45e49c925eed81fe2da7.r2.dev"; + +/** which drained segments hold rows for a namespace, as public parquet URLs the page can hand to duckdb-wasm. + * app.bsky is private by policy, so it is refused here. */ +async function partitions(url: URL, env: Env): Promise { + const ns = url.searchParams.get("ns"); + if (ns === null || !/^[a-z0-9-]+\.[a-z0-9-]+$/i.test(ns)) return json({ error: "ns must be an authority like fm.teal" }, 400); + if (ns === "app.bsky") return json({ error: "app.bsky rows are not public; use the aggregates" }, 403); + const listed = await env.PUBLIC.list({ prefix: `events/ns=${ns}/`, limit: 1000 }); + const urls = listed.objects.map((o) => `${PUBLIC_BASE}/${o.key}`); + const bytes = listed.objects.reduce((a, o) => a + o.size, 0); + return json({ ns, files: urls, bytes, truncated: listed.truncated }, 200, { "cache-control": "public, max-age=120" }); +} + async function namespaces(env: Env): Promise { const { results } = await env.DB.prepare( "SELECT ns, SUM(count) AS count, COUNT(DISTINCT nsid) AS members FROM segment_collections GROUP BY ns ORDER BY count DESC", @@ -310,13 +324,15 @@ export default { return collections(url, env); case "/api/namespaces": return namespaces(env); + case "/api/partitions": + return partitions(url, env); case "/": return new Response(page, { headers: { "content-type": "text/html; charset=utf-8", "cache-control": "public, max-age=300" } }); case "/api": return json({ name: "strata", what: "per-segment, per-collection event counts of the stream.waow.tech archive", - endpoints: ["/api/progress", "/api/heat?step=N&top=N&group=namespaces|collections", "/api/heat?step=N&ns=", "/api/namespaces", "/api/collections?ns="], + endpoints: ["/api/progress", "/api/heat?step=N&top=N&group=namespaces|collections", "/api/heat?step=N&ns=", "/api/namespaces", "/api/collections?ns=", "/api/partitions?ns="], source: "https://tangled.org/zat.dev/strata", }); default: diff --git a/src/page.html b/src/page.html index e7798fe..67015a0 100644 --- a/src/page.html +++ b/src/page.html @@ -4,263 +4,285 @@ strata - - + + + + + +
-

strata

-

the shape of the stream.waow.tech archive, by lexicon — read from the sealed segments, not the process

+ ~  s t r a t a  ~ + · reading the archive +

the stream archive, cut across. every lexicon on the network is a layer: thickness is how much of it there is, shade is how it comes and goes.

+
+
+
—segments
+
—events
+
—namespaces
+
—collections
+
-
loading…
+
+ + + + + +
-
- - - - -
+
+ +
hover a layer to read it · click a namespace to split it into its collections
+
-
-
- - +
+ nothing in that column + fewermore +
-
fewermore
-
- x is archive position (segment index; each segment ≈ 3.2M events, ~270 MB). the dates under it are when - stream witnessed the events, not when they happened: the bootstrap era replayed years of history - inside a six-day window from 2026-07-28, so those columns are dense; segments after it are live-era, about - two minutes each. counts come from each segment's collection index; account/identity/sync markers carry no - collection and are excluded. "other" folds every collection outside the top rows. -
-
- +

columns are archive position: sealed segments in order, ≈3.2M events each. the dates are when stream witnessed the events, not when they happened — the bootstrap band replayed years of history inside six days from 2026-07-28, so it is dense; the live band is about two minutes per segment. account, identity and sync markers carry no collection and are not counted. "other" is every namespace below the ones shown.

+ + +
ask the tail
+
+
+ + pick one + +
+
+ +
every row this namespace ever wrote — rows(seq, time_us, did, kind, op, collection, rkey) — queried in your browser with duckdb, straight from the public archive. app.bsky is aggregates-only by policy.
+
+
+
+
-- 2.51.2