Fachdokumente nach docs/, Entscheidungen festgehalten

CLAUDE.md und README.md verweisen auf docs/, die Dateien lagen aber im
Wurzelverzeichnis. Verschoben.

docs/13-entscheidungen.md hält fest, wo die Dokumente sich widersprechen und
wie es aufgelöst wurde. Der wichtigste Punkt: 04-datenmodell.md verlangt eine
Regel, die jedes UPDATE auf CaseEntryVersion verwirft, 05-akten-und-vorlagen.md
verlangt, dass eine Umklassifizierung rückwirkend auf alle Versionen wirkt.
Beides zusammen geht nicht. Aufgelöst über einen Trigger, der die Tabelle
anhängend hält, aber das Anheben von minClearance zulässt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Harlekin
2026-09-01 00:00:58 +02:00
co-authored by Claude Opus 5
commit 4446e3f0ac
16 changed files with 1919 additions and 0 deletions
+89
View File
@@ -0,0 +1,89 @@
# AfiS-Aktensystem
Interne Web-Anwendung für die Abteilung für innere Sicherheit (AfiS) eines SCP-RP-Servers.
Verwaltet Fallakten, Personalakten und Ermittlungen mit einem mehrstufigen Klassifizierungssystem.
Anmeldung und Berechtigungen laufen vollständig über Discord.
Dies ist ein Rollenspiel-Werkzeug für eine geschlossene Gruppe von etwa 10 bis 50 Personen,
selbst gehostet auf einem Homeserver. Kein Multi-Tenant, keine öffentliche Registrierung.
## Stack
- Next.js 15, App Router, React 19, TypeScript strict
- Auth.js v5 (Discord Provider)
- Prisma + PostgreSQL 16
- Tailwind CSS, keine Komponentenbibliothek (siehe `docs/10-design-system.md`)
- Separater Node-Dienst `worker/` mit discord.js für Rollen-Abgleich
- ClamAV und Playwright als eigene Container
- Betrieb als **ein** Dockge-Stack, siehe `docs/11-betrieb.md`. Kein Reverse Proxy im Stack,
TLS und Kompression macht der Cloudflare Tunnel.
## Dokumentation
Vor dem Bau eines Bereichs immer das passende Dokument lesen:
| Datei | Inhalt |
|---|---|
| `docs/01-produkt.md` | Domäne, Glossar, Rollen der Nutzer |
| `docs/02-architektur.md` | Dienste, Datenflüsse, Verzeichnisstruktur |
| `docs/03-auth-und-rechte.md` | Discord-Login, Rollen-Mapping, Zugriffsprüfung |
| `docs/04-datenmodell.md` | Prisma-Schema, Indizes, Migrationen |
| `docs/05-akten-und-vorlagen.md` | Aktenaufbau, Vorlagen, Versionierung, Schwärzung |
| `docs/06-chat-und-realtime.md` | Aktenchat, SSE, Benachrichtigungen |
| `docs/07-dateien-und-sicherheit.md` | Upload-Prüfkette, Auslieferung |
| `docs/08-suche-und-export.md` | Volltextsuche, PDF-Export |
| `docs/09-performance-und-ux.md` | Ladezustände, optimistische Updates, Latenzbudgets |
| `docs/10-design-system.md` | Farben, Typografie, Komponentenregeln |
| `docs/11-betrieb.md` | Dockge-Stack, compose.yaml, Backups |
| `docs/13-entscheidungen.md` | Aufgelöste Widersprüche der Dokumente, getroffene Festlegungen |
`TASKS.md` enthält die Bauphasen. Arbeite sie in Reihenfolge ab und hake ab, was fertig ist.
## Harte Regeln
1. **Berechtigungsprüfung immer serverseitig und immer in der Datenbankabfrage.**
Niemals alle Datensätze laden und danach filtern. Siehe `docs/03-auth-und-rechte.md`.
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`.
Welche Änderungen erlaubt sind, steuert die Änderungsrichtlinie in
`docs/05-akten-und-vorlagen.md`.
3. **Jede schreibende Aktion und jeder Lesezugriff auf Stufe 3+ erzeugt einen Audit-Eintrag.**
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 Mutation eine sofortige
Reaktion. Siehe `docs/09-performance-und-ux.md`, das ist keine Kür.
6. **Existenz ist auch eine Information.** Akten oberhalb der Sichtstufe des Nutzers tauchen
weder in Listen noch in Trefferzahlen noch in Rückverweisen auf.
7. Keine Secrets im Repo. Alles über `.env`, Vorlage in `.env.example`.
8. **Keine Einmal-Container und keine Init-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.
## Sprachkonvention
- **Code, Datenbank, API**: Englisch. `Case`, `CaseEntry`, `PersonnelFile`, `ClearanceLevel`.
- **Oberfläche und Dokumentation**: Deutsch. Alle UI-Texte zentral in `lib/i18n/de.ts`,
nie hart im JSX. Das Glossar in `docs/01-produkt.md` legt die Übersetzungen fest.
## Kommandos
```bash
pnpm dev # Next.js Dev-Server
pnpm worker:dev # Discord-Sync-Worker
pnpm db:migrate # Prisma Migration anwenden
pnpm db:seed # Testdaten inkl. Vorlagen
pnpm db:studio # Prisma Studio
pnpm test # Vitest
pnpm test:e2e # Playwright
pnpm lint && pnpm typecheck
pnpm build # Standalone-Build für das Container-Image
```
## Arbeitsweise
- Kleine Commits pro abgeschlossener Aufgabe aus `TASKS.md`.
- Für jede Zugriffsregel einen Test, der den **negativen** Fall prüft: Nutzer ohne Freigabe
sieht nichts, findet nichts, bekommt 404 statt 403.
- Bei Unklarheiten in der Fachlichkeit nicht raten, sondern nachfragen.
- Nach jeder Phase `pnpm lint && pnpm typecheck && pnpm test` laufen lassen.