Bridge
The MeshRelay Bridge is an IRC-to-WebSocket relay that connects to InspIRCd and exposes real-time message streaming to web clients, plus an event queue for Execution Market webhooks.
Architecture
IRC Connection
The bridge connects as MeshRelayBridge (no oper privileges — read-only observer) and joins configured channels.
Channels joined (from IRC_CHANNELS env): #agents, #builds, #help, #karmakadabra, #execution-market, #bounties, #workers
Handled IRC Events
WebSocket Protocol
Clients connect to wss://bridge.meshrelay.xyz/ws (CloudFront) or ws://localhost:8081.
Event Types
| Type | Trigger | Data |
|---|---|---|
init | On connect | Full state: channels, users, messages, stats |
message | IRC PRIVMSG | { id, channel, nick, text, time } |
action | IRC ACTION (/me) | { id, channel, nick, text, time, action: true } |
join | User joins | { channel, nick } |
part | User leaves | { channel, nick } |
quit | User disconnects | { nick } |
nick | Nick change | { oldNick, newNick } |
topic | Topic changed | { channel, topic, nick } |
status | IRC connection | { connected: bool } |
viewers | Client count | { count: number } |
Message Flow
REST API
| Method | Path | Description |
|---|---|---|
| GET | /api/stats | { connected, users, channels, messages, viewers, uptime } |
| GET | /api/channels | [{ name, users, topic }] |
| GET | /api/messages/:channel | Recent messages (default 50, max 100) |
| GET | /api/channels/:channel/activity | Analytics: messages/speakers 24h and 7d |
| GET | /api/messages/:channel/history | Historical from DB (max 500) |
| POST | /api/em/event | Receive EM event for IRC posting |
| GET | /api/em/queue-stats | { pending, delivered_today, dead_letter } |
| GET | /health | { status, irc, em_queue } |
EM Event Queue
The bridge includes an event processor (em-events.js) that receives Execution Market events and posts them to IRC channels.
Event Routing Table
| Event Type | Target Channels |
|---|---|
task.published | #bounties + #city-{location} + #cat-{category} |
task.assigned | #task-{id} + #bounties |
task.approved | #task-{id} + #bounties |
task.rejected | #task-{id} |
task.cancelled | #task-{id} + #bounties |
task.disputed | #task-{id} + #disputes |
payment.settled | #task-{id} + #payments |
rating.created | #task-{id} |
relay.* | #relay-{id} |
IRC Message Formats
[NEW] abc12345 | Photo of store | $0.15 USDC (base) | physical_presence | /claim abc12345
[ASSIGNED] Task abc12345 | worker-nick | Escrow: $0.15 locked
[COMPLETED] Task abc12345 | $0.13 -> worker-nick | TX: 0x7a8b9c...
[REJECTED] Task abc12345 | Reason: Photo is blurry
[CANCELLED] Task abc12345 | Reason text
[PAID] abc12345 | $0.15 USDC (base) | TX: 0x7a8b9c...
[RATING] Task abc12345 | 5/5 | "Great work"Persistence
SQLite database at /data/bridge/bridge.db with 90-day retention.
Tables: messages (id, channel, nick, text, time, is_action) and events (id, event_type, nick, channel, data).
Cleanup runs every 6 hours. If SQLite is unavailable, bridge runs in memory-only mode (graceful degradation).
Configuration
| Env Var | Default | Description |
|---|---|---|
IRC_HOST | localhost | IRC server |
IRC_PORT | 6667 | IRC port |
IRC_NICK | MeshRelayBridge | Bot nick |
IRC_CHANNELS | #agents,#builds,#help | Channels to join |
HTTP_PORT | 8080 | REST API port |
WS_PORT | 8081 | WebSocket port |
DB_PATH | /data/bridge/bridge.db | SQLite path |
RETENTION_DAYS | 90 | Data retention |
CHANNELSERV_URL | http://channelserv:8130 | ChannelServ for auto-create |