Files
wownerogue/test
jwinterm 12b887f8f1 feat(chat): NostrChatProvider — global cross-server chat over nostr (Pillar 5)
Layers global chat on the existing ChatProvider seam without changing callers.
NostrChatProvider DECORATES the local SocketChatProvider: every message is still
delivered in-game + persisted exactly as before, and a global message is also
signed and fanned out to nostr relays (relay.smirk.cash). Messages from the relay
are delivered locally-only (never re-published) so there are no echo loops.

North-star fit: relay.smirk.cash's default inbox-outbox policy only lets
REGISTERED Smirk npubs publish — so putting a message in global chat is a concrete
reason to sign in with Smirk. Signer is injectable: a server bridge key today
(createBridgeSigner, must be a registered npub to publish; omit -> receive-only),
each player's own Smirk npub later (chat identity == wallet identity) by swapping
the signer, no provider change.

- src/utils/nostrLoader.js: shared nostr-tools loader (prod require / Jest bundle
  shim), factored from the nip98 pattern.
- src/utils/escapeChat.js: entity-escape + length cap, applied to untrusted remote
  messages (they have no trusted caller, unlike local ones).
- src/network/chat/nostr/{NostrTransport,bridgeSigner}.js: SimplePool transport
  (degrades to noop if nostr-tools/ws unavailable — enabling can't crash the
  server) + server key signer.
- src/network/chat/NostrChatProvider.js: decorator; echo dedupe (own pubkey +
  seen-id FIFO), remote-delivery rate limit, XSS escape on remote content/username.
- src/network/chat/index.js buildChatProvider: opt-in via NOSTR_CHAT_ENABLED /
  NOSTR_CHAT_SCOPE / NOSTR_RELAYS / NOSTR_CHAT_TAG / NOSTR_BRIDGE_SK. chatHandler
  wraps its local provider through it and calls initialize().

Behavior-preserving: NOSTR_CHAT_ENABLED unset (today) => the plain local provider
is returned, chat is byte-for-byte unchanged. Server stays moderation authority
(bans/rate-limit/history in Postgres via the local provider). Tests: +10 (decorate/
fan-out/room-skip, remote deliver+escape+dedupe+rate-limit, factory, real schnorr
round-trip). Suite 54 suites / 382 tests green. Not yet live against relay.smirk.cash.
2026-07-10 18:51:13 -04:00
..