
Engagement Manager ist eine Webanwendung zur Verfolgung von Offensive-Security-Engagements. Sie bietet eine moderne Benutzeroberfläche, die mit Next.js, Prisma und PostgreSQL erstellt wurde.
Engagement Manager ist eine Webanwendung zur Verfolgung von Offensive-Security-Engagements. Sie verfügt über eine moderne UI, die mit Next.js, Prisma und PostgreSQL erstellt wurde. Die App umfasst einen Kalender, Engagements, Kunden, Kontakte, Findings und Operatoren.

| Scanner-/Export-Familie | Akzeptierter Export |
|---|---|
| Burp Suite | Issues XML, einschließlich der inerten internen Schema-DTD |
| Nessus / Tenable | Nessus v2 XML (.nessus) |
| Nmap | XML; offene Ports und deren Skriptausgabe werden zu informativen Beobachtungen, nicht zu abgeleiteten Schwachstellen |
| OpenVAS / Greenbone | Nativer XML-Bericht oder GMP get_reports_response |
| OWASP ZAP | Traditioneller JSON-Bericht mit Sites und Alerts |
| Nuclei | JSON Lines (-jsonl) |
| Qualys | Scan-Ergebnis-XML (SCAN/IP-Struktur), nicht das separate Host-Detection-API-Format |
| Semgrep / CodeQL und andere SARIF-Produzenten | SARIF-JSON-Runs, Regeln und Ergebnisse |
Exporte sind auf 2 MB und 500 Findings pro Import begrenzt, mit Rate Limits pro Benutzer für Vorschau und Bestätigung. Die Anwendung akzeptiert insgesamt höchstens 10.000 Findings und 500 für ein einzelnes Engagement über manuelle Erstellung, Vorlagen und Scanner-Importe hinweg. Die globale Findings-Liste lädt 100 Zeilen pro Seite, und Engagement-/Berichts-Finding-Abfragen sind durch dasselbe Limit pro Engagement begrenzt. Unbekannte Layouts schlagen sichtbar fehl, anstatt stillschweigend als erfolgreicher Import behandelt zu werden. Scanner-Schweregrade sind Vorschläge: Prüfen Sie ihren Kontext vor der Genehmigung. Referenzierte URLs, HTML und eingebettete Remote-Bilder werden nicht abgerufen oder ausgeführt.
Berichte erlauben 1–100 Findings, bis zu 100 Nachweisbilder (je 5 MB, insgesamt 20 MB Eingabe), 500 Seiten und 25 MB Ausgabe. Die Ausstellung ist auf 50 Versionen pro Engagement und 1 GB ausgestellter PDFs in der gesamten Anwendung begrenzt. Vorschau und Ausstellung haben Rate Limits pro Benutzer, und es wird jeweils nur ein PDF-Render pro Anwendungsprozess zugelassen. Findings behalten höchstens 1000 Revisionen und 500 Kommentare; das Erreichen eines Limits schlägt fehl, ohne die Historie zu überschreiben. DejaVu-Schriftarten und ihre Weiterverteilungslizenz sind in assets/fonts enthalten; Deployments müssen diese Assets beibehalten (Next Output Tracing schließt sie ein).
Next.js Server Actions teilen sich ein einzelnes 25mb-Body-Größenlimit (festgelegt in next.config.ts) für Nachweis-Uploads. Die Anmeldung verwendet eine dedizierte Same-Origin-URL-kodierte Route mit einem 4-KB-Streaming-Limit vor Authentifizierung oder Datenbankarbeit.
Dies bewahrt den bestehenden gemeinsam genutzten authentifizierten Workspace, kein neues Mandantenmodell pro Kunde. Alle neuen Seiten, Actions und PDF-Downloads prüfen eine aktuelle datenbankgestützte Sitzung. Entwürfe sind auf ihren Eigentümer beschränkt; Berechtigungen für Review, Vorlagengenehmigung und Ausstellung werden serverseitig durchgesetzt. Vertrauliche PDF-Antworten sind private/no-store. Finale PDFs enthalten nur eine explizite Allowlist von Berichtsfeldern, niemals private Entwürfe, Review-Kommentare oder nicht zugehörige Engagements.
Die Implementierung verwendet die OWASP Top 10:2025-Checkliste: Zugriffskontrollen (A01), private Antworten und bestehende CSP/CSRF-Kontrollen (A02), gepinnte Abhängigkeiten und CI (A03), bestehende Sitzungs-/Secret-Schutzmaßnahmen plus Berichtsintegritätsprüfungen (A04/A08), inertes Markdown/XML und parametrisierten Datenbankzugriff (A05), begrenzte Verarbeitung und unabhängige Überprüfung (A06), Live-Sitzungsprüfungen (A07), inhaltsfreie Audit-Ereignisse (A09) und transaktionale Änderungen mit Bereinigung bei Fehlern (A10). Ein Digest erkennt versehentliche Korruption; er ist keine digitale Signatur und kein Schutz vor einem Datenbankadministrator. Dies ist keine Compliance-Zertifizierung. Die Produktion erfordert weiterhin HTTPS, geschützten Datenbank-/Backup-Speicher und operatives Monitoring der Audit-Ausgabe.
Bevor Sie dieses Upgrade bereitstellen, erstellen Sie ein normales Anwendungs-Backup und wenden Sie die additiven Migrationen 20260904221808_reporting_workflow und 20260906194500_add_revocable_sessions mit npm run db:migrate an, generieren Sie dann den Prisma Client neu und bauen Sie neu. Bestehende Findings beginnen als Draft in Version 1, und bestehende Browser-Cookies müssen sich erneut anmelden, damit sie eine servergestützte Sitzungs-ID erhalten. Setzen Sie eine bestehende Datenbank nicht zurück. Backups enthalten die neuen Tabellen und ausgestellten PDFs über den bestehenden Voll-Datenbank-Export.
npm test npm run lint npx tsc --noEmit --noUnusedLocals --noUnusedParameters npm run build npm audit
`npm test` verwendet den nicht isolierten Testmodus von Node mit `tsx`, damit die einzelnen TypeScript-Testfälle ausgeführt werden, anstatt lediglich den Erfolg des Datei-Subprozesses zu melden. Halten Sie die expliziten Assertion-Gesamtzahlen in CI sichtbar.
Datenbank- und Browser-Regressionstests erfordern eine **dedizierte lokale Datenbank namens `reporting_tests`**, auf die Migrationen angewendet wurden. Sie erstellen und löschen ihre eigenen Fixture-Zeilen; richten Sie diese Tests niemals auf eine Anwendungsdatenbank. Setzen Sie `REPORTING_TEST_DATABASE_URL` auf diese Testdatenbank und führen Sie dann aus:```bash
DATABASE_URL="$REPORTING_TEST_DATABASE_URL" npx prisma migrate deploy
npm run test:reporting
npx playwright install chromium
npm run test:browser
Die Browser-Suite startet einen eigenen Loopback-Entwicklungsserver auf Port 3317 mit einem nur für Tests vorgesehenen Sitzungsgeheimnis; sie weigert sich, einen vorhandenen Server wiederzuverwenden. Setzen Sie REPORTING_TEST_BROWSER auf eine installierte Chromium-Executable, falls gewünscht. Sie testet Entwurfsdatenschutz, konkurrierende Bearbeitungen, Beweis-Upload, unabhängige Überprüfung, PDF-Berechtigungen/Unveränderlichkeit, Vorlagenerstellung ohne JavaScript und selektive deduplizierte Importe. Integrationstests üben tatsächliche transaktionale Konflikte und Rollback. Die Suiten ersetzen nicht die Verifizierung über Remote-LAN, Safari oder Produktionsbereitstellung.
Diese Anwendung ist für den Betrieb auf Ubuntu konzipiert und erfordert Folgendes:```bash sudo apt update && sudo apt install -y nodejs npm postgresql postgresql-client postgresql-contrib zip
`postgresql-client` stellt `pg_dump`, `pg_restore` und `psql` bereit; `zip` erstellt Backup-Archive. Die Wiederherstellungsextraktion wird von der Anwendung mit strikter Validierung von Einträgen und Größe durchgeführt.
Die Installation der Pakete führt nicht immer dazu, dass PostgreSQL läuft. Starten und aktivieren Sie den Dienst, bevor Sie Rollen erstellen oder die App starten:```bash
sudo systemctl enable --now postgresql
sudo systemctl status postgresql --no-pager
Wenn die App später mit Can't reach database server at 127.0.0.1:5432 fehlschlägt, führe sudo systemctl start postgresql aus und bestätige mit pg_isready -h 127.0.0.1 -p 5432.
Die App erfordert Node.js ^22.12.0 oder >=24.0.0 (siehe engines in package.json). Wenn das OS-Paket älter ist, installiere eine unterstützte Version aus einer vertrauenswürdigen Paketquelle, deren Signaturen du vor der Ausführung von setup.sh verifizierst.
Erstelle eine .env-Datei im Projektstammverzeichnis, bevor du Prisma oder die App ausführst:```bash
cat > .env << 'EOF'
DATABASE_URL="postgresql://em_admin:em_pass@localhost:5432/engagement_manager?schema=public"
JWT_SECRET="replace-with-a-long-random-secret-at-least-32-characters"
EOF
chmod 600 .env
| Variable | Erforderlich | Hinweise |
|----------|----------|-------|
| `DATABASE_URL` | Ja | PostgreSQL-Verbindungszeichenfolge. Prisma verwendet den Query-Parameter `schema=public`. Backup und Wiederherstellung verwenden eine temporäre pgpass-Datei, auf die nur der Eigentümer Zugriff hat, damit das Passwort nicht in Subprozess-Argumenten platziert wird. |
| `JWT_SECRET` | Ja in der Produktion | Muss mindestens **32 Zeichen** lang sein. Die App verweigert den Start in der Produktion ohne dieses. Eine Rotation dieses Werts macht alle bestehenden Sitzungen ungültig. |
| `TRUST_PROXY` | Nein | Auf `1` (oder `true`) setzen, nur wenn die App hinter einem Reverse-Proxy steht, der `X-Forwarded-For` / `X-Real-IP` und `X-Forwarded-Host` **überschreibt**. Login-Origin-Prüfungen verwenden `X-Forwarded-Host`, wenn in diesem Modus vorhanden; es muss einen öffentlichen Host enthalten, einschließlich eines nicht standardmäßigen Ports, falls verwendet. Andernfalls muss der Proxy den öffentlichen `Host`-Header beibehalten. Dies ist die erforderliche Produktionstopologie für genaue Login-Limits pro Quelle. Wenn nicht gesetzt, werden Header ignoriert, um Spoofing zu verhindern, und der Login verwendet ein höheres gemeinsames Ein-Minuten-Fallback-Budget, damit ein Client keine 15-minütige globale Sperre verhängen kann. |
| `ALLOWED_DEV_ORIGINS` | Nein | **Nur für die Entwicklung.** Zusätzliche Hostnamen, die `/_next`-Assets laden dürfen (kommagetrennt). Die aktuellen LAN-IPv4-Adressen des Servers sind automatisch erlaubt. Verwenden Sie dies für einen stabilen DNS-Namen. Produktions-Builds ignorieren dies. |
Ein starkes Secret generieren:```bash
openssl rand -base64 32
Stellen Sie zunächst sicher, dass PostgreSQL läuft (siehe Voraussetzungen). Das automatisierte ./setup.sh startet den Dienst für Sie; die manuellen Schritte unten gehen davon aus, dass er bereits läuft.
Führen Sie die folgenden Befehle aus, um die PostgreSQL-Datenbank und den Benutzer zu erstellen:```bash sudo -u postgres createuser --pwprompt em_admin sudo -u postgres psql -c "ALTER USER em_admin CREATEDB;" sudo -u postgres createdb --owner=em_admin engagement_manager sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE engagement_manager TO em_admin;"
### Produktion
Verwenden Sie einen dedizierten Datenbankbenutzer mit **minimalen Rechten** — gewähren Sie keine `CREATEDB`- oder Superuser-Rechte:```bash
sudo -u postgres createuser --pwprompt em_app
sudo -u postgres createdb --owner=em_app engagement_manager
Setze DATABASE_URL, um em_app (oder deinen gewählten Benutzernamen) zu verwenden. Migrationen werden als dieser Benutzer über npm run db:migrate ausgeführt.
Hinweis: Die Datenbankdateien werden im PostgreSQL-Datenverzeichnis gespeichert (typischerweise
/var/lib/postgresql/<version>/main/).
Führe vom Repository-Stammverzeichnis aus Folgendes aus:```bash chmod +x setup.sh ./setup.sh
Das Skript installiert Voraussetzungen, startet und aktiviert den PostgreSQL-Dienst, fordert einen Datenbank-Benutzernamen und ein Passwort an, schreibt eine `chmod 600` `.env`, erstellt die PostgreSQL-Rolle und -Datenbank, wendet Migrationen an und legt das Standard-Admin-Konto an. Der Produktionsmodus führt zusätzlich `npm run build` aus und gibt nur den Produktionsstartbefehl aus. Es installiert Node.js nicht über ein Remote-Shell-Skript; installieren Sie zuerst eine unterstützte Node.js-Version.
Für Headless- oder CI-Nutzung:```bash
sudo install -d -m 700 -o "$USER" /secure
openssl rand -base64 24 > /secure/db-password
chmod 600 /secure/db-password
./setup.sh -y --db-user=em_admin --db-pass-file=/secure/db-password
Führen Sie ./setup.sh --help aus, um alle Optionen anzuzeigen.
--db-pass=... wurde entfernt, da Kommandozeilen-Geheimnisse für andere Prozesse sichtbar sind. Legen Sie das Passwort in einer Datei ab, auf die nur der Eigentümer Zugriff hat, und ersetzen Sie das alte Argument durch --db-pass-file=/secure/db-password; das obige automatisierte Setup-Beispiel ist direkt kopierbar.setup.sh installiert Node.js nicht mehr. Installieren Sie eine unterstützte Node.js-Version (^22.12.0 oder >=24.0.0) aus einer vertrauenswürdigen Paketquelle, bevor Sie es ausführen.npm ci, daher muss package-lock.json vorhanden und mit package.json synchron sein..sql-Backups können nicht wiederhergestellt werden. Bevor Sie einen alten Server außer Betrieb nehmen, aktualisieren Sie ihn auf eine Version, die das strukturierte Anwendungs-Backup erstellen kann, und exportieren Sie die Daten erneut als .zip.Aus dem Projektverzeichnis installiert ein einziger Befehl Paketaktualisierungen, startet PostgreSQL, falls es gestoppt ist, und startet die Anwendung:```bash ./run.sh
Lass dieses Fenster geöffnet. Verwende die Local- oder Network-Adresse, die es ausgibt.
Um es stattdessen selbst zu starten: PostgreSQL muss laufen (`sudo systemctl start postgresql`, falls nötig). Starte dann den Entwicklungsserver:```bash
npm run dev
Startup gibt sowohl eine Loopback-URL als auch die LAN-Adresse dieser Maschine aus:```
`npm run dev` und `npm start` binden `0.0.0.0`, damit die Network-URL im LAN funktioniert. Behandle den LAN-Zugriff als reine Laborumgebung in einem vertrauenswürdigen Netzwerk. Der Dev-Modus ist nicht für das öffentliche Internet gehärtet.
Wenn du die App über den **Hostnamen** (nicht die IP) öffnest und der entfernte Browser eine leere weiße Seite anzeigt, füge diesen Namen zu `.env` hinzu und starte neu:```bash
ALLOWED_DEV_ORIGINS=dev.office.example
^22.12.0 oder >=24.0.0 (siehe engines in package.json)Secure markiert.uploads/ (Finding-Screenshots)Repository klonen und Abhängigkeiten installieren: ```bash npm ci
Erstellen Sie .env mit Produktionswerten (DATABASE_URL, JWT_SECRET ≥ 32 Zeichen).
Wenden Sie Datenbankmigrationen an: ```bash npm run db:migrate
Führen Sie Pre-Deploy-Prüfungen durch: ```bash npm run audit npm run typecheck npm run build
Starten Sie die Anwendung mit NODE_ENV=production: ```bash
NODE_ENV=production npm run start
Für einen echten Server führen Sie dies unter einem Prozessmanager (systemd, PM2 usw.) aus und platzieren Sie einen Reverse-Proxy davor für die TLS-Terminierung.
JWT_SECRET ist mindestens 32 Zeichen lang und nicht in git eingechecktNODE_ENV=production ist für den laufenden Prozess gesetztCREATEDB- oder Superuser-Rechteuploads/ liegt auf einem persistenten Datenträger und ist in Backups enthaltenbackups/ liegt auf einem persistenten Datenträger, wenn Admins Backup verwendenpg_dump, pg_restore und zip sind verfügbar, wenn Admins Backup/Restore verwenden werdenNach dem Seeden der Datenbank können Sie sich mit dem generierten temporären Admin-Konto anmelden:
admininitial-admin-credentials.txt geschrieben durch npx prisma db seed / npm run db:seedHinweis: Sie werden beim ersten Login aufgefordert, dieses temporäre Passwort zu ändern. Löschen Sie
initial-admin-credentials.txtunmittelbar danach. Alle Passwörter müssen mindestens 16 Zeichen lang sein und einen Großbuchstaben, einen Kleinbuchstaben, eine Zahl und ein Sonderzeichen enthalten.
/dashboard/users) sichern und wiederherstellen.Unter Admin zeigt das Database-Panel die Schaltflächen Backup, Restore und Reset. Das Users-Panel listet Konten auf und bietet eine Schaltfläche New User zum Hinzufügen von Benutzern. Das Appearance-Panel ermöglicht es einem Admin, die anwendungsweite Hervorhebungsfarbe zu wählen.
Backup erfordert Ihr Admin-Passwort und speichert dann eine .zip-Datei namens em-backup-YYYY-MM-DD-HHMM.zip in backups/ im Anwendungsverzeichnis (engagement-mgr/backups/). Nach einem erfolgreichen Export verwenden Sie Download auf der Admin-Seite. Eine kurzlebige signierte Berechtigung wird in einem HttpOnly-Cookie gehalten und funktioniert nur für den Admin, der das Backup erstellt hat.
em-backup-2026-06-02-1430.zip.| Pfad | Inhalt |
|---|---|
engagement-manager-backup/database.dump | Vollständiger PostgreSQL-Dump im Custom-Format (Schema, Tabellen, Daten, Enums, Beziehungen) von pg_dump |
engagement-manager-backup/uploads/ | In der Datenbank referenzierte Screenshot-Dateien von Findings |
.zip-Datei, die von Backup erstellt wurde, und ersetzt die aktuelle Datenbank und den uploads/-Ordner. Die Wiederherstellung über den Browser ist auf 8 MB begrenzt, damit die Dekomprimierung nicht den Web-Prozess monopolisiert. Für ein größeres Archiv stoppen Sie die Anwendung und führen Sie npm run db:restore -- /absolute/path/to/em-backup.zip als Anwendungsbenutzer aus. Der Offline-Befehl lädt .env aus dem Arbeitsverzeichnis und erfordert eine nicht leere DATABASE_URL in .env oder der Umgebung. Er akzeptiert reguläre Dateien bis zu 500 MB und streamt jeden Archiveintrag durch sein erweitertes Größenlimit. Die Datenbankwiederherstellung läuft in einer einzigen Transaktion; Archiv-Eintragsanzahlen, Pfade, Komprimierungsverhältnisse und erweiterte Größen werden validiert, bevor Dateien installiert werden. Backup, Restore, Reset und Änderungen an Screenshot-Dateien teilen sich eine exklusive Wartungssperre, sodass Datenbank-Commits und Dateisystem-Austauschvorgänge sich nicht überschneiden können. Erfordert zur Bestätigung Ihr Admin-Passwort.admin neu. Erfordert die Eingabe von RESET und die erneute Eingabe des aktuellen Passworts des bestätigenden Administrators. Dieses Passwort wird zum temporären Passwort des neu erstellten Kontos und muss beim ersten Login geändert werden.Alter Server
.zip-Datei und kopieren Sie sie auf den neuen Server (zum Beispiel mit scp oder rsync): ```bash
scp em-backup-2026-06-02-1430.zip user@new-server:/path/to/
Neuer Server
.env mit DATABASE_URL und JWT_SECRET (siehe Umgebungskonfiguration).npm ci.admin mit den nur für den Eigentümer bestimmten initial-admin-credentials.txt an, ändern Sie das temporäre Passwort und löschen Sie die Datei mit den Anmeldedaten./dashboard/users), klicken Sie auf Restore (unter Database), wählen Sie die .zip-Datei vom alten Server aus, geben Sie Ihr Admin-Passwort ein und bestätigen Sie.Hinweise
uploads/.git clone (oder stellen Sie dieselbe Revision bereit) auf dem neuen Server, damit die App dem vom Backup erwarteten Schema entspricht. Wenn auf dem alten Server ein neueres Schema als im geklonten Code lief, gleichen Sie die Versionen vor dem Import ab.Dieser Abschnitt dokumentiert die Architektur, das Datenbankschema, die Sicherheitsmaßnahmen und die abgeschlossenen Entwicklungsphasen für die Engagement-Manager-Anwendung.
Modal.tsx und .modal-panel in globals.css.Reporting-Ergänzungen: Finding speichert außerdem version, reviewStatus, authorId, reviewerId, templateId und importFingerprint; Screenshot speichert sortOrder. FindingTemplate enthält geprüfte wiederverwendbare Formulierungen; FindingRevision enthält unveränderliche Textrevisionen; FindingDraft enthält private Drafts pro Benutzer mit Konfliktversionen; FindingComment zeichnet Review-Diskussionen auf; EngagementReport enthält Berichtstitel, Executive Summary und geordnete Finding-IDs; IssuedReport speichert ein unveränderliches PDF, einen Content-Snapshot und einen SHA-256-Digest für jede ausgegebene Version. Benutzerbeziehungen als Autor/Reviewer verwenden SetNull; private Drafts werden entfernt, wenn ihr Benutzer entfernt wird. Reporting-Datensätze folgen dem Lebenszyklus ihres übergeordneten Engagements/Findings.
id, username, passwordHash, role (Admin, User), lastPasswordChange, lastLogin, sessions, createdAt, updatedAt.id, userId, expiresAt, createdAt — serverseitige Datensätze machen jede signierte Login-Sitzung beim Logout einzeln widerrufbar.key, count, resetAt — atomare Reservierungen für Quell- und Passwortbestätigungsversuche. Die Passwortverifikation hat zudem ein begrenztes Nebenläufigkeitslimit.highlightColor (Red, Blue, Teal, Green, Purple oder Amber) und updatedAt.id, codeName, clientId, chargeCode, status (Prep, Recon, Testing, Reporting, Complete), focus, type (AI, Code_Review, Firewall, Multi, Pentest, Phishing, Physical, Purple_Team, Red_Team, USB_Drop, Vishing, Web_App, Wireless), location (Internal, External), startPrep, endPrep, startRecon, endRecon, startTesting, endTesting, startReporting, , , , , , , (M:N), / (M:N mit Contact), , , , .id, company (DB-Spalte: companyName), address, city, state, zip, phone (DB-Spalte: phoneNumber), website, notes, contacts, engagements, createdAt, updatedAt.id, clientId, name, title, email, phone (DB-Spalte: phoneNumber), notes, assignedEngagements, trustedEngagements, createdAt, updatedAt.id, engagementId (optional), title, category, severity, background, remediation, supportingData (DB-Spalte: supportingLinks), screenshots, engagementContext, createdAt, updatedAt.id, engagementId, findingId, observation, affectedHosts, createdAt, updatedAt.id, findingId, filePath, description, createdAt.id, name, title, email, phoneNumber, discord, github, notes, engagements (M:N), createdAt, updatedAt.Um ein neues Feld zu einem bestehenden Modell hinzuzufügen (z. B. focus zu Engagement):
prisma/schema.prisma und fügen Sie das Feld zum gewünschten Modell hinzu: ```prisma
model Engagement {
id String @id @default(uuid())
codeName String
focus String? // new field
...
}
prisma/schema.prisma muss gefolgt werden von: ```bash
npx prisma migrate dev --name describe_your_change
Dies erstellt eine Migration, aktualisiert die Datenbank und generiert die Prisma-Client-Typen neu.
admin-Konto wird über den Prisma-Seed generiert. Admin-Rollen haben vollständigen Lese-, Bearbeitungs- und Löschzugriff auf alle Datensätze. User-Rollen können Findings und Screenshots erstellen, bearbeiten und löschen; alle anderen Entitäten (Engagements, Clients, Kontakte, Operatoren) sind für Benutzer schreibgeschützt. Jede Dashboard-Seite aktualisiert die Sitzung gegen die Datenbank, bevor vertrauliche Daten gelesen werden. Nur Administratoren können auf die Admin-Seite (/dashboard/users) zugreifen, Konten verwalten, die anwendungsweite Hervorhebungsfarbe ändern sowie die Datenbank sichern, wiederherstellen oder zurücksetzen. Sicherung, Wiederherstellung und Zurücksetzen erfordern eine erneute Passwortbestätigung. Das Erstellen einer Sicherung ist eine Server Action; der Browser-Download verwendet GET /api/db/backup?file=… mit der Admin-Sitzung und einer fünfminütigen signierten Berechtigung in einem HttpOnly-Cookie.jose-JWTs, die in HttpOnly-, SameSite=Lax-Cookies gespeichert werden, sowie eine übereinstimmende serverseitige Session-Zeile, die beim Logout widerrufen wird. Der Cookie-Ablauf wird absichtlich weggelassen, um das Browser-Sitzungsverhalten beizubehalten; sowohl das signierte Token als auch der Datenbankeintrag laufen nach einem Tag ab. Die transaktionale Zulassung behält höchstens zehn aktive Sitzungen pro Konto bei.src/proxy.ts) erzwingt Sitzungsprüfungen und eine 90-tägige Passwortrotation über alle geschützten Routen./api/uploads verhindert IDOR und gibt no-store-Antworten zurück.endReportingoutbriefobjectivestargetsexclusionsnotesoperatorscontactstrustedAgentsfindingsfindingContextscreatedAtupdatedAt