mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
`AppSettings.telegramGlobal`, `.ntfyGlobal` and `.webPushGlobal` were read in two places, and neither of them was the one that matters: the setup-card visibility on Settings -> Integrations and an echo in the preferences payload. The dispatcher never looked at them. An operator who switched a channel off instance-wide lost the setup card and kept every existing delivery on that channel, indefinitely. Gate each of the three in the dispatcher, in the shape `isApiGloballyEnabled()` already uses for the twelve API routes. The read sits above the per-user channel row and below the per-event preference, it happens at most once per dispatch, and only when a switchable channel is actually in the cascade. A skip writes a `globally_disabled` row to the push-attempt ledger so the admin diagnostics name the cause, and does not count as an attempt, so `dispatched` keeps telling the truth. The account's own channel row is left enabled: the switch is the operator's, and flipping it back has to restore delivery without every user re-enabling anything. APNs, the generic webhook and email carry no instance-wide switch and are not gated here; they are turned off at their source instead. The unit test drives the real dispatcher over a stubbed settings row; the integration test writes the actual singleton and reads the ledger back out of Postgres, which is the layer that proves the column the admin route writes is the column the dispatcher reads.