@volter/twin-stream
v0.1.37
Published
Local GetStream Chat twin (chat.stream-io-api.com) — users/channels/messages/reactions/moderation, real HS256 server+user JWTs signed with the API secret, built on @volter/world-core.
Readme
@volter/twin-stream
A local, stateful, vendor-faithful twin of the GetStream Chat API (chat.stream-io-api.com),
built on the shared @volter/world-core kernel. Point the unmodified official stream-chat SDK at it
(client.setBaseURL(...)) and it speaks Stream Chat back — users, channels, members, messages,
reactions, channel types, devices, and moderation, all backed by the append-only event/action log.
Not to be confused with HTTP streaming — this is GetStream.io, the chat/feeds/video vendor.
The core: real HS256 auth
Stream authenticates every request with an HS256 JWT signed with the app's API secret:
- a server token (
{ server: true }) for full admin access, and - a user token (
{ user_id }, optionalexp/iat) that the SDK'screateToken(userId)mints.
The twin mints and verifies these with genuine node:crypto HMAC-SHA256 over the configured
secret (STREAM_API_SECRET, default qa-stream-api-secret). A token the twin (or the real SDK)
mints verifies against the secret unmodified; a missing/tampered/wrong-secret token gets a real
401 from the handler — faithful to Stream's edge. Auth is not a stub.
Usage
bun run packages/twin/stream/src/cli.ts serve --port 4500 --secret qa-stream-api-secret
# then point the SDK: StreamChat.getInstance(apiKey, secret).setBaseURL('http://127.0.0.1:4500')CLI: world-stream serve|conformance [--port N] [--root DIR] [--secret S] [--read-only].
Coverage
This manifest is the real Stream Chat surface as the denominator — coverage is honest and
partial: core users/channels/messages/reactions/moderation/devices + the full token crypto are
modeled and proven; a long tail (threads, search, read state, polls, attachments, RBAC, automod,
campaigns, …) is enumerated as todo. Run bun scripts/manifest-baseline-one.ts stream for the live
count (currently done=36 / total=83, regressions=0). Each done has a failable offline
verify() (real create→read→assert values + the vendor's negative 4xx).
API-first: Stream's dashboard is an internal admin console, not a dev-facing data UI, so this pack has no React mirror and no UI capabilities (per the contributor recipe §"How a twin should work" — omit rather than fabricate). Coverage = API + connector + crypto.
Planned (todo)
- WebSocket gateway — serve the persistent connect/watch protocol and deliver
message.new, typing and presence frames to connected clients (today only the REST state those events reflect is modeled). - Attachment bytes — persist uploaded file/image bytes and serve them at the url the upload API returns.
- Stream Video call state over REST — create/get/update a call, membership and the join token.
World operations
syncStreamFromReal observes users and channels through an injected client. The kernel invokes
performStreamAction for supported real execution and owns receipts. Simulated requests read
and write the local tree. Branch, fetch, push and deploy follow the
shared model, rather than a package-specific commit loop.
readOnly forbids writes (405); an unmodeled route fails like the vendor (404, error code 16).
