# Block User: Community Removal & Visibility

**Date:** 2026-07-21  
**Status:** Approved design  
**Approach:** Extend existing `BlockUser` + membership cleanup (no new schema)

## Problem

Blocking a user restricts chat and post interactions, but the blocked user can remain a member of communities the blocker created. Blocking should fully cut community interaction in those spaces and hide the blocked user from the blocker’s community views everywhere.

## Goals

1. On block, remove the blocked user from all communities created by the blocker.
2. While blocked, prevent join and join-request for those communities.
3. On unblock, do not restore membership; the user must rejoin or request again.
4. Hide blocked users’ posts from the viewer (leave posts in the database).
5. In communities the blocker did not create, keep membership but hide the blocked user from member lists and related views for the viewer.

## Non-goals

- New `bannedMembers` (or similar) fields on community documents.
- Auto-restoring membership on unblock.
- Hard-deleting community posts authored by the blocked user.
- Changing admin/moderation flows beyond user-to-user block.

## Source of truth

Existing `BlockUser` records (`blockedBy`, `blockedUser`) remain the single source of truth for the relationship. Community membership is mutated only for communities owned by the blocker; visibility filtering uses `BlockUser` in both directions.

## Behavior

### On block (`blockUserToggle` — create path)

Keep existing behavior (unfollow both ways, mark conversation `blockedBy`).

Additionally:

1. Find communities where `createdBy === blocker` and `members` contains the blocked user.
2. For each (or via bulk update): `$pull` blocked user from `members`, decrement `membersCount`.
3. Delete pending join requests from the blocked user for those communities.

### On unblock

- Delete the `BlockUser` record and clear conversation block as today.
- Do **not** re-add the user to communities or recreate join requests.

### Join / request gate

If a `BlockUser` exists in either direction between the joining (or requesting) profile and `community.createdBy`:

- Public join → reject with `403`.
- Private join request create → reject with `403`.
- Approving an existing request → reject with `403` if a block exists at approve time.

### Visibility (reads)

For the authenticated viewer, exclude profiles in a block relationship (either direction):

1. **Member lists** — filter response; do not mutate membership for non-owned communities.
2. **Community posts / reply counts** — exclude blocked authors for the viewer; posts remain stored.
3. **Other community endpoints that return member-like profiles** — apply the same filter.

## Components

| Area | Change |
|------|--------|
| `auth.controller` `blockUserToggle` | After creating block: membership cleanup + pending request deletion for creator-owned communities |
| `community.controller` join / request / approve | Block check against community creator |
| `getCommunityMembers`, `getCommunityPosts` (and related) | Filter by blocked profile IDs |
| Shared helper | Resolve blocked profile IDs for a viewer (both directions) to avoid duplicated queries |

## Error handling

- Join/request when blocked: `403` with a clear message (e.g. unable to join this community).
- Membership/request cleanup runs in the block flow; failures should surface so the client is not told the user was blocked while community state is inconsistent.

## Testing

1. Block removes the user from the blocker’s communities and cancels pending requests.
2. Blocked user cannot join or request those communities while blocked.
3. Unblock does not restore membership.
4. Member list and community posts hide the blocked user for the viewer.
5. Shared (non-owned) community: membership unchanged; visibility still filtered for the viewer.

## Out of scope for follow-ups

- Notifying the blocked user that they were removed from a community.
- Client UI copy beyond API error messages.
