init: extract dsgvo-trainer from qognio-bot-widget-template@d2c816f
Source files (src/) and rendered bundle (www/) extracted on 2026-04-29T01:35:46+02:00. Adds nginx:alpine Dockerfile + docker-compose.yml (Caddy-labels) so the bot runs stand-alone or as a per-customer template clone. Parent monorepo commit: d2c816f3edbc9760802a11b29ff4151c7aad4b46 Bot version: 2026-04-21
This commit is contained in:
commit
20e069df3b
16 changed files with 3953 additions and 0 deletions
7
.dockerignore
Normal file
7
.dockerignore
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
README.md
|
||||||
|
bot.json
|
||||||
|
src/
|
||||||
|
docker-compose.yml
|
||||||
|
*.md
|
||||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
.DS_Store
|
||||||
|
*.log
|
||||||
|
*.tmp
|
||||||
|
node_modules/
|
||||||
13
Dockerfile
Normal file
13
Dockerfile
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Static-bundle bot — nginx:alpine serves www/ on port 80.
|
||||||
|
FROM nginx:1.27-alpine
|
||||||
|
|
||||||
|
# nginx config: gzip + cache headers + index.html no-store
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# Static bundle
|
||||||
|
COPY www/ /usr/share/nginx/html/
|
||||||
|
|
||||||
|
# Run as non-root via nginx's built-in unprivileged image features
|
||||||
|
EXPOSE 80
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
|
CMD wget -q --spider http://127.0.0.1/index.html || exit 1
|
||||||
67
README.md
Normal file
67
README.md
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
# Cora — DSGVO Compliance Companion
|
||||||
|
|
||||||
|
Cora — dein DSGVO-Sparringspartner. Gamifiziertes Compliance-Training für HR, IT und Führungskräfte. Läuft im deutschen Bunker.
|
||||||
|
|
||||||
|
```
|
||||||
|
slug : dsgvo-trainer
|
||||||
|
version : 2026-04-21
|
||||||
|
accent : #059669
|
||||||
|
runtime : nginx:alpine (static bundle)
|
||||||
|
template : qognio-bot-template-core (former qognio-bot-widget-template)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── src/ source — config.yaml, welcome.html, curricula.json, etc.
|
||||||
|
├── www/ rendered, directly servable static bundle
|
||||||
|
├── Dockerfile nginx:alpine + www/ → port 80
|
||||||
|
├── docker-compose.yml bot-host pattern (Caddy-labels, restart unless-stopped)
|
||||||
|
├── nginx.conf gzip + cache + SPA fallback
|
||||||
|
└── bot.json metadata + parent_core_commit
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run locally
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up --build
|
||||||
|
# → http://localhost (you'll need to tweak ports for local-only use)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Re-render after upstream core changes
|
||||||
|
|
||||||
|
This repo only stores src + rendered output; the rendering engine lives in
|
||||||
|
`qognio-bot-template-core`. To pull in core changes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /path/to/qognio-bot-template-core
|
||||||
|
./scripts/render.sh dsgvo-trainer --bot-repo /path/to/this/repo
|
||||||
|
git -C /path/to/this/repo commit -am "render: refresh from core@<sha>"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Per-customer copy (template usage)
|
||||||
|
|
||||||
|
This repo is a **template**. To clone for a customer:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone <this-repo> my-customer-dsgvo-trainer
|
||||||
|
cd my-customer-dsgvo-trainer
|
||||||
|
# tweak src/config.yaml (slug, bot_key_value, accent), src/welcome.html, src/curricula.json
|
||||||
|
docker compose -f docker-compose.yml up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy to qognio bot-host (.42 LXC pattern — legacy)
|
||||||
|
|
||||||
|
The bot-manager spawns LXC containers named after the slug. Push www/ via:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh fmh@46.243.203.42
|
||||||
|
sudo lxc file push /tmp/www/* dsgvo-trainer/var/www/html/
|
||||||
|
```
|
||||||
|
|
||||||
|
(Or run the docker-compose pattern on a Docker host — same network as Caddy.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Generated by `qognio-bot-template-core/scripts/extract-to-repo.sh` on 2026-04-29T01:35:46+02:00.
|
||||||
14
bot.json
Normal file
14
bot.json
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"slug": "dsgvo-trainer",
|
||||||
|
"name": "Cora",
|
||||||
|
"title": "DSGVO Compliance Companion",
|
||||||
|
"tagline": "Compliance-Companion",
|
||||||
|
"description": "Cora — dein DSGVO-Sparringspartner. Gamifiziertes Compliance-Training für HR, IT und Führungskräfte. Läuft im deutschen Bunker.",
|
||||||
|
"version": "2026-04-21",
|
||||||
|
"accent": "#059669",
|
||||||
|
"extracted_from": "qognio-bot-widget-template",
|
||||||
|
"parent_core_commit": "d2c816f3edbc9760802a11b29ff4151c7aad4b46",
|
||||||
|
"extracted_at": "2026-04-29T01:35:46+02:00",
|
||||||
|
"runtime": "nginx:alpine",
|
||||||
|
"default_port": 80
|
||||||
|
}
|
||||||
20
docker-compose.yml
Normal file
20
docker-compose.yml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Stand-alone bot container.
|
||||||
|
# Designed for the "caddy" external network on the bot host (qognio pattern).
|
||||||
|
# Override the hostname via SLUG env var if you reuse this template per customer.
|
||||||
|
services:
|
||||||
|
bot:
|
||||||
|
build: .
|
||||||
|
image: qognio/bot-dsgvo-trainer:${TAG:-latest}
|
||||||
|
container_name: bot-dsgvo-trainer
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- caddy
|
||||||
|
labels:
|
||||||
|
caddy: "dsgvo-trainer.on.qognio.com"
|
||||||
|
caddy.reverse_proxy: "{{upstreams 80}}"
|
||||||
|
qognio.bot.slug: "dsgvo-trainer"
|
||||||
|
qognio.bot.version: "2026-04-21"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
caddy:
|
||||||
|
external: true
|
||||||
27
nginx.conf
Normal file
27
nginx.conf
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# gzip
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_types text/css application/javascript application/json image/svg+xml text/plain;
|
||||||
|
gzip_min_length 512;
|
||||||
|
|
||||||
|
# index.html: never cache (so welcome screen / wiring updates land instantly)
|
||||||
|
location = /index.html {
|
||||||
|
add_header Cache-Control "no-store, must-revalidate" always;
|
||||||
|
}
|
||||||
|
|
||||||
|
# static assets: cache 1h
|
||||||
|
location ~* \.(?:css|js|json|svg|png|jpe?g|webp|gif|ico|woff2?)$ {
|
||||||
|
add_header Cache-Control "public, max-age=3600" always;
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/check-badges.js
Normal file
19
src/check-badges.js
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Erste Löschanfrage — 1 korrekte Antwort im Lösch-Modul
|
||||||
|
if ((state.moduleCorrect && state.moduleCorrect['loeschung'] >= 1)) unlockBadge('erste_loeschanfrage');
|
||||||
|
// AVV-Detektiv — 10 AVV-Fragen korrekt
|
||||||
|
if ((state.moduleCorrect && state.moduleCorrect['avv'] >= 10)) unlockBadge('avv_detektiv');
|
||||||
|
// 72-Stunden-Held — alle Datenpannen-Flashcards bestanden
|
||||||
|
if ((state.modulePassedFlash && state.modulePassedFlash['datenpannen'])) unlockBadge('meldepflicht');
|
||||||
|
// Betriebsrat-Flüsterer — HR-Module komplett (3 Quiz korrekt in jedem)
|
||||||
|
if ((state.moduleCorrect &&
|
||||||
|
(state.moduleCorrect['bewerbung'] || 0) >= 3 &&
|
||||||
|
(state.moduleCorrect['personalakte'] || 0) >= 3 &&
|
||||||
|
(state.moduleCorrect['betriebsrat'] || 0) >= 3)) unlockBadge('betriebsrat');
|
||||||
|
// DSGVO-Master — 20 von 26 Modulen mit ≥80% Quiz-Score abgeschlossen (~77% Master-Coverage)
|
||||||
|
if ((state.completedCurricula || []).length >= 20) unlockBadge('dsgvo_master');
|
||||||
|
// Compliance-Disziplin — 30-Tage-Streak
|
||||||
|
if (state.maxStreak >= 30) unlockBadge('streak_30');
|
||||||
|
// Night Owl & Early Bird (beibehalten)
|
||||||
|
const h = new Date().getHours();
|
||||||
|
if (h >= 22) unlockBadge('night_owl');
|
||||||
|
if (h < 7) unlockBadge('early_bird');
|
||||||
38
src/config.yaml
Normal file
38
src/config.yaml
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
slug: dsgvo-trainer
|
||||||
|
bot_name: Cora
|
||||||
|
bot_title: DSGVO Compliance Companion
|
||||||
|
brand_letter: C
|
||||||
|
title: "Cora · DSGVO-Compliance-Companion"
|
||||||
|
tagline: DSGVO-Compliance-Companion
|
||||||
|
tagline_short: Compliance-Companion
|
||||||
|
meta_description: "Cora — dein DSGVO-Sparringspartner. Gamifiziertes Compliance-Training für HR, IT und Führungskräfte. Läuft im deutschen Bunker."
|
||||||
|
bot_key_var: __CORA_KEY__
|
||||||
|
bot_key_value: qb_wie4qzjrjwuh
|
||||||
|
ls_prefix: cora
|
||||||
|
bot_version: "2026-04-21"
|
||||||
|
|
||||||
|
# Color theme
|
||||||
|
accent: "#059669"
|
||||||
|
accent_2: "#10b981"
|
||||||
|
accent_dark: "#047857"
|
||||||
|
accent_rgb: "5, 150, 105"
|
||||||
|
accent_rgb_compact: "5,150,105"
|
||||||
|
success_color: "#10b981"
|
||||||
|
msg_strong_color: "#a7f3d0"
|
||||||
|
|
||||||
|
# UI Labels
|
||||||
|
tab_flash_label: Karten
|
||||||
|
tab_curriculum_label: Artikel
|
||||||
|
curriculum_long_label: Artikel-Library
|
||||||
|
|
||||||
|
# Bot-personality strings
|
||||||
|
quiz_intro_hint: "Wähle ein Modul — Cora generiert Szenario-Fragen aus dem HR-Alltag."
|
||||||
|
quiz_verb: erstellt
|
||||||
|
quiz_noun: "Szenario-Fragen"
|
||||||
|
flash_intro_hint: "Cora erstellt Karteikarten zu einem Thema. Bewerte dein Erinnerungsvermögen — das System wiederholt schwere Karten öfter (SM-2)."
|
||||||
|
flash_verb: erstellt
|
||||||
|
|
||||||
|
# Levels-fallback, welcome.html, check-badges.js are sibling files
|
||||||
|
# in this directory — render.sh injects their full contents into the
|
||||||
|
# corresponding {{LEVELS_FALLBACK}}, {{WELCOME_HTML}}, {{CHECK_BADGES_BODY}}
|
||||||
|
# placeholders verbatim.
|
||||||
403
src/curricula.json
Normal file
403
src/curricula.json
Normal file
|
|
@ -0,0 +1,403 @@
|
||||||
|
{
|
||||||
|
"version": "2026-04-24",
|
||||||
|
"updated": "2026-04-24",
|
||||||
|
"curricula": [
|
||||||
|
{
|
||||||
|
"id": "grundlagen",
|
||||||
|
"title": "1 · Grundlagen",
|
||||||
|
"short": "Personenbezogene Daten, Art. 6, Zweckbindung",
|
||||||
|
"icon": "shield",
|
||||||
|
"color": "#059669",
|
||||||
|
"description": "Was sind personenbezogene Daten, welche Rechtsgrundlagen gibt es nach Art. 6 DSGVO, und wie laufen die 7 Grundsätze im Alltag auf.",
|
||||||
|
"source_md": "00-grundlagen.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "pb-daten",
|
||||||
|
"title": "Personenbezogene Daten (Art. 4 Nr. 1)",
|
||||||
|
"objectives": [
|
||||||
|
"Erkennen, wann ein Datum personenbezogen ist",
|
||||||
|
"Pseudonymisiert vs. anonymisiert abgrenzen",
|
||||||
|
"Typische Grauzonen (IP, Personalnr, Kombinationen)"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 4 Nr. 1", "Pseudonym", "Anonym", "Identifizierbarkeit"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Was ist ein personenbezogenes Datum?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "grundsaetze",
|
||||||
|
"title": "Die 7 Grundsätze (Art. 5)",
|
||||||
|
"objectives": [
|
||||||
|
"Alle 7 Grundsätze benennen und im HR-Kontext anwenden",
|
||||||
|
"Rechenschaftspflicht praktisch umsetzen",
|
||||||
|
"Zweckbindung vs. Datenminimierung unterscheiden"
|
||||||
|
],
|
||||||
|
"topics": ["Rechtmäßigkeit", "Zweckbindung", "Datenminimierung", "Speicherbegrenzung", "Rechenschaft"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Die 7 Grundsätze (Art. 5 DSGVO)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rechtsgrundlagen",
|
||||||
|
"title": "Rechtsgrundlagen (Art. 6)",
|
||||||
|
"objectives": [
|
||||||
|
"Die 6 Rechtsgrundlagen a-f sicher zuordnen",
|
||||||
|
"Beispiele aus HR: Vertrag, Einwilligung, berechtigtes Interesse",
|
||||||
|
"Kombination mit Art. 9 bei Gesundheitsdaten"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 6 Abs. 1 lit. a-f", "Einwilligung", "Vertrag", "Berechtigtes Interesse", "Art. 9"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Rechtsgrundlagen für die Verarbeitung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "einwilligung",
|
||||||
|
"title": "Einwilligung (Art. 7)",
|
||||||
|
"objectives": [
|
||||||
|
"Freiwilligkeit, Spezifität, Informiertheit, Widerruflichkeit",
|
||||||
|
"Kritische Punkte im Beschäftigungsverhältnis",
|
||||||
|
"Kopplungsverbot kennen"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 7", "Freiwilligkeit", "Widerruf", "Kopplungsverbot"],
|
||||||
|
"difficulty": "schwer",
|
||||||
|
"source_heading": "Einwilligung — die heikelste Grundlage"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "betroffenenrechte",
|
||||||
|
"title": "2 · Betroffenenrechte",
|
||||||
|
"short": "Art. 12-22, Fristen, Formate",
|
||||||
|
"icon": "handshake",
|
||||||
|
"color": "#10b981",
|
||||||
|
"description": "Die Rechte der Betroffenen: Auskunft, Berichtigung, Löschung, Einschränkung, Datenportabilität, Widerspruch — mit Fristen und Ablehnungsgründen.",
|
||||||
|
"source_md": "01-betroffenenrechte.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "auskunft",
|
||||||
|
"title": "Auskunftsrecht (Art. 15)",
|
||||||
|
"objectives": [
|
||||||
|
"1-Monats-Frist und Verlängerung sicher anwenden",
|
||||||
|
"Umfang der Auskunftspflicht abgrenzen (Art. 15 Abs. 4)",
|
||||||
|
"Kopie vs. Personalakte unterscheiden"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 15", "Monatsfrist", "Kopie", "Ex-Mitarbeiter"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Art. 15 — Auskunftsrecht"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "loeschung",
|
||||||
|
"title": "Recht auf Löschung (Art. 17)",
|
||||||
|
"objectives": [
|
||||||
|
"Löschgründe nach Abs. 1 aufzählen",
|
||||||
|
"Ausnahmen (Aufbewahrungspflicht, Rechtsverfolgung) erkennen",
|
||||||
|
"Einschränkung (Art. 18) als Alternative prüfen"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 17", "Aufbewahrungspflicht", "Art. 18", "Vergessenwerden"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Art. 17 — Recht auf Löschung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "berichtigung",
|
||||||
|
"title": "Berichtigung & Widerspruch (Art. 16, 21)",
|
||||||
|
"objectives": [
|
||||||
|
"Berichtigung vs. Meinungsäußerung trennen",
|
||||||
|
"Widerspruchsrecht bei Art. 6 Abs. 1 lit. f",
|
||||||
|
"Informationspflicht an Empfänger (Art. 19)"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 16", "Art. 21", "Art. 19", "Zeugnis"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Art. 16 — Berichtigung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "portabilitaet",
|
||||||
|
"title": "Datenportabilität (Art. 20)",
|
||||||
|
"objectives": [
|
||||||
|
"Anwendungsbereich: nur Einwilligung/Vertrag + automatisiert",
|
||||||
|
"Strukturiertes, maschinenlesbares Format",
|
||||||
|
"Abgrenzung zur Auskunft"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 20", "Format", "Automatisierung"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Art. 20 — Datenübertragbarkeit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "identitaetspruefung",
|
||||||
|
"title": "Identitätsprüfung bei Anträgen",
|
||||||
|
"objectives": [
|
||||||
|
"Art. 12 Abs. 6 sinnvoll anwenden",
|
||||||
|
"Nicht automatisch Ausweiskopie verlangen",
|
||||||
|
"Balance: Beweisbarkeit vs. Datenminimierung"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 12 Abs. 6", "Ausweiskopie", "Authentifizierung"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Identitätsprüfung"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "verarbeiter",
|
||||||
|
"title": "3 · Verarbeiter-Governance",
|
||||||
|
"short": "AVV, TOMs, Verzeichnis",
|
||||||
|
"icon": "shield",
|
||||||
|
"color": "#0ea5e9",
|
||||||
|
"description": "Auftragsverarbeiter, TOMs nach Art. 32, Verzeichnis von Verarbeitungstätigkeiten — wer wann welche Daten wie schützt.",
|
||||||
|
"source_md": "02-avv.md, 03-toms.md, 08-werkzeuge.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "avv",
|
||||||
|
"title": "Auftragsverarbeitung (Art. 28)",
|
||||||
|
"objectives": [
|
||||||
|
"AV erkennen vs. eigene Verantwortliche",
|
||||||
|
"12 Pflicht-Inhalte des AVV kennen",
|
||||||
|
"Unterauftragsverarbeiter-Regelung"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 28", "AVV", "Weisungsabhängigkeit", "Subunternehmer"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Pflicht-Inhalt eines AVV"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "toms",
|
||||||
|
"title": "TOMs (Art. 32)",
|
||||||
|
"objectives": [
|
||||||
|
"4 Schutzziele: Vertraulichkeit, Integrität, Verfügbarkeit, Belastbarkeit",
|
||||||
|
"Risikoadaptiv argumentieren",
|
||||||
|
"Typische Maßnahmen Zutritts-/Zugangs-/Zugriffskontrolle"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 32", "Verschlüsselung", "Backup", "Zugriffskontrolle"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Die vier Schutzziele"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "vvt",
|
||||||
|
"title": "Verzeichnis der Verarbeitungstätigkeiten (Art. 30)",
|
||||||
|
"objectives": [
|
||||||
|
"Pflicht auch <250 MA bei HR-Daten",
|
||||||
|
"8 Pflicht-Inhalte je Eintrag",
|
||||||
|
"Pflegeprozess + Eigentümer"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 30", "VVT", "Löschfristen"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Verzeichnis von Verarbeitungstätigkeiten"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "dsfa",
|
||||||
|
"title": "DSFA (Art. 35)",
|
||||||
|
"objectives": [
|
||||||
|
"Wann ist eine DSFA verpflichtend?",
|
||||||
|
"7 Bewertungskriterien der WP248",
|
||||||
|
"KI im Recruiting als Trigger"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 35", "DSFA", "Hochrisiko", "AI Act"],
|
||||||
|
"difficulty": "schwer",
|
||||||
|
"source_heading": "DSFA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "drittlaender",
|
||||||
|
"title": "Drittland-Transfer (Kap. V)",
|
||||||
|
"objectives": [
|
||||||
|
"Angemessenheitsbeschluss, SCC, BCR",
|
||||||
|
"Transfer Impact Assessment (TIA)",
|
||||||
|
"USA nach EU-US Data Privacy Framework"
|
||||||
|
],
|
||||||
|
"topics": ["SCC", "TIA", "Art. 46", "EU-US DPF"],
|
||||||
|
"difficulty": "schwer",
|
||||||
|
"source_heading": "Drittland"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "incident",
|
||||||
|
"title": "4 · Incident Response",
|
||||||
|
"short": "Datenpannen, Eskalation",
|
||||||
|
"icon": "clock",
|
||||||
|
"color": "#ef4444",
|
||||||
|
"description": "Datenpannen erkennen, melden, dokumentieren — die 72-Stunden-Uhr, Art. 33/34 und sauberes Eskalieren an den DSB.",
|
||||||
|
"source_md": "04-datenpannen.md, 09-eskalation.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "datenpannen",
|
||||||
|
"title": "Datenpanne erkennen (Art. 4 Nr. 12)",
|
||||||
|
"objectives": [
|
||||||
|
"Meldepflichtige vs. nicht-meldepflichtige Vorfälle",
|
||||||
|
"Typische HR-Szenarien (Fehlversand, verlorener Laptop)",
|
||||||
|
"Dokumentationspflicht auch ohne Meldung"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 4 Nr. 12", "Risikobewertung", "Fehlversand"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Was ist eine Verletzung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "meldepflicht",
|
||||||
|
"title": "72-Stunden-Meldung (Art. 33)",
|
||||||
|
"objectives": [
|
||||||
|
"Meldeformulare der Aufsichtsbehörden",
|
||||||
|
"6 Pflicht-Inhalte der Meldung",
|
||||||
|
"Verspätete Meldung mit Begründung"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 33", "Aufsichtsbehörde", "72h", "Meldeinhalt"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Die 72-Stunden-Uhr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "benachrichtigung",
|
||||||
|
"title": "Betroffenen-Benachrichtigung (Art. 34)",
|
||||||
|
"objectives": [
|
||||||
|
"Wann? Bei hohem Risiko für Rechte und Freiheiten",
|
||||||
|
"Verständliche Sprache (Klartext)",
|
||||||
|
"Drei Ausnahmen kennen"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 34", "Hohes Risiko", "Klartext", "Ausnahmen"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Benachrichtigung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "eskalation",
|
||||||
|
"title": "Eskalationsmatrix: Wann zum DSB?",
|
||||||
|
"objectives": [
|
||||||
|
"Sofort-Fälle (Datenpanne, Behördenpost) erkennen",
|
||||||
|
"Vor-Umsetzungs-Fälle (neues System, KI) erkennen",
|
||||||
|
"Saubere Eskalations-Mail schreiben"
|
||||||
|
],
|
||||||
|
"topics": ["DSB", "Aufsichtsbehörde", "Rechtsanwalt", "BR-Einbindung"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Zwingend an den DSB"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hr",
|
||||||
|
"title": "5 · HR-Datenschutz",
|
||||||
|
"short": "Bewerbung, Personalakte, Betriebsrat",
|
||||||
|
"icon": "handshake",
|
||||||
|
"color": "#a855f7",
|
||||||
|
"description": "HR-spezifische Anwendung der DSGVO nach dem BAG-Urteil vom 8.5.2025: Bewerbung, Personalakte, Gesundheitsdaten, Betriebsrat.",
|
||||||
|
"source_md": "05-hr-bewerbung.md, 06-hr-personalakte.md, 07-hr-betriebsrat.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "bewerbung",
|
||||||
|
"title": "Bewerbungsprozess",
|
||||||
|
"objectives": [
|
||||||
|
"6-Monats-Aufbewahrungsregel nach Absage kennen",
|
||||||
|
"Talentpool nur mit expliziter Einwilligung",
|
||||||
|
"Social-Media-Recherche korrekt abgrenzen"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 6 lit. b", "AGG", "ArbGG", "Talentpool"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Aufbewahrung nach Absage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "personalakte",
|
||||||
|
"title": "Personalakte & Gesundheitsdaten",
|
||||||
|
"objectives": [
|
||||||
|
"Was gehört rein, was nicht (Diagnose, BEM, SchwbG)",
|
||||||
|
"Art. 15 + § 83 BetrVG richtig umsetzen",
|
||||||
|
"BAG 8.5.2025: § 26 BDSG unanwendbar"
|
||||||
|
],
|
||||||
|
"topics": ["Personalakte", "BEM", "AU", "§ 83 BetrVG", "Art. 9"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Umfang der Personalakte"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "betriebsrat",
|
||||||
|
"title": "Betriebsrat & Mitbestimmung",
|
||||||
|
"objectives": [
|
||||||
|
"§ 87 Abs. 1 Nr. 6 BetrVG sicher anwenden",
|
||||||
|
"EuGH C-65/23 Betriebsvereinbarungen als Rechtsgrundlage",
|
||||||
|
"BR-Informationsanspruch vs. Schutz Einzelner"
|
||||||
|
],
|
||||||
|
"topics": ["§ 87 Nr. 6", "EuGH C-65/23", "§ 80 BetrVG", "§ 83 BetrVG"],
|
||||||
|
"difficulty": "schwer",
|
||||||
|
"source_heading": "Mitbestimmung des Betriebsrats"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "zeugnis",
|
||||||
|
"title": "Zeugnis & Offboarding",
|
||||||
|
"objectives": [
|
||||||
|
"Art. 16 Grenzen bei Zeugnissen",
|
||||||
|
"Löschkonzept nach Austritt",
|
||||||
|
"Aufbewahrungspflicht Lohn-/Steuerdaten"
|
||||||
|
],
|
||||||
|
"topics": ["Zeugnis", "Offboarding", "§ 147 AO", "Löschkonzept"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Zeugnis"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tools",
|
||||||
|
"title": "6 · Tools & FAQ",
|
||||||
|
"short": "Werkzeugkasten + Alltags-Fragen",
|
||||||
|
"icon": "medal",
|
||||||
|
"color": "#f59e0b",
|
||||||
|
"description": "Der Werkzeugkasten: VVT, DSFA, TIA, Vorlagen — und 20 häufige Alltagsfragen lokaler Datenschutzkoordinatoren.",
|
||||||
|
"source_md": "08-werkzeuge.md, 10-faq.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "werkzeugkasten",
|
||||||
|
"title": "Der Werkzeugkasten",
|
||||||
|
"objectives": [
|
||||||
|
"VVT-Pflege und Eigentümer",
|
||||||
|
"DSFA-Template-Struktur",
|
||||||
|
"TIA für Drittland-Transfers"
|
||||||
|
],
|
||||||
|
"topics": ["VVT", "DSFA", "TIA", "Templates"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Verzeichnis von Verarbeitungstätigkeiten"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "faq-rechte",
|
||||||
|
"title": "FAQ: Betroffenenrechte",
|
||||||
|
"objectives": [
|
||||||
|
"Auskunftsantrag Ex-Mitarbeiter",
|
||||||
|
"Löschung der Personalakte",
|
||||||
|
"Berichtigung vs. Meinungen"
|
||||||
|
],
|
||||||
|
"topics": ["Auskunft", "Löschung", "Berichtigung"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Betroffenenrechte"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "faq-alltag",
|
||||||
|
"title": "FAQ: HR-Alltag",
|
||||||
|
"objectives": [
|
||||||
|
"AU ohne Diagnose",
|
||||||
|
"BEM-Akten trennen",
|
||||||
|
"Private vs. berufliche Profile"
|
||||||
|
],
|
||||||
|
"topics": ["AU", "BEM", "Social Media", "Einsicht"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Bewerbung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "faq-incident",
|
||||||
|
"title": "FAQ: Datenpanne & KI",
|
||||||
|
"objectives": [
|
||||||
|
"Fehlversand-Triage (melden oder nicht)",
|
||||||
|
"KI-Screening: immer DSB + BR",
|
||||||
|
"Webcam im Homeoffice: grundsätzlich nein"
|
||||||
|
],
|
||||||
|
"topics": ["Fehlversand", "KI-Recruiting", "Monitoring", "Homeoffice"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Datenpanne"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"badges": [
|
||||||
|
{"id": "erste_loeschanfrage", "title": "Art. 17 Reflex", "icon": "award", "description": "1. Quiz zu Löschpflicht erfolgreich."},
|
||||||
|
{"id": "avv_detektiv", "title": "AVV-Detektiv", "icon": "detective", "description": "10 AVV-Fragen korrekt beantwortet."},
|
||||||
|
{"id": "meldepflicht", "title": "72-Stunden-Held", "icon": "clock", "description": "Meldepflicht-Flashcards alle mit Gut/Leicht bestanden."},
|
||||||
|
{"id": "betriebsrat", "title": "Betriebsrat-Flüsterer", "icon": "handshake", "description": "HR-Modul (Bewerbung + Personalakte + BR) je 3 richtig."},
|
||||||
|
{"id": "dsgvo_master", "title": "DSGVO-Master", "icon": "crown", "description": "6 oder mehr Module mit ≥80% abgeschlossen."},
|
||||||
|
{"id": "streak_30", "title": "Compliance-Disziplin", "icon": "flame", "description": "30 Tage in Folge aktiv gewesen."},
|
||||||
|
{"id": "night_owl", "title": "Nachteule", "icon": "moon", "description": "Nach 22 Uhr gelernt."},
|
||||||
|
{"id": "early_bird", "title": "Frühaufsteher", "icon": "sun", "description": "Vor 7 Uhr gelernt."}
|
||||||
|
],
|
||||||
|
"levels": [
|
||||||
|
{"min": 0, "title": "Azubi"},
|
||||||
|
{"min": 50, "title": "Mitarbeiter:in"},
|
||||||
|
{"min": 200, "title": "Key-User:in"},
|
||||||
|
{"min": 500, "title": "Compliance-Expert:in"},
|
||||||
|
{"min": 1250, "title": "DSB-Kandidat:in"},
|
||||||
|
{"min": 2500, "title": "Datenschutzbeauftragte:r"},
|
||||||
|
{"min": 5000, "title": "Senior-DSB"}
|
||||||
|
]
|
||||||
|
}
|
||||||
4
src/levels-fallback.js
Normal file
4
src/levels-fallback.js
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{ min: 0, title: 'Azubi' }, { min: 50, title: 'Mitarbeiter:in' },
|
||||||
|
{ min: 200, title: 'Key-User:in' }, { min: 500, title: 'Compliance-Expert:in' },
|
||||||
|
{ min: 1250, title: 'DSB-Kandidat:in' }, { min: 2500, title: 'Datenschutzbeauftragte:r' },
|
||||||
|
{ min: 5000, title: 'Senior-DSB' }
|
||||||
25
src/welcome.html
Normal file
25
src/welcome.html
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
<h2>Willkommen bei Cora!</h2>
|
||||||
|
<p>Ich bin dein:e DSGVO-Sparringspartner:in — pragmatisch, trocken-humorvoll, präzise. Warum das Ganze? <strong>Bußgelder vermeiden</strong>, <strong>Mitarbeiter:innen empowern</strong>, <strong>Rechtssicherheit</strong>. Alles läuft im deutschen Bunker — keine Daten verlassen dein Unternehmen.</p>
|
||||||
|
<div class="mode-grid">
|
||||||
|
<button class="mode-card" data-goto="chat">
|
||||||
|
<strong>Chat</strong>
|
||||||
|
<span>Frag mich alles zu DSGVO, BDSG, HR-Datenschutz.</span>
|
||||||
|
</button>
|
||||||
|
<button class="mode-card" data-goto="quiz">
|
||||||
|
<strong>Quiz</strong>
|
||||||
|
<span>Szenario-Fragen aus dem HR-Alltag, mit XP.</span>
|
||||||
|
</button>
|
||||||
|
<button class="mode-card" data-goto="flash">
|
||||||
|
<strong>Flashcards</strong>
|
||||||
|
<span>Artikel, Begriffe, TOMs — mit Spaced-Repetition.</span>
|
||||||
|
</button>
|
||||||
|
<button class="mode-card" data-goto="progress">
|
||||||
|
<strong>Fortschritt</strong>
|
||||||
|
<span>XP, Streaks, Badges, Level.</span>
|
||||||
|
</button>
|
||||||
|
<button class="mode-card" data-goto="curriculum">
|
||||||
|
<strong>Artikel</strong>
|
||||||
|
<span>6 Curricula / 26 Module: von Grundlagen bis Eskalation.</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p style="font-size:.82rem;color:var(--text-mute)">In 3 Sätzen: Chat zum Verstehen → Quiz zum Testen → Flashcards zum Merken. Fortschritt zeigt dir, wo du stehst; die Artikel-Library gibt dir 26 kuratierte Module in 6 Themen-Säulen.</p>
|
||||||
1750
www/app.js
Normal file
1750
www/app.js
Normal file
File diff suppressed because it is too large
Load diff
403
www/curricula.json
Normal file
403
www/curricula.json
Normal file
|
|
@ -0,0 +1,403 @@
|
||||||
|
{
|
||||||
|
"version": "2026-04-24",
|
||||||
|
"updated": "2026-04-24",
|
||||||
|
"curricula": [
|
||||||
|
{
|
||||||
|
"id": "grundlagen",
|
||||||
|
"title": "1 · Grundlagen",
|
||||||
|
"short": "Personenbezogene Daten, Art. 6, Zweckbindung",
|
||||||
|
"icon": "shield",
|
||||||
|
"color": "#059669",
|
||||||
|
"description": "Was sind personenbezogene Daten, welche Rechtsgrundlagen gibt es nach Art. 6 DSGVO, und wie laufen die 7 Grundsätze im Alltag auf.",
|
||||||
|
"source_md": "00-grundlagen.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "pb-daten",
|
||||||
|
"title": "Personenbezogene Daten (Art. 4 Nr. 1)",
|
||||||
|
"objectives": [
|
||||||
|
"Erkennen, wann ein Datum personenbezogen ist",
|
||||||
|
"Pseudonymisiert vs. anonymisiert abgrenzen",
|
||||||
|
"Typische Grauzonen (IP, Personalnr, Kombinationen)"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 4 Nr. 1", "Pseudonym", "Anonym", "Identifizierbarkeit"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Was ist ein personenbezogenes Datum?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "grundsaetze",
|
||||||
|
"title": "Die 7 Grundsätze (Art. 5)",
|
||||||
|
"objectives": [
|
||||||
|
"Alle 7 Grundsätze benennen und im HR-Kontext anwenden",
|
||||||
|
"Rechenschaftspflicht praktisch umsetzen",
|
||||||
|
"Zweckbindung vs. Datenminimierung unterscheiden"
|
||||||
|
],
|
||||||
|
"topics": ["Rechtmäßigkeit", "Zweckbindung", "Datenminimierung", "Speicherbegrenzung", "Rechenschaft"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Die 7 Grundsätze (Art. 5 DSGVO)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rechtsgrundlagen",
|
||||||
|
"title": "Rechtsgrundlagen (Art. 6)",
|
||||||
|
"objectives": [
|
||||||
|
"Die 6 Rechtsgrundlagen a-f sicher zuordnen",
|
||||||
|
"Beispiele aus HR: Vertrag, Einwilligung, berechtigtes Interesse",
|
||||||
|
"Kombination mit Art. 9 bei Gesundheitsdaten"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 6 Abs. 1 lit. a-f", "Einwilligung", "Vertrag", "Berechtigtes Interesse", "Art. 9"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Rechtsgrundlagen für die Verarbeitung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "einwilligung",
|
||||||
|
"title": "Einwilligung (Art. 7)",
|
||||||
|
"objectives": [
|
||||||
|
"Freiwilligkeit, Spezifität, Informiertheit, Widerruflichkeit",
|
||||||
|
"Kritische Punkte im Beschäftigungsverhältnis",
|
||||||
|
"Kopplungsverbot kennen"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 7", "Freiwilligkeit", "Widerruf", "Kopplungsverbot"],
|
||||||
|
"difficulty": "schwer",
|
||||||
|
"source_heading": "Einwilligung — die heikelste Grundlage"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "betroffenenrechte",
|
||||||
|
"title": "2 · Betroffenenrechte",
|
||||||
|
"short": "Art. 12-22, Fristen, Formate",
|
||||||
|
"icon": "handshake",
|
||||||
|
"color": "#10b981",
|
||||||
|
"description": "Die Rechte der Betroffenen: Auskunft, Berichtigung, Löschung, Einschränkung, Datenportabilität, Widerspruch — mit Fristen und Ablehnungsgründen.",
|
||||||
|
"source_md": "01-betroffenenrechte.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "auskunft",
|
||||||
|
"title": "Auskunftsrecht (Art. 15)",
|
||||||
|
"objectives": [
|
||||||
|
"1-Monats-Frist und Verlängerung sicher anwenden",
|
||||||
|
"Umfang der Auskunftspflicht abgrenzen (Art. 15 Abs. 4)",
|
||||||
|
"Kopie vs. Personalakte unterscheiden"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 15", "Monatsfrist", "Kopie", "Ex-Mitarbeiter"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Art. 15 — Auskunftsrecht"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "loeschung",
|
||||||
|
"title": "Recht auf Löschung (Art. 17)",
|
||||||
|
"objectives": [
|
||||||
|
"Löschgründe nach Abs. 1 aufzählen",
|
||||||
|
"Ausnahmen (Aufbewahrungspflicht, Rechtsverfolgung) erkennen",
|
||||||
|
"Einschränkung (Art. 18) als Alternative prüfen"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 17", "Aufbewahrungspflicht", "Art. 18", "Vergessenwerden"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Art. 17 — Recht auf Löschung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "berichtigung",
|
||||||
|
"title": "Berichtigung & Widerspruch (Art. 16, 21)",
|
||||||
|
"objectives": [
|
||||||
|
"Berichtigung vs. Meinungsäußerung trennen",
|
||||||
|
"Widerspruchsrecht bei Art. 6 Abs. 1 lit. f",
|
||||||
|
"Informationspflicht an Empfänger (Art. 19)"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 16", "Art. 21", "Art. 19", "Zeugnis"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Art. 16 — Berichtigung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "portabilitaet",
|
||||||
|
"title": "Datenportabilität (Art. 20)",
|
||||||
|
"objectives": [
|
||||||
|
"Anwendungsbereich: nur Einwilligung/Vertrag + automatisiert",
|
||||||
|
"Strukturiertes, maschinenlesbares Format",
|
||||||
|
"Abgrenzung zur Auskunft"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 20", "Format", "Automatisierung"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Art. 20 — Datenübertragbarkeit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "identitaetspruefung",
|
||||||
|
"title": "Identitätsprüfung bei Anträgen",
|
||||||
|
"objectives": [
|
||||||
|
"Art. 12 Abs. 6 sinnvoll anwenden",
|
||||||
|
"Nicht automatisch Ausweiskopie verlangen",
|
||||||
|
"Balance: Beweisbarkeit vs. Datenminimierung"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 12 Abs. 6", "Ausweiskopie", "Authentifizierung"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Identitätsprüfung"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "verarbeiter",
|
||||||
|
"title": "3 · Verarbeiter-Governance",
|
||||||
|
"short": "AVV, TOMs, Verzeichnis",
|
||||||
|
"icon": "shield",
|
||||||
|
"color": "#0ea5e9",
|
||||||
|
"description": "Auftragsverarbeiter, TOMs nach Art. 32, Verzeichnis von Verarbeitungstätigkeiten — wer wann welche Daten wie schützt.",
|
||||||
|
"source_md": "02-avv.md, 03-toms.md, 08-werkzeuge.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "avv",
|
||||||
|
"title": "Auftragsverarbeitung (Art. 28)",
|
||||||
|
"objectives": [
|
||||||
|
"AV erkennen vs. eigene Verantwortliche",
|
||||||
|
"12 Pflicht-Inhalte des AVV kennen",
|
||||||
|
"Unterauftragsverarbeiter-Regelung"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 28", "AVV", "Weisungsabhängigkeit", "Subunternehmer"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Pflicht-Inhalt eines AVV"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "toms",
|
||||||
|
"title": "TOMs (Art. 32)",
|
||||||
|
"objectives": [
|
||||||
|
"4 Schutzziele: Vertraulichkeit, Integrität, Verfügbarkeit, Belastbarkeit",
|
||||||
|
"Risikoadaptiv argumentieren",
|
||||||
|
"Typische Maßnahmen Zutritts-/Zugangs-/Zugriffskontrolle"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 32", "Verschlüsselung", "Backup", "Zugriffskontrolle"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Die vier Schutzziele"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "vvt",
|
||||||
|
"title": "Verzeichnis der Verarbeitungstätigkeiten (Art. 30)",
|
||||||
|
"objectives": [
|
||||||
|
"Pflicht auch <250 MA bei HR-Daten",
|
||||||
|
"8 Pflicht-Inhalte je Eintrag",
|
||||||
|
"Pflegeprozess + Eigentümer"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 30", "VVT", "Löschfristen"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Verzeichnis von Verarbeitungstätigkeiten"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "dsfa",
|
||||||
|
"title": "DSFA (Art. 35)",
|
||||||
|
"objectives": [
|
||||||
|
"Wann ist eine DSFA verpflichtend?",
|
||||||
|
"7 Bewertungskriterien der WP248",
|
||||||
|
"KI im Recruiting als Trigger"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 35", "DSFA", "Hochrisiko", "AI Act"],
|
||||||
|
"difficulty": "schwer",
|
||||||
|
"source_heading": "DSFA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "drittlaender",
|
||||||
|
"title": "Drittland-Transfer (Kap. V)",
|
||||||
|
"objectives": [
|
||||||
|
"Angemessenheitsbeschluss, SCC, BCR",
|
||||||
|
"Transfer Impact Assessment (TIA)",
|
||||||
|
"USA nach EU-US Data Privacy Framework"
|
||||||
|
],
|
||||||
|
"topics": ["SCC", "TIA", "Art. 46", "EU-US DPF"],
|
||||||
|
"difficulty": "schwer",
|
||||||
|
"source_heading": "Drittland"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "incident",
|
||||||
|
"title": "4 · Incident Response",
|
||||||
|
"short": "Datenpannen, Eskalation",
|
||||||
|
"icon": "clock",
|
||||||
|
"color": "#ef4444",
|
||||||
|
"description": "Datenpannen erkennen, melden, dokumentieren — die 72-Stunden-Uhr, Art. 33/34 und sauberes Eskalieren an den DSB.",
|
||||||
|
"source_md": "04-datenpannen.md, 09-eskalation.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "datenpannen",
|
||||||
|
"title": "Datenpanne erkennen (Art. 4 Nr. 12)",
|
||||||
|
"objectives": [
|
||||||
|
"Meldepflichtige vs. nicht-meldepflichtige Vorfälle",
|
||||||
|
"Typische HR-Szenarien (Fehlversand, verlorener Laptop)",
|
||||||
|
"Dokumentationspflicht auch ohne Meldung"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 4 Nr. 12", "Risikobewertung", "Fehlversand"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Was ist eine Verletzung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "meldepflicht",
|
||||||
|
"title": "72-Stunden-Meldung (Art. 33)",
|
||||||
|
"objectives": [
|
||||||
|
"Meldeformulare der Aufsichtsbehörden",
|
||||||
|
"6 Pflicht-Inhalte der Meldung",
|
||||||
|
"Verspätete Meldung mit Begründung"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 33", "Aufsichtsbehörde", "72h", "Meldeinhalt"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Die 72-Stunden-Uhr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "benachrichtigung",
|
||||||
|
"title": "Betroffenen-Benachrichtigung (Art. 34)",
|
||||||
|
"objectives": [
|
||||||
|
"Wann? Bei hohem Risiko für Rechte und Freiheiten",
|
||||||
|
"Verständliche Sprache (Klartext)",
|
||||||
|
"Drei Ausnahmen kennen"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 34", "Hohes Risiko", "Klartext", "Ausnahmen"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Benachrichtigung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "eskalation",
|
||||||
|
"title": "Eskalationsmatrix: Wann zum DSB?",
|
||||||
|
"objectives": [
|
||||||
|
"Sofort-Fälle (Datenpanne, Behördenpost) erkennen",
|
||||||
|
"Vor-Umsetzungs-Fälle (neues System, KI) erkennen",
|
||||||
|
"Saubere Eskalations-Mail schreiben"
|
||||||
|
],
|
||||||
|
"topics": ["DSB", "Aufsichtsbehörde", "Rechtsanwalt", "BR-Einbindung"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Zwingend an den DSB"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hr",
|
||||||
|
"title": "5 · HR-Datenschutz",
|
||||||
|
"short": "Bewerbung, Personalakte, Betriebsrat",
|
||||||
|
"icon": "handshake",
|
||||||
|
"color": "#a855f7",
|
||||||
|
"description": "HR-spezifische Anwendung der DSGVO nach dem BAG-Urteil vom 8.5.2025: Bewerbung, Personalakte, Gesundheitsdaten, Betriebsrat.",
|
||||||
|
"source_md": "05-hr-bewerbung.md, 06-hr-personalakte.md, 07-hr-betriebsrat.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "bewerbung",
|
||||||
|
"title": "Bewerbungsprozess",
|
||||||
|
"objectives": [
|
||||||
|
"6-Monats-Aufbewahrungsregel nach Absage kennen",
|
||||||
|
"Talentpool nur mit expliziter Einwilligung",
|
||||||
|
"Social-Media-Recherche korrekt abgrenzen"
|
||||||
|
],
|
||||||
|
"topics": ["Art. 6 lit. b", "AGG", "ArbGG", "Talentpool"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Aufbewahrung nach Absage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "personalakte",
|
||||||
|
"title": "Personalakte & Gesundheitsdaten",
|
||||||
|
"objectives": [
|
||||||
|
"Was gehört rein, was nicht (Diagnose, BEM, SchwbG)",
|
||||||
|
"Art. 15 + § 83 BetrVG richtig umsetzen",
|
||||||
|
"BAG 8.5.2025: § 26 BDSG unanwendbar"
|
||||||
|
],
|
||||||
|
"topics": ["Personalakte", "BEM", "AU", "§ 83 BetrVG", "Art. 9"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Umfang der Personalakte"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "betriebsrat",
|
||||||
|
"title": "Betriebsrat & Mitbestimmung",
|
||||||
|
"objectives": [
|
||||||
|
"§ 87 Abs. 1 Nr. 6 BetrVG sicher anwenden",
|
||||||
|
"EuGH C-65/23 Betriebsvereinbarungen als Rechtsgrundlage",
|
||||||
|
"BR-Informationsanspruch vs. Schutz Einzelner"
|
||||||
|
],
|
||||||
|
"topics": ["§ 87 Nr. 6", "EuGH C-65/23", "§ 80 BetrVG", "§ 83 BetrVG"],
|
||||||
|
"difficulty": "schwer",
|
||||||
|
"source_heading": "Mitbestimmung des Betriebsrats"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "zeugnis",
|
||||||
|
"title": "Zeugnis & Offboarding",
|
||||||
|
"objectives": [
|
||||||
|
"Art. 16 Grenzen bei Zeugnissen",
|
||||||
|
"Löschkonzept nach Austritt",
|
||||||
|
"Aufbewahrungspflicht Lohn-/Steuerdaten"
|
||||||
|
],
|
||||||
|
"topics": ["Zeugnis", "Offboarding", "§ 147 AO", "Löschkonzept"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Zeugnis"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tools",
|
||||||
|
"title": "6 · Tools & FAQ",
|
||||||
|
"short": "Werkzeugkasten + Alltags-Fragen",
|
||||||
|
"icon": "medal",
|
||||||
|
"color": "#f59e0b",
|
||||||
|
"description": "Der Werkzeugkasten: VVT, DSFA, TIA, Vorlagen — und 20 häufige Alltagsfragen lokaler Datenschutzkoordinatoren.",
|
||||||
|
"source_md": "08-werkzeuge.md, 10-faq.md",
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "werkzeugkasten",
|
||||||
|
"title": "Der Werkzeugkasten",
|
||||||
|
"objectives": [
|
||||||
|
"VVT-Pflege und Eigentümer",
|
||||||
|
"DSFA-Template-Struktur",
|
||||||
|
"TIA für Drittland-Transfers"
|
||||||
|
],
|
||||||
|
"topics": ["VVT", "DSFA", "TIA", "Templates"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Verzeichnis von Verarbeitungstätigkeiten"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "faq-rechte",
|
||||||
|
"title": "FAQ: Betroffenenrechte",
|
||||||
|
"objectives": [
|
||||||
|
"Auskunftsantrag Ex-Mitarbeiter",
|
||||||
|
"Löschung der Personalakte",
|
||||||
|
"Berichtigung vs. Meinungen"
|
||||||
|
],
|
||||||
|
"topics": ["Auskunft", "Löschung", "Berichtigung"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Betroffenenrechte"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "faq-alltag",
|
||||||
|
"title": "FAQ: HR-Alltag",
|
||||||
|
"objectives": [
|
||||||
|
"AU ohne Diagnose",
|
||||||
|
"BEM-Akten trennen",
|
||||||
|
"Private vs. berufliche Profile"
|
||||||
|
],
|
||||||
|
"topics": ["AU", "BEM", "Social Media", "Einsicht"],
|
||||||
|
"difficulty": "einfach",
|
||||||
|
"source_heading": "Bewerbung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "faq-incident",
|
||||||
|
"title": "FAQ: Datenpanne & KI",
|
||||||
|
"objectives": [
|
||||||
|
"Fehlversand-Triage (melden oder nicht)",
|
||||||
|
"KI-Screening: immer DSB + BR",
|
||||||
|
"Webcam im Homeoffice: grundsätzlich nein"
|
||||||
|
],
|
||||||
|
"topics": ["Fehlversand", "KI-Recruiting", "Monitoring", "Homeoffice"],
|
||||||
|
"difficulty": "mittel",
|
||||||
|
"source_heading": "Datenpanne"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"badges": [
|
||||||
|
{"id": "erste_loeschanfrage", "title": "Art. 17 Reflex", "icon": "award", "description": "1. Quiz zu Löschpflicht erfolgreich."},
|
||||||
|
{"id": "avv_detektiv", "title": "AVV-Detektiv", "icon": "detective", "description": "10 AVV-Fragen korrekt beantwortet."},
|
||||||
|
{"id": "meldepflicht", "title": "72-Stunden-Held", "icon": "clock", "description": "Meldepflicht-Flashcards alle mit Gut/Leicht bestanden."},
|
||||||
|
{"id": "betriebsrat", "title": "Betriebsrat-Flüsterer", "icon": "handshake", "description": "HR-Modul (Bewerbung + Personalakte + BR) je 3 richtig."},
|
||||||
|
{"id": "dsgvo_master", "title": "DSGVO-Master", "icon": "crown", "description": "6 oder mehr Module mit ≥80% abgeschlossen."},
|
||||||
|
{"id": "streak_30", "title": "Compliance-Disziplin", "icon": "flame", "description": "30 Tage in Folge aktiv gewesen."},
|
||||||
|
{"id": "night_owl", "title": "Nachteule", "icon": "moon", "description": "Nach 22 Uhr gelernt."},
|
||||||
|
{"id": "early_bird", "title": "Frühaufsteher", "icon": "sun", "description": "Vor 7 Uhr gelernt."}
|
||||||
|
],
|
||||||
|
"levels": [
|
||||||
|
{"min": 0, "title": "Azubi"},
|
||||||
|
{"min": 50, "title": "Mitarbeiter:in"},
|
||||||
|
{"min": 200, "title": "Key-User:in"},
|
||||||
|
{"min": 500, "title": "Compliance-Expert:in"},
|
||||||
|
{"min": 1250, "title": "DSB-Kandidat:in"},
|
||||||
|
{"min": 2500, "title": "Datenschutzbeauftragte:r"},
|
||||||
|
{"min": 5000, "title": "Senior-DSB"}
|
||||||
|
]
|
||||||
|
}
|
||||||
121
www/index.html
Normal file
121
www/index.html
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Cora · DSGVO-Compliance-Companion</title>
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
||||||
|
<meta name="theme-color" content="#0a0a0f">
|
||||||
|
<meta name="description" content="Cora — dein DSGVO-Sparringspartner. Gamifiziertes Compliance-Training für HR, IT und Führungskräfte. Läuft im deutschen Bunker.">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
<script>window.__CORA_KEY__ = 'qb_wie4qzjrjwuh';</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="app" role="application" aria-label="Cora DSGVO-Compliance-Companion">
|
||||||
|
|
||||||
|
<header class="topbar">
|
||||||
|
<div class="brand">
|
||||||
|
<span class="brand-icon" aria-hidden="true">C</span>
|
||||||
|
<span>Cora <small>Compliance-Companion</small></span>
|
||||||
|
</div>
|
||||||
|
<div class="spacer"></div>
|
||||||
|
<span class="status" role="status" aria-live="polite">Online</span>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<nav class="tabbar" role="tablist" aria-label="Modi">
|
||||||
|
<button class="tab" role="tab" aria-selected="true" aria-controls="view-chat" data-mode="chat">
|
||||||
|
Chat
|
||||||
|
<span class="tab-kbd">⌃1</span>
|
||||||
|
</button>
|
||||||
|
<button class="tab" role="tab" aria-selected="false" aria-controls="view-quiz" data-mode="quiz">
|
||||||
|
Quiz
|
||||||
|
<span class="tab-kbd">⌃2</span>
|
||||||
|
</button>
|
||||||
|
<button class="tab" role="tab" aria-selected="false" aria-controls="view-flash" data-mode="flash">
|
||||||
|
Karten
|
||||||
|
<span class="tab-kbd">⌃3</span>
|
||||||
|
</button>
|
||||||
|
<button class="tab" role="tab" aria-selected="false" aria-controls="view-progress" data-mode="progress">
|
||||||
|
Fortschritt
|
||||||
|
<span class="tab-kbd">⌃4</span>
|
||||||
|
</button>
|
||||||
|
<button class="tab" role="tab" aria-selected="false" aria-controls="view-curriculum" data-mode="curriculum">
|
||||||
|
Artikel
|
||||||
|
<span class="tab-kbd">⌃5</span>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="main">
|
||||||
|
<!-- CHAT -->
|
||||||
|
<section id="view-chat" class="view" role="tabpanel" aria-labelledby="tab-chat" data-active="true">
|
||||||
|
<div id="welcome-screen" class="welcome hidden" aria-hidden="true">
|
||||||
|
<h2>Willkommen bei Cora!</h2>
|
||||||
|
<p>Ich bin dein:e DSGVO-Sparringspartner:in — pragmatisch, trocken-humorvoll, präzise. Warum das Ganze? <strong>Bußgelder vermeiden</strong>, <strong>Mitarbeiter:innen empowern</strong>, <strong>Rechtssicherheit</strong>. Alles läuft im deutschen Bunker — keine Daten verlassen dein Unternehmen.</p>
|
||||||
|
<div class="mode-grid">
|
||||||
|
<button class="mode-card" data-goto="chat">
|
||||||
|
<strong>Chat</strong>
|
||||||
|
<span>Frag mich alles zu DSGVO, BDSG, HR-Datenschutz.</span>
|
||||||
|
</button>
|
||||||
|
<button class="mode-card" data-goto="quiz">
|
||||||
|
<strong>Quiz</strong>
|
||||||
|
<span>Szenario-Fragen aus dem HR-Alltag, mit XP.</span>
|
||||||
|
</button>
|
||||||
|
<button class="mode-card" data-goto="flash">
|
||||||
|
<strong>Flashcards</strong>
|
||||||
|
<span>Artikel, Begriffe, TOMs — mit Spaced-Repetition.</span>
|
||||||
|
</button>
|
||||||
|
<button class="mode-card" data-goto="progress">
|
||||||
|
<strong>Fortschritt</strong>
|
||||||
|
<span>XP, Streaks, Badges, Level.</span>
|
||||||
|
</button>
|
||||||
|
<button class="mode-card" data-goto="curriculum">
|
||||||
|
<strong>Artikel</strong>
|
||||||
|
<span>6 Curricula / 26 Module: von Grundlagen bis Eskalation.</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p style="font-size:.82rem;color:var(--text-mute)">In 3 Sätzen: Chat zum Verstehen → Quiz zum Testen → Flashcards zum Merken. Fortschritt zeigt dir, wo du stehst; die Artikel-Library gibt dir 26 kuratierte Module in 6 Themen-Säulen.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="chat-box" class="chat-box" aria-live="polite" aria-label="Gespräch"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- QUIZ -->
|
||||||
|
<section id="view-quiz" class="view" role="tabpanel" aria-labelledby="tab-quiz">
|
||||||
|
<div id="quiz-host"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- FLASHCARDS -->
|
||||||
|
<section id="view-flash" class="view" role="tabpanel" aria-labelledby="tab-flash">
|
||||||
|
<div id="flash-host"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- PROGRESS -->
|
||||||
|
<section id="view-progress" class="view" role="tabpanel" aria-labelledby="tab-progress">
|
||||||
|
<div id="progress-host"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- CURRICULUM -->
|
||||||
|
<section id="view-curriculum" class="view" role="tabpanel" aria-labelledby="tab-curr">
|
||||||
|
<div id="curr-host"></div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<form id="composer-form" class="composer" aria-label="Nachricht verfassen">
|
||||||
|
<div id="attach-strip" class="attach-strip" aria-live="polite"></div>
|
||||||
|
<div class="composer-row">
|
||||||
|
<button type="button" class="btn-attach" id="composer-attach" aria-label="Datei anhängen" title="Datei anhängen (PDF, Bild, Text — max 5 Dateien, 8 MB)">📎</button>
|
||||||
|
<input type="file" id="composer-file" multiple accept=".pdf,.txt,.md,.csv,.json,.xml,.yaml,.yml,.log,.png,.jpg,.jpeg,.webp,.gif" hidden>
|
||||||
|
<textarea id="composer" rows="1" placeholder="Frag Cora — Enter zum Senden, Shift+Enter für Zeilenumbruch" aria-label="Nachricht"></textarea>
|
||||||
|
<button type="submit" class="btn-primary" id="composer-send">Senden</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
Sovereign AI · Deutscher Bunker · <a href="https://qognio.com">Qognio</a> · DSGVO-konform · Keine externen Fonts · Keine Cookies
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="toast-stack" class="toast-stack" aria-live="polite"></div>
|
||||||
|
|
||||||
|
<script src="app.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1038
www/styles.css
Normal file
1038
www/styles.css
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue