feat(benachrichtigung): E-Mail und Webhook bei Drift und Ablauf (#028)
Drift, ablaufende und abgelaufene Schluessel, unerreichbare Hosts und geaenderte Host-Keys sollen auffallen, ohne dass jemand taeglich in die Oberflaeche schaut. Versand per SMTP (Microsoft 365, STARTTLS) und per Webhook mit HMAC-Signatur, eingestellt unter /einstellungen. Die Anlaesse liest der Worker aus der Datenbank, statt sie im Abgleich auszuloesen: der Abgleich-Ablauf bleibt unberuehrt, und ein verpasster Lauf holt sich der naechste. Ein Versandprotokoll (Zustellung) mit Anlass-Fingerabdruck verhindert Doppelmeldungen und haelt Fehlschlaege fuer begrenzte Wiederholungen fest. Taeglich eine Zusammenfassung, geaenderte Host-Keys im Fuenf-Minuten-Takt sofort. Versand und Testnachricht laufen im Worker, damit der Webprozess keinen Weg zu Mailserver oder Webhook-Ziel braucht. Passwort und Geheimnis liegen nur verschluesselt in der Datenbank; die Seite zeigt "gesetzt". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
-- #028: Benachrichtigungen. Versandprotokoll gegen Doppelmeldungen und eine Vorgangsart fuer
|
||||
-- die Testnachricht (Versand laeuft im Worker).
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "MeldungsKanal" AS ENUM ('EMAIL', 'WEBHOOK');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ZustellErgebnis" AS ENUM ('GESENDET', 'FEHLGESCHLAGEN');
|
||||
|
||||
-- AlterEnum
|
||||
ALTER TYPE "VorgangsArt" ADD VALUE 'BENACHRICHTIGUNG_TEST';
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Zustellung" (
|
||||
"id" TEXT NOT NULL,
|
||||
"anlass" TEXT NOT NULL,
|
||||
"kanal" "MeldungsKanal" NOT NULL,
|
||||
"ergebnis" "ZustellErgebnis" NOT NULL,
|
||||
"fehler" TEXT,
|
||||
"versuche" INTEGER NOT NULL DEFAULT 1,
|
||||
"naechsterVersuchAm" TIMESTAMP(3),
|
||||
"sendung" TEXT NOT NULL,
|
||||
"betreff" TEXT NOT NULL,
|
||||
"zeitpunkt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "Zustellung_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Zustellung_zeitpunkt_idx" ON "Zustellung"("zeitpunkt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Zustellung_sendung_idx" ON "Zustellung"("sendung");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Zustellung_anlass_kanal_key" ON "Zustellung"("anlass", "kanal");
|
||||
@@ -114,6 +114,8 @@ enum VorgangsArt {
|
||||
ZIELKONTO_ANLEGEN
|
||||
/// sudoers und – falls von sshkv angelegt – den Benutzer entfernen (#018, #024).
|
||||
ZIELKONTO_ENTFERNEN
|
||||
/// Testnachricht ueber einen Benachrichtigungskanal (#028).
|
||||
BENACHRICHTIGUNG_TEST
|
||||
}
|
||||
|
||||
enum VorgangsStatus {
|
||||
@@ -125,6 +127,17 @@ enum VorgangsStatus {
|
||||
ABGEBROCHEN
|
||||
}
|
||||
|
||||
/// Versandweg einer Benachrichtigung (#028).
|
||||
enum MeldungsKanal {
|
||||
EMAIL
|
||||
WEBHOOK
|
||||
}
|
||||
|
||||
enum ZustellErgebnis {
|
||||
GESENDET
|
||||
FEHLGESCHLAGEN
|
||||
}
|
||||
|
||||
enum ProtokollErgebnis {
|
||||
ERFOLG
|
||||
FEHLER
|
||||
@@ -496,6 +509,30 @@ model Einstellung {
|
||||
geaendertAm DateTime @updatedAt
|
||||
}
|
||||
|
||||
/// Versandprotokoll der Benachrichtigungen (#028): je Anlass und Kanal hoechstens eine Zeile.
|
||||
/// Vor jedem Versand wird hiergegen geprueft – so meldet sshkv dieselbe Abweichung oder dieselbe
|
||||
/// Ablaufstufe nie zweimal, auch wenn ein Zeitplan doppelt feuert oder der Worker neu startet.
|
||||
model Zustellung {
|
||||
id String @id @default(cuid())
|
||||
/// Fingerabdruck des Anlasses, z. B. drift:<abweichungId>, ablauf:<schluesselId>:7:<datum>.
|
||||
anlass String
|
||||
kanal MeldungsKanal
|
||||
ergebnis ZustellErgebnis
|
||||
/// Kurzer Fehlertext ohne Zugangsdaten.
|
||||
fehler String?
|
||||
versuche Int @default(1)
|
||||
/// Wann ein Fehlschlag fruehestens erneut versucht wird; leer = nicht mehr.
|
||||
naechsterVersuchAm DateTime?
|
||||
/// Gemeinsame Kennung aller Anlaesse einer Nachricht – die Oberflaeche zeigt je Nachricht eine Zeile.
|
||||
sendung String
|
||||
betreff String
|
||||
zeitpunkt DateTime @default(now())
|
||||
|
||||
@@unique([anlass, kanal])
|
||||
@@index([zeitpunkt])
|
||||
@@index([sendung])
|
||||
}
|
||||
|
||||
/// Einfaches Rate-Limit fuer Anmeldung und Re-Auth (feste Fenster).
|
||||
model Ratenbegrenzung {
|
||||
schluessel String @id
|
||||
|
||||
Reference in New Issue
Block a user