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
Die README beschrieb das Vorgehen statt der Anwendung. Sie erklärt jetzt, was das System kann, wie es aufgebaut ist und wie man es lokal und im Betrieb fährt. Dazu tragen die acht Zusicherungen dort ihre Nummern — Berechtigungsprüfung in der Abfrage, kein DELETE im Verlauf, Protokollpflicht ab Stufe 3, Magic Bytes statt Dateiendungen, Skelette statt Spinner, Existenz als Information, keine Geheimnisse im Repository, keine Einmal-Container. Achtzehn Dateien verwiesen für ebendiese Regeln auf eine Datei, die nicht mehr mitverfolgt wird; sie zeigen jetzt auf die README. Arbeitsunterlagen bleiben auf der Platte, werden aber nicht mehr verfolgt. Die Ausschlussregel steht in .git/info/exclude statt in .gitignore, damit sie nicht selbst im Repository steht.
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 |
|