Skip to content

Conversation

@hunmar
Copy link

@hunmar hunmar commented Jan 4, 2026

This PR enhances the upstream feature/ephemeral-chat branch with additional features for better rate limiting, local testing support, and comprehensive documentation.

Key Additions

  • Advanced Rate Limiting: Cooldown (2s) + burst limit (5 messages/30s) with visual UI feedback
  • Nickname System: Optional ephemeral nicknames stored in localStorage
  • TCP Relay Server: Workaround for DHT discovery issues in WSL2/Docker environments
  • Visual Cooldown Timer: Input blocking with countdown display during rate limit
  • AGENTS.md: Comprehensive documentation for AI coding agents (800+ lines)

Changes from Upstream

New Files

File Description
AGENTS.md Deep technical documentation for AI agents
relay-server.js Simple TCP relay for local multi-node testing
src/state/ratelimit.js ChatRateLimiter class with burst + cooldown logic

Enhanced Features

Feature Upstream This PR
Rate Limiting Simple 5s cooldown 2s cooldown + 5/30s burst limit
Rate Limit UI Prompt color change Disabled input + countdown timer
Nicknames None Optional, localStorage persisted
Local Testing DHT only DHT + TCP relay fallback
Documentation README only README + AGENTS.md

Technical Changes

  • src/config/constants.js: Added CHAT_MIN_COOLDOWN, CHAT_BURST_LIMIT, CHAT_BURST_WINDOW, CHAT_MAX_LENGTH, CHAT_NICK_MAX_LENGTH
  • src/p2p/swarm.js: Added RELAY_PORT support, connectToRelay(), getAllConnections()
  • src/p2p/messaging.js: Integrated ChatRateLimiter, signature verification for chat
  • src/web/routes.js: Enhanced /api/chat with rate limiting and nickname support
  • public/app.js: Cooldown timer UI, nickname modal, improved message display
  • public/index.html: Nickname modal, cooldown indicator element
  • public/style.css: Cooldown animation, nickname modal styling

Protocol Enhancement

CHAT Message Format

{
  "type": "CHAT",
  "id": "<node-public-key>",
  "nick": "optional_nickname",
  "msg": "message content",
  "ts": 1704326400000,
  "hops": 0,
  "nonce": 12345,
  "sig": "<signature of 'chat:${msg}:${ts}'>"
}

Rate Limiting Rules

  • Cooldown: 2 seconds between messages
  • Burst: Maximum 5 messages per 30-second window
  • Response: 429 with cooldown field in milliseconds

Local Testing with TCP Relay

For environments where DHT discovery fails (WSL2, Docker, corporate networks):

# Terminal 1 - Start relay
node relay-server.js

# Terminal 2 - Node 1
RELAY_PORT=4000 ENABLE_CHAT=true PORT=3000 node server.js

# Terminal 3 - Node 2
RELAY_PORT=4000 ENABLE_CHAT=true PORT=3001 node server.js

Cooldown Timer

When rate limited, the input is disabled and shows remaining seconds:

  • Orange pulsing countdown (e.g., "1.8s")
  • Input field grayed out
  • Re-enables automatically when cooldown ends

Nickname Modal

Click [set nick] to open modal:

  • Alphanumeric only, max 16 characters
  • Persists in localStorage across sessions

Test Plan

  • npm install && npm start — node starts without errors
  • Open dashboard with ENABLE_CHAT=true — chat panel visible
  • Send message — appears in chat, cooldown timer starts
  • Rapid messages — input disabled, timer counts down
  • Set nickname — persists after refresh
  • Two-node relay test:
    node relay-server.js &
    RELAY_PORT=4000 ENABLE_CHAT=true PORT=3000 node server.js &
    RELAY_PORT=4000 ENABLE_CHAT=true PORT=3001 node server.js
  • Messages propagate between nodes via relay
  • direct count shows 1 (relay connection counted)

Breaking Changes

None. All changes are additive and backward compatible with existing nodes.

Related PR

#20

Combines upstream's ephemeral chat implementation with additional features:

From upstream:
- Peer map with Leaflet-based world visualization
- Minimizable chat terminal with persistent state
- System messages for peer connect/disconnect
- ENABLE_CHAT environment variable toggle

Added enhancements:
- Nickname system with localStorage persistence
- Advanced rate limiting (2s cooldown + 5/30s burst limit)
- ChatRateLimiter class with proper burst tracking
- TCP relay server for local testing (WSL2/Docker workaround)
- Cryptographic signature verification on chat messages
- AGENTS.md documentation for AI agents

Technical changes:
- CHAT message protocol with id, nick, msg, ts, hops, nonce, sig
- ChatRateLimiter replaces simple Map-based rate limiting
- SwarmManager supports RELAY_PORT for TCP relay connections
- getAllConnections() method for unified connection handling
- Update SSE documentation to reflect simplified broadcast method
- Update ChatRateLimiter documentation (instantiated in routes.js)
- Fix routes.js to use getSwarm().connections.size consistently
- Update frontend notes for nickname storage and chat handling
- Add cooldown indicator element showing remaining seconds
- Disable input field while on cooldown
- Visual feedback with orange color and pulsing animation
- Start cooldown timer based on server response
- Block send attempts during cooldown period
The getAllConnections() method was added to SwarmManager to unify
connection counting across both DHT (Hyperswarm) and TCP relay modes.

Why this matters:
- getSwarm().connections only returns Hyperswarm DHT connections
- extraConnections stores TCP relay connections (RELAY_PORT mode)
- Without getAllConnections(), using RELAY_PORT shows "direct: 0"

Changes:
- server.js: Use getAllConnections().size for SSE broadcasts
- server.js: Use getAllConnections().size for diagnostics logging
- routes.js: Use getAllConnections().size for all API responses
- AGENTS.md: Document connection types and getAllConnections() method

This ensures consistent connection counting regardless of whether
the node is using DHT discovery or TCP relay for local testing.
@DataDalton
Copy link
Contributor

DataDalton commented Jan 4, 2026

Please remove agents.md, I recommend opening a new PR and creating proper documentation for humans, otherwise you're grouping too much into a single PR

Documentation should be in a separate PR to keep feature changes focused.
@lklynet lklynet deleted the branch lklynet:feature/ephemeral-chat January 6, 2026 00:46
@lklynet lklynet closed this Jan 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants