Wie wir deine Daten schützen

Technische und organisatorische Maßnahmen nach Art. 32 DSGVO, samt der Punkte, die noch offen sind.

Die technischen und organisatorischen Maßnahmen nach Art. 32 DSGVO, gegliedert nach den üblichen Prüfkategorien. Was noch nicht umgesetzt ist, steht als offen dabei. Wir nennen Lücken lieber, als sie zu umschreiben.

Was nicht bei uns liegt, kann bei uns nicht abfließen

Noten, Stundenpläne und Prüfungsdaten liegen ausschließlich auf deinem Gerät. Aus den mobilen Apps erreicht dein Hochschul-Login unsere Server zu keinem Zeitpunkt.

Vertraulichkeit

  • Wer an die Daten herankommt.

Physischer Zugang

Wir betreiben keine eigenen Rechenzentren. Die physische Sicherheit liegt bei den Hostern.

Supabase: verwaltetes PostgreSQL und Anmeldung, Standort EU.

Google Cloud Run: Anwendungsserver, Region europe-west1 (Belgien).

netcup: ein Server in Deutschland für die Workspace-Daten und ihre Datenbank. Hochgeladene Dateien liegen derzeit auf der Platte dieses Servers; ein Objektspeicher in der EU ist vorbereitet.

Anmeldung

Wer sich anmelden kann, und wie systematisches Passwortraten verhindert wird.

Anmeldung über Supabase Auth. Die Server prüfen jedes Token gegen den öffentlichen Schlüsselsatz (JWKS, RS256 bzw. ES256); die Schlüssel werden rotiert.

Sitzungstoken gelten eine Stunde. Refresh-Token werden bei jeder Verlängerung der Sitzung ausgetauscht.

Ab dem fünften Fehlversuch wächst die Wartezeit exponentiell, höchstens bis 15 Minuten. Der Zähler liegt in der Datenbank und wirkt über alle Serverinstanzen hinweg. Dazu kommt eine grobe Ratenbegrenzung je IP-Adresse.

Fehlversuche mit unbekannten Kennungen zählen mit. Sonst ließe sich an der Sperre ablesen, welche Benutzernamen es gibt.

Zugriff auf Daten

  • Was eine angemeldete Person sehen kann.

Row-Level Security in PostgreSQL: Die Datenbank prüft selbst, wem eine Zeile gehört, anhand einer je Transaktion gesetzten Kontokennung. Ein Fehler im Anwendungscode hebt die Trennung nicht auf.

Die beiden Betreiber greifen nur über persönliche Konten zu, nie über geteilte Anmeldungen. Schlüssel und Zugangsdaten liegen in einem Secret Manager, nicht im Quellcode.

Kein Tracking. Absturzberichte sind standardmäßig aus und werden vor dem Versand um Tokens, iTAN-Codes, Anmeldezeilen des Mailzugangs und absolute Dateipfade bereinigt.

Trennung

Wie die Daten verschiedener Personen und Hochschulen getrennt bleiben.

Die Trennung nach Hochschule und nach Person setzt dieselbe Row-Level-Security-Schicht durch, nicht ein Filter in der Anwendung.

Änderungen an gemeinsam bearbeiteten Dokumenten werden nur angehängt, nie überschrieben. Eine Datenbankbedingung verhindert, dass ein Konto unter fremder Kennung schreibt.

Das Sicherheitsprotokoll nimmt keine Schreibvorgänge von Clients an und ist für Clients nicht lesbar. Einsehbar ist es nur für den Betrieb.

Integrität

Dass Daten unterwegs und im Nachhinein unverändert bleiben.

Übertragung und Speicherung

Verschlüsselt auf dem Weg, bei den Hostern und auf deinem Gerät.

TLS auf allen Verbindungen zwischen App, Servern, Datenbank und den Systemen deiner Hochschule.

Verschlüsselung im Ruhezustand durch die Hoster.

Zugangsdaten auf deinem Gerät verschlüsselt: mobil in iOS-Keychain bzw. Android-Keystore, im Browser mit AES-GCM unter einem Schlüssel, der mit Argon2id aus deinem Passwort abgeleitet oder als gerätegebundener, nicht exportierbarer WebCrypto-Schlüssel gehalten wird.

Hochschul-Login: aus den mobilen Apps nie an unsere Server; im Browser je Anfrage mitgesendet und für Moodle höchstens 24 Stunden im Arbeitsspeicher. Nie in einer Datenbank, nie in einer Protokolldatei.

Schutz der Web-App

  • Browserseitige Schutzmechanismen.

CORS schließt in der Produktion im Zweifel: Eine nicht ausdrücklich zugelassene Herkunft wird abgewiesen, nicht durchgelassen.

Die Sicherheits-Header X-Content-Type-Options und X-Frame-Options sind aktiv.

Die Content-Security-Policy läuft derzeit nur im Report-Only-Modus: Sie meldet Verstöße, blockiert aber noch nicht.

Nachvollziehbarkeit

Sicherheitsrelevante Vorgänge landen in einem Protokoll, an das nur angehängt werden kann, jeweils mit IP-Adresse, Browserkennung, Aktion und Zeitpunkt. Clients können Einträge weder erzeugen noch ändern. IP-Adresse und Browserkennung werden nach 30 Tagen entfernt, die Einträge nach 12 Monaten gelöscht.

Verfügbarkeit

  • Was passiert, wenn etwas kaputtgeht.

Nächtliche Sicherung

Jede Nacht eine vollständige Sicherung der Datenbank (pg_dump) auf dem Server, 14 Tage aufbewahrt.

Wiederherstellung geprüft

Ein vollständiger Test der Wiederherstellung wurde durchgeführt und bestanden. Eine Sicherung, die nie zurückgespielt wurde, ist für uns keine Sicherung.

Kein Handgriff ohne zweites Paar Augen

Wie Änderungen geprüft werden, bevor sie live gehen.

Zwei Personen betreiben UNI-fied, beide mit persönlichen Konten.

Der gesamte Quellcode steht unter Versionskontrolle. Jede Änderung sieht vor der Übernahme die jeweils andere Person durch.

Bei jeder Änderung laufen automatisierte Prüfungen (Continuous Integration), darunter Tests der Zugriffsregeln.

Ein automatischer Scanner verhindert, dass Schlüssel oder Passwörter in den Quellcode gelangen.

Datenbankmigrationen werden in der CI von Grund auf neu aufgebaut und auf Wiederholbarkeit geprüft. Der Stand der Datenbank ist reproduzierbar und nicht das Ergebnis von Handgriffen.

Offene Punkte

In Umsetzung. Sobald ein Punkt erledigt ist, wandert er nach oben.

Sicherungskopie außerhalb des Servers

Sicherung und gesicherter Bestand liegen derzeit auf demselben Server. Vorgesehen ist eine verschlüsselte Ablage in einem getrennten Objektspeicher in der EU.

Wiederherstellung auf einen beliebigen Zeitpunkt

Derzeit lässt sich nur der Stand der letzten Nacht wiederherstellen. Vorgesehen ist eine fortlaufende Sicherung des Transaktionsprotokolls (Point-in-Time-Recovery).

Automatische Alarmierung

Störungen fallen bislang bei der Durchsicht auf, nicht durch eine Meldung. Vorgesehen sind Schwellwerte für Fehlerrate, Antwortzeit und den Ausfall der Sicherung.

Content-Security-Policy durchsetzen

Läuft im Report-Only-Modus. Nach Auswertung der Meldungen wird sie blockierend geschaltet.

How we protect your data

Technical and organisational measures under Art. 32 GDPR, including the items that are still open.

Our technical and organisational measures under Art. 32 GDPR, grouped by the usual audit categories. Anything not yet in place is marked as open. We would rather name a gap than talk around it.

What we don't hold can't leak from us

Grades, timetables and exam data live only on your device. From the mobile apps, your university login never reaches our servers.

Confidentiality

  • Who can get to the data.

Physical access

We run no data centres of our own. Physical security lies with our hosting providers.

Supabase: managed PostgreSQL and sign-in, located in the EU.

Google Cloud Run: application servers, region europe-west1 (Belgium).

netcup: one server in Germany for Workspace data and its database. Uploaded files currently sit on that server's disk; EU object storage is prepared.

Sign-in

Who can sign in, and how systematic password guessing is stopped.

Sign-in runs through Supabase Auth. Our servers verify every token against the public key set (JWKS, RS256 or ES256); the keys are rotated.

Session tokens are valid for one hour. Refresh tokens are replaced every time the session is extended.

From the fifth failed attempt the wait grows exponentially, capped at 15 minutes. The counter lives in the database, so it applies across all server instances. A coarse per-IP rate limit sits on top.

Failed attempts against unknown usernames count too. Otherwise the lockout itself would reveal which usernames exist.

Access to data

  • What a signed-in person can see.

Row-level security in PostgreSQL: the database itself checks who owns a row, using an account ID set per transaction. A bug in application code does not break the separation.

The two operators use personal accounts only, never shared logins. Keys and credentials live in a secret manager, not in the source code.

No tracking. Crash reports are off by default and are stripped of tokens, iTAN codes, mail login lines and absolute file paths before they are sent.

Separation

How different people's and universities' data stays apart.

Separation by university and by person is enforced by the same row-level security layer, not by a filter in the application.

Changes to shared documents are only ever appended, never overwritten. A database constraint stops an account from writing under someone else's ID.

The audit log accepts no writes from clients and cannot be read by clients. Only operations staff can see it.

Integrity

Data stays unaltered in transit and after the fact.

Transfer and storage

Encrypted in transit, at the hosting providers and on your device.

TLS on every connection between the app, our servers, the database and your university's systems.

Encryption at rest by the hosting providers.

Credentials encrypted on your device: in the iOS Keychain or Android Keystore on mobile; in the browser with AES-GCM under a key that is either derived from your password with Argon2id or held as a device-bound, non-exportable WebCrypto key.

University login: never sent to our servers from the mobile apps; in the browser, sent with each request and kept in memory for Moodle for 24 hours at most. Never in a database, never in a log file.

Protecting the web app

  • Browser-side safeguards.

CORS fails closed in production: an origin that is not explicitly allowed is rejected, not let through.

The X-Content-Type-Options and X-Frame-Options security headers are active.

The Content Security Policy currently runs in report-only mode: it reports violations but does not block them yet.

Traceability

Security-relevant actions are written to an append-only log, each with IP address, browser identifier, action and time. Clients can neither create nor change entries. IP address and browser identifier are removed after 30 days, the entries themselves deleted after 12 months.

Availability

  • What happens when something breaks.

Nightly backup

A full database backup (pg_dump) every night on the server, kept for 14 days.

Restore tested

A full restore test has been carried out and passed. A backup that has never been restored doesn't count as a backup to us.

Nothing ships without a second pair of eyes

How changes are checked before they go live.

Two people run UNI-fied, both with personal accounts.

All source code is under version control. Every change is reviewed by the other person before it is merged.

Automated checks (continuous integration) run on every change, including tests of the access rules.

An automated secret scanner stops keys and passwords from getting into the source code.

Database migrations are rebuilt from scratch in CI and checked for repeatability. The database state is reproducible, not the result of manual tweaks.

Open items

In progress. When an item is done, it moves up this page.

Backup copy off the server

Backups and the data they protect currently sit on the same server. The plan is encrypted storage in a separate EU object store.

Restore to any point in time

Right now only last night's state can be restored. The plan is continuous archiving of the transaction log (point-in-time recovery).

Automatic alerting

Problems are currently noticed during review, not reported automatically. The plan is thresholds on error rate, response time and a failed backup.

Enforce the Content Security Policy

Runs in report-only mode. Once the reports have been reviewed, it will be switched to blocking.