@@ -53,6 +53,25 @@ async function checkDedup(userId, eventType, title) {
5353 return result === 'OK' ; // true = new, false = duplicate
5454}
5555
56+ // ── Channel deactivation ──────────────────────────────────────────────────────
57+
58+ async function deactivateChannel ( userId , channelType ) {
59+ try {
60+ const res = await fetch ( `${ CONVEX_SITE_URL } /relay/deactivate` , {
61+ method : 'POST' ,
62+ headers : {
63+ 'Content-Type' : 'application/json' ,
64+ 'Authorization' : `Bearer ${ RELAY_SECRET } ` ,
65+ } ,
66+ body : JSON . stringify ( { userId, channelType } ) ,
67+ signal : AbortSignal . timeout ( 10000 ) ,
68+ } ) ;
69+ if ( ! res . ok ) console . warn ( `[relay] Deactivate failed ${ userId } /${ channelType } : ${ res . status } ` ) ;
70+ } catch ( err ) {
71+ console . warn ( `[relay] Deactivate request failed for ${ userId } /${ channelType } :` , err . message ) ;
72+ }
73+ }
74+
5675// ── Private IP guard ─────────────────────────────────────────────────────────
5776
5877function isPrivateIP ( ip ) {
@@ -72,8 +91,7 @@ async function sendTelegram(userId, chatId, text) {
7291 const body = await res . json ( ) . catch ( ( ) => ( { } ) ) ;
7392 if ( res . status === 403 || body . description ?. includes ( 'chat not found' ) ) {
7493 console . warn ( `[relay] Telegram 403/400 for ${ userId } — deactivating channel` ) ;
75- // deactivateChannel is auth-gated; log warning only — Phase 4 limitation
76- console . warn ( `[relay] Manual deactivation required for userId=${ userId } channelType=telegram` ) ;
94+ await deactivateChannel ( userId , 'telegram' ) ;
7795 }
7896 return ;
7997 }
@@ -122,8 +140,7 @@ async function sendSlack(userId, webhookEnvelope, text) {
122140 } ) ;
123141 if ( res . status === 404 || res . status === 410 ) {
124142 console . warn ( `[relay] Slack webhook gone for ${ userId } — deactivating` ) ;
125- // deactivateChannel is auth-gated; log warning only — Phase 4 limitation
126- console . warn ( `[relay] Manual deactivation required for userId=${ userId } channelType=slack` ) ;
143+ await deactivateChannel ( userId , 'slack' ) ;
127144 } else if ( ! res . ok ) {
128145 console . warn ( `[relay] Slack send failed: ${ res . status } ` ) ;
129146 }
@@ -173,7 +190,8 @@ async function processEvent(event) {
173190
174191 const matching = enabledRules . filter ( r =>
175192 ( r . eventTypes . length === 0 || r . eventTypes . includes ( event . eventType ) ) &&
176- matchesSensitivity ( r . sensitivity , event . severity ?? 'high' )
193+ matchesSensitivity ( r . sensitivity , event . severity ?? 'high' ) &&
194+ ( ! event . variant || ! r . variant || r . variant === event . variant )
177195 ) ;
178196
179197 if ( matching . length === 0 ) return ;
0 commit comments