Repository navigation
Description
Priority: P0 (part of the local-room invite chain the owner asked for on 2026-10-23). This is the buildable half of #876, split out the way #877/#881 split their umbrellas: the plumbing and the shared component are green and blocking everyone else, while the Members-card row they hang on is not written yet. #876 stays open for that row and the redeem dialog, and this issue does not close it.
What this issue owns
Everything in #876 except the Members card's Invite by link row and the redeem dialog:
- the core shared preview component (
RoomInvitePreview+invitePreviewOf) exposed on__flybot__, so the face-room cards and the local-room dialog render one component and cannot drift into two copies; - host wiring for the room's own ticket:
room-invite(read),room-invite-mint(mint),room-invite-revoke(withdraw); - the tests and documentation that go with those.
Evidence it is ready
At tip 4fafe2c5, rebuilt on main 690093bc (single commit, 27 files): core 1314/1314 (serial --test-concurrency=1), plugins/social 386/386 including the hold_reason assertions #869 merged, build-client --check ok, ds-bot-patches check ok (10 patches), core lint 0 errors, 31 changelog sections, arch-docs ok.
That branch also caught a silent rollback: an earlier tip carried plugins/social/test/social.test.js at +34/−84 against the new main — the −84 being the hold_reason cases #869 had just merged — and docs/subsystems/social.md reverted #869's paragraph. It was found by comparing per-file shas against main, and the rebuilt branch is now social.test.js +19/−0 and social.md +1/−1.
Acceptance
- PR body:
Fixes #<this>plusRefs #876; the row and the dialog are explicitly left to#876. - One ticket per room: a local room has exactly one
localInvite; the Members card and the face-room card both read the same record throughroom-invite/room-invite-mint/room-invite-revokeand neither keeps or mints a copy of its own.mintRoomInvitestill refusesface-to-faceandinbound-sharerooms (/its own invitation/), so two cards cannot produce two tickets. - One preview component: a test asserts that no second
face-link-preview-*markup exists inplugins/social/client.js, and that both flows render__flybot__'s single component with only thedata-flybotprefix differing bykind. - No silent rollback: the PR body states the per-file diff against base, and
social.test.js/social.mdshow additions only — no line of#869's work removed. This is the check that caught the −84. - The three host ops fail closed with their own sentence each: unknown room, a room with its own invitation (face / inbound-share), and a mint with no identity that can be carried in a link (
/no Bot Social identity yet/,/no Bot handle a link can carry/). - Docs:
docs/subsystems/social.mdand the plugin/core docs name the local ticket next to the face-room one, and a changelog fragment is present.
Out of scope
The Members card row (Invite by link: mint, copy, countdown, withdraw), the QR code, and the redeem dialog — all #876.
Related
#876 — the umbrella this was split from. #864 — the envelope half already on main. #878 — what one ticket admits (the dialog's copy depends on it). #883 / #884 — the stranger path this link eventually feeds.
Activity
feat(rooms): the local room invite's plumbing and one shared preview …