diff --git a/community-runbook.md b/community-runbook.md index 6f5dc82..fa3531d 100644 --- a/community-runbook.md +++ b/community-runbook.md @@ -4,6 +4,36 @@ The public community should be a live product proof: people can watch two different agents use one ContextStream project, ask setup questions, and see approved project decisions survive handoffs. +## Provisioning paths + +A Buzz community is selected by its relay URL. Use one of Buzz's supported +operator paths: + +- **Hosted relay:** use Buzz's [one-click Railway + deployment](https://railway.com/deploy/buzz-relay-block), then pin the deployed + image/version and record the public HTTPS/WSS URL. +- **Owned infrastructure:** use Buzz's production + [Compose bundle](https://github.com/block/buzz/tree/main/deploy/compose) on a + VPS with DNS and TLS. The root Buzz development Compose file is not the + public deployment bundle. + +Whichever path is chosen, the community owner must control the hosting account, +relay signing key, DNS, database/object-store backups, and moderator identities. +Do not put those credentials in this repository or in ContextStream project +memory. + +Before calling the community public, retain this evidence: + +- the pinned Buzz release or commit and deployment configuration; +- a successful relay `/_liveness` check over the public origin; +- a working `wss://` connection from a clean Buzz client; +- a tested backup and credential-rotation procedure; +- the owner and moderator public keys, with private keys held outside the repo; +- closed membership during validation, followed by an explicit admission + policy for launch; +- both agent identities online, stoppable, and restricted to the public-safe + ContextStream demo project. + ## Community structure - `#start-here` — the five-minute setup, permission model, and code of conduct diff --git a/reference.test.mjs b/reference.test.mjs index 7cdf79e..d2b84ca 100644 --- a/reference.test.mjs +++ b/reference.test.mjs @@ -73,12 +73,22 @@ test("upstream contribution stays small and preserves the product boundary", asy assert.doesNotMatch(upstream, /install ContextStream as a Buzz dependency/i); }); +test("community runbook requires a real public relay and operator evidence", async () => { + const runbook = await read("community-runbook.md"); + assert.match(runbook, /one-click Railway/); + assert.match(runbook, /production\s+\[Compose bundle\]/); + assert.match(runbook, /\/\_liveness/); + assert.match(runbook, /working `wss:\/\//); + assert.match(runbook, /tested backup and credential-rotation procedure/); +}); + test("examples contain no live-looking ContextStream or Buzz secrets", async () => { const files = [ await read("README.md"), await read("buzz-acp.env.example"), await read("demo-script.md"), await read("claude-settings.local.example.json"), + await read("community-runbook.md"), ].join("\n"); assert.doesNotMatch(files, /cs_(live|test)_[A-Za-z0-9]{16,}/); assert.doesNotMatch(files, /nsec1[023456789acdefghjklmnpqrstuvwxyz]{24,}/);