Raven ScottandCursor 99c3603c43 Docs: document Phase 468 contacts/DM bundle re-verification (v0.8.431)
Note test:phase468-discovery-dm re-verifies contacts mesh, sidebar guards,
contacts.accept span metadata, and composer DM E2E hints.

Co-authored-by: Cursor <[email protected]>
2026-05-24 02:36:01 -04:00

pearcord-contacts

P2P friend requests, blocks, and friend presence on the contacts Hyperswarm mesh.

Mission

Maintain the signed-in user's contact graph in JsonStore (pending_in/out, accepted, blocked), gossip request/accept/decline/remove/block RPCs to peer-specific contactsTopic buffers, join friend topics for ongoing PRESENCE_UPDATE and profile cosmetic sync, and expose friend presence map for DM sidebar and activity feed.

When to use / not

Use when:

  • You need friend list operations in isolation from guild discovery.
  • You are running contacts mesh live smokes with two Hyperswarm peers.

Do not use when:

  • You need guild member lists — use pearcord-guild roster.
  • You need notification inbox — use pearcord-notifications (separate settings topic).

Public API

Export Role
PearcordContacts EventEmitter mesh + store
CONTACT_STATUS pending_out, pending_in, accepted, blocked
contactsTopic(userId) Topic string helper
ready, list, get, listAccepted, listPending* CRUD reads
sendRequest, acceptRequest, declineRequest, removeContact Outbound + gossip
blockContact, unblockContact, listBlocked Block graph
ingestRequest / ingestAccept / … Inbound handlers
broadcastPresence, broadcastProfileCosmetic Fanout to friends
ingestFriendPresence, getFriendPresenceMap Friend activity cache
joinMesh(swarm) / leaveMesh contactsTopic(self) server+client
simulateGossip, gossipLocal, getStats Tests

Uses pearcord-drive mux wire via ./mesh (contacts Protomux protocol).

P2P surface

Topic Role
contactsTopic(userId) Inbox for requests to that user
Friend topics Joined for each accepted peer (client)
RPC CONTACT_*, PRESENCE_UPDATE, PROFILE_COSMETIC_UPDATE

Ephemeral topic join for one-shot request delivery when not yet friends.

Storage

Collection Path
@pearcord/contacts {storagePath}/contacts

Primary key: { ownerId, peerUserId }. Friend presence is in-memory _friendPresence Map.

Platform integration

const { PearcordContacts } = require('pearcord-contacts')

this.contacts = new PearcordContacts({ userId, username, displayName, storagePath })
await this.contacts.ready()
await this._joinContactsMesh()  // dedicated Hyperswarm + joinMesh
// friend-request IPC → sendRequest / acceptRequest
// setPresence → contacts.broadcastPresence after presence.setStatus

Platform README lists contactsTopic alongside dmTopic in mesh table.

UI / IPC

IPC Platform path
send-friend-request sendRequest
accept-friend-request acceptRequest
list-contacts accepted + pending + blocked + presence map
Friends activity getFriendPresenceMap + buildActivityFeed

Tests

  • smoke-contacts-mesh-live.cjs
  • smoke-runner.cjscontactsTopic assertion
  • Platform friend flows in onboarding smokes
  • v0.8.431 (Phase 468): bundled in test:phase468-discovery-dm; test:contacts-guild-loading (.friend-item guards); platform contacts.accept span.end peerUserId + error: key; clipboard contactsPendingCount/dmChannelCount; UI #composer-dm-hint + 🔒 E2E badge
  • v0.8.396 (Phase 433): bundled in test:phase433-discovery-dm; test:contacts-modal-escape-focus; platform contacts.* error logs for dm-errors filter

Code example

const { PearcordContacts, CONTACT_STATUS } = require('pearcord-contacts')
const Hyperswarm = require('hyperswarm')

const contacts = new PearcordContacts({
  userId: 'alice',
  username: 'alice',
  storagePath: './pearcord-storage'
})
await contacts.ready()
await contacts.joinMesh(new Hyperswarm())
const row = await contacts.sendRequest({
  peerUserId: 'bob',
  peerDisplayName: 'Bob'
})
console.log(row.status === CONTACT_STATUS.PENDING_OUT)

Repository

Part of Pearcord.

  • Org: pearcord
  • Clone: git clone https://git.ssh.surf/pearcord/pearcord-contacts.git
  • Install: npm install git+https://git.ssh.surf/pearcord/pearcord-contacts.git#main
S
Description
Pearcord module: pearcord-contacts
Readme
196 KiB
Languages
JavaScript 100%