The "New subscribers" notification toggle controls nothing, and its Slack ping cannot be muted — one of six notification types bypasses notifyUser
Found in the D1 sweep prompted by #438. Two writers of notifications rows with different behaviour, and the type the console offers a control for is on the wrong one.
Verified — the subscribe path calls createNotification directly
workers/api/src/routes/instances.ts:264-269:
await createNotification(
c.env.DB, creator.owner_id, "subscribe",
`New subscriber: ${subscriber?.github_login || "someone"}`,
`${subscriber?.github_login || "A user"} subscribed to ${agent.name}.`,
agent.id,
);
grep -rn "createNotification(" workers/api/src --include="*.ts" | grep -v test → 3
(the definition at routes/notifications.ts:65, routes/push.ts:273, routes/instances.ts:264)
grep -rn 'notifyUser(…, "subscribe"' workers/api/src --include="*.ts" | grep -v test → 0
notifyUser (routes/push.ts:234-278) is the funnel that consults the preference:
interrupt = pushAllowedByPreference(parseAccountPreferences(row?.preferences).notifications, type, kind);
grep -rn "pushAllowedByPreference" workers/api/src --include="*.ts" | grep -v test → 3 hits: the definition (lib/notifications.ts:172), the import and the single call in routes/push.ts:251. Nothing else reads the preference.
Verified — the type IS offered as a control
workers/api/src/lib/notifications.ts:76-81:
{
id: "subscribe",
label: "New subscribers",
description: "Someone subscribing to an agent you publish.",
alerts: false,
},
served at routes/preferences.ts:51 (notificationTypes: NOTIFICATION_TYPES) and rendered as a toggle by store/console/src/components/NotificationPreferences.tsx, mounted at store/console/src/pages/Preferences.tsx:162-166.
The other five declared types (apply, coding, deploy, loop, trigger) all go through notifyUser — 13 call sites.
Verified — what the bypass costs
workers/api/src/routes/notifications.ts:75 — const interrupt = opts.interrupt !== false;. The subscribe call passes no opts, so interrupt is true, and :95-105 then fires the Slack webhook:
// Slack is an interruption channel like the push is, so a suppressed copy is silent there
// too. Muting deploys in the console and still being pinged in Slack would make the control
// a half-truth.
if (!interrupt) return;
It also passes no dedupeKey, so the #361 duplicate floor (routes/push.ts:255-270) has no key to match on, and it never calls sendPushToUser.
User-visible impact
A creator who turns off "New subscribers" keeps getting Slack pings on every subscription, and the toggle gives no feedback that it did nothing — the card's own copy promises the opposite. The mute is vacuously honoured for web push only because no push is attempted for this type at all, which is a second, quieter surprise: the toggle is advertised for a channel that never fires.
Not claimed
Not reproduced against a live Slack webhook. The three code paths above settle it.
Refs #438, #361.
The "New subscribers" notification toggle controls nothing, and its Slack ping cannot be muted — one of six notification types bypasses
notifyUserFound in the D1 sweep prompted by #438. Two writers of
notificationsrows with different behaviour, and the type the console offers a control for is on the wrong one.Verified — the subscribe path calls
createNotificationdirectlyworkers/api/src/routes/instances.ts:264-269:notifyUser(routes/push.ts:234-278) is the funnel that consults the preference:grep -rn "pushAllowedByPreference" workers/api/src --include="*.ts" | grep -v test→ 3 hits: the definition (lib/notifications.ts:172), the import and the single call inroutes/push.ts:251. Nothing else reads the preference.Verified — the type IS offered as a control
workers/api/src/lib/notifications.ts:76-81:served at
routes/preferences.ts:51(notificationTypes: NOTIFICATION_TYPES) and rendered as a toggle bystore/console/src/components/NotificationPreferences.tsx, mounted atstore/console/src/pages/Preferences.tsx:162-166.The other five declared types (
apply,coding,deploy,loop,trigger) all go throughnotifyUser— 13 call sites.Verified — what the bypass costs
workers/api/src/routes/notifications.ts:75—const interrupt = opts.interrupt !== false;. The subscribe call passes noopts, sointerruptistrue, and:95-105then fires the Slack webhook:It also passes no
dedupeKey, so the #361 duplicate floor (routes/push.ts:255-270) has no key to match on, and it never callssendPushToUser.User-visible impact
A creator who turns off "New subscribers" keeps getting Slack pings on every subscription, and the toggle gives no feedback that it did nothing — the card's own copy promises the opposite. The mute is vacuously honoured for web push only because no push is attempted for this type at all, which is a second, quieter surprise: the toggle is advertised for a channel that never fires.
Not claimed
Not reproduced against a live Slack webhook. The three code paths above settle it.
Refs #438, #361.