reclaim/app/lib/pages/legal_page.dart
flemming-it 214f909c1f feat(legal): add Recht page (disclaimer, AI Act, UrhG, GDPR, Impressum, OSS)
Recl∆Im now carries the six-section legal layer that any
public-facing duty-evaluation tool needs before either the
.app or the web build can go live to an audience beyond the
working group itself.

Sections, in the order a careful reader cares about them:

  1. Disclaimer — keine Rechtsberatung, RDG-konform geframed,
     T1–T4 Tier-Bedeutung explizit, Demo-Daten klar abgesetzt.
  2. EU AI Act Art. 50 — Transparenz-Notice, klare 'kein
     Hochrisiko-KI-System nach Anhang III'-Positionierung,
     Human-in-the-Loop via system.approval@^0, Modell-Digest
     im Audit-Log.
  3. Quellen + Urheberrecht — § 5 UrhG-Hinweis für die
     dargestellten amtlichen Werke, T1- und T2-Quellen-Liste,
     Apache 2.0 für eigenen Code und Methodik.
  4. Datenschutz — DSGVO Art. 13-Pflichtangaben, Hosting-
     Provider-Platzhalter, Server-Log-Rechtsgrundlage Art. 6
     Abs. 1 lit. f, Betroffenenrechte, Berliner
     Aufsichtsbehörde.
  5. Impressum — § 5 TMG + § 18 Abs. 2 MStV-Pflichtangaben
     als Vorlage, ODR-Plattform-Hinweis.
  6. Open Source — Apache 2.0, Repo-Link, Commit-Konvention.

Jede Section markiert deployment-spezifische Werte
(Anbieter-Adresse, Hosting-Provider, AVV-Stand,
Kontakt-E-Mail) als [PLACEHOLDER] und der Schlussabsatz weist
ausdrücklich darauf hin, dass eine Volljuristen-Prüfung vor
der ersten öffentlichen Veröffentlichung pflichtig ist.

Plumbing

  - ShellPage gets a fifth NavigationRail-Destination 'Recht'
    mit gavel-Icon.
  - LegalPage scrollt mit ReclaimCard-Sektionen und nutzt
    SelectableText überall, damit Reviewer-Zitate direkt
    rauskopierbar sind.
  - DemoBanner erweitert um 'KEINE Rechtsberatung'-Hinweis und
    verweist auf den Recht-Reiter — der politische Disclaimer-
    Pfad ist damit aus jeder Datenseite einen Klick entfernt.

flutter analyze: clean. flutter test: 2/2 grün. Web- und
macOS-Build laufen, Recht-Reiter rendert auf beiden Targets
identisch.

Signed-off-by: flemming-it <sf@flemming.it>
2026-06-18 13:52:45 +02:00

334 lines
14 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

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

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import '../theme/reclaim_tokens.dart';
import '../widgets/reclaim_card.dart';
/// Combined legal-information page. Six sections in the order
/// a careful reader cares about them:
///
/// 1. Disclaimer (kein Rechtsrat) — top, most visible
/// 2. EU AI Act Art. 50 (Transparenz)
/// 3. Quellen + Urheberrecht (§ 5 UrhG)
/// 4. Datenschutz (DSGVO Art. 13)
/// 5. Impressum (§ 5 TMG, § 18 MStV)
/// 6. Open Source + Lizenz
///
/// Each section carries placeholder markers `[PLACEHOLDER]`
/// where the deployment-specific value (Anbieter-Adresse,
/// AVV-Stand, Hosting-Provider) must be filled in before any
/// public publication. The text is drafted conservatively;
/// review by einem Volljuristen bleibt obligatorisch vor der
/// ersten öffentlichen Veröffentlichung.
class LegalPage extends StatelessWidget {
const LegalPage({super.key});
@override
Widget build(BuildContext context) {
final t = Theme.of(context).textTheme;
return SingleChildScrollView(
padding: const EdgeInsets.all(ReclaimSpace.xl),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Recht & Hinweise', style: t.displaySmall),
const SizedBox(height: ReclaimSpace.xs),
Text(
'Disclaimer, AI-Act-Transparenz, Urheberrecht, '
'Datenschutz, Impressum, Lizenz.',
style: t.bodyLarge?.copyWith(color: ReclaimColors.mute),
),
const SizedBox(height: ReclaimSpace.lg),
// 1. Disclaimer
ReclaimCard(
accent: true,
child: _Section(
title: '1. Disclaimer — keine Rechtsberatung',
children: [
_p(t,
'Recl∆Im liefert eine methodisch-strukturierte '
'Wirkungsanalyse von Rechtsnormen. Die Ergebnisse sind '
'KEINE Rechtsberatung im Sinne des '
'Rechtsdienstleistungsgesetzes (RDG) und ersetzen weder '
'eine individuelle juristische Prüfung noch eine '
'Auskunft der zuständigen Behörden oder Kammern.'),
_p(t,
'Alle Bewertungs-Zahlen tragen eine Evidenz-Tier-Stufe '
'(T1T4). Stufen T3/T4 sind nicht peer-reviewed und '
'dienen ausschließlich als Hinweis-/Anregung-Wert. '
'Eine Reform- oder Streichungs-Empfehlung der '
'Anwendung ist ein methodischer Vorschlag, keine '
'politische Forderung.'),
_p(t,
'Die Demo-Daten (fünf Pilot-Normen) sind '
'Plausibilitäts-Schätzungen ohne NKR-Validierung. '
'Bevor eine Zahl in eine politische Vorlage übernommen '
'wird, ist die zugrundeliegende Quelle einzeln zu '
'prüfen.'),
],
),
),
const SizedBox(height: ReclaimSpace.lg),
// 2. AI Act
ReclaimCard(
child: _Section(
title:
'2. EU AI Act — Transparenz nach Art. 50',
children: [
_p(t,
'Recl∆Im setzt Künstliche-Intelligenz-Komponenten ein: '
'Large-Language-Modelle (LLM) zur Vorschlags-Extraktion '
'aus Norm-Texten und zur Synthese von Reform-Texten. '
'Jede LLM-erzeugte Aussage ist kennzeichnungspflichtig '
'und mit RAG-Quellen-Pflicht hinterlegt; Aussagen ohne '
'zitierfähige Quelle werden verworfen.'),
_p(t,
'Recl∆Im ist KEIN Hochrisiko-KI-System nach Anhang III '
'der KI-Verordnung. Die Anwendung trifft keine '
'Verwaltungsentscheidungen, generiert keine Rechtsakte, '
'beeinflusst nicht direkt Beschäftigungs-, Bildungs- '
'oder Sozialleistungs-Verfahren. Sie dient ausschließlich '
'der Recherche, Visualisierung und Vorschlags-Generierung '
'für menschliche Entscheidungsträger.'),
_p(t,
'Jede Bewertung durchläuft vor Veröffentlichung einen '
'`system.approval@^0`-Schritt (Human-in-the-Loop). '
'Die menschliche Letztverantwortung ist nicht '
'überschreibbar.'),
_p(t,
'Verwendete Modelle und ihre Digests werden im '
'tamper-evidenten Audit-Log des Ch∆In-Hubs gespeichert. '
'Reproduzierbarkeit erfolgt mit Temperature ≤ 0,1 und '
'festem Prompt-Hash.'),
],
),
),
const SizedBox(height: ReclaimSpace.lg),
// 3. Quellen + UrhG
ReclaimCard(
child: _Section(
title: '3. Quellen & Urheberrecht (§ 5 UrhG)',
children: [
_p(t,
'Die in der Anwendung dargestellten Gesetzes- und '
'Verordnungs-Texte sind amtliche Werke im Sinne des '
'§ 5 UrhG und damit gemeinfrei. Die kanonischen Quellen '
'sind verlinkt und durch SHA-256-Prüfsummen im '
'Audit-Log nachvollziehbar.'),
_p(t,
'Primärquellen (T1):'),
_bullet(t,
'Bundesrecht: gesetze-im-internet.de (BMJ) — § 5 UrhG.'),
_bullet(t,
'EU-Recht: EUR-Lex (Europäische Kommission) — '
'Mehrsprachigkeit nach Verordnung (EU) Nr. 1257/2012.'),
_bullet(t,
'Landesrecht Berlin: gesetze.berlin.de / '
'landesrecht-berlin.de — § 5 UrhG.'),
_p(t,
'Sekundärquellen (T1/T2):'),
_bullet(t,
'Nationaler Normenkontrollrat (NKR) — '
'Bürokratiekosten-Datenbank, Methodenleitfaden.'),
_bullet(t,
'Statistisches Bundesamt (DESTATIS) — '
'Unternehmensregister, Bürokratiekostenindex.'),
_bullet(t,
'DIHK, ZDH, IHK Berlin, BDI — '
'Verbands-Erhebungen mit Quellen-Angabe.'),
_p(t,
'Eigene Methodik und Software-Code sind unter '
'Apache License 2.0 veröffentlicht; Code-Repository: '
'git.flemming.ai/fai/reclaim.'),
],
),
),
const SizedBox(height: ReclaimSpace.lg),
// 4. Datenschutz
ReclaimCard(
child: _Section(
title:
'4. Datenschutzerklärung (DSGVO Art. 13)',
children: [
_p(t,
'Verantwortlicher i.S.d. Art. 4 Nr. 7 DSGVO: '
'[PLACEHOLDER — Name und Anschrift des Anbieters '
'einsetzen].'),
_p(t,
'Diese Anwendung verarbeitet personenbezogene Daten '
'nur in dem Umfang, der für ihren Betrieb erforderlich '
'ist. In der Demo-Konfiguration werden keine '
'personenbezogenen Daten erhoben; alle Pilot-Norm-Daten '
'sind lokal im Browser/auf dem Endgerät gespeichert.'),
_p(t, 'Beim Aufruf der Anwendung über das Internet:'),
_bullet(t,
'Hosting-Provider: [PLACEHOLDER — etwa Hetzner Online '
'GmbH, Falkenstein, EU-Hosting]. AVV nach Art. 28 '
'DSGVO abgeschlossen.'),
_bullet(t,
'Server-Logs (IP-Adresse, User-Agent, Zeitstempel): '
'für 7 Tage zur Missbrauchs-Abwehr (Rechtsgrundlage '
'Art. 6 Abs. 1 lit. f DSGVO, berechtigtes Interesse).'),
_bullet(t,
'Kein Tracking, keine Analytics, keine '
'Marketing-Cookies.'),
_p(t,
'Betroffenenrechte (Art. 1522 DSGVO): Auskunft, '
'Berichtigung, Löschung, Einschränkung, Datenübertragbarkeit, '
'Widerspruch. Kontakt: '
'[PLACEHOLDER — Kontakt-E-Mail].'),
_p(t,
'Beschwerderecht bei der Aufsichtsbehörde: '
'Berliner Beauftragte für Datenschutz und '
'Informationsfreiheit, Friedrichstr. 219, 10969 Berlin, '
'mailbox@datenschutz-berlin.de.'),
],
),
),
const SizedBox(height: ReclaimSpace.lg),
// 5. Impressum
ReclaimCard(
child: _Section(
title:
'5. Impressum (§ 5 TMG, § 18 Abs. 2 MStV)',
children: [
_p(t,
'Anbieter: [PLACEHOLDER — Name].'),
_p(t,
'Anschrift: [PLACEHOLDER — Straße, Hausnummer, '
'PLZ, Ort, Land].'),
_p(t,
'Kontakt: [PLACEHOLDER — E-Mail, ggf. Telefon].'),
_p(t,
'Vertretungsberechtigt: [PLACEHOLDER — bei Vereinen, '
'GmbHs etc.].'),
_p(t,
'Verantwortlich für den Inhalt nach § 18 Abs. 2 MStV: '
'[PLACEHOLDER — Name und ladungsfähige Anschrift, '
'in der Regel identisch mit Anbieter].'),
_p(t,
'Umsatzsteuer-Identifikationsnummer / Register-'
'eintrag, sofern einschlägig: [PLACEHOLDER].'),
_p(t,
'Plattform der Europäischen Kommission zur '
'außergerichtlichen Online-Streitbeilegung (Art. 14 '
'Abs. 1 ODR-VO): ec.europa.eu/consumers/odr. Wir sind '
'nicht bereit oder verpflichtet, an '
'Streitbeilegungsverfahren vor einer '
'Verbraucherschlichtungsstelle teilzunehmen.'),
],
),
),
const SizedBox(height: ReclaimSpace.lg),
// 6. Open Source
ReclaimCard(
child: _Section(
title: '6. Open Source & Lizenz',
children: [
_p(t,
'Recl∆Im ist freie Software, lizenziert unter der '
'Apache License, Version 2.0. Der Quelltext, die '
'Module und die Methodik sind öffentlich einsehbar '
'unter:'),
InkWell(
onTap: () => launchUrl(
Uri.parse('https://git.flemming.ai/fai/reclaim'),
mode: LaunchMode.externalApplication,
),
child: Text(
'https://git.flemming.ai/fai/reclaim',
style: t.bodyLarge?.copyWith(
color: ReclaimColors.signal,
decoration: TextDecoration.underline,
fontFamily: ReclaimTypography.mono,
),
),
),
const SizedBox(height: ReclaimSpace.sm),
_p(t,
'Plattform: Ch∆In (Apache 2.0, '
'git.flemming.ai/fai/chain-private). Methodische '
'Vorbilder und Lizenz-Hinweise stehen in der Datei '
'NOTICE im Repository.'),
_p(t,
'Beiträge willkommen. DCO Sign-off und Conventional '
'Commits in Englisch sind Konvention.'),
],
),
),
const SizedBox(height: ReclaimSpace.xxl),
Text(
'Hinweis: Vor der ersten öffentlichen Veröffentlichung '
'müssen alle [PLACEHOLDER]-Stellen durch konkrete '
'Anbieter-Angaben ersetzt und das gesamte Dokument von '
'einem Volljuristen geprüft werden. Diese Seite ist eine '
'methodische Vorlage.',
style: t.labelSmall?.copyWith(
color: ReclaimColors.tierT4,
fontStyle: FontStyle.italic,
),
),
],
),
);
}
}
class _Section extends StatelessWidget {
const _Section({required this.title, required this.children});
final String title;
final List<Widget> children;
@override
Widget build(BuildContext context) {
final t = Theme.of(context).textTheme;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: t.headlineSmall),
const SizedBox(height: ReclaimSpace.md),
...children,
],
);
}
}
Widget _p(TextTheme t, String s) => Padding(
padding: const EdgeInsets.only(bottom: ReclaimSpace.sm),
child: SelectableText(s, style: t.bodyLarge?.copyWith(height: 1.55)),
);
Widget _bullet(TextTheme t, String s) => Padding(
padding: const EdgeInsets.only(
left: ReclaimSpace.lg,
bottom: ReclaimSpace.xs,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(top: 8, right: 10),
child: Container(
width: 5,
height: 5,
decoration: const BoxDecoration(
color: ReclaimColors.signal,
shape: BoxShape.circle,
),
),
),
Expanded(
child: SelectableText(s,
style: t.bodyLarge?.copyWith(height: 1.55)),
),
],
),
);