feat(iios): notification engine — presence-gated Web Push (engine phase)
Generic notification engine: reacts to message.sent and runs three gates before delivering — policy (DM always; group only on @mention or reply-to-you), presence (skip if the recipient is focused on that thread), mute (per-thread). Delivery via a swappable NotificationPort (Web Push/VAPID adapter); a 'gone' (404/410) prunes the sub. - PresenceService + gateway `focus_thread` signal + disconnect cleanup (room membership != viewing, since the sidebar joins every thread room). - IiosNotificationSubscription table + `muted` on IiosThreadParticipant (migration). - Endpoints: GET vapid-public-key, POST/DELETE subscribe, POST threads/:id/mute|unmute; listThreads returns the caller's `muted`. - DM-vs-group read from the opaque `membership` attribute in the notification POLICY only — kernel stays generic (grep-verified). Tests: 13 new (3 gates + reply-to-you + prune + web-push adapter states); full suite 205 green. Verified live: module boots, subscribe stored, mute/unmute round-trips. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import { ThreadsModule } from './threads/threads.module';
|
||||
import { MessageModule } from './messaging/message.module';
|
||||
import { InboxModule } from './inbox/inbox.module';
|
||||
import { MediaModule } from './media/media.module';
|
||||
import { NotificationModule } from './notifications/notification.module';
|
||||
import { SupportModule } from './support/support.module';
|
||||
import { AdaptersModule } from './adapters/adapters.module';
|
||||
import { RoutingModule } from './routing/routing.module';
|
||||
@@ -35,6 +36,7 @@ import { DevController } from './dev/dev.controller';
|
||||
MessageModule,
|
||||
InboxModule,
|
||||
MediaModule,
|
||||
NotificationModule,
|
||||
SupportModule,
|
||||
AdaptersModule,
|
||||
RoutingModule,
|
||||
|
||||
Reference in New Issue
Block a user