mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-27 18:57:09 +00:00
feat: add Apprise as a fourth notification channel (#1644)
* feat: add Apprise as a fourth notification channel Support keyed and stateless Apprise endpoints with secret-safe public DTOs, fail-closed malformed config, and mode-specific Settings UI. Docs and screenshots updated for four-channel Channels and routing. * fix: harden Apprise secrets at rest and preserve-on-write saves Encrypt Apprise endpoint and config with CryptoService so a downgrade cannot leak via SELECT *. Align channel and routing saves so blank destination fields omit config on same-mode URL edits, enforce keyed notify IDs, and keep secrets_redacted truthful. * fix: harden Apprise route type changes and mixed-version config UI Require a raw channel_url when switching notification-route types so ciphertext cannot strand under Discord/Slack/webhook. Default missing remote apprise status, replace Channels state on node switch, and exercise the production config-column migrator. * fix: tolerate stub fleet configuration payloads without agents Normalize remote Apprise agent status only when notifications.agents is present so successful Pilot/stub fetches stay online instead of throwing into the offline catch path. * fix: correct TypeScript in configuration normalize tests * fix: ignore stale Channels agent bodies after node switch Compare the active node after response JSON parsing so a slow body cannot overwrite the newly selected node's channel state. * fix: isolate corrupt Apprise crypto and keep keyed Tags visible Decrypt failures on one Apprise row no longer 500 agent/route lists or suppress sibling channel dispatch. Treat public /notify/<redacted> as keyed so Tags remain editable after reload.
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
import { useFleetSyncStatus } from '@/hooks/useFleetSyncStatus';
|
||||
import { STICKY_CONTROL_IDENTITY_MISMATCH, type FleetSyncStatus } from '@/lib/fleetSyncApi';
|
||||
import type { ConfigurationStatusPayload } from '@/components/dashboard';
|
||||
import { normalizeConfigurationAgents } from '@/lib/configurationStatus';
|
||||
|
||||
interface FleetNodeConfiguration {
|
||||
id: number;
|
||||
@@ -115,11 +116,13 @@ function NodeCard({ node, policySyncState }: {
|
||||
}
|
||||
|
||||
const { notifications, automation, security, backup, thresholds } = node.configuration;
|
||||
const agents = normalizeConfigurationAgents(notifications.agents);
|
||||
|
||||
const agentCount = [
|
||||
notifications.agents.discord.enabled,
|
||||
notifications.agents.slack.enabled,
|
||||
notifications.agents.webhook.enabled,
|
||||
agents.discord.enabled,
|
||||
agents.slack.enabled,
|
||||
agents.webhook.enabled,
|
||||
agents.apprise.enabled,
|
||||
].filter(Boolean).length;
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user