Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
3fcb24c
docs(plan): add room-service mute.toggle implementation plan
claude May 21, 2026
b6e5b05
docs(plan): drop data-migration section from mute.toggle plan
claude May 21, 2026
dbfe0b0
refactor(model): rename Subscription.DisableNotification → DisableNot…
claude May 21, 2026
2860733
feat(subject): add MuteToggle subject builders
claude May 21, 2026
b327f82
feat(model): add MuteToggleResponse + SubscriptionMuteToggledEvent
claude May 21, 2026
998cd62
feat(room-service): declare ToggleSubscriptionMute in RoomStore
claude May 21, 2026
c7ca631
feat(room-service): implement ToggleSubscriptionMute on MongoStore
claude May 21, 2026
3b2fc06
feat(room-service): inject publishCore alongside publishToStream
claude May 21, 2026
a18ab35
feat(room-service): add mute.toggle RPC handler
claude May 21, 2026
9ae124d
feat(inbox-worker): mirror subscription_mute_toggled outbox event
claude May 21, 2026
8277488
docs(client-api): document mute.toggle RPC
claude May 21, 2026
d0bdc03
review(branch): header + executive summary
claude May 21, 2026
5671f1f
review(branch): service room-service
claude May 21, 2026
9c9e0b3
review(branch): service inbox-worker
claude May 21, 2026
fc007fa
review(branch): service room-worker
claude May 21, 2026
b65c67a
review(branch): go expert
claude May 21, 2026
0c9bc9f
review(branch): test automation
claude May 21, 2026
a548d61
review(branch): bug and security
claude May 21, 2026
7a8ce98
review(branch): performance
claude May 21, 2026
602163e
review(branch): observability
claude May 21, 2026
8aef3ad
review(branch): prioritized action list
claude May 21, 2026
6f32c4b
fix(room-service): doc + span coverage on mute.toggle handler
claude May 22, 2026
65a25e5
fix(room-service): sanitizeError passes invalid-mute-toggle through
claude May 22, 2026
711d250
fix(room-service): GetUserSiteID failure aborts mute.toggle
claude May 22, 2026
9954ac9
refactor(room-service): drop pre-fetch in mute.toggle, return post-fl…
claude May 22, 2026
ffd274b
test(room-service): cover cross-site outbox publish failure in mute.t…
claude May 22, 2026
7361df0
chore: trim mute.toggle comments per 2-line / 65% rule
claude May 22, 2026
86c02dd
Merge remote-tracking branch 'origin/main' into claude/explore-room-s…
claude May 22, 2026
fc9d443
fix(room-service): use mustInsertSub helper in mute-toggle integratio…
claude May 22, 2026
f38e7d5
fix(room-service): correct $not operand shape in mute toggle pipeline
claude May 22, 2026
3b7a12e
test(room-service): pin publishCore non-fatal contract on mute toggle
claude May 22, 2026
57681d3
refactor: rename Subscription.DisableNotifications → Muted
claude May 22, 2026
d44c8c9
chore: drop branch review artifact
claude May 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions docs/client-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,55 @@ See [Error envelope](#6-error-envelope-reference). Common errors:

---

#### Toggle Mute

**Subject:** `chat.user.{account}.request.room.{roomID}.{siteID}.mute.toggle`
**Reply subject:** auto-generated `_INBOX.>` (NATS request/reply)

Synchronous RPC. `room-service` flips `Subscription.muted` for the requester in a single atomic Mongo `FindOneAndUpdate`, replies with the resulting value, fans out a `subscription.update` event to the user's other client sessions, and (for cross-site users) publishes a `subscription_mute_toggled` outbox event so `inbox-worker` mirrors the change on the user's home site.

Idempotency: this is a toggle, not a set — every successful call flips the bit. Clients must debounce the user-visible action; redelivery of the same RPC will flip back.

##### Request body

The subject already carries `account` and `roomID`, so no body fields are required. Clients may send `{}` or omit the body entirely; any body content is ignored.

##### Success response

| Field | Type | Notes |
|------------------------|---------|-------|
| `status` | string | Always `"ok"`. |
| `muted` | boolean | The resulting value of `Subscription.muted` after the flip. |

```json
{ "status": "ok", "muted": true }
```

##### Error response

See [Error envelope](#6-error-envelope-reference). Common errors:

- `"only room members can list members"` — the user has no subscription in the room (sentinel reused across membership-gated RPCs).
- `"invalid mute-toggle subject: …"` — the subject is malformed.

##### Triggered events — success path

**`chat.user.{account}.event.subscription.update`** — emitted once for the requester so other client sessions reconcile.

| Field | Type | Notes |
|----------------|--------|-------|
| `userId` | string | The requester's internal user ID. |
| `subscription` | object | The `Subscription` record with the updated `muted`. |
| `action` | string | `"mute_toggled"`. |
| `timestamp` | number | Milliseconds since Unix epoch (UTC). |

##### Behaviour notes

- **Cross-site federation:** if the user's home site (`users.siteId`) differs from the handler's site, a `subscription_mute_toggled` outbox event is published to `outbox.{handlerSite}.to.{userSite}.subscription_mute_toggled` with payload `{account, roomId, muted, timestamp}`. The destination `inbox-worker` applies an unconditional `$set` on the local subscription mirror.
- **Notification delivery:** `notification-worker` does **not** yet consult `muted` before sending. End-to-end mute behaviour is wired only as far as the persisted flag; honouring it in fan-out is a follow-up.

---

#### Read Message Receipts

**Subject:** `chat.user.{account}.request.room.{roomID}.{siteID}.message.read-receipt`
Expand Down
Loading
Loading