feat(realtime): live enclave member + room lists on the landing page (LC-170) #215
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/lc-170-live-enclave-lists"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes LC-170 (the in-scope surfaces). Follow-up to LC-161 (live invitations), extending the LC-160 typed-topic WebSocket channel to the
/enclave/{id}landing page so the member and room lists update live instead of needing a manual reload. Addresses audit gap C1 (docs/audit/2026-05-22-lc148-audit-report.md).What updates live
Wiring
enclave:{id}topic viadata-lc-live-topic.live.jssends theSubscribeTopicframe;ws.rs::topic_subscribe_allowedauthorizes enclave membership before joining the fan-out set (the LC-160 contract).enclave/members_items.html,enclave/rooms_items.html) so the full page and the OOB fragments (ws/enclave_members_live.html,ws/enclave_rooms_live.html) render identically. The static controls (Add room form, invite box, settings link) stay in the page, outside the swapped#lc-enclave-members/#lc-enclave-roomsregions.broadcast_enclave_topichelper. A newEnclaveMemberRoleChangedevent carries role changes (none existed). This replaces the older per-memberbroadcast_to_user/broadcast_to_enclavefan, whose four enclave events sat inrender_event'sNonearm (rendered nothing) and only reached the mutation's own subject anyway.broadcast_to_enclaveis removed.get_landing).Out of scope (separate C1 gaps, spin-out candidates)
post_delete) stays onbroadcast_to_user- that is a sidebar/switcher concern, not a landing-list one.Known limitation (follow-up)
A kicked or departed user keeps their
enclave:{id}topic subscription until they disconnect - the hub has onlydisconnect, no unsubscribe-by-topic. So they can briefly see further list updates until they navigate (any navigation/reload then 403s on the lost access). This is inherent to the LC-160 topic model, low severity, and worth a dedicated follow-up if we want hard cutoff.Verification
just testandjust test-saasboth green (106test result: okeach, zero failures);cargo clippyandcargo fmtclean. No existing test asserts on the rewired broadcasts.Follow-up to LC-161 (live invitations), extending the LC-160 typed-topic channel to the /enclave/{id} landing page. The member list and room list now update over the WebSocket when membership, roles, or rooms change, instead of requiring a manual reload. Wiring: - The landing page subscribes to the enclave:{id} topic via data-lc-live-topic (live.js sends the SubscribeTopic frame; ws.rs::topic_subscribe_allowed authorizes enclave membership before joining the fan-out set). - The member and room lists are extracted into shared partials (enclave/members_items.html, enclave/rooms_items.html) so the full page and the OOB fragments (ws/enclave_members_live.html, ws/enclave_rooms_live.html) render identically. The static controls (Add room form, invite box, settings link) stay in the page outside the swapped regions. - The five list-mutating handlers now broadcast on the topic: member add (discover-join, join-by-code, accept-invite), member remove (kick, leave), role change (new EnclaveMemberRoleChanged event), and room add/remove. These replace the older per-member broadcast_to_user / broadcast_to_enclave fan, whose events rendered nothing (the four enclave events were in render_event's None arm) and only reached the mutation's own subject. broadcast_to_enclave is removed; broadcast_enclave_topic replaces it. - The WS send task renders the member list once per recipient (read-only label + role, identical for everyone) and the room list per recipient (the per-row Remove control and the access-filtered room set depend on the viewer's manage rights, mirroring get_landing). Out of scope (separate gaps from the audit's C1): the whole-enclave-delete fan (post_delete) stays on broadcast_to_user since it is a sidebar/switcher concern, not a landing-list one; sidebar live-refresh on room add; the settings-page member list; and settings own-profile, which the issue flags as cross-surface and hardest. A kicked/left user keeps their topic subscription until they disconnect (the hub has no unsubscribe-by-topic API), so they can briefly see further list updates before they navigate and lose access; this is inherent to the LC-160 topic model and tracked as a follow-up. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>get_landing grants site admins god-mode read of any enclave's member/room lists, but topic_subscribe_allowed only permitted actual enclave members on the enclave:{id} topic. A non-member admin viewing the landing page therefore saw a static list with no live updates. Allow user.role == "admin" on the enclave topic for parity with the page-level access they already have; this exposes no data an admin cannot already fetch via get_landing. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>