Datenschutz: Was den Mac verlässt
Eine vollständige Liste aller ausgehenden Verbindungen von Pulsaria, wann sie stattfinden und was sie übertragen.
Pulsaria speichert deine KPIs als einfache Dateien auf deinem Mac und hat für diese Daten kein Backend. Trotzdem ist es keine reine Offline-App: Sie holt Zahlen von den Diensten, die du verbindest, prüft auf Updates und spricht mit dem Lizenzserver. Diese Seite listet jede einzelne dieser Verbindungen auf — wann sie passiert und was sie überträgt.
Alle ausgehenden Requests in einer Tabelle
| Request | Geht an | Passiert wann | Enthält |
|---|---|---|---|
| Connector-Abruf | die API des Anbieters, direkt (Google, Plausible, Polar, Stripe, Awin) | ein Connector-KPI läuft nach Zeitplan, oder du drückst Jetzt ausführen, Aktualisieren oder Testen | die Zugangsdaten der Verbindung und ihre Parameter |
| Google-Token-Tausch | oauth2.googleapis.com | vor einem Search-Console- oder GA4-Abruf, höchstens einmal pro Stunde und Verbindung | ein mit deinem Service-Account-Key signiertes JWT |
| Eigene HTTP-Quelle | die URL, die du eingetragen hast | dieser KPI läuft oder du drückst Test ausführen | deine URL und deine Header-Zeilen |
| Update-Prüfung | www.pulsaria-kpi.com | 5 Sekunden nach dem Start, beim Öffnen der Updates-Karte und bei Jetzt prüfen | nichts außer dem Request selbst |
| Update-Download | www.pulsaria-kpi.com | erst nachdem du Herunterladen & installieren gedrückt hast | nichts außer dem Request selbst |
| Lizenz aktivieren / prüfen / deaktivieren | api.polar.sh | bei Aktivieren, Neu prüfen, Dieses Gerät deaktivieren und einmal beim Start, wenn die letzte Prüfung über 30 Tage her ist | dein Lizenzschlüssel und der Hostname deines Macs |
| Absturzbericht | ingest.de.sentry.io (Sentry EU) | nur wenn du Absturzberichte eingeschaltet hast, und nur bei einem Absturz | Fehlertyp und Stacktrace |
Alles andere bleibt lokal. Shell-Befehle laufen auf deinem Rechner, deine Datendateien werden auf der Platte gelesen und geschrieben, und die Testphase wird aus zwei lokalen Dateien gezählt — ohne Server.
Ohne konfigurierte Connectoren, ohne aktivierte Lizenz und mit ausgeschalteten Absturzberichten — also im Zustand einer frischen Installation — macht Pulsaria genau eine Art von ausgehendem Request: die Update-Prüfung.
Connector-Abrufe
Ein Connector-KPI spricht direkt mit dem Anbieter. Es gibt keinen Pulsaria-Proxy, kein Relay, keinen Zwischenhändler: Der Request geht von deinem Mac an searchconsole.googleapis.com, analyticsdata.googleapis.com, plausible.io, api.polar.sh, api.stripe.com oder api.awin.com, und die Antwort kommt direkt zurück.
Ein Abruf passiert in genau vier Situationen:
- Der Cron-Zeitplan des KPI ist fällig und Pulsaria läuft.
- Du drückst den Play-Button auf einer KPI-Karte oder Jetzt ausführen auf der KPI-Detailseite.
- Du drückst Aktualisieren im Dashboard-Header — das führt alle automatischen KPIs aus.
- Du drückst Test starten im Verbindungs-Assistenten der Verbindung oder den Test-Button in einer Zeile unter App-Einstellungen → Verbindungen.
Jeder Request trägt die Zugangsdaten der Verbindung in einem Authorization: Bearer-Header, dazu die Parameter, die du eingetragen hast (Site-URL, Property-ID, Publisher-ID, Region), einen Accept: application/json-Header und den User-Agent pulsaria/<version>. Nichts über deinen KPI — weder Name noch Ziel noch Historie — ist Teil des Requests. Requests laufen in der nativen Schicht der App mit 10 Sekunden Timeout und einem Limit von 64 KB für die Antwort.
Was jeder Connector liest, steht unter Connectoren.
Google-Connectoren und der Token-Tausch
Die beiden Google-Connectoren brauchen ein Access-Token, bevor sie etwas abfragen können. Pulsaria baut ein JWT mit den Claims, die Google verlangt, signiert es mit dem Private Key aus deiner Service-Account-Datei und schickt es an https://oauth2.googleapis.com/token. Google antwortet mit einem kurzlebigen Access-Token.
Dein Private Key selbst wird nirgendwohin gesendet — nur die Signatur, die er erzeugt. Das zurückgegebene Token liegt im Arbeitsspeicher (nicht auf der Platte) und wird bis fünf Minuten vor Ablauf weiterverwendet, sodass mehrere KPIs derselben Verbindung sich eine Stunde lang ein Token teilen. Beim Beenden der App geht der Cache verloren; das kostet beim nächsten Abruf einen zusätzlichen Token-Request.
Eigene HTTP-Quellen
Ein eigener HTTP-KPI schickt ein GET an die URL, die du eingetragen hast, mit den Header-Zeilen, die du angelegt hast — und sonst nichts. Pulsaria untersucht, protokolliert oder leitet diese URL nirgendwohin weiter. Es gelten dieselben Regeln: 10 Sekunden Timeout, 64 KB Limit, nur http/https und maximal fünf Redirects.
Header-Werte einer eigenen HTTP-Quelle liegen im Klartext in
kpi-definitions.json— anders als Connector-Zugangsdaten landen sie nicht im Schlüsselbund, und sie sind Teil eines JSON-Exports. Wenn du ein API-Token in eine Header-Zeile einträgst, behandle deine Export-Datei wie ein Geheimnis.
Mehr dazu unter Eigene HTTP-Quellen.
Shell-Befehle
Ein Shell-KPI führt /bin/sh -c <dein Befehl> auf deinem Mac aus. Pulsaria sendet dabei nichts. Wenn dein Befehl selbst ins Netz geht — curl oder ein CLI, das eine API aufruft — dann ist das dein Request, ausgeführt unter deinem Benutzer, und Pulsaria sieht davon nichts außer der Zahl, die auf stdout landet. Der Befehl läuft mit geleerter Umgebung (nur PATH, HOME und LANG werden durchgereicht) und wird nach 10 Sekunden abgebrochen.
Siehe Shell-Befehle.
Die Update-Prüfung
Pulsaria prüft auf eine neue Version, indem es ein Manifest von https://www.pulsaria-kpi.com/api/update-check.php?c=pa_8x2rK9mVqL anfordert. Das passiert:
- 5 Sekunden nach dem Öffnen des App-Fensters, still — du erfährst nur davon, wenn es ein Update gibt,
- einmal, wenn die Updates-Karte in den App-Einstellungen sichtbar wird, ebenfalls still,
- und jedes Mal, wenn du Jetzt prüfen oder Erneut prüfen drückst.
Der Request trägt keinen Account, keinen Lizenzschlüssel und keine Geräte-ID. Das ?c=-Token in der URL ist in jeder Kopie von Pulsaria dieselbe Zeichenkette; es sagt dem Server nur, dass der Aufrufer die App ist und kein Crawler.
Was der Update-Server festhält
Für Requests mit diesem Token schreibt der Pulsaria-Server eine Zeile: einen gesalzenen SHA-256-Hash der IP-Adresse des Aufrufers und einen „zuletzt gesehen“-Zeitstempel. Die rohe IP wird nicht gespeichert, und der Hash ist ohne das Salt nicht umkehrbar. Die Zeile wird bei der nächsten Prüfung überschrieben — es entsteht also eine Zählung aktiver Installationen, keine Historie.
Das passiert unabhängig davon, ob Absturzberichte eingeschaltet sind; die beiden haben nichts miteinander zu tun. Eine Einstellung, um die Prüfung beim Start abzuschalten, gibt es nicht.
Ein Update herunterladen
Es wird nichts heruntergeladen oder installiert, bevor du Herunterladen & installieren drückst. Das Paket wird dann von https://www.pulsaria-kpi.com/updates/Pulsaria.app.tar.gz geholt und gegen einen in die App einkompilierten Minisign-Public-Key geprüft; ein Paket, das diese Prüfung nicht besteht, wird nicht installiert. Nach der Installation startet die App sich selbst neu.
Lizenz aktivieren und prüfen
Alles rund um die Lizenz geht an Polar, den Zahlungsanbieter, unter https://api.polar.sh/v1/customer-portal/license-keys/. Es gibt drei Aufrufe:
| Aufruf | Ausgelöst durch | Inhalt |
|---|---|---|
activate | Aktivieren in App-Einstellungen → Lizenz | dein Lizenzschlüssel, Pulsarias öffentliche Organization-ID, ein Gerätename |
validate | Neu prüfen sowie einmal beim Start, wenn die letzte erfolgreiche Prüfung über 30 Tage her ist | dein Lizenzschlüssel, die Organization-ID, die Aktivierungs-ID |
deactivate | Dieses Gerät deaktivieren | dein Lizenzschlüssel, die Organization-ID, die Aktivierungs-ID |
Der Gerätename ist der Hostname deines Macs — $HOSTNAME, sonst die Ausgabe von hostname, sonst wörtlich Unknown Device. Er wird mitgeschickt, damit du deine Geräte im Polar-Kundenportal auseinanderhalten kannst. Pulsaria zeigt ihn nirgends an und lässt ihn nicht ändern.
Zwei Punkte sind wichtig. Erstens läuft die Prüfung beim Start nur, wenn eine Lizenz existiert und ihre letzte erfolgreiche Verifikation über 30 Tage zurückliegt — ein lizenzierter Mac meldet sich nicht bei jedem Start. Zweitens braucht die Testphase überhaupt kein Netz: Sie wird aus ~/.pulsaria-trial und dem Erststart-Zeitstempel in config.json berechnet, beides lokale Dateien. Der Kauf passiert im Browser auf der Checkout-Seite von Polar; Pulsaria sieht nie eine Kartennummer und zeigt auch nie einen Preis an.
Mehr dazu unter Testphase & Lizenz.
Absturzberichte (opt-in)
App-Einstellungen → Absturzberichte → Anonyme Absturzberichte senden ist standardmäßig aus. Solange der Schalter aus ist, wird das Sentry-SDK nicht einmal geladen — es wird erst nach deiner Zustimmung importiert. Eine Installation ohne Zustimmung führt diesen Code also nie aus und öffnet erst recht keine Verbindung.
Mit eingeschaltetem Schalter werden zwei Dinge gemeldet: ein Absturz, den die Error-Boundary der App abfängt, und eine unbehandelte Promise-Rejection. Die Berichte gehen in Sentrys EU-Region (ingest.de.sentry.io).
Was ein Bericht enthält
- Den Fehlertyp, seine Meldung und den Stacktrace.
- Den Release-Tag
pulsaria@<version>und übliche SDK-Metadaten.
Was vor dem Senden entfernt wird
- Breadcrumbs — restlos alle. Konsolen-Logs und aufgezeichnete Klicks werden komplett unterdrückt, denn die Logs des Schedulers enthalten KPI-Namen.
- Die Felder
request,userundserver_name, jedeextra-Nutzlast und der Trace-Kontext. - Absolute Dateipfade in der Meldung und in den Fehlerwerten, ersetzt durch das wörtliche
<path>. Ein Fehler beim Schreiben nach/Users/du/Library/…kommt als<path>an. - Personenbezogene Daten, die das SDK sonst automatisch anhängen würde, sind abgeschaltet (
sendDefaultPii: false).
Die Stack-Frames nennen weiterhin die Dateien und Funktionen des App-Bundles — genau das macht einen Bericht brauchbar. KPI-Namen oder Werte enthalten sie nicht.
Was nie gemeldet wird
Fehler, die die App selbst abfängt, werden nicht gesendet: ein fehlgeschlagener Abruf, den du als Toast siehst, ein abgelehnter Lizenzschlüssel, ein misslungener Connector-Test. Abstürze auf der Rust-Seite landen im System-Log und gehen nirgendwohin. Produkt-Analytics, Nutzungs-Tracking, Session-Replay oder Feature-Flags gibt es in Pulsaria nicht.
Schaltest du den Regler wieder aus, wird der Sentry-Client sofort geschlossen — ohne Neustart. Es gibt keine In-App-Ansicht dessen, was gesendet wurde, und keinen „Daten löschen“-Button; das ist eine echte Lücke, keine Haltung.
Was nur den Browser oder das Mail-Programm öffnet
Manche Buttons geben an eine andere Anwendung ab. Pulsaria selbst überträgt dabei nichts:
- Pulsaria kaufen öffnet die Polar-Checkout-Seite in deinem Standardbrowser.
- Die Buttons der Setup-Anleitung im Verbindungs-Assistenten und der Link Offizielle API-Doku in der Connector-Library öffnen die jeweilige Anbieter-Seite im Browser.
- Feedback senden unter App-Einstellungen → Feedback und Anfrage senden in der Connector-Library erzeugen beide einen
mailto:-Entwurf anadmin@one-pixel-ahead.comund öffnen dein Mail-Programm. Drei Zeilen werden angehängt —Version:,Platform:undLocale:— unter der Überschrift „Automatisch angehängt (keine KPI-Daten):“. Du kannst vor dem Senden alles ändern oder löschen, und nichts geht raus, bevor du in deinem Mail-Programm auf Senden drückst.
Was deinen Mac nie verlässt
- Deine KPI-Werte und jeder Eintrag, den du erfasst.
- Deine KPI-Namen, Projektnamen, Ziele, Zeiträume und Verbindungsnamen.
- Warnungen, das Fetch-Log und deine App-Einstellungen in
config.json. - Deine Datendateien selbst — Export-Dateien werden nur dort geschrieben, wohin du den Speichern-Dialog zeigst.
- Connector-Zugangsdaten in dem Sinne, dass sie an genau eine Stelle gehen: an den Anbieter, zu dem sie gehören, als
Authorization-Header auf dessen eigenem Request. Sie werden nie an Pulsaria gesendet, nie in eine Datendatei geschrieben und nie exportiert.
Die Web-Schicht der App ist passend dazu abgeriegelt: Ihre Content Security Policy erlaubt Verbindungen nur zu sich selbst und zu Sentry. Jeder andere Request — Connectoren, HTTP-Quellen, Lizenzaufrufe, Update-Prüfung — läuft über die native Schicht. Deshalb lässt sich ein Connector-KPI nicht dazu bringen, etwas aufzurufen, was die App nicht selbst gebaut hat.
Wo Zugangsdaten gespeichert werden
Die Geheimnisse einer Verbindung landen im macOS-Schlüsselbund, unter dem Service-Namen com.onepixelahead.pulsaria und einem Account-Namen der Form connection.<verbindungs-id>. In der Schlüsselbundverwaltung kannst du sie ansehen. Der Wert ist ein kleines JSON-Objekt, das die Art der Zugangsdaten nennt und den Schlüssel oder das Token enthält.
Was das praktisch bedeutet:
- Das Geheimnis wird von macOS geschützt, nicht von Pulsaria. Es unterliegt der Verschlüsselung und dem Anmeldeschutz deines Macs.
- macOS fragt beim ersten Lesen unter Umständen nach einer Erlaubnis. Mit „Immer erlauben“ bleiben spätere Zugriffe still.
- Löschst du eine Verbindung, wird auch ihr Schlüsselbund-Eintrag entfernt.
- Ein JSON-Export enthält Name, Connector und Parameter der Verbindung sowie den Namen des Schlüsselbund-Eintrags — nie das Geheimnis dahinter. Genau deshalb fragt der Umzug auf einen neuen Mac jeden Schlüssel erneut ab. Siehe Backup, Export & Umzug.
Zwei Dateien liegen nicht im Schlüsselbund und sind nicht verschlüsselt:
license.jsonenthält deinen vollständigen Lizenzschlüssel im Klartext, weil die erneute Prüfung ihn braucht.kpi-definitions.jsonenthält die Header-Werte eigener HTTP-Quellen im Klartext, wie oben beschrieben.
Alles Weitere, was Pulsaria schreibt, ist einfaches, lesbares JSON. Es gibt keine Verschlüsselung im Ruhezustand und kein Passwort auf den Datendateien oder auf einem Export — der Schutz ist der deines Macs und die Wahl, wo du die Dateien ablegst. Die Pfade stehen unter Wo deine Daten liegen.
Was es in Pulsaria nicht gibt
Keinen Account, keine Registrierung, keine E-Mail-Adresse. Keine Produkt-Analytics, kein Nutzungs-Tracking. Keine Werbung und keine Tracker von Dritten. Keinen Sync-Dienst von uns — zwischen Macs synchronisieren heißt, zwei Installationen auf denselben Ordner in deinem eigenen Cloud-Speicher zeigen zu lassen. Und keine serverseitige Kopie deiner Zahlen, weil es dafür schlicht keinen Server gibt.