init: extract vera-website-check from qognio-bot-widget-template@d2c816f
Source files (src/) and rendered bundle (www/) extracted on 2026-04-29T01:35:49+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-27
This commit is contained in:
commit
6e7c7ffd2e
16 changed files with 3309 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 @@
|
|||
# Vera — Website-Compliance-Inspektorin
|
||||
|
||||
Vera prüft deine Website auf Vollständigkeit von Impressum (TMG § 5), Datenschutzerklärung (DSGVO Art. 13) und Cookie-Banner (TTDSG § 25). URL rein, Score raus. Demo auf Qognio.
|
||||
|
||||
```
|
||||
slug : vera-website-check
|
||||
version : 2026-04-27
|
||||
accent : #7c3aed
|
||||
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 vera-website-check --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-vera-website-check
|
||||
cd my-customer-vera-website-check
|
||||
# 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/* vera-website-check/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:49+02:00.
|
||||
14
bot.json
Normal file
14
bot.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"slug": "vera-website-check",
|
||||
"name": "Vera",
|
||||
"title": "Website-Compliance-Inspektorin",
|
||||
"tagline": "Website-Check",
|
||||
"description": "Vera prüft deine Website auf Vollständigkeit von Impressum (TMG § 5), Datenschutzerklärung (DSGVO Art. 13) und Cookie-Banner (TTDSG § 25). URL rein, Score raus. Demo auf Qognio.",
|
||||
"version": "2026-04-27",
|
||||
"accent": "#7c3aed",
|
||||
"extracted_from": "qognio-bot-widget-template",
|
||||
"parent_core_commit": "d2c816f3edbc9760802a11b29ff4151c7aad4b46",
|
||||
"extracted_at": "2026-04-29T01:35:49+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-vera-website-check:${TAG:-latest}
|
||||
container_name: bot-vera-website-check
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- caddy
|
||||
labels:
|
||||
caddy: "vera-website-check.on.qognio.com"
|
||||
caddy.reverse_proxy: "{{upstreams 80}}"
|
||||
qognio.bot.slug: "vera-website-check"
|
||||
qognio.bot.version: "2026-04-27"
|
||||
|
||||
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 @@
|
|||
// DSGVO-Erstkontakt — 1 Modul "dsgvo-grundlagen" Quiz korrekt
|
||||
if ((state.moduleCorrect && state.moduleCorrect['dsgvo-grundlagen'] >= 1)) unlockBadge('dsgvo_erstkontakt');
|
||||
// AI-Act-Spürnase — Modul "ai-act" Quiz mit ≥3 korrekt
|
||||
if ((state.moduleCorrect && state.moduleCorrect['ai-act'] >= 3)) unlockBadge('ai_act_spuernase');
|
||||
// NIS2-Versteher:in — Modul "nis2" Quiz mit ≥3 korrekt
|
||||
if ((state.moduleCorrect && state.moduleCorrect['nis2'] >= 3)) unlockBadge('nis2_versteher');
|
||||
// GoBD-Kenner:in — Modul "gobd" Quiz bestanden
|
||||
if ((state.moduleCorrect && state.moduleCorrect['gobd'] >= 3)) unlockBadge('gobd_kenner');
|
||||
// Mittelstands-Lotse — Schwellenwert-Modul (Flashcards bestanden ODER Quiz mit ≥3 korrekt)
|
||||
if ((state.modulePassedFlash && state.modulePassedFlash['schwellenwerte-uebersicht']) ||
|
||||
(state.moduleCorrect && state.moduleCorrect['schwellenwerte-uebersicht'] >= 3)) unlockBadge('mittelstands_lotse');
|
||||
// Compliance-Generalist:in — mindestens 4 Module mit ≥80% abgeschlossen (Module aus 4 Säulen)
|
||||
if ((state.completedCurricula || []).length >= 4) unlockBadge('compliance_generalist');
|
||||
// Compliance-Disziplin — 14-Tage-Streak
|
||||
if (state.maxStreak >= 14) unlockBadge('streak_14');
|
||||
// Night Owl & Early Bird (beibehalten)
|
||||
const h = new Date().getHours();
|
||||
if (h >= 22) unlockBadge('night_owl');
|
||||
if (h < 7) unlockBadge('early_bird');
|
||||
31
src/config.yaml
Normal file
31
src/config.yaml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
slug: vera-website-check
|
||||
bot_name: Vera
|
||||
bot_title: Website-Compliance-Inspektorin
|
||||
brand_letter: V
|
||||
title: "Vera · Website-Compliance-Check"
|
||||
tagline: "Impressum + Datenschutz + Cookie-Banner-Check"
|
||||
tagline_short: Website-Check
|
||||
meta_description: "Vera prüft deine Website auf Vollständigkeit von Impressum (TMG § 5), Datenschutzerklärung (DSGVO Art. 13) und Cookie-Banner (TTDSG § 25). URL rein, Score raus. Demo auf Qognio."
|
||||
bot_key_var: __VERA_KEY__
|
||||
bot_key_value: qb_veraejii0evf
|
||||
ls_prefix: vera
|
||||
bot_version: "2026-04-27"
|
||||
|
||||
accent: "#7c3aed"
|
||||
accent_2: "#a78bfa"
|
||||
accent_dark: "#5b21b6"
|
||||
accent_rgb: "124, 58, 237"
|
||||
accent_rgb_compact: "124,58,237"
|
||||
success_color: "#06b6d4"
|
||||
msg_strong_color: "#ddd6fe"
|
||||
|
||||
tab_flash_label: "Pflichten"
|
||||
tab_curriculum_label: "Recht"
|
||||
|
||||
quiz_intro_hint: "Vera fragt dich Grundlagen-Wissen zum Website-Recht ab."
|
||||
quiz_verb: stellt
|
||||
quiz_noun: "Recht-Quiz-Fragen"
|
||||
flash_intro_hint: "Pflicht-Inhalte als Karteikarten — TMG/DSGVO/TTDSG-Kerninhalte."
|
||||
flash_verb: zeigt
|
||||
|
||||
curriculum_long_label: Recht-Library
|
||||
52
src/curricula.json
Normal file
52
src/curricula.json
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
"version": "2026-04-27",
|
||||
"updated": "2026-04-27",
|
||||
"curricula": [
|
||||
{
|
||||
"id": "tmg-mstv",
|
||||
"title": "1 · Impressum (TMG § 5 + § 18 MStV)",
|
||||
"short": "Anbieterkennzeichnung + Pflicht-Angaben",
|
||||
"icon": "file-text",
|
||||
"color": "#7c3aed",
|
||||
"description": "Pflicht-Angaben für jede geschäftsmäßige Telemedien-Webseite: Anbieter, Vertretung, Kontakt, HR-Eintrag, USt-IdNr, Aufsichtsbehörde, OS-Plattform, VSBG.",
|
||||
"source_md": "01-impressum-tmg-mstv.md",
|
||||
"modules": [
|
||||
{"id": "anbieter-anschrift", "title": "Anbieter + Anschrift (TMG § 5 Abs. 1 Nr. 1)", "objectives":["Pflicht-Format kennen","Postfach-Verbot","Bei jur. Person zusätzlich Vertretungsberechtigte"], "topics":["Anschrift","Vertretung"], "difficulty":"einfach", "source_heading":"Pflicht-Angaben"},
|
||||
{"id": "kontakt", "title": "Kontakt + 2. Kommunikationsweg", "objectives":["Email Pflicht","Telefon vs Web-Formular (EuGH C-298/07)"], "topics":["Email","Telefon"], "difficulty":"einfach", "source_heading":"Schnelle Kontaktaufnahme"},
|
||||
{"id": "hr-ust", "title": "Handelsregister + USt-IdNr", "objectives":["Wann HR-Eintrag-Pflicht","USt-IdNr-Format"], "topics":["HR","UStG"], "difficulty":"mittel", "source_heading":"Handelsregister"},
|
||||
{"id": "os-vsbg", "title": "OS-Plattform-Link + VSBG-Hinweis", "objectives":["B2C-Pflicht ODR-VO","VSBG ab 11 MA"], "topics":["ODR","VSBG"], "difficulty":"mittel", "source_heading":"OS-Plattform-Link"},
|
||||
{"id": "redaktionell", "title": "Verantwortlich i.S.d. § 18 MStV", "objectives":["Wann redaktionell","Format der Angabe"], "topics":["MStV","Redaktion"], "difficulty":"mittel", "source_heading":"Verantwortlich"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "dsgvo-art13",
|
||||
"title": "2 · Datenschutzerklärung (DSGVO Art. 13)",
|
||||
"short": "Pflicht-Inhalte der DSE",
|
||||
"icon": "shield",
|
||||
"color": "#06b6d4",
|
||||
"description": "Pflicht-Inhalte einer Datenschutzerklärung nach Art. 13 DSGVO: Verantwortlicher, DSB, Zwecke, Rechtsgrundlagen, Speicherdauer, Empfänger, Drittland, Betroffenenrechte, Beschwerderecht.",
|
||||
"source_md": "02-datenschutzerklaerung-dsgvo.md",
|
||||
"modules": [
|
||||
{"id": "verantwortlicher", "title": "Verantwortlicher + DSB", "objectives":["Cross-Reference Impressum","DSB-Pflicht ab 20 MA"], "topics":["Verantwortlicher","DSB","BDSG § 38"], "difficulty":"einfach", "source_heading":"Verantwortliche Stelle"},
|
||||
{"id": "zwecke-rechtsgrundlagen", "title": "Zwecke + Rechtsgrundlagen Art. 6", "objectives":["Pro Zweck separat","6 Rechtsgrundlagen kennen"], "topics":["Art. 6","Zwecke"], "difficulty":"mittel", "source_heading":"Zwecke"},
|
||||
{"id": "speicher-empfaenger", "title": "Speicherdauer + Empfänger", "objectives":["Konkrete Fristen","AVV mit Auftragsverarbeitern"], "topics":["Speicherdauer","Empfänger"], "difficulty":"mittel", "source_heading":"Speicherdauer"},
|
||||
{"id": "drittland", "title": "Drittland-Übermittlung (Art. 44ff)", "objectives":["DPF/Adäquanz/SCC","Garantien benennen"], "topics":["Drittland","DPF"], "difficulty":"schwer", "source_heading":"Drittland"},
|
||||
{"id": "betroffenenrechte", "title": "Betroffenenrechte + Beschwerderecht", "objectives":["Art. 15-22 alle nennen","Aufsichtsbehörde namentlich"], "topics":["Art. 15","Art. 21","Art. 77"], "difficulty":"mittel", "source_heading":"Betroffenenrechte"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ttdsg",
|
||||
"title": "3 · Cookies + Tracking (TTDSG § 25)",
|
||||
"short": "Cookie-Banner + Pre-Consent-Tracking",
|
||||
"icon": "cookie",
|
||||
"color": "#f59e0b",
|
||||
"description": "TTDSG § 25 + DSK-Empfehlungen 2022/2025 zu Cookie-Bannern: Opt-In-Pflicht, Reject-All-Button, keine Pre-Consent-Tracker.",
|
||||
"source_md": "03-cookies-ttdsg.md",
|
||||
"modules": [
|
||||
{"id": "ttdsg-25", "title": "TTDSG § 25 — Opt-In-Pflicht", "objectives":["Was unbedingt erforderlich ist","Was Einwilligung braucht"], "topics":["TTDSG","Cookies"], "difficulty":"mittel", "source_heading":"TTDSG § 25"},
|
||||
{"id": "banner-design", "title": "Banner-Design (DSK-Beschluss)", "objectives":["Reject-All-Button","Keine Dark Patterns"], "topics":["Banner","DSK"], "difficulty":"mittel", "source_heading":"Cookie-Banner"},
|
||||
{"id": "fonts-maps", "title": "Google Fonts, Maps, YouTube", "objectives":["LG München-Urteil zu Google Fonts","nocookie-Mode"], "topics":["Drittanbieter","Embed"], "difficulty":"mittel", "source_heading":"Google Fonts"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
4
src/levels-fallback.js
Normal file
4
src/levels-fallback.js
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{ min: 0, title: 'Pflicht-Anfänger:in' }, { min: 50, title: 'Pflicht-Spürnase' },
|
||||
{ min: 200, title: 'Compliance-Generalist:in' }, { min: 500, title: 'Compliance-Lotse' },
|
||||
{ min: 1250, title: 'Senior-Compliance-Manager:in' }, { min: 2500, title: 'Compliance-Architekt:in' },
|
||||
{ min: 5000, title: 'Compliance-Veteran:in' }
|
||||
25
src/welcome.html
Normal file
25
src/welcome.html
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<h2>Hi, ich bin Vera.</h2>
|
||||
<p>Ich bin die <strong>Website-Compliance-Inspektorin</strong> auf der Qognio-Plattform. Gib mir eine URL — ich prüfe <strong>Impressum</strong> (TMG § 5 + § 18 MStV), <strong>Datenschutzerklärung</strong> (DSGVO Art. 13) und <strong>Cookie-Banner</strong> (TTDSG § 25). Du kriegst Score + Lücken-Liste + nächste Schritte. <strong>Disclaimer:</strong> Demo-Check, keine Rechtsberatung.</p>
|
||||
<div class="mode-grid">
|
||||
<button class="mode-card" data-prompt="Bitte prüfe https://example.com auf Compliance.">
|
||||
<strong>URL prüfen</strong>
|
||||
<span>Tippe „Prüfe https://example.com" — ich crawle + scoren.</span>
|
||||
</button>
|
||||
<button class="mode-card" data-prompt="Was muss ins Impressum nach TMG § 5? Bitte mit Quelle.">
|
||||
<strong>Impressum-Pflichten</strong>
|
||||
<span>Was alles ins Impressum gehört — TMG, MStV, ODR, VSBG.</span>
|
||||
</button>
|
||||
<button class="mode-card" data-prompt="Was muss in eine Datenschutzerklärung nach DSGVO Art. 13?">
|
||||
<strong>DSE-Pflichten</strong>
|
||||
<span>Pflicht-Inhalte einer DSGVO-konformen Datenschutzerklärung.</span>
|
||||
</button>
|
||||
<button class="mode-card" data-prompt="Wann brauche ich ein Cookie-Banner und wie muss es aussehen?">
|
||||
<strong>Cookies + TTDSG</strong>
|
||||
<span>Banner-Pflicht, Opt-In, Reject-All, Pre-Consent-Tracker.</span>
|
||||
</button>
|
||||
<button class="mode-card" data-goto="curriculum">
|
||||
<strong>Recht-Library</strong>
|
||||
<span>3 Curricula: TMG/MStV · DSGVO Art. 13 · TTDSG § 25.</span>
|
||||
</button>
|
||||
</div>
|
||||
<p style="font-size:.82rem;color:var(--text-mute)">Vera prüft FORMAL — sie kann inhaltliche Korrektheit (z.B. ob Speicherdauer rechtskonform) nicht bewerten. Bei wichtigen Befunden: Fachanwalt für IT-Recht ziehen.</p>
|
||||
1815
www/app.js
Normal file
1815
www/app.js
Normal file
File diff suppressed because it is too large
Load diff
52
www/curricula.json
Normal file
52
www/curricula.json
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
"version": "2026-04-27",
|
||||
"updated": "2026-04-27",
|
||||
"curricula": [
|
||||
{
|
||||
"id": "tmg-mstv",
|
||||
"title": "1 · Impressum (TMG § 5 + § 18 MStV)",
|
||||
"short": "Anbieterkennzeichnung + Pflicht-Angaben",
|
||||
"icon": "file-text",
|
||||
"color": "#7c3aed",
|
||||
"description": "Pflicht-Angaben für jede geschäftsmäßige Telemedien-Webseite: Anbieter, Vertretung, Kontakt, HR-Eintrag, USt-IdNr, Aufsichtsbehörde, OS-Plattform, VSBG.",
|
||||
"source_md": "01-impressum-tmg-mstv.md",
|
||||
"modules": [
|
||||
{"id": "anbieter-anschrift", "title": "Anbieter + Anschrift (TMG § 5 Abs. 1 Nr. 1)", "objectives":["Pflicht-Format kennen","Postfach-Verbot","Bei jur. Person zusätzlich Vertretungsberechtigte"], "topics":["Anschrift","Vertretung"], "difficulty":"einfach", "source_heading":"Pflicht-Angaben"},
|
||||
{"id": "kontakt", "title": "Kontakt + 2. Kommunikationsweg", "objectives":["Email Pflicht","Telefon vs Web-Formular (EuGH C-298/07)"], "topics":["Email","Telefon"], "difficulty":"einfach", "source_heading":"Schnelle Kontaktaufnahme"},
|
||||
{"id": "hr-ust", "title": "Handelsregister + USt-IdNr", "objectives":["Wann HR-Eintrag-Pflicht","USt-IdNr-Format"], "topics":["HR","UStG"], "difficulty":"mittel", "source_heading":"Handelsregister"},
|
||||
{"id": "os-vsbg", "title": "OS-Plattform-Link + VSBG-Hinweis", "objectives":["B2C-Pflicht ODR-VO","VSBG ab 11 MA"], "topics":["ODR","VSBG"], "difficulty":"mittel", "source_heading":"OS-Plattform-Link"},
|
||||
{"id": "redaktionell", "title": "Verantwortlich i.S.d. § 18 MStV", "objectives":["Wann redaktionell","Format der Angabe"], "topics":["MStV","Redaktion"], "difficulty":"mittel", "source_heading":"Verantwortlich"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "dsgvo-art13",
|
||||
"title": "2 · Datenschutzerklärung (DSGVO Art. 13)",
|
||||
"short": "Pflicht-Inhalte der DSE",
|
||||
"icon": "shield",
|
||||
"color": "#06b6d4",
|
||||
"description": "Pflicht-Inhalte einer Datenschutzerklärung nach Art. 13 DSGVO: Verantwortlicher, DSB, Zwecke, Rechtsgrundlagen, Speicherdauer, Empfänger, Drittland, Betroffenenrechte, Beschwerderecht.",
|
||||
"source_md": "02-datenschutzerklaerung-dsgvo.md",
|
||||
"modules": [
|
||||
{"id": "verantwortlicher", "title": "Verantwortlicher + DSB", "objectives":["Cross-Reference Impressum","DSB-Pflicht ab 20 MA"], "topics":["Verantwortlicher","DSB","BDSG § 38"], "difficulty":"einfach", "source_heading":"Verantwortliche Stelle"},
|
||||
{"id": "zwecke-rechtsgrundlagen", "title": "Zwecke + Rechtsgrundlagen Art. 6", "objectives":["Pro Zweck separat","6 Rechtsgrundlagen kennen"], "topics":["Art. 6","Zwecke"], "difficulty":"mittel", "source_heading":"Zwecke"},
|
||||
{"id": "speicher-empfaenger", "title": "Speicherdauer + Empfänger", "objectives":["Konkrete Fristen","AVV mit Auftragsverarbeitern"], "topics":["Speicherdauer","Empfänger"], "difficulty":"mittel", "source_heading":"Speicherdauer"},
|
||||
{"id": "drittland", "title": "Drittland-Übermittlung (Art. 44ff)", "objectives":["DPF/Adäquanz/SCC","Garantien benennen"], "topics":["Drittland","DPF"], "difficulty":"schwer", "source_heading":"Drittland"},
|
||||
{"id": "betroffenenrechte", "title": "Betroffenenrechte + Beschwerderecht", "objectives":["Art. 15-22 alle nennen","Aufsichtsbehörde namentlich"], "topics":["Art. 15","Art. 21","Art. 77"], "difficulty":"mittel", "source_heading":"Betroffenenrechte"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ttdsg",
|
||||
"title": "3 · Cookies + Tracking (TTDSG § 25)",
|
||||
"short": "Cookie-Banner + Pre-Consent-Tracking",
|
||||
"icon": "cookie",
|
||||
"color": "#f59e0b",
|
||||
"description": "TTDSG § 25 + DSK-Empfehlungen 2022/2025 zu Cookie-Bannern: Opt-In-Pflicht, Reject-All-Button, keine Pre-Consent-Tracker.",
|
||||
"source_md": "03-cookies-ttdsg.md",
|
||||
"modules": [
|
||||
{"id": "ttdsg-25", "title": "TTDSG § 25 — Opt-In-Pflicht", "objectives":["Was unbedingt erforderlich ist","Was Einwilligung braucht"], "topics":["TTDSG","Cookies"], "difficulty":"mittel", "source_heading":"TTDSG § 25"},
|
||||
{"id": "banner-design", "title": "Banner-Design (DSK-Beschluss)", "objectives":["Reject-All-Button","Keine Dark Patterns"], "topics":["Banner","DSK"], "difficulty":"mittel", "source_heading":"Cookie-Banner"},
|
||||
{"id": "fonts-maps", "title": "Google Fonts, Maps, YouTube", "objectives":["LG München-Urteil zu Google Fonts","nocookie-Mode"], "topics":["Drittanbieter","Embed"], "difficulty":"mittel", "source_heading":"Google Fonts"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
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>Vera · Website-Compliance-Check</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
||||
<meta name="theme-color" content="#0a0a0f">
|
||||
<meta name="description" content="Vera prüft deine Website auf Vollständigkeit von Impressum (TMG § 5), Datenschutzerklärung (DSGVO Art. 13) und Cookie-Banner (TTDSG § 25). URL rein, Score raus. Demo auf Qognio.">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<script>window.__VERA_KEY__ = 'qb_veraejii0evf';</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app" role="application" aria-label="Vera Impressum + Datenschutz + Cookie-Banner-Check">
|
||||
|
||||
<header class="topbar">
|
||||
<div class="brand">
|
||||
<span class="brand-icon" aria-hidden="true">V</span>
|
||||
<span>Vera <small>Website-Check</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">
|
||||
Pflichten
|
||||
<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">
|
||||
Recht
|
||||
<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>Hi, ich bin Vera.</h2>
|
||||
<p>Ich bin die <strong>Website-Compliance-Inspektorin</strong> auf der Qognio-Plattform. Gib mir eine URL — ich prüfe <strong>Impressum</strong> (TMG § 5 + § 18 MStV), <strong>Datenschutzerklärung</strong> (DSGVO Art. 13) und <strong>Cookie-Banner</strong> (TTDSG § 25). Du kriegst Score + Lücken-Liste + nächste Schritte. <strong>Disclaimer:</strong> Demo-Check, keine Rechtsberatung.</p>
|
||||
<div class="mode-grid">
|
||||
<button class="mode-card" data-prompt="Bitte prüfe https://example.com auf Compliance.">
|
||||
<strong>URL prüfen</strong>
|
||||
<span>Tippe „Prüfe https://example.com" — ich crawle + scoren.</span>
|
||||
</button>
|
||||
<button class="mode-card" data-prompt="Was muss ins Impressum nach TMG § 5? Bitte mit Quelle.">
|
||||
<strong>Impressum-Pflichten</strong>
|
||||
<span>Was alles ins Impressum gehört — TMG, MStV, ODR, VSBG.</span>
|
||||
</button>
|
||||
<button class="mode-card" data-prompt="Was muss in eine Datenschutzerklärung nach DSGVO Art. 13?">
|
||||
<strong>DSE-Pflichten</strong>
|
||||
<span>Pflicht-Inhalte einer DSGVO-konformen Datenschutzerklärung.</span>
|
||||
</button>
|
||||
<button class="mode-card" data-prompt="Wann brauche ich ein Cookie-Banner und wie muss es aussehen?">
|
||||
<strong>Cookies + TTDSG</strong>
|
||||
<span>Banner-Pflicht, Opt-In, Reject-All, Pre-Consent-Tracker.</span>
|
||||
</button>
|
||||
<button class="mode-card" data-goto="curriculum">
|
||||
<strong>Recht-Library</strong>
|
||||
<span>3 Curricula: TMG/MStV · DSGVO Art. 13 · TTDSG § 25.</span>
|
||||
</button>
|
||||
</div>
|
||||
<p style="font-size:.82rem;color:var(--text-mute)">Vera prüft FORMAL — sie kann inhaltliche Korrektheit (z.B. ob Speicherdauer rechtskonform) nicht bewerten. Bei wichtigen Befunden: Fachanwalt für IT-Recht ziehen.</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 Vera — 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