Skip to content

Push follows the phone's mutes, and goes quiet for phones nobody uses (GRYT-1689) - #284

Merged
sivert-io merged 1 commit into
mainfrom
claude/GRYT-1689-push-mutes
Oct 7, 2026
Merged

sivert-io merged 1 commit into
mainfrom
claude/GRYT-1689-push-mutes

Conversation

@sivert-io

@sivert-io sivert-io commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Push follows the phone's mutes, and goes quiet for phones nobody uses (GRYT-1689)

Three changes to what the server sends the relay. Each one means fewer requests to it:

  • Mutes. push:register takes a muted list of conversation ids, which is whatever the phone has at "Nothing", channels and DMs alike. A mention or DM there never reaches the relay. It's stored as JSON in a new push_devices.muted column. The list is capped at 1,000 ids of up to 128 characters, and anything else is refused.
  • Stale phones. The phone checks in on every connect. One that hasn't for 30 days gets no pushes, and its row is deleted the next time that account is looked up.
  • Leaving. setUserInactive now deletes the account's push rows. Leaving, a kick and a ban all go through it. A phone that comes back registers again.

New test, pushAudience.test.ts, runs the real chat, DM and push handlers with a local server standing in for the relay. It has 19 cases:

  • who a mention wakes: a background phone yes, someone at a screen no, an idle desktop yes, no socket yes, a channel they can't read no, the sender no, @everyone and @here no, someone who blocked the sender no
  • mutes: on the channel, on some other channel, on a DM
  • DMs: the recipient and never the sender, and one buzz for a burst
  • taking it back: unregister, a 410 from the relay, 30 days of silence, leaving
  • bad muted lists and capabilities refused

Each rule was checked by breaking it and watching its test fail: the read check, blocks, mutes, presence, the throttle, the leave cleanup and the staleness cutoff. Full suite: 2,021 passing.

Checked against the phone branch (Gryt-chat/mobile#308) on the simulator, with a local relay. Muting General sent ["general"]. A mention there then made no request to the relay, and one in Random made exactly one.

Review-required (src/db). Things to look at:

  • The migration adds muted with ALTER TABLE when it's missing. Only dev servers ever had the table without it, but it runs everywhere.
  • Deleting push rows inside setUserInactive puts a push concern in the users file. It's the one place every way of leaving goes through, which is why it's there.
  • resetPushState() is exported for tests only.

🤖 Generated with Claude Code

… (GRYT-1689)

Three changes to what the server sends the relay. Each one means fewer requests to it:

- **Mutes.** `push:register` takes a `muted` list of conversation ids, which is whatever the phone has at "Nothing", channels and DMs alike. A mention or DM there never reaches the relay. It's stored as JSON in a new `push_devices.muted` column. The list is capped at 1,000 ids of up to 128 characters, and anything else is refused.
- **Stale phones.** The phone checks in on every connect. One that hasn't for 30 days gets no pushes, and its row is deleted the next time that account is looked up.
- **Leaving.** `setUserInactive` now deletes the account's push rows. Leaving, a kick and a ban all go through it. A phone that comes back registers again.

New test, `pushAudience.test.ts`, runs the real chat, DM and push handlers with a local server standing in for the relay. It has 19 cases:

- who a mention wakes: a background phone yes, someone at a screen no, an idle desktop yes, no socket yes, a channel they can't read no, the sender no, @everyone and @here no, someone who blocked the sender no
- mutes: on the channel, on some other channel, on a DM
- DMs: the recipient and never the sender, and one buzz for a burst
- taking it back: unregister, a 410 from the relay, 30 days of silence, leaving
- bad `muted` lists and capabilities refused

Each rule was checked by breaking it and watching its test fail: the read check, blocks, mutes, presence, the throttle, the leave cleanup and the staleness cutoff. Full suite: 2,021 passing.

Checked against the phone branch (the phone branch) on the simulator, with a local relay. Muting General sent `["general"]`. A mention there then made no request to the relay, and one in Random made exactly one.

Review-required (src/db). Things to look at:
- The migration adds `muted` with `ALTER TABLE` when it's missing. Only dev servers ever had the table without it, but it runs everywhere.
- Deleting push rows inside `setUserInactive` puts a push concern in the users file. It's the one place every way of leaving goes through, which is why it's there.
- `resetPushState()` is exported for tests only.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@sivert-io
sivert-io merged commit 7242830 into main Oct 7, 2026
6 checks passed
@sivert-io
sivert-io deleted the claude/GRYT-1689-push-mutes branch October 7, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant