feat: Wordeck-Vorarbeiten — Datenschutz-Seite + Text-Only-Migration
Some checks are pending
CI / validate (push) Waiting to run

Privacy/+page.svelte: Cards → Wordeck, MinIO-Erwähnung entfernt
(text-only, kein Object-Storage), Bilder/Audio explizit als
"speichern wir NICHT" markiert, Bundle ev.mana.wordeck.

0004_wordeck_text_only.sql: Migration für CardType-Cutoff
(image-occlusion/audio raus, CHECK-Constraint, media_files-DROP).
Vor-Audit gegen prod hat 0 betroffene Karten gezeigt — die Migration
ist defensiv und idempotent, kann ohne Daten-Verlust gefahren werden.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-05-17 20:36:20 +02:00
parent 29351f881d
commit 22927fbe59
2 changed files with 68 additions and 11 deletions

View file

@ -0,0 +1,52 @@
-- Wordeck-Rebrand: Text-Only-Architektur (CardType-Cutoff).
--
-- Mit dem Brand-Wechsel von Cards zu Wordeck (siehe
-- mana/docs/playbooks/WORDECK_REBRAND.md) entfallen die CardTypes
-- `image-occlusion` und `audio` ersatzlos. Wordeck speichert nur Worte.
--
-- Vor-Audit gegen prod am 2026-05-17:
-- SELECT type, COUNT(*) FROM cards.cards GROUP BY type;
-- basic 123
-- cloze 44
-- multiple-choice 19
-- basic-reverse 0 (keine in der DB — alle Marketplace-Decks)
-- type-in 0
-- image-occlusion 0 ← Cutoff ist trivial
-- audio 0 ← Cutoff ist trivial
-- SELECT COUNT(*) FROM cards.media_files; → 0
--
-- Diese Migration ist deshalb defensiv: löscht eventuelle Karten der
-- gestrichenen Typen, fügt einen CHECK-Constraint hinzu und entfernt
-- die ungenutzte media_files-Tabelle + media_refs-Spalte.
--
-- Idempotent geschrieben (IF EXISTS / DO-Blocks), damit Re-Runs
-- harmlos sind.
-- 1. Verbleibende Karten der gestrichenen Typen löschen
-- (sollte nach Audit 0 betreffen).
DELETE FROM "cards"."cards" WHERE "type" IN ('image-occlusion', 'audio');
-- 2. CHECK-Constraint für erlaubte CardTypes.
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'cards_type_check'
) THEN
ALTER TABLE "cards"."cards"
ADD CONSTRAINT "cards_type_check"
CHECK ("type" IN ('basic', 'basic-reverse', 'cloze', 'type-in', 'multiple-choice'));
END IF;
END$$;
-- 3. media_refs-Spalte aus cards droppen (war nie produktiv genutzt).
ALTER TABLE "cards"."cards" DROP COLUMN IF EXISTS "media_refs";
-- 4. media_files-Tabelle droppen.
DROP TABLE IF EXISTS "cards"."media_files";
-- 5. Optional: Wenn fields ein image_ref-Key enthält, säubern.
-- (Image-Occlusion-Karten sind oben schon gelöscht — das ist ein
-- Defense-in-Depth-Schritt für falsch annotierte basic-Karten.)
UPDATE "cards"."cards"
SET "fields" = "fields" - 'image_ref' - 'mask_regions'
WHERE "fields" ?| array['image_ref', 'mask_regions'];

View file

@ -1,14 +1,15 @@
<svelte:head>
<title>Datenschutz — Cardecky</title>
<meta name="description" content="Datenschutzerklärung für Cardecky, die Karteikarten-App des Vereins mana e.V." />
<title>Datenschutz — Wordeck</title>
<meta name="description" content="Datenschutzerklärung für Wordeck, die text-first Spaced-Repetition-App des Vereins mana e.V." />
</svelte:head>
<main class="page">
<h1>Datenschutz</h1>
<p class="lead">
Cardecky ist die Karteikarten-App des Vereins <strong>mana e.V.</strong> (in Gründung,
Sitz Schweiz). Wir hosten die Daten selbst, sammeln nur was wir für den Betrieb brauchen, und
Wordeck ist die text-first Lernkarten-App des Vereins <strong>mana e.V.</strong> (in
Gründung, Sitz Schweiz). Wir speichern <strong>nur Worte</strong> — keine Bilder, kein
Audio. Wir hosten die Daten selbst, sammeln nur was wir für den Betrieb brauchen, und
geben nichts an Dritte weiter, die nicht in dieser Erklärung genannt sind.
</p>
@ -25,8 +26,8 @@
Login-Zeitpunkte. Über <code>auth.mana.how</code> (mana-auth-Service).
</li>
<li>
<strong>Inhalte</strong>: Decks, Karten, Tags, Hashtags, Bilder/Audio, die du selbst
erstellst.
<strong>Inhalte</strong>: Decks, Karten, Tags, Hashtags, die du selbst erstellst —
alles als Text (Markdown). Wordeck speichert keine Bilder und kein Audio.
</li>
<li>
<strong>Lernfortschritt</strong>: FSRS-Zustand pro Karte (next-due, stability,
@ -40,6 +41,10 @@
<h2>Was wir NICHT machen</h2>
<ul>
<li>
Keine Speicherung von Bildern oder Audio — Wordeck ist bewusst text-first und braucht
keinen Object-Storage.
</li>
<li>Kein Werbe-Tracking, kein Re-Targeting, keine Google/Facebook/Meta-Pixels.</li>
<li>Kein Crash-Reporting-SaaS (Sentry/Firebase/Crashlytics).</li>
<li>Keine Weitergabe an Dritte zu Marketing- oder Analyse-Zwecken.</li>
@ -48,13 +53,13 @@
<h2>Welche Dienste wir nutzen</h2>
<ul>
<li>
<strong>Cloudflare</strong> als Tunnel + CDN für <code>cardecky.mana.how</code> und
<code>cardecky-api.mana.how</code>. Cloudflare kann Verbindungs-Metadaten sehen, die
<strong>Cloudflare</strong> als Tunnel + CDN für <code>wordeck.com</code> und
<code>api.wordeck.com</code>. Cloudflare kann Verbindungs-Metadaten sehen, die
Inhalte sind HTTPS-verschlüsselt.
</li>
<li>
<strong>mana e.V.-Eigenhosting</strong> (Mac Mini in der Schweiz) für Application-
Server, Postgres-DB und MinIO-Object-Storage. Niemand außer dem Vorstand hat Zugang.
Server und Postgres-DB. Niemand außer dem Vorstand hat Zugang.
</li>
</ul>
@ -76,7 +81,7 @@
<h2>Native Apps</h2>
<p>
Die iOS-App <strong>Cards</strong> (Bundle <code>ev.mana.cardecky</code>) speichert
Die iOS-App <strong>Wordeck</strong> (Bundle <code>ev.mana.wordeck</code>) speichert
zusätzlich lokal auf deinem Gerät: gecachte Decks (SwiftData),
Offline-Grade-Queue, Auth-Token im iOS-Keychain. Beim Logout werden alle lokalen Daten
gelöscht. Keine Telemetrie an uns oder Apple, keine Push-Server.
@ -85,7 +90,7 @@
<h2>Änderungen</h2>
<p>
Wir aktualisieren diese Erklärung wenn sich Praxis oder Dienste ändern. Größere
Änderungen kündigen wir per Email an. Stand: 2026-05-13.
Änderungen kündigen wir per Email an. Stand: 2026-05-17 (Rebrand zu Wordeck, text-only).
</p>
<p>