Repository navigation
Description
What happens
#923 fixed the pair enumeration by reading the link's own record of who it seated, but it reads only one of the two places that record keeps that fact. A room whose invite was accepted before invite.homes was written still enumerates no pair, so its group envelopes still fall back to a friendship the two homes never had — the exact symptom #923 closed, surviving on rooms that already existed when it merged.
Lines (main 137cd2fd)
core/src/host/reach.js:209linkSeats(room)walksroom.localInvite/room.localInvitesand readsObject.values(invite.homes ?? {})only (:213-219).ticketPeersuses it at:241(linkOf.get(handleOf(p))?.ticket), so a seat whose handle appears in nohomesentry getsticket === undefinedand is skipped (:248-249).core/src/host/room-membership.js:1205homesOf(invite)is the same fact with the older shape recovered: ifinvite.homeshas no entry for a home,invite.acceptedBysupplies one, withinvite.seats(or[acceptedBy]) as its handles (:1207). The writer paths deleteacceptedByoncehomesis written (:1608-1609,:1710), which is exactly why a record that hasacceptedByis one that never gothomes.
So the two halves disagree: room-membership.js treats acceptedBy + seats as "this home was seated", reach.js does not.
What to change
Make linkSeats see the same records homesOf sees. Either export homesOf from core/src/host/room-membership.js and use it (one source of truth, preferred), or repeat its one-line recovery in reach.js with a comment naming homesOf as the authority. Whichever: keep linkSeats read-only — no state writes, no events, no roster re-send, and loading a room must not mutate it (#923's constraint).
Acceptance
- A room whose invite record is the old shape —
acceptedByplusseats, nohomes— has its seat enumerated byticketPeers(), withscopethe room id and the ticket from the invite. - The new shape (with
homes) enumerates exactly as today. - a link-admitted guest still needs a friendship: its room envelopes are carded, and approving the card ends in no_relationship #923's negative control still holds: a friend's Bot added by hand (named by no link) is not a pair.
- Both halves agree on the same fixture: a record for which
homesOf(invite)is non-empty must produce a pair, and one for which it is empty must not — a test that asserts the two functions cannot drift apart again. - The new test is red on pristine
137cd2fd(it must, sincelinkSeatstoday readshomesonly) and the rest of the room tests stay green.
Why it matters beyond tidiness
Rooms that predate this work are exactly the ones a user already belongs to; a fix that only covers newly accepted links leaves the reported "cannot send into the group" symptom in place for them, and the code gives no sign of it (the pair just is not there).
Activity
Read a link's seats through homesOf, so a room older than the field e…