> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tuturuuu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Hive Realtime Runbook

> Operating notes for the Hive WebSocket service and satellite app deployment.

Hive realtime lives in `apps/hive-realtime`. It is a Bun WebSocket service used
only by Hive; do not replace it with Supabase Realtime. The shared protocol and
Yjs helpers live in `@tuturuuu/realtime/hive` so `apps/hive`,
`apps/hive-realtime`, and `apps/web` use the same message schemas.

## Required Environment

* `HIVE_REALTIME_TOKEN_SECRET`: preferred shared HMAC secret used by `apps/web`
  to mint short-lived join tokens and by `apps/hive-realtime` to validate them.
  If this is not set, both services fall back to the existing platform
  Supabase service secret from the shared `apps/web` environment. This keeps
  Hive deployable with the same Supabase setup as `apps/web`, while still
  allowing operators to rotate Hive realtime signing independently later.
* `HIVE_REALTIME_URL`: internal server URL used by `apps/web` and `apps/hive`
  when they need the service-side endpoint.
* `NEXT_PUBLIC_HIVE_REALTIME_URL`: browser-facing WebSocket URL, normally
  `wss://hive.tuturuuu.com/realtime` in production.
* `HIVE_DATABASE_URL`: Postgres URL for the dedicated Hive product database.
  Realtime uses this database to load compacted CRDT snapshots, append Yjs
  update bytes, and persist audit events. Supabase is not the Hive product store
  after backfill.
* `INTERNAL_WEB_API_ORIGIN`: Docker-internal web gateway origin used by
  `apps/hive` API rewrites. In production Compose this should resolve to
  `http://web-proxy:7803` so editor saves do not leave the Docker network and
  re-enter through the public web origin.
* Supabase credentials already used by `apps/web`, especially
  `NEXT_PUBLIC_SUPABASE_URL` with `SUPABASE_SECRET_KEY`. `SUPABASE_SERVER_URL`
  may still override the server-side URL when the deployment needs a
  Docker-internal Supabase origin. These credentials are identity/session
  infrastructure only for Hive realtime token validation and web auth.

`apps/hive` shares the same Supabase setup as `apps/web`. Docker runtime env
comes from `.env.local` with the same `apps/web/.env.local` fallback, and the
production Hive image receives the `web_env` BuildKit secret during `next build`
so prerendered auth routes can resolve `NEXT_PUBLIC_SUPABASE_URL` and related
platform Supabase variables.

When Hive is exposed as `https://hive.tuturuuu.com` through a Cloudflare tunnel
to `http://localhost:7814`, keep browser-facing realtime URLs secure. Use
`NEXT_PUBLIC_HIVE_REALTIME_URL=wss://hive.tuturuuu.com/realtime` or leave it
unset so the client falls back to the same-origin `/realtime` route. Keep
Docker-internal or host-local forwarding in `HIVE_REALTIME_HTTP_URL` or
`HIVE_REALTIME_URL`; do not expose `ws://...` as the browser URL for an HTTPS
page.

## Local production-style servers (Turbo)

From the repo root, Turbo runs workspace dependency builds first, then starts
each process (see `turbo.json` tasks `@tuturuuu/hive#serve:hive` and
`@tuturuuu/hive-realtime#serve:hive-realtime`):

* `bun serve:hive` — production Next server for Hive on port `7814` (requires a
  prior `next build` output; Turbo schedules `build` before `serve:hive`).
* `bun serve:hive-realtime` — Bun WebSocket server (default port `7815` via
  `PORT`).

## Blue/Green Deployment

`docker-compose.web.prod.yml` runs `hive-blue`, `hive-green`, and
`hive-realtime` with the same production Supabase environment as `apps/web`.
`scripts/docker-web/blue-green.js` promotes Hive with the same active color as
web and waits for the target Hive color before proxy handoff.

The generated nginx config routes:

* `hive.tuturuuu.com/` to the active `hive-{color}` satellite app on port
  `7814`.
* `hive.tuturuuu.com/realtime` to `hive-realtime` on port `7815`.

The production proxy also listens on host port `7814`, so a Cloudflare tunnel
mapping `hive.tuturuuu.com` to `localhost:7814` still goes through the
blue/green proxy instead of bypassing it to a stale single Hive container.

`scripts/watch-blue-green-deploy.js` watches the Hive Dockerfiles, package
manifests, realtime source files, and `docker-compose.web.prod.yml`; changes to
these files trigger the watcher container refresh path.

## Protocol

Clients connect with a short-lived token from
`POST /api/v1/hive/servers/:serverId/realtime-token`. Tokens include user ID,
server ID, role, expiry, and event scopes.

Accepted client messages are CRDT sync, awareness, compatibility, and health
messages:

* `sync.hello`
* `sync.update`
* `sync.diff`
* `sync.compacted`
* `awareness.update`
* `presence`
* `server.status`
* `error`
* `world.event`
* `world.event.applied`

The durable shared world is a Yjs document per server. Clients send encoded Yjs
deltas as base64 in `sync.update`, and the realtime service appends those bytes
to `hive_crdt_updates`. State-vector sync lets a reconnecting client request
only missing updates, while periodic compaction stores merged snapshots in
`hive_world_states.crdt_snapshot`.

`revision` is a compatibility display value backed by `op_seq`; it is not a
write precondition for commutative CRDT world edits. Money, item ownership,
warehouses, trades, LLM spend, and bankruptcy still go through the `apps/web`
Hive APIs and Hive Postgres transactions. Realtime broadcasts only the committed
visual projections for those authoritative writes.

`world.event` and `world.event.applied` remain as temporary compatibility
wrappers for older full-world edit flows. The service converts accepted payloads
into CRDT updates before broadcasting them to the room.

Do not store full `world_data` snapshots in `hive_world_events` for compatibility
events. The current world snapshot belongs in `hive_world_states`; event rows
should keep compact metadata and payloads so high-frequency editor saves do not
double the amount of JSON written per operation.

Awareness is ephemeral and TTL-based. It includes user ID, display name, avatar
URL, role, color, active tool, selected entity, terrain cursor, camera position,
world avatar position, viewport focus, and `lastSeenAt`. Do not persist
awareness state into `hive_world_states`, `hive_crdt_updates`, or audit events.

Operationally, the client should expect token refresh on reconnect,
exponential backoff, heartbeat/TTL presence cleanup, actor echo suppression,
offline edit queue replay, cursor/position throttling, and slow-client
backpressure handling.
