docs(website): per-channel notification preferences (engagement Phase 3) #182
Reference in New Issue
Block a user
No description provided.
Delete Branch "docs/engagement-channel-prefs"
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?
Companion to website#169. The documentation §6.0b assigns Phase 3 —
BACKEND_DESIGN.md's route table andandroid/PLAN.md§11 — plus the phase's as-built section and one correction the build forced.ENGAGEMENT.mdinstant" reads naturally beside §3.1's "email opt-IN, push opt-OUT" — but §3.1 borrowed that fromteam_notification_prefs, where no row genuinely does mean notified. Push stream subscriptions have never worked that way (notification_subscriptionsholds a row only on opt-in), soinstantwould have projected the entire catalog into the legacy GET for every existing user and switched every toggle on in the shipped app. §3.1's own comment is corrected in the same pass rather than left to contradict the phase below it.BACKEND_DESIGN.md/me/notifications/channelsroute row: the union catalog, the effective-mode semantics, the sparse PUT and its drop-don't-refuse posture.notification_channel_prefstable entry — including that absence means the channel's default, notoff, and that all three channels agreeing onofftoday is a fact about the declarations rather than about the table, which code must not assume.notification_subscriptionsthat it is now the push projection and stays whatutils/pushDispatchreads.android/PLAN.md§11Nothing above the new section changed — the shipped APK keeps working and the
{"streams":[]}gotcha still applies to that endpoint. What the new section tells whoever adopts the superset endpoint:channels, never a hardcoded three — a trigger-only id has no pushmodesis the effective mode; the client must not re-implement the defaultingoffis a row like any otherstaff-ceilinged trigger is not offered to a non-staff caller🤖 Generated with Claude Code
The documentation §6.0b assigns Phase 3 — `BACKEND_DESIGN.md`'s route table and `android/PLAN.md` §11 — plus the phase's as-built section and one correction the build forced. `ENGAGEMENT.md`: - Phase 3's as-built: the three decisions settled before any code, why the channel registry could not wait for Phase 6, what the sparse PUT buys, the projection stated as an invariant, and the staff-ceiling filter. - **The phase's own acceptance line was wrong and is struck through.** "A fresh user's … push defaults `instant`" reads naturally beside §3.1's "email opt-IN, push opt-OUT", but §3.1 borrowed that from `team_notification_prefs`, where no row genuinely does mean notified. Push STREAM subscriptions have never worked that way — `notification_subscriptions` holds a row only on opt-in — so `instant` would have projected the entire catalog into the legacy GET for every existing user. §3.1's comment is corrected in the same pass. `BACKEND_DESIGN.md`: the `/me/notifications/channels` row, the `notification_channel_prefs` table entry (including that absence means the channel's default rather than `off`, and that all three agreeing on `off` today is a fact about the declarations and not about the table), and a note on `notification_subscriptions` that it is now the push projection. `android/PLAN.md` §11: nothing above it changed — the shipped APK keeps working and the `{"streams":[]}` gotcha still applies to that endpoint. The new section documents the superset endpoint for whenever the app adopts it: render toggles from each item's `channels` rather than a hardcoded three, `modes` is the effective mode and the client must not re-implement the defaulting, the PUT is sparse so the empty-array gotcha does NOT apply here, and one id may be missing that the app expects (a `staff`-ceilinged trigger is not offered to a non-staff caller). Companion to website#169. Co-Authored-By: Claude <noreply@anthropic.com>