# 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](https://blog.tangled.org/bobbin/) 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](https://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 listening ``` Both 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, `complete` repository count — and reserve process-local figures for `/status`, where a reader is looking at *this process* rather than the archive. `0 listening` is 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.