OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-rooms commits / f1a5910

RoomPairing: carry opaque meta + export decodeRoomPairingInvite
Lets a domain wrapper (hyper-orgs / hyper-issues) attach its name in the invite's meta and read it back (+ the bootstrapKey) before joining, so it can key its own records and derive its own namespace. RoomPairing stays domain-agnostic (meta is opaque). Proof still 9/9. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
f1a59101c1818ded609140377ac7dab603d00484
by plankatron <fleeky@gmail.com> · 2026-05-27T18:37:24.000Z

Changed files (2) +14 -3

index.js +1 -1
……@@ -15,4 +15,4 @@ export { Room } from './lib/room.js'
1515export { jsonSchema } from './lib/json-schema.js'
1616export { composeSchemas } from './lib/compose-schemas.js'
1717export { encodeInvite, decodeInvite, newSeed, isExpired, ROLES } from './lib/invitations.js'
18export { createRoomPairing, joinRoomPairing } from './lib/room-pairing.js'
18export { createRoomPairing, joinRoomPairing, decodeRoomPairingInvite } from './lib/room-pairing.js'
lib/room-pairing.js +13 -2
……@@ -53,6 +53,17 @@ function decodeInvite (str) {
5353 return obj
5454}
5555
56/**
57 * Decode a room-pairing invite WITHOUT joining — exposes { bootstrapKey,
58 * role, meta } so a domain wrapper (hyper-orgs / hyper-issues) can read its
59 * advisory `meta` (e.g. the org/repo name) and derive its own namespace
60 * before calling joinRoomPairing.
61 */
62export function decodeRoomPairingInvite (str) {
63 const o = decodeInvite(str)
64 return { bootstrapKey: o.bootstrapKey, role: o.role || 'reader', meta: o.meta || null }
65}
66
5667/**
5768 * Host side. `room` must be ready and writable (the owner). Returns a
5869 * shareable `invite` string + a `close()` to tear down the pairing member.
……@@ -100,7 +111,7 @@ export function createRoomPairing (room, opts = {}) {
100111 })
101112
102113 return {
103 invite: encodeInvite({ v: 1, invite: b4a.toString(invite, 'hex'), bootstrapKey: room.keyHex, role }),
114 invite: encodeInvite({ v: 1, invite: b4a.toString(invite, 'hex'), bootstrapKey: room.keyHex, role, meta: opts.meta || null }),
104115 discoveryKey,
105116 async close () {
106117 // Drain so the confirm ack reaches the candidate before teardown
……@@ -154,5 +165,5 @@ export async function joinRoomPairing (inviteStr, opts = {}) {
154165 try { await bp.close() } catch {}
155166 }
156167
157 return { room, role: decoded.role, localKeyHex }
168 return { room, role: decoded.role, meta: decoded.meta || null, localKeyHex }
158169}