syncova-policies/README.md
Weapie 328f042307 Syncova Policies: Portal für DSGVO-Datenschutzerklärungen
Next.js 15 App Router mit öffentlicher Übersicht und geschütztem
Admin-Bereich zur Pflege von Datenschutzerklärungen nach Art. 12ff. DSGVO.

- Oberfläche auf Basis von shadcn/ui, Inter lokal eingebunden
- Prisma/SQLite, Auth.js mit Credentials-Provider und Rollen
- Massenimport der Merkblätter des Amtes Leezen aus PDF
- Docker-Image (standalone) und Gitea-Workflow zur Veröffentlichung

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 16:23:51 +02:00

117 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Syncova Policies
Verwaltung und Veröffentlichung von Datenschutzerklärungen nach DSGVO (Art. 12ff.).
Öffentliche Übersicht für Betroffene, geschützter Admin-Bereich zur Pflege.
Next.js 15 (App Router) · React 19 · Tailwind CSS 4 · shadcn/ui · Prisma + SQLite · Auth.js
---
## Schnellstart (lokal)
```bash
npm install
cp .env.example .env # NEXTAUTH_SECRET eintragen (siehe unten)
npx prisma migrate deploy
npm run seed-admin # legt den ersten Admin an und zeigt das Passwort einmalig
npm run dev
```
Die Anwendung läuft anschließend auf http://localhost:3000, der Admin-Bereich
unter `/admin`.
### Umgebungsvariablen
| Variable | Pflicht | Bedeutung |
|---|---|---|
| `NEXTAUTH_SECRET` | ja | Signiert die Session-Token. Erzeugen mit `node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"` |
| `NEXTAUTH_URL` | ja | Öffentliche URL der Anwendung, z. B. `https://datenschutz.example.de` |
| `DATABASE_URL` | ja | SQLite-Pfad. Lokal `file:./dev.db`, im Container `file:/app/data/syncova.db` |
| `ADMIN_EMAIL` | nein | Vorgabe für `seed-admin` / `reset-admin` |
| `ADMIN_NAME` | nein | Anzeigename des Admin-Kontos |
| `ADMIN_PASSWORD` | nein | Leer lassen für ein generiertes Zufallspasswort |
> `.env` ist absichtlich nicht versioniert – sie enthält das Session-Secret.
> Ebenso wenig die SQLite-Datei, die Benutzerkonten und Passwort-Hashes enthält.
---
## Betrieb per Docker
```bash
docker run -d --name syncova-policies \
-p 3000:3000 \
-e NEXTAUTH_SECRET="$(node -e "console.log(require('crypto').randomBytes(32).toString('base64'))")" \
-e NEXTAUTH_URL="https://datenschutz.example.de" \
-v syncova-data:/app/data \
git.jfritzsche.de/jf/syncova-policies:latest
```
Oder mit Compose:
```bash
export NEXTAUTH_SECRET="…"
export NEXTAUTH_URL="https://datenschutz.example.de"
docker compose up -d
```
Beim Start wendet der Container ausstehende Migrationen selbst an
(`prisma migrate deploy`). Die Datenbank liegt im Volume unter `/app/data` –
**ohne dieses Volume gehen alle Daten beim Neustart verloren.**
Ersten Admin-Zugang anlegen:
```bash
docker exec -it syncova-policies node scripts/seed-admin.js
```
Passwort zurücksetzen:
```bash
docker exec -it syncova-policies node scripts/reset-admin.js --email admin@example.de
```
---
## Datenpflege
Datenschutzerklärungen werden normalerweise im Admin-Bereich gepflegt. Für
Massenimporte gibt es zwei Wege:
| Befehl | Zweck |
|---|---|
| `npm run import-policy -- data/policies/<datei>.json` | Einzelne Erklärung aus JSON importieren (`--update` überschreibt) |
| `npm run analyze-pdfs` | PDFs in `data/import/` analysieren, ohne zu schreiben |
| `npm run import-pdfs` | Alle PDFs aus `data/import/` importieren (`--dry-run`, `--public`) |
Der PDF-Import ist auf die Merkblatt-Vorlage des Amtes Leezen zugeschnitten
(`scripts/lib/pdf-policy.js`). Er vergleicht den Textbaustein-Teil jedes
Dokuments gegen ein Referenzdokument und meldet jede Abweichung, statt sie
stillschweigend zu übernehmen. Importierte Datensätze werden am Titel erkannt
und aktualisiert, nicht dupliziert.
---
## Veröffentlichung des Images
`.gitea/workflows/publish-image.yml` baut bei jedem Push auf `main` sowie bei
`v*`-Tags ein Image und lädt es in die Gitea-Registry.
Voraussetzung: im Repository unter **Settings → Actions → Secrets** ein Secret
`REGISTRY_TOKEN` mit einem Token hinterlegen, das `write:package` darf.
---
## Projektstruktur
```
app/ Routen (öffentlich, /admin, /auth, /api)
components/ UI-Komponenten; components/ui = shadcn/ui
hooks/ SWR-Datenzugriff, Theme
lib/ Prisma/Auth-Helfer, Markdown, Formatierung
prisma/ Schema und Migrationen
scripts/ Admin- und Importskripte
data/import/ Quell-PDFs für den Massenimport
data/policies/ Aufbereitete Datensätze als JSON
```