Files
AfiS-Aktensystem/CLAUDE.md
T
HarlekinandClaude Opus 5 e5211dcb5d Wissensgraph in der Projektanweisung verankert
graphify ist eingerichtet (786 Knoten, 1179 Kanten) und in CLAUDE.md als
erster Griff bei Fragen zum Bestand festgehalten, statt Dateien durchzulesen.

Mit der Stolperfalle dokumentiert: das `graphify` im PATH läuft nicht, weil es
für Python 3.10 installiert ist und das System-python3 3.12 ist. Der Aufruf
muss über python3.10 mit gesetztem PYTHONPATH laufen.

graphify-out/ ist ein Bauartefakt und bleibt aus dem Repository.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 23:03:06 +02:00

5.9 KiB

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.

Wissensgraph (graphify)

Für Fragen zum Bestand zuerst den Graphen befragen, statt Dateien durchzulesen. Das spart Kontext und zeigt Zusammenhänge über Dateigrenzen hinweg.

# Achtung: das `graphify` im PATH läuft nicht — es ist für Python 3.10
# installiert, das System-python3 ist 3.12. Deshalb immer so aufrufen:
export PYTHONPATH="$HOME/.local/lib/python3.10/site-packages"
python3.10 -m graphify query "<Frage>" --budget 2000
python3.10 -m graphify path "<A>" "<B>"      # Zusammenhang zwischen zwei Knoten
python3.10 -m graphify explain "<Begriff>"   # ein Knoten und seine Nachbarn
python3.10 -m graphify affected "<X>"        # was hängt an X, rückwärts
python3.10 -m graphify god-nodes --top 10    # die am stärksten verdrahteten Stellen

Nach jeder Änderung am Code den Graphen nachziehen, das kostet nichts und braucht kein LLM:

python3.10 -m graphify update . --no-cluster

graphify-out/ ist ein Bauartefakt und liegt nicht im Repository.

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.
  • Fachbegriffe der Domäne bleiben englisch, so wie sie auf dem Discord heißen: Rollennamen, Dienstgrade und die Bezeichnungen der Freigabestufen (Sensitive Access, nicht Geheim). Die Oberfläche ist deutsch, die Begriffe darin sind es nicht. Nicht eindeutschen. Diese Namen sind Daten, keine Oberflächentexte: sie stehen in der Datenbank und sind im Adminbereich änderbar, nicht in lib/i18n/de.ts.

Kommandos

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.