Product and copy context #
This file preserves ecosystem facts and language decisions that should survive individual implementation sessions. It is input to public copy, not a license to turn an inference into a product claim.
Bobbin, Hydrant, and Jetstream V2 #
The Bobbin announcement describes Bobbin as a read-only, API-only Tangled AppView with no permanent local storage. Its in-memory view is rebuilt from an upstream source on restart.
Public follow-up context supplied on 14 July 2026 adds two important details:
- Paul Frazee recommended the upcoming Jetstream V2 backfill for this class of restart hydration.
- Lewis says Bobbin hydrates from its Hydrant twin. Under normal operation, this does not repeatedly request repository CARs from origin PDSes. Origin network load is reserved for exceptional Hydrant recovery, such as corrupted storage or an intentional wipe.
Treat those bullets as attributed public statements until the corresponding architecture or API contract is available in source. The useful architectural shape is:
origin PDS network -> durable Hydrant/Jetstream archive -> ephemeral Bobbin view
The distinction matters. “Rebuilt from upstream every restart” does not imply “fan out to every PDS every restart.” A durable, colocated or nearby archive can make ephemeral consumers cheap without making the network absorb the rebuild.
Attribution #
Jetstream V2 (bluesky-social/jetstream) is designed and written by Jim
Calabro (calabro.io); upstream itself runs on atmos, his
Go atproto library. The archival design — full-network history in columnar
segments behind the live tail — is upstream's choice, which this port carries;
public copy must not present it as Stream's invention. Upstream is pre-1.0 and
unannounced, and its own instances exist independently of this port; do not
describe stream.waow.tech as the only archival jetstream.
Namespace doctrine (decided 2026-08-12) #
Stream serves upstream's NSIDs (network.bsky.jetstream.*) at their
lexicon-canonical /xrpc/ paths. The NSID names the schema contract and its
authority (Bluesky owns the definition), not the server — implementing
someone else's lexicon is ordinary atproto interoperability, exactly as every
PDS serves com.atproto.*. Renaming would break every upstream-compatible
client and redefine the project from "implementation of Jetstream V2" to "a
protocol that resembles it."
If Stream ever adds a surface upstream does not define, that method must NOT
be minted inside network.bsky.* (namespace squatting); it gets an NSID
under a domain we control (e.g. dev.zat.stream.* with a
_lexicon.stream.zat.dev TXT record, published/linted via goat as pollz
does). Today Stream deliberately has zero such extensions.
Claims the public pages may make #
-
Say historical bootstrap only when it is configured and actually running.
-
Distinguish a live-only canary from a whole-network historical archive.
-
While filling, say that completion is not yet proven and subscriptions remain gated. Do not describe the experiment as a completed full-network archive.
-
A sequence number is the upstream network position. Prefer “following the network at sequence …” over shorthand such as “waves are seq …”.
-
The moving waves are ambient animation, not evidence that the document refreshes itself. Do not tell readers to refresh unless the page actually auto-refreshes or offers a meaningful refresh action.
-
If the browser page labels a value as live, that value must update in place. Sequence, event count, uptime, listener count, and the sequence-derived river should advance from one shared metrics sample so they cannot contradict one another.
-
Dated compatibility and load-test results are audit receipts, not timeless statements about the currently running build.
-
Runtime facts belong on /status; the / page should remain legible, welcoming, and honest about whether it is filling or serving.
-
Do not put process-local counters on a page that describes the run. "up N" and "N live events this run" are measured from process start, and the process currently restarts at every backfill batch boundary. Checked on experiment 6 at 55.6 h elapsed, with 16,728,092,842 events archived, the homepage read:
up 12m · 289,369 live events this run · 0 listeningBoth numbers were correct and both were useless: they understated a two-and-a-half-day archive by roughly 275x, because the last restart was 12 minutes earlier. A visitor cannot tell a permanently-young instance from a new one. Prefer durable values — archived event count, elapsed since the run began,
completerepository count — and reserve process-local figures for/status, where a reader is looking at this process rather than the archive.0 listeningis fine and honest: serving is gated until steady state.This is the batch-boundary restart defect surfacing publicly rather than a copy mistake (
gotchas.md,HttpConnectionClosing). Worth fixing in the copy regardless, since a durable counter is the right thing to show even once the process stops dying.
Presentation guardrails #
- Give the quote, attribution, runtime note, endpoint inventory, and footer distinct vertical space.
- Endpoint methods begin in one left-aligned column. Paths begin in a second left-aligned column; do not right-align GET against POST.
- Browser copy must remain usable on a phone. Horizontal scrolling is acceptable for the ASCII river, but the document should start at the left edge on narrow screens rather than centering an overflowing block off-screen.
- Prefer ordinary language over implementation jokes. A clever detail earns its place only when a visitor can understand it without knowing Stream internals.
- Do not promote the implementation language in the homepage footer. The build identifier and source link are useful provenance; “written in Zig” is not a visitor-facing capability.