Prüfung / Lint, Typen, Tests (push) Canceled after 0s
Prüfung / Images bauen (pdf) (push) Canceled after 0s
Prüfung / Images bauen (web) (push) Canceled after 0s
Prüfung / Images bauen (worker) (push) Canceled after 0s
Images / bauen (pdf, docker/pdf.Dockerfile) (push) Canceled after 0s
Images / bauen (web, docker/web.Dockerfile) (push) Canceled after 0s
Images / bauen (worker, docker/worker.Dockerfile) (push) Canceled after 0s
375 Vorkommen in 210 Dateien. Betrifft Kommentare, Oberflaechentexte und die README; an keiner Stelle Bedeutung, nur Zeichensetzung.
110 lines
4.6 KiB
Markdown
110 lines
4.6 KiB
Markdown
# AfiS-Aktensystem
|
|
|
|
Fall- und Personalaktenverwaltung für die Abteilung für innere Sicherheit eines
|
|
SCP-RP-Servers. Anmeldung und Berechtigungen laufen vollständig über Discord.
|
|
|
|
Interne Anwendung für eine geschlossene Gruppe von zehn bis fünfzig Personen, selbst
|
|
gehostet. Keine Mandantentrennung, keine öffentliche Registrierung.
|
|
|
|
## Was es kann
|
|
|
|
- **Fallakten** mit Kopfdaten, Abschnitten nach Vorlage und einem Verlauf, der nur wächst
|
|
- **Personalakten**, überwiegend für Externe, mit Aktenblatt zum Ausdrucken
|
|
- **Abteilungen** als Ebene darüber: was zu ihnen aktenkundig ist, ergibt sich aus ihren
|
|
Mitgliedern
|
|
- **Dokumente** nach Vorlage, an einer Fall- oder Personalakte
|
|
- **Fünfstufige Klassifizierung** mit feldgenauer Schwärzung
|
|
- **Volltextsuche** je Freigabestufe, Kommandopalette auf Strg+K
|
|
- **Chat** in jeder Akte, mit Übernahme einer Nachricht als Vermerk
|
|
- **Export** als PDF mit Wasserzeichen, jeder Abruf protokolliert
|
|
- **Zugriffsprotokoll** über jede schreibende Aktion und jeden Lesezugriff ab Stufe 3
|
|
|
|
## Zusicherungen
|
|
|
|
Acht Regeln, die im Code und wo möglich in der Datenbank durchgesetzt sind. Sie sind der
|
|
Grund, warum das System so gebaut ist, wie es gebaut ist - Codekommentare verweisen unter
|
|
ihrer Nummer hierher.
|
|
|
|
1. **Berechtigungsprüfung immer serverseitig und immer in der Datenbankabfrage.** Niemals
|
|
alle Datensätze laden und danach filtern.
|
|
2. **Verlaufseinträge dürfen nachträglich geändert werden, aber niemals unsichtbar.** Jede
|
|
Änderung erzeugt eine Version, jede Zurücknahme lässt einen Grabstein stehen, beides ist
|
|
für alle sichtbar, die den Eintrag sehen dürfen. Es gibt kein `DELETE` - das steht als
|
|
Regel in der Datenbank, nicht nur in der Anwendung.
|
|
3. **Jede schreibende Aktion und jeder Lesezugriff ab Stufe 3 erzeugt einen
|
|
Protokolleintrag.**
|
|
4. **Keine Dateiendungen als Typprüfung.** Immer Magic Bytes. Kein SVG, kein HTML, keine
|
|
Archive.
|
|
5. **Keine Blockade-Spinner.** Jede Ansicht hat ein Skelett, jede Änderung eine sofortige
|
|
Rückmeldung.
|
|
6. **Existenz ist auch eine Information.** Akten oberhalb der Sichtstufe tauchen weder in
|
|
Listen noch in Trefferzahlen noch in Rückverweisen auf. Kein Zugriff heisst 404, nicht 403.
|
|
7. **Keine Geheimnisse im Repository.** Alles über `.env`, Vorlage in `.env.example`.
|
|
8. **Keine Einmal-Container.** Der Betrieb läuft über Dockge, das beendete Container nicht
|
|
dauerhaft anzeigt. Migrationen gehören ins Startkommando von `web`, wiederkehrende
|
|
Aufgaben in Dauerläufer mit eigenem Cron. Jeder Dienst braucht einen Healthcheck, weil
|
|
das in Dockge die Statusanzeige ist.
|
|
|
|
## Aufbau
|
|
|
|
```
|
|
web/ Next.js 15, App Router, React 19
|
|
worker/ discord.js, gleicht Rollen und Mitgliedschaft ab
|
|
pdf/ Playwright, erzeugt die PDF-Ausdrucke
|
|
packages/db/ Prisma-Schema, Migrationen, Seed
|
|
docker/ Dockerfiles für web, worker und pdf
|
|
compose.yaml Der Dockge-Stack
|
|
.env.example Vorlage für den .env-Reiter in Dockge
|
|
```
|
|
|
|
Stack: Next.js 15 mit React 19 und TypeScript, Auth.js v5 mit Discord-Provider, Prisma auf
|
|
PostgreSQL 16, Tailwind ohne Komponentenbibliothek. ClamAV und Playwright laufen als eigene
|
|
Container.
|
|
|
|
## Einrichten
|
|
|
|
Discord-Application anlegen, Bot auf den Server einladen und **Server Members Intent
|
|
aktivieren** - ohne das liefert der Bot keine Rollen.
|
|
|
|
## Lokal entwickeln
|
|
|
|
Node 22 und pnpm 9.
|
|
|
|
```bash
|
|
corepack enable && pnpm install
|
|
|
|
docker run -d --name afis-db -e POSTGRES_DB=afis -e POSTGRES_USER=afis \
|
|
-e POSTGRES_PASSWORD=afis -p 5434:5432 postgres:16-alpine
|
|
|
|
cp .env.example .env
|
|
# DATABASE_URL und DIRECT_DATABASE_URL auf localhost:5434 zeigen lassen
|
|
|
|
pnpm --filter @afis/db run build # erzeugt den Prisma-Client
|
|
pnpm db:deploy && pnpm db:seed
|
|
pnpm dev
|
|
```
|
|
|
|
Prüfen wie die CI:
|
|
|
|
```bash
|
|
pnpm lint && pnpm typecheck && pnpm test
|
|
pnpm test:e2e
|
|
```
|
|
|
|
`pnpm test` legt sich eine eigene Datenbank `afis_test` an und lässt die
|
|
Entwicklungsdatenbank in Ruhe: Verlaufseinträge und Protokollzeilen sind nach Regel 2 nicht
|
|
löschbar, was ein Test dort anlegt, bliebe für immer stehen.
|
|
|
|
## Betrieb
|
|
|
|
Gehostet als **ein** Dockge-Stack. Die `.env` wird nicht im Repository gepflegt, sondern im
|
|
`.env`-Reiter von Dockge.
|
|
|
|
| | |
|
|
|---|---|
|
|
| Verwaltung | Dockge, ein Stack namens `afis` unter `/opt/stacks/afis/` |
|
|
| Erreichbarkeit | Cloudflare Tunnel, kein offener Port am Router |
|
|
| Aktualisieren | Dockge → Stack → Update, Migration läuft automatisch mit |
|
|
| Backup | zwei Dauerläufer mit Cron: nächtlicher Dump plus restic offsite |
|
|
| Wiederherstellung | `scripts/restore-test.sh` spielt einen Dump in eine Wegwerf-Datenbank und vergleicht Zeilenzahlen, Regeln und Trigger |
|