Create whitepaper.md
This commit is contained in:
+799
@@ -0,0 +1,799 @@
|
|||||||
|
# Bürgerabstimmung — Whitepaper
|
||||||
|
|
||||||
|
**Digitale Bürgerbeteiligung mit dem Personalausweis. Themen einbringen, abstimmen, gemeinsam prüfen.**
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| Arbeitstitel / Marke | **Bürgerabstimmung** |
|
||||||
|
| Domain (vorgeschlagen) | **buergerabstimmung.de** (Alternativen: buergerabstimmung.eu, abstimmungsportal.de) |
|
||||||
|
| Status | Konzept & technischer Prototyp (Testbetrieb, keine offizielle Seite einer Behörde) |
|
||||||
|
| Sprachen | Deutsch (Standard), Englisch |
|
||||||
|
| Version | 1.0 · August 2026 |
|
||||||
|
|
||||||
|
> **Wichtiger Hinweis:** Bürgerabstimmung ist ein privates Konzept- und Demonstrationsprojekt.
|
||||||
|
> Es ist **keine offizielle Seite der Bundesregierung oder einer Behörde** und erhebt
|
||||||
|
> nicht den Anspruch, staatliche Verfahren rechtlich zu ersetzen. Der Prototyp zeigt,
|
||||||
|
> wie eine solche Plattform funktionieren könnte. Solange der Testbetrieb läuft, zeigt
|
||||||
|
> die Seite dauerhaft ein entsprechendes Hinweisbanner an (im Code über die
|
||||||
|
> Konfigurationsvariable `show_test_banner = true` gesteuert). Eine frische
|
||||||
|
> Installation startet im **Testmodus**; er wird über die Oberfläche beendet und
|
||||||
|
> löscht dabei alle bis dahin entstandenen Testdaten (Kapitel 5.3b).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Zusammenfassung
|
||||||
|
|
||||||
|
Bürgerabstimmung ist eine Plattform für direkte, fortlaufende Bürgerbeteiligung. Jede Person
|
||||||
|
mit deutschem Personalausweis kann:
|
||||||
|
|
||||||
|
- **Themen einbringen** — maximal eines pro Tag, mit Ziel, Begründung, Kategorie und
|
||||||
|
räumlicher Ebene (Landkreis/kreisfreie Stadt, Bundesland, Deutschland; die
|
||||||
|
Gemeindeebene folgt in der Ausbaustufe),
|
||||||
|
- **abstimmen** — dafür oder dagegen; wer sich enthält, stimmt schlicht nicht ab,
|
||||||
|
- **rechtswidrige Inhalte melden** — geprüft nicht von einer Redaktion, sondern von
|
||||||
|
einer zufällig ausgelosten **Bürger-Jury** (1 % aller aktiven Ausweis-Pseudonyme),
|
||||||
|
- **seine Gesamtansicht abrufen** — durch Auflegen des Ausweises (NFC) erscheinen alle
|
||||||
|
eigenen Themen, Stimmen und Favoriten.
|
||||||
|
|
||||||
|
Die Identität wird ausschließlich über die **eID-Funktion des Personalausweises**
|
||||||
|
nachgewiesen: Der Chip beweist kryptographisch die Echtheit der Karte (privater
|
||||||
|
Schlüssel im Chip). Die Plattform kennt als Identität nur den **öffentlichen
|
||||||
|
Schlüssel** — keinen Namen, keine Adresse, kein Geburtsdatum, kein abgeleitetes
|
||||||
|
Pseudonym. Eine Karte = ein Konto. Das persönliche Profil wird an diesen
|
||||||
|
öffentlichen Schlüssel **verschlüsselt** und vom Server **signiert**
|
||||||
|
(manipulationssicher); die Stimmen werden **unverkettbar** gespeichert, sodass
|
||||||
|
niemand rückschließen kann, wer wie gestimmt hat.
|
||||||
|
|
||||||
|
Die Plattform ist bewusst **schlicht und amtlich-neutral** gestaltet, funktioniert
|
||||||
|
gleichwertig auf Smartphone und PC, passt sich hellem und dunklem Systemdesign an und
|
||||||
|
ist auch an öffentlichen Geräten (z. B. in Gemeindebüros oder Bibliotheken) nutzbar —
|
||||||
|
für Menschen ohne eigenes Gerät.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Marke, Domain, Gestaltung
|
||||||
|
|
||||||
|
### 2.1 Name
|
||||||
|
|
||||||
|
**Bürgerabstimmung** — bewusst **kein Kunstwort und keine Marke**, sondern die
|
||||||
|
schlichte Sachbezeichnung: Bürgerinnen und Bürger stimmen ab. So würde eine
|
||||||
|
Verwaltung die Sache benennen, und genau das ist der Zweck des Namens — er
|
||||||
|
verspricht nichts, was er nicht ist.
|
||||||
|
|
||||||
|
Bewusst **nicht** gewählt wurden „Wahl…“ und „Bürgerentscheid“: Beides sind
|
||||||
|
rechtlich belegte Begriffe für verbindliche Verfahren nach Wahl- und
|
||||||
|
Gemeinderecht. Diese Plattform ist ein Meinungsbildungs-Kanal **ohne
|
||||||
|
Rechtsverbindlichkeit**; ein Name aus dem Wahlrecht würde eine Wirkung
|
||||||
|
suggerieren, die sie nicht hat.
|
||||||
|
|
||||||
|
Zugleich ist der Name **nicht mit staatlichen Kennzeichen verwechselbar**: kein
|
||||||
|
Bundesadler, keine Bundesfarben-Imitation, kein „bund.de“-Look. Vor einem echten
|
||||||
|
Betrieb sind Marken- und Domainrecherche erforderlich — die reine
|
||||||
|
Sachbezeichnung ist als Wortmarke voraussichtlich nicht schutzfähig, was für
|
||||||
|
diesen Zweck kein Nachteil ist.
|
||||||
|
|
||||||
|
### 2.2 Domain
|
||||||
|
|
||||||
|
Vorschlag: **buergerabstimmung.de** (Sachbezeichnung, aussprechbar, .de passt
|
||||||
|
zum Zweck). Ausweichoptionen: buergerabstimmung.eu, buerger-abstimmung.de,
|
||||||
|
abstimmungsportal.de. Im Auslieferungszustand ist in der Konfiguration **keine
|
||||||
|
Domain eingetragen** — sie wird erst beim Aufsetzen gesetzt.
|
||||||
|
|
||||||
|
### 2.3 Gestaltungsprinzipien
|
||||||
|
|
||||||
|
1. **Schlicht wie eine App:** ruhige graue Fläche, weiße Karten mit weichen
|
||||||
|
Ecken, Haarlinien statt Rahmen, Systemschrift, **ein** blauer Akzent —
|
||||||
|
die Formensprache verbreiteter Messenger-/Systemoberflächen (iOS, Signal).
|
||||||
|
Keine Verläufe, keine Deko-Effekte, keine „KI-Regenbogen“-Ästhetik; Rot
|
||||||
|
bleibt destruktiven Aktionen (Löschen) vorbehalten, Gelb allein dem
|
||||||
|
Testbetrieb-Banner.
|
||||||
|
2. **Keine KI-Hinweistexte** auf der Seite. Die Seite spricht als Produkt, nüchtern
|
||||||
|
und in Sie-Form. Es steht nur Text da, der eine Entscheidung trägt:
|
||||||
|
Erklärsätze unter selbsterklärenden Überschriften, Wiederholungen von Zahlen
|
||||||
|
und Beschriftungen wie „Eingebracht am“ entfallen.
|
||||||
|
3. **Hell/Dunkel automatisch:** Das Design folgt ausschließlich der
|
||||||
|
Systemeinstellung (`prefers-color-scheme`) — es wird bewusst nichts im
|
||||||
|
Browser gespeichert, auch keine Design-Präferenz.
|
||||||
|
4. **Symbolhafter Einstieg:** Beim Sitzungsbeginn nur der Schriftzug und die
|
||||||
|
Sprachwahl — **Deutsch/English als Knöpfe mit Flagge**, ohne Bildmarke; die
|
||||||
|
Anmeldung führt ein Ausweis-Piktogramm mit NFC-Wellen an, Text bleibt
|
||||||
|
minimal. Die Kopfzeile der Seite trägt weder Wortmarke noch Anmeldestatus,
|
||||||
|
sondern nur die nötigen Bedienelemente; die Fußzeile nur Impressum und
|
||||||
|
Datenschutz. Das Impressum trägt im Prototyp bewusst nur einen Platzhalter
|
||||||
|
(ein `*` als Überschrift und als Text) — es ist vor einem echten Betrieb mit
|
||||||
|
den Pflichtangaben des Betreibers zu füllen, die Datenschutzerklärung ist an
|
||||||
|
den tatsächlichen Betrieb anzupassen.
|
||||||
|
|
||||||
|
**Bildmarke (Tab-/App-Icon):** ein **Häkchen im Feld** — scharfe Kanten,
|
||||||
|
keine abgerundeten Ecken, keine Farbe. Als SVG folgt es der
|
||||||
|
Systemeinstellung (schwarze Fläche mit weißem Kreuz im Hellmodus, weiße
|
||||||
|
Fläche mit schwarzem Kreuz im Dunkelmodus); PNG und ICO für Safari/iOS
|
||||||
|
liefern dieselbe Marke als geschlossene dunkle Kachel.
|
||||||
|
5. **Responsiv:** eine Codebasis für Smartphone, Tablet, PC und Terminals. Die
|
||||||
|
**tragenden** Funktionen — anmelden, Thema einbringen, abstimmen, melden,
|
||||||
|
Jury — laufen ohne JavaScript; alle Fenster sind `:target`-Dialoge, alle
|
||||||
|
Eingaben normale Formulare. JavaScript ergänzt: Countdown, NFC-Auslösung,
|
||||||
|
die stufige Geltungsbereichs-Auswahl, die Live-Zahlen und den Hinweis auf
|
||||||
|
ähnliche Themen. **Eine Ausnahme:** die `profil.yaml` wird ausschließlich per
|
||||||
|
`fetch` geladen — ohne JavaScript gibt es keine Selbstauskunft. Das ist vor
|
||||||
|
einem Echtbetrieb zu ergänzen.
|
||||||
|
6. **Testbetrieb-Banner:** Solange die Konfigurationsvariable
|
||||||
|
`show_test_banner` auf `true` steht (Auslieferungszustand), zeigt jede Seite oben
|
||||||
|
ein deutliches Banner: *„Testbetrieb — keine offizielle Seite der
|
||||||
|
Bundesregierung oder einer Behörde.“* Der **Testmodus** selbst ist keine
|
||||||
|
Variable, sondern ein Zustand der Installation (Kapitel 5.3b).
|
||||||
|
7. **Barrierearmut:** semantisches HTML, Tastaturbedienung, ausreichende Kontraste.
|
||||||
|
Die Abstimmungsbalken nutzen **Akzentblau gegen Neutralgrau** — auf
|
||||||
|
Farbfehlsichtigkeit geprüft (CVD-Abstand ΔE 18,3 hell / 16,6 dunkel) — und
|
||||||
|
tragen immer Beschriftung samt Prozentwert; Bedeutung hängt nie an Farbe
|
||||||
|
allein. Vollständige BITV-Konformität ist Ziel der Ausbaustufe.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Leitidee und Einordnung
|
||||||
|
|
||||||
|
Bürgerabstimmung versteht sich als **ständiger Meinungsbildungs-Kanal**: Statt alle vier
|
||||||
|
Jahre ein Kreuz zu machen, können Bürgerinnen und Bürger laufend Anliegen einbringen
|
||||||
|
und gewichten — von der Radweg-Frage in der Gemeinde bis zur bundespolitischen
|
||||||
|
Grundsatzfrage. Die Ergebnisse sind ein präzises, manipulationsarmes Stimmungsbild,
|
||||||
|
das Politik auf allen Ebenen nutzen kann.
|
||||||
|
|
||||||
|
Bewusste Abgrenzung:
|
||||||
|
|
||||||
|
- Bürgerabstimmung **ersetzt keine rechtlich bindenden Verfahren** (Wahlen, Volksentscheide).
|
||||||
|
Ergebnisse sind Meinungsbilder; eine rechtliche Bindung wäre ein politischer
|
||||||
|
Folgeschritt, kein technischer.
|
||||||
|
- Die Plattform ist **strikt neutral**: Zum Start existieren ausschließlich
|
||||||
|
Kategorien über das gesamte politische Spektrum, keine vorbefüllten Themen
|
||||||
|
(siehe 6.3); die Moderation erfolgt durch geloste Jurys nach
|
||||||
|
strafrechtlichen — nicht politischen — Kriterien.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Zugänge und Zielgruppen
|
||||||
|
|
||||||
|
- **Smartphone:** Ausweis per NFC ans Gerät halten, PIN in der eID-App eingeben,
|
||||||
|
fertig. Der Browser selbst berührt die Karte nie.
|
||||||
|
- **PC:** eID-Client (z. B. AusweisApp) mit USB-Kartenleser oder gekoppeltem
|
||||||
|
Smartphone als Leser.
|
||||||
|
- **Öffentliche Geräte:** Gemeinden, Bürgerbüros und Bibliotheken können Terminals
|
||||||
|
bereitstellen. Dafür ausgelegt: kurze Sitzungen, automatische Abmeldung nach
|
||||||
|
Inaktivität, keine lokalen Datenspuren, prominenter Abmelden-Knopf.
|
||||||
|
- **Fremde Geräte:** Da die Anmeldung nur mit physischer Karte + PIN funktioniert und
|
||||||
|
keine Passwörter existieren, kann bedenkenlos das Gerät einer anderen Person
|
||||||
|
genutzt werden.
|
||||||
|
|
||||||
|
Sprachen: **Deutsch und Englisch**. Die Wahl erfolgt beim Sitzungsbeginn,
|
||||||
|
gilt für die Sitzung und wird **nirgends gespeichert** — weder im Browser noch
|
||||||
|
am Konto. Ohne aufgelegten Ausweis ist die Seite nicht sichtbar (nur Anmeldung
|
||||||
|
und Rechtliches sind offen).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Identität: die eID des Personalausweises
|
||||||
|
|
||||||
|
### 5.1 Prinzip
|
||||||
|
|
||||||
|
Jeder deutsche Personalausweis (seit 2010) enthält einen Chip mit
|
||||||
|
Online-Ausweisfunktion (eID). Die Echtheit beweist der Chip kryptographisch: Er
|
||||||
|
besitzt **private Schlüssel, die das Chipmaterial nie verlassen**, und die Gegenseite
|
||||||
|
prüft die zugehörigen Zertifikate gegen die **staatliche Zertifikatskette** (Country
|
||||||
|
Verifying CA / Document Verifier, BSI-Standards TR-03110, TR-03130). Kopierte oder
|
||||||
|
gefälschte Karten fallen bei dieser Prüfung durch.
|
||||||
|
|
||||||
|
Für Bürgerabstimmung entscheidend ist die Funktion **„dienstespezifisches Kennzeichen“
|
||||||
|
(Restricted Identification)**: Der Chip errechnet pro Dienst ein stabiles Pseudonym.
|
||||||
|
|
||||||
|
- Dasselbe Pseudonym bei jedem Anhalten derselben Karte bei Bürgerabstimmung → **ein
|
||||||
|
Konto pro Karte**, Wiedererkennung ohne Klarnamen.
|
||||||
|
- Ein anderes Pseudonym bei jedem anderen Dienst → **keine Verkettbarkeit** über
|
||||||
|
Dienste hinweg.
|
||||||
|
- Bürgerabstimmung fragt **keine** Klardaten ab (kein Name, keine Anschrift, kein
|
||||||
|
Geburtsdatum). Es wird auch **kein eigenes Pseudonym erzeugt oder
|
||||||
|
zugeordnet**: Identität ist unmittelbar der öffentliche Schlüssel („on
|
||||||
|
the go“); Stimmen werden auf dem Server direkt für diesen Schlüssel
|
||||||
|
eingetragen.
|
||||||
|
|
||||||
|
### 5.2 Ablauf (Produktion)
|
||||||
|
|
||||||
|
1. Nutzer wählt „Ausweis auflegen“. Die Plattform startet über den eID-Client
|
||||||
|
(AusweisApp, Schnittstelle nach TR-03124) eine Authentisierung beim zugelassenen
|
||||||
|
**eID-Server** (TR-03130).
|
||||||
|
2. Nutzer hält die Karte an das NFC-Smartphone bzw. den Kartenleser und gibt die
|
||||||
|
sechsstellige **Ausweis-PIN** ein.
|
||||||
|
3. Chip und eID-Server authentisieren sich gegenseitig (PACE, Terminal- und
|
||||||
|
Chip-Authentisierung); der eID-Server prüft Echtheit und Sperrliste und übermittelt
|
||||||
|
Bürgerabstimmung **nur das Pseudonym**.
|
||||||
|
4. Bürgerabstimmung nimmt den geprüften öffentlichen Schlüssel unmittelbar als Kennung und meldet die Sitzung an.
|
||||||
|
|
||||||
|
Voraussetzung für den Echtbetrieb ist ein **Berechtigungszertifikat** der
|
||||||
|
Vergabestelle für Berechtigungszertifikate (Bundesverwaltungsamt) mit dem
|
||||||
|
Berechtigungsumfang „pseudonymer Zugang“ sowie ein zertifizierter eID-Server
|
||||||
|
(eigenbetrieben oder als Dienstleistung).
|
||||||
|
|
||||||
|
### 5.3 Prototyp (dieses Repository)
|
||||||
|
|
||||||
|
Der Prototyp bildet das Verfahren originalgetreu nach: Eine simulierte
|
||||||
|
Testkarte im Browser übernimmt die Rolle des Chips und hält ein echtes
|
||||||
|
Ed25519-Schlüsselpaar (libsodium). Beim „Ausweis auflegen“ signiert der
|
||||||
|
private Schlüssel eine Zufallsnachricht; der Server prüft die Signatur
|
||||||
|
gegen den öffentlichen Schlüssel und leitet daraus das Pseudonym ab.
|
||||||
|
**Zwei getrennte Vorgänge:**
|
||||||
|
|
||||||
|
1. **Profil laden (initiales Anhalten):** Die statische Challenge ist der
|
||||||
|
öffentliche Schlüssel selbst, zeitgebunden versiegelt. Der Server öffnet
|
||||||
|
den Nachweis mit dem öffentlichen Schlüssel und liefert die
|
||||||
|
**profil.yaml** (alle eigenen Stimmen, Themen, Favoriten, Jury-Status)
|
||||||
|
in den Browser; der Abmelde-Knopf löscht sie dort wieder. Der Nachweis
|
||||||
|
ist **TOTP-artig zeitbegrenzt** (5-Minuten-Fenster, Anmeldung gilt
|
||||||
|
höchstens zwei Fenster) — danach ist erneutes Anhalten nötig.
|
||||||
|
2. **Stimmabgabe und jede andere Änderung (unabhängig davon):** Die Karte
|
||||||
|
erstellt je Vorgang einen **versiegelten Umschlag** (kombinierte
|
||||||
|
Signatur über Aktion + Zeitfenster + Zufallswert); der Server
|
||||||
|
**öffnet ihn mit dem öffentlichen Schlüssel** und trägt die Stimme für
|
||||||
|
genau diesen Schlüssel ein. Derselbe Vorgang ergibt zu anderer Zeit
|
||||||
|
einen anderen Umschlag; alte Umschläge verfallen.
|
||||||
|
|
||||||
|
Zusätzlich trägt jedes Formular ein **Einmal-Token** (beim Einlösen
|
||||||
|
verbraucht — Wiederholungen laufen ins Leere), und im Browser liegt außer
|
||||||
|
der Sitzungs-ID nur die bewusst geladene profil.yaml. Am Smartphone ist
|
||||||
|
der NFC-Leser auf der Anmeldeseite automatisch scharf: Das Auflegen des
|
||||||
|
(echten) Personalausweises löst die Anmeldung direkt aus (Web NFC; der
|
||||||
|
Knopf bleibt Rückfall und Berechtigungsgeste).
|
||||||
|
|
||||||
|
### 5.3b Testmodus als Zustand, nicht als Variable
|
||||||
|
|
||||||
|
Eine frische Installation startet **im Testmodus**. Er ist kein Schalter in
|
||||||
|
der Konfigurationsdatei, sondern ein Zustand in der Datenbank
|
||||||
|
(`schema_info.test_mode`), damit eine Vorführung ohne Codeänderung möglich
|
||||||
|
ist und der Übergang in den Echtbetrieb protokolliert wird.
|
||||||
|
|
||||||
|
- **Im Testmodus** zeigt die Anmeldeseite **genau einen Knopf**. Er erzeugt
|
||||||
|
eine zufällige, als gültig behandelte Sitzung; Ausweis-Aufforderungen bei
|
||||||
|
Änderungen entfallen. Das Banner bleibt unabhängig davon sichtbar.
|
||||||
|
- **Beendet wird er über die Oberfläche**: Der Chip „Testmodus“ in der
|
||||||
|
Kopfzeile führt auf die Seite **„Echtbetrieb einrichten“** (Kapitel 5.3c).
|
||||||
|
Dort wird der Zugang für den Echtbetrieb festgelegt, geprüft und
|
||||||
|
umgeschaltet. Das Umschalten **löscht alle im Testbetrieb entstandenen
|
||||||
|
Daten** — Themen, Stimmen, Merkzettel, Meldungen, Jury-Sitze, Konten und die
|
||||||
|
im Testmodus erzeugten Ausweis-Schlüssel. Kategorien, System-Konto und eine
|
||||||
|
echte Freigabeliste bleiben. Der Schritt ist bewusst nicht umkehrbar.
|
||||||
|
- **Danach** existiert kein Weg mehr in die Anwendung, der ohne Ausweis
|
||||||
|
auskommt: Die Anmeldeseite bietet nur noch die Ausweis-Apps an, und die
|
||||||
|
Einrichtungsseite ist geschlossen.
|
||||||
|
|
||||||
|
### 5.3c Einrichtung des Echtbetriebs aus der Anwendung heraus
|
||||||
|
|
||||||
|
Der Übergang vom Testbetrieb zum Echtbetrieb ist kein Eingriff in den
|
||||||
|
Quelltext, sondern ein geführter Schritt in der Oberfläche. Die Seite
|
||||||
|
„Echtbetrieb einrichten“ leistet dreierlei:
|
||||||
|
|
||||||
|
1. **Voraussetzungen prüfen.** Sie zeigt, ob das Datenverzeichnis beschreibbar
|
||||||
|
ist, HTTPS anliegt, die Kryptographie-Erweiterung vorhanden ist, der
|
||||||
|
Zugriffsschutz greift und wie viele Ausweis-Schlüssel freigegeben sind.
|
||||||
|
2. **Zugang festlegen.** Zur Wahl stehen der **eigene eID-Server** (Anmeldung
|
||||||
|
über die Ausweis-App; setzt Berechtigungszertifikat und einen Server nach
|
||||||
|
TR-03130 voraus) und die **eigene Trust-Liste** (Anmeldung nur mit
|
||||||
|
Schlüsseln aus der Freigabeliste, befüllt über eine Abgleich-Adresse oder
|
||||||
|
`issue-card`). Erfasst werden SOAP-Adresse, Client-Zertifikat und
|
||||||
|
-Schlüssel, die Aktivierungsadresse der Ausweis-App, die Abgleich-Adresse
|
||||||
|
der Freigabeliste und die Startadresse von Nect. Ein Knopf **prüft die
|
||||||
|
Verbindung** zum eID-Server, bevor irgendetwas verändert wird.
|
||||||
|
3. **Umschalten.** Erst wenn die Eingaben gültig sind, der eID-Server
|
||||||
|
antwortet und der **Einrichtungsschlüssel** stimmt, werden die Einstellungen
|
||||||
|
nach `data/config.yaml` (Rechte 0600, vom Web nicht erreichbar)
|
||||||
|
geschrieben, die Testdaten gelöscht und der Echtbetrieb dauerhaft
|
||||||
|
aktiviert.
|
||||||
|
|
||||||
|
Der **Einrichtungsschlüssel** steht in `data/setup.token` und ist nur über
|
||||||
|
Dateizugriff oder `php index.php setup-token` lesbar. Damit kann das
|
||||||
|
Umschalten nur, wer den Server betreibt — nicht jeder, der sich im Testbetrieb
|
||||||
|
per Knopfdruck eine Sitzung erzeugen kann. Nach dem Umschalten wird die Datei
|
||||||
|
gelöscht.
|
||||||
|
|
||||||
|
Die Einstellungen aus `config.yaml` überlagern beim Start die Vorgaben im
|
||||||
|
Quelltext; übernommen wird ausschließlich eine feste Liste erlaubter
|
||||||
|
Schlüssel. `php index.php config` zeigt den wirksamen Stand.
|
||||||
|
|
||||||
|
Der Wechsel auf einen echten eID-Server ersetzt nur den Karten-Block; Regeln
|
||||||
|
und Abläufe bleiben identisch.
|
||||||
|
|
||||||
|
### 5.3d Anbindung der AusweisApp (TR-03124/TR-03130)
|
||||||
|
|
||||||
|
Die Anmeldung mit der AusweisApp ist direkt eingebaut und braucht auf der
|
||||||
|
Serverseite nichts als den Webserver und diese Datei:
|
||||||
|
|
||||||
|
1. Der Knopf „Mit AusweisApp anmelden“ leitet den Browser auf die
|
||||||
|
**Aktivierungsadresse des eID-Clients** nach TR-03124:
|
||||||
|
`http://127.0.0.1:24727/eID-Client?tcTokenURL=…`. Die AusweisApp — am PC wie
|
||||||
|
am Smartphone — fängt diese Adresse ab.
|
||||||
|
2. Die App holt das **tcToken** unter `/eid/tctoken` ab. Sie tut das als
|
||||||
|
eigener HTTP-Client **ohne Browser-Cookie**; deshalb trägt die tcTokenURL
|
||||||
|
einen **Einmal-Nonce** (10 Minuten gültig), der Browsersitzung und
|
||||||
|
Ausweis-Vorgang verbindet.
|
||||||
|
3. Mit hinterlegtem **eID-Server** (TR-03130, `eid_server_url`) fordert der
|
||||||
|
Server dort per `useID` eine Sitzung an und liefert der App ServerAddress,
|
||||||
|
SessionIdentifier und RefreshAddress. Die App liest den Chip PIN-geschützt
|
||||||
|
aus und schickt den Browser zurück auf `/eid/callback`.
|
||||||
|
4. **Ohne** eID-Server liefert das tcToken bewusst nur eine
|
||||||
|
`CommunicationErrorAddress`. Die AusweisApp bricht sauber ab, der Browser
|
||||||
|
kehrt zurück — **angemeldet wird niemand**. Das ist die ehrliche Grenze:
|
||||||
|
Einen eID-Server darf nur betreiben, wer ein **Berechtigungszertifikat des
|
||||||
|
BVA** besitzt (Kapitel 5.3e).
|
||||||
|
|
||||||
|
### 5.3e Autorisierte Schlüssel (Freigabeliste) und ehrliche Grenzen der eID
|
||||||
|
|
||||||
|
Anmelden kann sich ausschließlich, wessen **öffentlicher Schlüssel in einer
|
||||||
|
serverseitigen Allowlist** steht (`data/authorized_keys.yaml`) und wer den
|
||||||
|
passenden **privaten Schlüssel** besitzt (zeitgebundene Signatur-Challenge).
|
||||||
|
Damit ist ausgeschlossen, dass ein Knopfdruck ohne Ausweis oder mit einem
|
||||||
|
fremden/gefälschten Schlüssel Zugang gewährt (fail-closed).
|
||||||
|
|
||||||
|
Ehrliche Einordnung zur oft gewünschten „Liste aller Ausweis-Schlüssel“:
|
||||||
|
Eine solche staatliche Liste **existiert nicht** und wäre auch nicht
|
||||||
|
wünschenswert (sie wäre ein Register der kryptographischen Identität aller
|
||||||
|
Bürgerinnen und Bürger). Der Personalausweis weist sich stattdessen über die
|
||||||
|
**BSI-Zertifikatskette** (TR-03110: Chip-Authentisierung gegen CVCA/DV) aus,
|
||||||
|
geprüft durch einen zertifizierten **eID-Server** (TR-03130); das Auslesen des
|
||||||
|
Chips erfolgt PIN-geschützt ausschließlich über die **AusweisApp** (ein Browser
|
||||||
|
kann den Chip nicht lesen). Im Prototyp ist die Allowlist deshalb der
|
||||||
|
Platzhalter für genau diese Vertrauensprüfung: Der Modus `eid` übergibt an den
|
||||||
|
eID-Server/die AusweisApp; der Modus `demo` nutzt per `issue-card` ausgegebene,
|
||||||
|
autorisierte Test-Ausweise. Die Funktion `sync-keys` ist der Anschlusspunkt für
|
||||||
|
eine eigene Trust-Liste bzw. eID-Server-Anbindung – kein Zugriff auf ein
|
||||||
|
Behördenregister.
|
||||||
|
|
||||||
|
### 5.4 Grenzen und Missbrauchsszenarien
|
||||||
|
|
||||||
|
- **Karte ≠ Person am Gerät:** Wie bei jeder eID-Nutzung kann eine Person freiwillig
|
||||||
|
ihre Karte + PIN einer anderen überlassen. Das ist rechtswidrig, skaliert aber
|
||||||
|
schlecht (physische Karte nötig) — genau dadurch werden Bot-Netze und
|
||||||
|
Massen-Manipulation wirksam verhindert.
|
||||||
|
- **Verlorene/gesperrte Ausweise** fallen über die Sperrlistenprüfung des eID-Servers
|
||||||
|
heraus.
|
||||||
|
- **Alters-/Staatsangehörigkeitsfragen:** Die eID steht auch Unionsbürgern (eAT,
|
||||||
|
eID-Karte) offen; ob deren Teilnahme gewünscht ist, ist eine politische
|
||||||
|
Konfigurationsentscheidung (Berechtigungszertifikat kann die Kartentypen
|
||||||
|
einschränken). Der Prototyp behandelt alle Karten gleich.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Funktionen im Einzelnen
|
||||||
|
|
||||||
|
### 6.1 Themen einbringen — „1 Thema pro Tag“
|
||||||
|
|
||||||
|
- Jedes Pseudonym kann **ein Thema pro Kalendertag** (Zeitzone Europe/Berlin)
|
||||||
|
erstellen; um **00:00 Uhr** beginnt der nächste Tag. Die Regel ist zusätzlich zur
|
||||||
|
Anwendungslogik als **Datenbank-Constraint** verankert (UNIQUE über Autor +
|
||||||
|
Erstelldatum) — sie kann also auch durch Programmierfehler nicht umgangen werden.
|
||||||
|
- Pflichtfelder beim Erstellen:
|
||||||
|
- **Titel** (kurz, prägnant),
|
||||||
|
- **Ziel** — was soll konkret erreicht werden?
|
||||||
|
- **Begründung** — warum?
|
||||||
|
- **Kategorie** (siehe 6.3),
|
||||||
|
- **Geltungsbereich** — eine hierarchische **Auswahl statt Freitext**,
|
||||||
|
wie auf Behördenseiten: Deutschland → Bundesland → Landkreis/kreisfreie
|
||||||
|
Stadt (eingebaute Gebietsliste mit allen 16 Ländern und rund 400
|
||||||
|
Kreisen; die Gemeindeebene folgt in der Ausbaustufe über das amtliche
|
||||||
|
Gemeindeverzeichnis, ARS/Destatis).
|
||||||
|
- **Themen sind nach Veröffentlichung unveränderlich.** Es gibt keinen
|
||||||
|
Bearbeiten-Weg — weder in der Oberfläche noch als Route. Damit ist die stille
|
||||||
|
Umdeutung einer laufenden Abstimmung ausgeschlossen: Woran abgestimmt wurde,
|
||||||
|
steht fest. Wer sich vertan hat, archiviert das Thema (solange noch keine
|
||||||
|
Stimme abgegeben ist) und bringt es neu ein. Eine spätere Ausbaustufe könnte
|
||||||
|
Korrekturen mit sichtbarer Versionsanzeige erlauben.
|
||||||
|
|
||||||
|
### 6.2 Abstimmen
|
||||||
|
|
||||||
|
- Pro Thema und Ausweis genau eine Stimme: **dafür** oder **dagegen**.
|
||||||
|
- **Neutral = nicht abstimmen.** Enthaltung wird nicht als eigene Stimmart gezählt.
|
||||||
|
- Die eigene Stimme ist **24 Stunden lang** änderbar oder zurückziehbar; danach
|
||||||
|
ist sie fest (auf der Hauptseite als eigene Gruppe „kürzlich abgestimmt,
|
||||||
|
noch änderbar“ sichtbar).
|
||||||
|
- **Stimmen sind unverkettbar gespeichert:** In der Datenbank steht kein
|
||||||
|
Ausweis-Bezug, sondern nur ein HMAC aus Thema + öffentlichem Schlüssel mit
|
||||||
|
serverseitigem Geheimnis. Doppelstimmen sind ausgeschlossen, doch ohne das
|
||||||
|
Geheimnis lässt sich nicht rückschließen, welcher Ausweis wie gestimmt hat.
|
||||||
|
- **Abstimmungsende je Thema — Datum, Zielwert oder beides:** Beim Einbringen
|
||||||
|
sind zwei Bedingungen ankreuzbar: ein **Enddatum** und ein **Zielwert**
|
||||||
|
(Einheit „X Stimmen“ für eine feste Zahl oder „% Stimmen“ für einen Anteil
|
||||||
|
der registrierten Ausweise).
|
||||||
|
Gesetzt werden darf eine von beiden **oder beide zugleich** — dann endet die
|
||||||
|
Abstimmung, **was zuerst eintritt**. Prozentangaben werden beim Anlegen in
|
||||||
|
eine absolute Zahl umgerechnet, damit das Ziel im Verlauf nicht mit der
|
||||||
|
Nutzerzahl wandert. Für **jeden** Zielwert gilt zusätzlich eine Untergrenze
|
||||||
|
von 10 Stimmen — auch ein ausdrücklich kleinerer Wert wird stillschweigend
|
||||||
|
darauf angehoben. Danach ist das Thema beendet.
|
||||||
|
- **Themen werden nie gelöscht.** Es gibt keinen Löschweg für Verfasser. Ein
|
||||||
|
Thema, zu dem **noch niemand abgestimmt** hat, lässt sich **archivieren**:
|
||||||
|
Es verschwindet aus Listen, Suche und Ähnlichkeitsabgleich, ist nicht mehr
|
||||||
|
wählbar und nicht mehr meldbar, bleibt aber unter
|
||||||
|
seiner Adresse erhalten und trägt dort die Kennzeichnung „Archiviert“.
|
||||||
|
- **Abgestimmte Themen bleiben unverändert bestehen.** Sobald die erste Stimme
|
||||||
|
abgegeben ist, entfällt auch das Archivieren — der Knopf ist dann schlicht
|
||||||
|
nicht mehr da. Damit bleibt jedes Thema, über das abgestimmt wurde, dauerhaft
|
||||||
|
nachvollziehbar. (Davon unberührt ist die Entfernung durch eine Bürger-Jury
|
||||||
|
nach festgestelltem Gesetzesverstoß, Kapitel 7.)
|
||||||
|
- **Gleiche Titel sind erlaubt, aber sichtbar.** Beim Einbringen zeigt das
|
||||||
|
Formular schon während des Tippens, ob es bereits ähnliche Themen gibt, und
|
||||||
|
verlinkt sie; einbringen lässt sich das Thema trotzdem. Auf der Themenseite
|
||||||
|
steht dieselbe Liste unter „Ähnliche Themen“. Der Abgleich vergleicht die
|
||||||
|
bedeutungstragenden Wörter des Titels, nicht die Zeichenkette.
|
||||||
|
- **Ergebnisse aktualisieren sich ohne Neuladen.** Ein schlanker JSON-Endpunkt
|
||||||
|
liefert Stimmenstände; Liste und Themenseite schreiben Balken, Zahlen und
|
||||||
|
Anteile im Hintergrund fort (alle zwölf Sekunden und beim Zurückkehren auf
|
||||||
|
den Tab). Ohne JavaScript bleibt der beim Aufruf gerenderte Stand stehen —
|
||||||
|
die Seite funktioniert weiterhin vollständig.
|
||||||
|
- Die Darstellung ist überall dieselbe und bewusst knapp: ein Balken, darunter
|
||||||
|
„Dafür n / x %“ und „Dagegen n / y %“ — in der Liste als Haarlinie, auf der
|
||||||
|
Themenseite kräftiger.
|
||||||
|
- **Drei Symbole oben rechts am Thema**, auf einer Höhe mit den Schildern für
|
||||||
|
Kategorie und Gebiet: ein **Lesezeichen** zum Merken (Thema, Kategorie,
|
||||||
|
Gebiet), eine **Archivbox** für den Verfasser eines Themas ohne Stimmen und
|
||||||
|
eine **rote Flagge** zum Melden. Die Flagge fehlt beim eigenen Thema und bei
|
||||||
|
beendeten Abstimmungen; läuft bereits eine Meldung, steht sie unterlegt und
|
||||||
|
ohne Funktion da. Beschriftungen tragen die Symbole nur als `title` und
|
||||||
|
`aria-label`.
|
||||||
|
- **Auf der Themenseite steht der eigene Stand in den Knöpfen, nicht in einem
|
||||||
|
Satz.** Dort gibt es keinen erklärenden Text zur eigenen Stimme; ihr Zustand
|
||||||
|
ist an den beiden Knöpfen ablesbar: beide grau, solange nicht gewählt wurde; die gewählte Seite
|
||||||
|
blau, solange sie sich noch ändern lässt; nach Ablauf der 24 Stunden und bei
|
||||||
|
beendeter Abstimmung die gewählte Seite blass-blau, die andere abgedunkelt,
|
||||||
|
beide nicht mehr bedienbar. Serverseitig wird eine dann noch abgesetzte
|
||||||
|
Stimme unabhängig davon abgewiesen. In der **Themenliste** und in der Gruppe
|
||||||
|
„kürzlich abgestimmt“ steht die eigene Stimme dagegen weiterhin als Text
|
||||||
|
(„Ihre Stimme: Dafür“, dort mit Frist) — Knöpfe, an denen man sie ablesen
|
||||||
|
könnte, gibt es dort nicht.
|
||||||
|
|
||||||
|
### 6.3 Kategorien — Neutralität durch Breite, keine vorbefüllten Themen
|
||||||
|
|
||||||
|
Damit die Plattform von Beginn an nicht als politisch gefärbt wahrgenommen wird,
|
||||||
|
gilt das **Breitenprinzip auf Kategorien-Ebene**: Zum Start existieren
|
||||||
|
ausschließlich die Kategorien — bewusst viele, quer über das gesamte politische
|
||||||
|
Spektrum. **Themen werden nicht vorbefüllt**; jeder einzelne Inhalt der
|
||||||
|
Plattform stammt aus der Bürgerschaft. So kann keine Startauswahl als
|
||||||
|
redaktionelle oder politische Setzung gelesen werden.
|
||||||
|
|
||||||
|
Kategorien (Start-Satz, erweiterbar):
|
||||||
|
|
||||||
|
Umwelt & Klima · Energie · Wirtschaft & Mittelstand · Arbeit & Soziales · Rente &
|
||||||
|
Alterssicherung · Gesundheit & Pflege · Bildung & Forschung · Familie & Jugend ·
|
||||||
|
Migration & Integration · Innere Sicherheit · Justiz & Bürgerrechte · Digitales &
|
||||||
|
Verwaltung · Verkehr & Infrastruktur · Wohnen & Mieten · Landwirtschaft & Ernährung ·
|
||||||
|
Finanzen & Steuern · Europa & Außenpolitik · Verteidigung · Kultur, Medien & Sport ·
|
||||||
|
Verbraucherschutz · Kommunales & Ehrenamt · Demokratie & Beteiligung
|
||||||
|
|
||||||
|
### 6.4 Merkzettel und eigener Stand
|
||||||
|
|
||||||
|
- **Einzelne Themen, Kategorien und Gebiete lassen sich merken**: Am Thema
|
||||||
|
steht dafür ein **Lesezeichen-Symbol**, das ein kleines Auswahlfeld mit drei
|
||||||
|
Einträgen öffnet — dieses Thema, seine Kategorie, sein Gebiet. Gemerktes ist
|
||||||
|
im Feld hervorgehoben und wird durch erneutes Antippen wieder entfernt.
|
||||||
|
Gemerkte Themen führen direkt zurück zum Thema, gemerkte Kategorien und
|
||||||
|
Gebiete filtern die Themenliste; alles ist am Schlüssel gespeichert und steht
|
||||||
|
auf jedem Gerät bereit.
|
||||||
|
- **Alles auf einer Seite.** Es gibt keine getrennte Unterseite „Meine
|
||||||
|
Übersicht“ mehr; `/me` und `/topics` führen auf dieselbe Hauptseite. Dort
|
||||||
|
stehen übereinander: Merkzettel-Chips, die Gruppe „kürzlich abgestimmt (noch
|
||||||
|
änderbar)“ mit der eigenen Stimme und der Frist, und die Themenliste. Eine
|
||||||
|
anstehende Jury-Aufgabe wird über einen Hinweis in der Kopfzeile und eine
|
||||||
|
Weiterleitung auf `/jury` erzwungen.
|
||||||
|
- Der vollständige eigene Stand — Stimmen, eingebrachte Themen, Merkzettel,
|
||||||
|
Meldungen, Jury-Zuteilungen — wird zusätzlich als **profil.yaml** ausgeliefert
|
||||||
|
(Kapitel 5.3), verschlüsselt an den eigenen Ausweis-Schlüssel.
|
||||||
|
|
||||||
|
### 6.5 Sprache
|
||||||
|
|
||||||
|
Deutsch ist Standard; Englisch vollwertig verfügbar. Die Wahl wird in der Sitzung
|
||||||
|
und — bei angemeldeten Nutzern — **am Pseudonym** gespeichert.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Meldung rechtswidriger Inhalte und Bürger-Jury
|
||||||
|
|
||||||
|
### 7.1 Grundsatz: Recht statt Richtung
|
||||||
|
|
||||||
|
Gemeldet werden können **mutmaßlich rechtswidrige Inhalte** — nicht politische
|
||||||
|
Meinungen. Zur Einordnung, weil danach oft gefragt wird: Auch extreme politische
|
||||||
|
Auffassungen sind in Deutschland **nicht als solche strafbar**; die
|
||||||
|
Meinungsfreiheit (Art. 5 GG) schützt auch scharfe und radikale Positionen. Strafbar
|
||||||
|
sind konkrete Delikte — und nur an diesen wird gemessen.
|
||||||
|
|
||||||
|
Eine Meldung besteht deshalb aus genau **einem Grund: dem Verstoß gegen ein
|
||||||
|
Gesetz**. Es gibt **keinen Auffangtatbestand** und **keinen Freitext** — es
|
||||||
|
wird ausschließlich am zitierten Gesetz bewertet. Beim Melden führt ein Suchfeld
|
||||||
|
(Schlagwort oder Paragraphennummer) zum eingebauten Register; der gewählte
|
||||||
|
Paragraph wird **wortgleich (1:1) zitiert** und der Jury unverändert vorgelegt.
|
||||||
|
|
||||||
|
Das Register umfasst im Prototyp **neun Tatbestände** des Strafgesetzbuchs:
|
||||||
|
|
||||||
|
| Norm | Tatbestand |
|
||||||
|
|---|---|
|
||||||
|
| § 130 Abs. 1 StGB | Volksverhetzung |
|
||||||
|
| § 86a Abs. 1 StGB | Verwenden von Kennzeichen verfassungswidriger und terroristischer Organisationen |
|
||||||
|
| § 111 Abs. 1 StGB | Öffentliche Aufforderung zu Straftaten |
|
||||||
|
| § 185 StGB | Beleidigung |
|
||||||
|
| § 186 StGB | Üble Nachrede |
|
||||||
|
| § 187 StGB | Verleumdung |
|
||||||
|
| § 240 Abs. 1 StGB | Nötigung |
|
||||||
|
| § 241 Abs. 1 StGB | Bedrohung |
|
||||||
|
| § 126a Abs. 1 StGB | Gefährdendes Verbreiten personenbezogener Daten |
|
||||||
|
|
||||||
|
Das Register ist erweiterbar; die hinterlegten Volltexte sind vor einem
|
||||||
|
Echtbetrieb wortgleich gegen gesetze-im-internet.de abzugleichen.
|
||||||
|
|
||||||
|
### 7.2 Bürger-Jury statt Redaktionsmoderation
|
||||||
|
|
||||||
|
Über die Meldung entscheidet keine Redaktion, sondern eine **zufällig geloste Jury
|
||||||
|
aus der Nutzerschaft** — das Losverfahren (wie beim Schöffenamt) macht gezielte
|
||||||
|
Beeinflussung praktisch unmöglich.
|
||||||
|
|
||||||
|
**Auswahl:**
|
||||||
|
|
||||||
|
- **1 % aller bereits auf der Plattform verwendeten Ausweis-Pseudonyme** wird per
|
||||||
|
kryptographisch sicherem Zufall (CSPRNG) gezogen. Die Mindestgröße
|
||||||
|
(Standard: 5) ist ein **Zielwert, keine Untergrenze**: Sind weniger geeignete
|
||||||
|
Personen verfügbar, besteht die Jury eben aus weniger — notfalls aus zweien.
|
||||||
|
Ebenso kann das Quorum unter den Standardwert 3 fallen, weil es auf die
|
||||||
|
tatsächliche Jurygröße gedeckelt wird. Bei kleiner Nutzerschaft entscheiden
|
||||||
|
also sehr wenige; das ist eine bewusste Abwägung zugunsten der
|
||||||
|
Funktionsfähigkeit und vor einem Echtbetrieb zu überdenken.
|
||||||
|
- **Ausgeschlossen** sind: Pseudonyme, die bereits einer **laufenden** Meldung als
|
||||||
|
Jury zugeteilt sind; die meldende Person; die Autorin/der Autor des gemeldeten
|
||||||
|
Themas; sowie Pseudonyme in der **Karenzzeit** — wer eine abgeschlossene
|
||||||
|
Jury-Runde hinter sich hat, ist erst **nach 3 Tagen** wieder losbar.
|
||||||
|
|
||||||
|
**Ablauf und Fristen (alle Zeiten Europe/Berlin):**
|
||||||
|
|
||||||
|
1. Meldung wird erstellt → Jury wird sofort gelost, die Abstimmung **startet zur
|
||||||
|
nächsten Mitternacht (00:00)**.
|
||||||
|
2. Ab Start läuft die reguläre Abstimmungsfrist von **24 Stunden**.
|
||||||
|
3. Nach Ablauf der 24 Stunden wird entschieden, **sofern mindestens 0,5 %** (bezogen
|
||||||
|
auf die Nutzerschaft, d. h. die Hälfte der Jury; Mindestquorum konfigurierbar)
|
||||||
|
ihre Stimme abgegeben haben.
|
||||||
|
4. Ist das Quorum nicht erreicht, **läuft die Meldung weiter**, bis es erreicht ist;
|
||||||
|
dann wird unmittelbar entschieden.
|
||||||
|
|
||||||
|
**Stimmoptionen der Jury:** *bestätigen* (Inhalt verstößt), *ablehnen* (kein
|
||||||
|
Verstoß), *Enthaltung* (zählt für das Quorum, nicht für die Mehrheit).
|
||||||
|
**Entscheidung:** einfache Mehrheit bestätigen > ablehnen → Inhalt wird entfernt
|
||||||
|
(Platzhalterseite „nach Gemeinschaftsprüfung entfernt“); sonst bleibt er stehen.
|
||||||
|
Bei Gleichstand bleibt der Inhalt stehen (im Zweifel für die Meinungsfreiheit).
|
||||||
|
|
||||||
|
**Mitwirkungspflicht:** Wer ausgelost wurde und noch nicht abgestimmt hat, wird beim
|
||||||
|
**nächsten Anhalten des Ausweises** (Sitzungsbeginn) zuerst zur Jury-Entscheidung
|
||||||
|
geführt und kann die übrigen Funktionen erst danach nutzen — oder wartet, bis die
|
||||||
|
Meldung abgeschlossen ist. Enthaltung ist ausdrücklich zulässig; niemand wird zu
|
||||||
|
einem inhaltlichen Urteil gezwungen.
|
||||||
|
|
||||||
|
**Schutz vor Melde-Missbrauch:** je Pseudonym maximal 3 Meldungen pro Tag; je Thema
|
||||||
|
höchstens **eine offene** Meldung (weitere Meldungen desselben Themas werden auf die
|
||||||
|
laufende Prüfung verwiesen); dasselbe Pseudonym kann dasselbe Thema nur einmal
|
||||||
|
melden. Alle Grenzwerte sind serverseitig durchgesetzt.
|
||||||
|
|
||||||
|
### 7.3 Grenzen des Verfahrens
|
||||||
|
|
||||||
|
Die Bürger-Jury ist eine **Plattform-Moderation**, kein Strafverfahren. Offenkundig
|
||||||
|
strafbare Inhalte können unabhängig vom Juryergebnis zusätzlich den
|
||||||
|
Strafverfolgungsbehörden gemeldet werden; gesetzliche Melde- und Löschpflichten
|
||||||
|
(insb. **Digital Services Act**, ggf. NetzDG-Nachfolgeregeln) gelten neben dem
|
||||||
|
Juryverfahren und erfordern im Echtbetrieb einen benannten Zustellungsbevollmächtigten
|
||||||
|
und Meldewege für Behörden. Das ist im Betriebskonzept der Ausbaustufe zu verankern.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Sicherheitsarchitektur
|
||||||
|
|
||||||
|
Bürgerabstimmung wäre im Echtbetrieb ein **hochwertiges Angriffsziel** (politische
|
||||||
|
Stimmungsbilder, staatsnahe Wahrnehmung). Der Prototyp ist deshalb von Grund auf
|
||||||
|
konservativ gebaut: wenig Code, wenig Abhängigkeiten, restriktive Standardwerte.
|
||||||
|
|
||||||
|
### 8.1 Prinzipien
|
||||||
|
|
||||||
|
- **Datenminimierung als Verteidigung:** Was nicht gespeichert ist, kann nicht
|
||||||
|
gestohlen werden. Keine Namen, keine E-Mail-Adressen, keine Passwörter, keine
|
||||||
|
Klar-IP-Adressen in der Datenbank.
|
||||||
|
- **Keine fremden Laufzeit-Abhängigkeiten:** Der Prototyp nutzt ausschließlich
|
||||||
|
PHP-Bordmittel (kein Framework, kein Composer-Paket, kein CDN, keine externen
|
||||||
|
Fonts/Skripte). Das eliminiert Lieferketten-Risiken und macht den gesamten Code
|
||||||
|
in einem Durchgang auditierbar.
|
||||||
|
- **Sichere Standardwerte:** Testbanner an, Mock-eID nur explizit, restriktivste
|
||||||
|
HTTP-Header, alle Grenzwerte serverseitig.
|
||||||
|
- **Tiefenstaffelung:** Kernregeln (1 Thema/Tag, eine Stimme pro Thema, eine offene
|
||||||
|
Meldung pro Thema, ein Juror nur einmal je Meldung) sind zusätzlich zur
|
||||||
|
Anwendungslogik als **Datenbank-Constraints** erzwungen.
|
||||||
|
|
||||||
|
### 8.2 Maßnahmen im Code (Prototyp)
|
||||||
|
|
||||||
|
| Bereich | Maßnahme |
|
||||||
|
|---|---|
|
||||||
|
| SQL | Ausschließlich PDO-**Prepared Statements**, kein String-SQL mit Nutzerdaten |
|
||||||
|
| XSS | Konsequentes Output-Escaping (`htmlspecialchars`, ENT_QUOTES) in allen Templates; CSS und JavaScript werden als eigene Routen ausgeliefert. Ausnahmen ohne CSP-Bezug: das Icon-SVG trägt einen eigenen `<style>`-Block, die beiden Notfallseiten vor dem Start nutzen Inline-Styles |
|
||||||
|
| CSP | `default-src 'none'` + explizite Freigaben nur für eigene Skripte/Styles/Bilder; `frame-ancestors 'none'`, `base-uri 'none'`, `form-action 'self'` |
|
||||||
|
| Clickjacking | `X-Frame-Options: DENY` + CSP frame-ancestors |
|
||||||
|
| Weitere Header | `X-Content-Type-Options: nosniff`, `Referrer-Policy: no-referrer`, restriktive `Permissions-Policy`, COOP/CORP; HSTS im HTTPS-Betrieb |
|
||||||
|
| CSRF/Replay | **Einmal-Token** auf jedem POST-Formular: beim Einlösen verbraucht — jede Aktion ist genau einmal gültig |
|
||||||
|
| Sessions | HttpOnly, SameSite, Secure (bei HTTPS), ID-Rotation bei An-/Abmeldung, Inaktivitäts- (30 min) und absolutes Timeout (8 h) — wichtig für öffentliche Terminals |
|
||||||
|
| Identität | Der öffentliche Ausweis-Schlüssel selbst ist die Kennung — kein abgeleitetes Pseudonym. Das Server-Geheimnis (`data/secret.key`, 0600) wird beim ersten Start erzeugt und nur für die Stimmen-Marker und die Ratenbegrenzung verwendet |
|
||||||
|
| Zufall | Jury-Losverfahren mit CSPRNG (`random_int`, Fisher-Yates), nicht mit SQL-`RANDOM()` |
|
||||||
|
| Rate-Limits | Serverseitig je Pseudonym bzw. gehashter IP: Anmeldeversuche, Stimmen, Meldungen, Formular-POSTs |
|
||||||
|
| Eingaben | Whitelist-Validierung (Enums, Längen, UTF-8-Prüfung, Kontrollzeichen-Filter); keine Datei-Uploads |
|
||||||
|
| Fehlerbilder | Keine Stacktraces oder Pfade nach außen; generische Fehlerseiten; Sicherheitsereignisse werden ohne personenbezogene Daten protokolliert |
|
||||||
|
| Struktur | Eine Datei im Webroot; Datenbank, Geheimnisse und Logs liegen in `data/` **innerhalb** des Webroots und sind über eine eigene `.htaccess` sowie eine 404-Regel in der Anwendung gesperrt. Ein Verzeichnis außerhalb des Webroots wäre stärker und ist für den Echtbetrieb zu empfehlen |
|
||||||
|
| Betrieb | Selbsttest (`php index.php selftest`, 122 Prüfungen) deckt die Kernregeln automatisiert ab: Tagesgrenze, Abstimmungsende, Jury-Ausschlüsse, Quorum, Fristen, Karenz, Freigabeliste, Dauerhaftigkeit abgestimmter Themen, Archivierung, Ähnlichkeitssuche, Einrichtung des Echtbetriebs, Sprachtabellen |
|
||||||
|
|
||||||
|
### 8.3 Bedrohungsmodell (Auszug)
|
||||||
|
|
||||||
|
| Bedrohung | Antwort |
|
||||||
|
|---|---|
|
||||||
|
| Bot-/Sockenpuppen-Armeen | eID: eine physische Karte = ein Konto; ohne Karte keine Stimme |
|
||||||
|
| Stimmenkauf/-zwang im großen Stil | Physische Karte + PIN nötig; skaliert schlecht; rechtlich sanktioniert |
|
||||||
|
| Manipulation der Jury-Auswahl | CSPRNG-Losung serverseitig; Ausschlusslisten; keine Selbstmeldung zur Jury möglich |
|
||||||
|
| Melde-Spam zur Zensur | Tageslimit, eine offene Meldung je Thema, Quorum + Mehrheit nötig, Gleichstand erhält Inhalt |
|
||||||
|
| SQL-Injection / XSS / CSRF | Siehe 8.2 — durchgängig parametrisiert, escaped, tokenisiert |
|
||||||
|
| Session-Diebstahl am Terminal | Kurze Timeouts, Abmelde-Knopf, HttpOnly-Cookies. Im Browser liegt außer dem Sitzungs-Cookie nur die `profil.yaml` im `sessionStorage`; „Abmelden“ löscht sie |
|
||||||
|
| Datenbank-Diebstahl | Enthält öffentliche Ausweis-Schlüssel, Themen und Stimmen — keine Klaridentitäten. Die Stimmen sind ohne das Server-Geheimnis nicht zuordenbar; wer Datenbank **und** `secret.key` erbeutet, kann die Zuordnung berechnen |
|
||||||
|
| Lieferkette (Pakete/CDN) | Keine externen Abhängigkeiten im Prototyp |
|
||||||
|
| DDoS / Lastspitzen | Ausbaustufe: CDN/Anycast vor statischen Assets, horizontale Skalierung, siehe 10.3 |
|
||||||
|
|
||||||
|
### 8.4 Echtbetrieb zusätzlich (Pflichtprogramm)
|
||||||
|
|
||||||
|
TLS ausschließlich (HSTS + Preload), getrennte Umgebungen, Härtung nach
|
||||||
|
BSI-IT-Grundschutz, externe Penetrationstests **vor** Start, laufendes
|
||||||
|
Schwachstellen-Management + Bug-Bounty, signierte Deployments, Backups mit
|
||||||
|
Wiederanlaufübungen, 24/7-Monitoring, DDoS-Schutz, und ein unabhängiges
|
||||||
|
Sicherheits-Audit des Jury-Losverfahrens (nachvollziehbare, aber nicht
|
||||||
|
vorhersagbare Ziehung — z. B. via veröffentlichtem Ziehungs-Commitment).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Datenschutz (DSGVO)
|
||||||
|
|
||||||
|
- **Datenminimierung:** gespeichert werden nur: der öffentliche Ausweis-Schlüssel
|
||||||
|
als Kennung, Zeitstempel, eigene Themen, Merkzettel, Meldungen und
|
||||||
|
Jury-Zuteilungen. Stimmen liegen **ohne Bezug zum Ausweis** (HMAC-Marker).
|
||||||
|
Die gewählte **Sprache wird nicht gespeichert** — sie gilt nur für die
|
||||||
|
laufende Sitzung; die Spalte in der Kontozeile trägt lediglich den Standardwert
|
||||||
|
aus der Anlage. Keine Klaridentität, keine IP-Adressen im Klartext (nur
|
||||||
|
kurzlebige Hashes für Rate-Limits), keine Tracker, keine Cookies außer dem
|
||||||
|
Sitzungs-Cookie.
|
||||||
|
- **Rechtsgrundlage** (Echtbetrieb): Art. 6 Abs. 1 lit. a/e DSGVO je nach
|
||||||
|
Trägerschaft; eID-Nutzung nach eIDAS/PAuswG mit Berechtigungszertifikat.
|
||||||
|
- **Betroffenenrechte — Stand im Prototyp, ehrlich:** Die *Auskunft* ist
|
||||||
|
umgesetzt: die **profil.yaml** enthält den vollständigen eigenen Stand, an den
|
||||||
|
eigenen Ausweis-Schlüssel verschlüsselt. Sie wird allerdings **nur per
|
||||||
|
JavaScript** abgerufen — ohne JavaScript gibt es keine Selbstauskunft.
|
||||||
|
Die *Löschung* ist als Routine vorhanden und automatisiert geprüft
|
||||||
|
(`account_delete` löscht die Kontozeile, wodurch Merkzettel, Meldungen und
|
||||||
|
Jury-Sitze per Fremdschlüssel mit entfernt werden, und hängt eingebrachte
|
||||||
|
Themen an ein System-Konto um; **abgegebene Stimmen bleiben erhalten**, weil
|
||||||
|
sie keinen Bezug zum Ausweis tragen und nach dem Löschen niemandem mehr
|
||||||
|
zuzuordnen sind). Sie hat in dieser Fassung **keine Schaltfläche** in der
|
||||||
|
Oberfläche — der Löschbereich wurde entfernt. **Vor einem Echtbetrieb ist
|
||||||
|
dafür zwingend ein Weg in der Oberfläche zu ergänzen**, sonst ist Art. 17
|
||||||
|
DSGVO nicht erfüllt.
|
||||||
|
- **Speicherbegrenzung:** Rate-Limit-Einträge verfallen automatisch;
|
||||||
|
Sicherheitslogs ohne Personenbezug.
|
||||||
|
- Für den Echtbetrieb: Datenschutz-Folgenabschätzung (Art. 35 DSGVO) zwingend,
|
||||||
|
benannte(r) DSB, Verzeichnis von Verarbeitungstätigkeiten.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Technik
|
||||||
|
|
||||||
|
### 10.1 Prototyp-Stack
|
||||||
|
|
||||||
|
- **PHP ≥ 8.0** (strict types, harte Versionssperre beim Start), keine externen Pakete.
|
||||||
|
- **SQLite** (WAL-Modus) als Prototyp-Datenbank — eine Datei, einfach zu prüfen;
|
||||||
|
die Datenzugriffsschicht ist so geschrieben, dass PostgreSQL in der Ausbaustufe
|
||||||
|
ein Austausch der Verbindung ist.
|
||||||
|
- **Server-gerendertes HTML**, genau eine CSS- und eine JS-Datei, dazu das
|
||||||
|
Icon — alles aus derselben Datei ausgeliefert. Hell/Dunkel ist reines CSS,
|
||||||
|
dafür gibt es kein Skript.
|
||||||
|
- Betrieb hinter Apache/nginx mit gesperrtem `data/` oder für Demos mit
|
||||||
|
dem eingebauten PHP-Server.
|
||||||
|
|
||||||
|
### 10.2 Hintergrundläufe
|
||||||
|
|
||||||
|
Zustandswechsel (Meldung „wartet“ → „läuft“ um 00:00, Entscheidung nach 24 h +
|
||||||
|
Quorum, Karenzzeiten) verarbeitet ein idempotenter **Maintenance-Tick**: er läuft
|
||||||
|
per Cron (`php index.php cron`) **und** zusätzlich beiläufig bei Seitenaufrufen (auf 30 Sekunden gedrosselt),
|
||||||
|
sodass der Prototyp auch ohne Cron korrekt bleibt.
|
||||||
|
|
||||||
|
### 10.3 Skalierungspfad
|
||||||
|
|
||||||
|
PostgreSQL + Read-Replicas → zustandslose PHP-Knoten hinter Load-Balancer →
|
||||||
|
CDN für Assets → Warteschlange für Jury-Benachrichtigungen → mandantenfähige
|
||||||
|
Gebietsdaten (amtliche Gemeindeschlüssel AGS/ARS statt Freitext-Gebieten).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Parameter (konfigurierbar)
|
||||||
|
|
||||||
|
| Parameter | Standard | Bedeutung |
|
||||||
|
|---|---|---|
|
||||||
|
| `show_test_banner` | **true** | Testbetrieb-Banner auf jeder Seite |
|
||||||
|
| `eid_mode` | `demo` | `demo` (ausgegebene Test-Ausweise) oder `eid` (nur Ausweis-Apps) |
|
||||||
|
| `eid_client_url` | `http://127.0.0.1:24727/eID-Client` | Aktivierungsadresse des eID-Clients (TR-03124) |
|
||||||
|
| `eid_server_url` | leer | SOAP-Endpunkt des eigenen eID-Servers (TR-03130); leer = fail-closed |
|
||||||
|
| `data/config.yaml` | fehlt | von der Einrichtungsseite geschriebene Überlagerung der Vorgaben |
|
||||||
|
| `default_lang` | `de` | Standardsprache |
|
||||||
|
| `jury_share` | 1 % | Anteil der Nutzerschaft je Jury |
|
||||||
|
| `jury_min` | 5 | Mindest-Jurygröße |
|
||||||
|
| `quorum_share` | 0,5 % | Quorum als Anteil der Nutzerschaft |
|
||||||
|
| `quorum_min` | 3 | Mindest-Quorum |
|
||||||
|
| `report_vote_hours` | 24 | Reguläre Jury-Abstimmungsdauer |
|
||||||
|
| `jury_cooldown_days` | 3 | Karenz nach abgeschlossener Jury-Runde |
|
||||||
|
| `reports_per_day` | 3 | Meldungen je Pseudonym und Tag |
|
||||||
|
| `timezone` | Europe/Berlin | Bezugszeitzone aller Tagesgrenzen |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Roadmap
|
||||||
|
|
||||||
|
1. **Prototyp (dieses Repository):** vollständige Fachlogik mit Mock-eID,
|
||||||
|
Zwei-Sprachen-UI, Jury-Verfahren, Selbsttests.
|
||||||
|
2. **Pilot:** Anbindung echter eID-Server (Berechtigungszertifikat, AusweisApp-Flow),
|
||||||
|
externes Sicherheits-Audit + Pentest, DSFA, Barrierefreiheit nach BITV,
|
||||||
|
PostgreSQL.
|
||||||
|
3. **Kommunal-Pilotgemeinden:** Terminals in Bürgerbüros, amtliche Gebietsschlüssel,
|
||||||
|
Auswertungs-Exporte für Räte und Verwaltungen.
|
||||||
|
4. **Ausbau:** Delegations-/Sachverständigen-Funktionen, strukturierte
|
||||||
|
Ergebnisberichte an Parlamente, offene Schnittstellen (Open Data) mit
|
||||||
|
Differential-Privacy-Schutz kleiner Gebiete.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Offene Punkte
|
||||||
|
|
||||||
|
- Marken-/Domainrecherche „Bürgerabstimmung“ und finale Namensentscheidung.
|
||||||
|
- Trägerschaft und Finanzierung (Verein/Stiftung empfohlen: neutralitätssichernd).
|
||||||
|
- Rechtsgutachten: eID-Berechtigungsumfang, DSA-Pflichtenkatalog, Jugendliche
|
||||||
|
(Ausweispflicht ab 16 — Teilnahmealter ist Konfigurationsfrage).
|
||||||
|
- Verifizierbare Jury-Ziehung (öffentliches Commitment-Verfahren) — Konzept in 8.4
|
||||||
|
skizziert, Umsetzung in der Pilotphase.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Anhang: Installation und Betrieb
|
||||||
|
|
||||||
|
Der technische Prototyp ist **eine einzige Datei**. Es genügt ein Webserver
|
||||||
|
mit PHP — kein Framework, kein Paketmanager, keine externen Dienste.
|
||||||
|
|
||||||
|
1. `index.php` in das Webverzeichnis legen (Hauptverzeichnis oder Unterordner;
|
||||||
|
der Basispfad wird erkannt).
|
||||||
|
2. PHP **8.0 oder neuer** mit `pdo_sqlite`, `mbstring` und `sodium` — alle drei
|
||||||
|
gehören zur Standardausstattung.
|
||||||
|
3. Seite aufrufen. Beim ersten Aufruf legt die Datei selbst an: `data/`
|
||||||
|
(SQLite-Datenbank, Server-Geheimnis, Protokolle, Zugriffssperre),
|
||||||
|
`.htaccess` (saubere Adressen und Schutz interner Dateien) und `robots.txt`.
|
||||||
|
|
||||||
|
Meldet die Seite „Fast geschafft“, fehlen dem Verzeichnis Schreibrechte
|
||||||
|
(755/775 setzen, neu laden). Ohne `.htaccess`-Unterstützung — etwa unter nginx —
|
||||||
|
arbeitet die Anwendung über automatisch erzeugte `/index.php/…`-Adressen
|
||||||
|
weiter; eine gleichwertige `try_files`-Regel stellt die sauberen Adressen her.
|
||||||
|
Dort ist zusätzlich `/data/` zu sperren — die Anwendung selbst beantwortet
|
||||||
|
jede Anfrage auf diesen Pfad mit 404, ausgeliefert würde sie sonst am
|
||||||
|
PHP-Prozess vorbei.
|
||||||
|
|
||||||
|
Der Auslieferungszustand ist der **Testmodus** (Kapitel 5.3b): ein Knopf meldet
|
||||||
|
ohne Ausweis an, damit sich die Plattform vorführen lässt. Über den Chip
|
||||||
|
„Testmodus“ führt die Seite **„Echtbetrieb einrichten“** (Kapitel 5.3c) durch
|
||||||
|
Prüfung, Zugangswahl und Umschaltung; sie schreibt die Einstellungen nach
|
||||||
|
`data/config.yaml`, löscht alle Testdaten und aktiviert dauerhaft die strenge
|
||||||
|
Ausweisprüfung. Der dafür nötige Einrichtungsschlüssel steht in
|
||||||
|
`data/setup.token`.
|
||||||
|
|
||||||
|
Wartung und Prüfung laufen über dieselbe Datei auf der Kommandozeile:
|
||||||
|
|
||||||
|
| Aufruf | Zweck |
|
||||||
|
|---|---|
|
||||||
|
| `php index.php selftest` | 122 automatisierte Prüfungen der Fachregeln |
|
||||||
|
| `php index.php cron` | Wartungslauf (sonst beiläufig bei Seitenaufrufen) |
|
||||||
|
| `php index.php seed 400` | Demo-Stimmen, anonym wie im Echtbetrieb |
|
||||||
|
| `php index.php jurysim` | Demo-Jury stimmt in laufenden Prüfungen ab |
|
||||||
|
| `php index.php issue-card 3` | autorisierte Demo-Ausweise samt Abhol-Verweis |
|
||||||
|
| `php index.php sync-keys` | Freigabeliste aus der konfigurierten Trust-Liste |
|
||||||
|
| `php index.php setup-token` | Einrichtungsschlüssel für die Umschaltung anzeigen |
|
||||||
|
| `php index.php config` | wirksame Einstellungen aus `data/config.yaml` anzeigen |
|
||||||
|
| `php -S 127.0.0.1:8080 index.php` | lokale Vorführung ohne Webserver |
|
||||||
Reference in New Issue
Block a user