IT-Firmen-Handbuch
🖥️ Für IT-Dienstleister
Leerer Empfangstresen am Abend
Manual 3 von 5 · IT-Firmen-Handbuch · Stand r396

Rosie — Architektur, Security, Betrieb

Die technische Referenz für IT-Dienstleister und IT-Beauftragte beim Kunden. Schweizer Instanz, Security-Header, PWA-Cache, Web-Push, DB-Migrationen, Backup, Observability und Eskalation — alles forensisch nachvollziehbar. Anbieternamen stehen hier bewusst, weil Sie Firewall-Freigaben setzen und die Auslagerung dokumentieren müssen.

🖥️ IT 🇨🇭 Infomaniak (CH) 🔒 HSTS Preload 📡 Web Vitals Stand r396
🏗️

System-Architektur

Vanilla-JS-PWA auf einer Schweizer Instanz

Rosie ist eine Vanilla-JS-PWA. Die Anwendung läuft als Node-Prozess auf einer Debian-Instanz bei Infomaniak in der Schweiz, davor Caddy als Reverse-Proxy mit automatischer Zertifikatsverwaltung. Persistenz erfolgt über libSQL/SQLite auf derselben Instanz (WAL-Modus), Objektspeicher über den S3-kompatiblen Objektspeicher von Infomaniak. Der Service Worker arbeitet mit einem CACHE_PREFIX pro Release. Der öffentlichen Website ist ein Schutzdienst vorgelagert — er hält keine Daten, die Schnittstelle läuft direkt auf die Schweizer Instanz.

🖥️
Compute
Node auf Debian bei Infomaniak (CH), Caddy als Reverse-Proxy. Beim Kunden keine Server, keine VMs.
🗄️
libSQL / SQLite
Auf derselben Instanz, WAL-Modus, verschlüsselte Backups ausser Haus. Datenhaltung Schweiz.
📦
Objektspeicher
Anhänge und Dokumente im S3-kompatiblen Objektspeicher von Infomaniak (Schweiz).
🤖
KI optional
Pro Mandant zuschaltbar. Welcher KI-Anbieter eingesetzt wird, steht im Sub-Bearbeiter-Verzeichnis des AVV — nicht in diesem Handbuch, damit es bei einem Wechsel nicht falsch wird.
ℹ️
Stack auf einen Blick: Vanilla JS · Node auf Debian (Infomaniak CH) · Caddy · libSQL/SQLite · S3-kompatibler Objektspeicher · Service Worker mit Release-Prefix · Web Push. Beim Kunden ist nichts zu installieren.
🌍

Browser-Kompatibilität

Welche Browser unterstützt werden
🟢
Chrome ≥ 90
Voll unterstützt inkl. PWA-Install.
🦊
Firefox ≥ 88
Voll unterstützt.
🔷
Edge ≥ 90
Voll unterstützt inkl. PWA-Install.
🧭
Safari ≥ 14.1
PWA-Install via „Zum Home-Bildschirm".
⚠️
Internet Explorer: nicht unterstützt. iOS-Splash-PNG-Pflicht: WebP wird seit r168 B8 NICHT mehr akzeptiert — iOS-Splash-Assets MÜSSEN als PNG vorliegen.
🌐

DNS und Domains

Haupt- und Aliasdomains, Kunden-Subdomains, Worker-Routes
  • Hauptdomain: rosie-app.ch (inkl. www).
  • Aliase / Mirror: rosie-planer.com — als 301-Redirect. Edge-Cache ~2 min stale-Window beachten (per-PoP-Lag, selbst-konvergierend). Sofortprüfung der Origin via ?cb=<random>.
  • App-Subdomäne: die Anwendung läuft unter einem eigenen Namen, der direkt auf die Schweizer Instanz zeigt («nur DNS», ohne vorgelagerten Dienst).
  • Kein Wildcard-Eintrag. *.rosie-app.ch existiert nicht — ein erfundener Name löst nicht auf. Das ist Absicht und schliesst die Subdomain-Übernahme aus.
  • Vorgelagerter Schutzdienst nur für die öffentliche Website; er hält keine Kundendaten.
💡
Stale-Window der Aliasdomäne: Nach einem Deploy kann der 301-Redirect auf rosie-planer.com kurz aus dem Zwischenspeicher des vorgelagerten Dienstes kommen. Er konvergiert selbst. Für Forensik: Origin-Request mit Cache-Buster.
🛡️

Security-Header (NEU / korrigiert)

HSTS Preload-ready, CSP, SRI, Worker-Forensik
🔒
HSTS (r168 preload-ready)
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload — von der Anwendung selbst gesetzt, damit der Header unabhängig vom vorgelagerten Dienst gilt. Submit auf hstspreload.org erfolgt manuell.
🧱
CSP strikt (r71)
Strikte Content-Security-Policy, deployed.
🧾
SRI (r166 A1)
Subresource Integrity auf externen Scripts.
🔖
X-Worker-Version / X-Request-Id
In jeder Response. WORKER_VERSION = RELEASE, importiert aus shared/version.mjs (eine Quelle).
ℹ️
Trivial verifizierbar: curl -I https://rosie-app.ch zeigt alle gesetzten Header inkl. HSTS, CSP, X-Worker-Version und X-Request-Id.
⚠️
Falle: includeSubDomains trifft jede Subdomäne, auch Test- und Staging-Namen. Und ein einmal ausgelieferter HSTS-Header bleibt bis zu zwei Jahre im Browser gültig — er lässt sich nicht kurzfristig zurücknehmen.
📦

Service Worker, Asset-Cache

CACHE_PREFIX, Edge-Cache, Lazy-Vendors, iOS-Splash, Re-Sync
  • sw.js mit CACHE_PREFIX, gestempelt aus shared/version.mjs (scripts/sync-version.mjs).
  • Edge-Cache: ~2 min stale nach Deploy (per-PoP-Lag, selbst-konvergiert).
  • immutable-Cache-Header (r166 B4) für versionierte Assets.
  • Lazy-loaded Vendors via _loadVendor — XLSX, html2canvas (r166 B2).
  • iOS-Splash-PNG-Pflicht — WebP-Drop seit r168 B8.
  • Kein Background-Sync — bewusst: ein Replay ohne offenen Tab hätte keinen frischen JWT und riskierte ohne Idempotenz-Keys Doppelbuchungen. Die Chat-Outbox flusht nur bei geöffneter App (s. docs/OFFLINE.md).
  • Web-Push auf iOS nur in installierter PWA — Add-to-Homescreen erzwingen.
💡
Deploy: RELEASE in shared/version.mjs anheben + npm run version:sync — CACHE_PREFIX in sw.js / src/constants.js wird automatisch gestempelt; nichts von Hand mitziehen.
📡

Web Push (RFC 8291)

VAPID, Idempotenz, Quiet Hours, Kategorien
  • VAPID-Schlüssel (öffentlich / privat) liegen als Secrets auf der Instanz unter /etc/rosie/env.
  • subscribeToPushNotifications ist ein idempotenter UPSERT.
  • Quiet Hours werden respektiert.
  • Ein/Aus pro Alarm-Kategorie: bounty · planPublished · adminAlert · messages · absenceResult.
⚠️
VAPID-Rotation invalidiert alle bestehenden Push-Subscriptions (bekannte Schuld) — Rotation gut planen.
🔥

Firewall / Netzwerk

Whitelist, Ports, Polling
  • Nur ausgehend HTTPS 443.
  • Freigabe für rosie-app.ch und die App-Subdomäne. Weitere Ziele sind nicht nötig — die App ruft von sich aus keine Dienste beim Kunden auf.
  • Keine eingehenden Ports.
  • WebSocket nicht erforderlich — die App ist polling-basiert (60 s).
📧

E-Mail-System

SMTP über Schweizer Postfach, SPF/DKIM/DMARC

Versand über SMTP auf ein Schweizer Postfach bei Hostpoint. Absender aller System-Mails ist support@rosie-app.ch — eine antwortbare Adresse, keine No-Reply-Sackgasse. SPF, DKIM und DMARC sind gesetzt; wir empfehlen, die Zustellung nach dem Erst-Setup einmal gegen den Spamfilter des Kunden zu testen.

💡
Wenn Einladungs-Mails nicht ankommen: zuerst Quarantäne und Spamfilter beim Kunden prüfen, dann SPF/DKIM/DMARC für rosie-app.ch nachschlagen. Die Adresse support@rosie-app.ch in die Freigabeliste aufzunehmen, löst die meisten Fälle.
📱

Mobile & MDM

iOS / Android, Webclips, PWA-Install
  • iOS 14.5+, Android 8.0+.
  • PWA — kein App-Store-Paket.
  • MDM kann bevorzugte Browser, Homescreen-Webclips und vertrauenswürdige Websites konfigurieren.
  • Beachten: Web-Push auf iOS = installierte PWA Pflicht; iOS-Splash PNG (kein WebP).
🗃️

DB-Migrationen / Schema-Versionierung

Versioniert, vorwärts, mit Prüfung nach jedem Lauf

Migrationen liegen unter database/migrations/ fortlaufend nummeriert und werden ausschliesslich vorwärts angewendet. Der jeweils aktuelle Stand steht im Verzeichnis selbst — diese Seite nennt bewusst keine Nummer, weil sie sonst beim nächsten Release falsch ist. Nach jedem Lauf folgt eine Schema-Verifikation. Die Migrationen sind so gebaut, dass sich eine leere Datenbank vollständig aus ihnen aufbauen lässt.

ℹ️
Migrationen laufen im Rahmen des Deployments und brauchen keinen Eingriff beim Kunden. Ein Rückwärtslauf ist nicht vorgesehen — der Weg zurück führt über die Wiederherstellung (siehe Backup & Recovery).
💾

Backup & Recovery

Verschlüsselte Backups, Wiederherstellungspunkte, Export
  • Automatische Backups der Datenbank, verschlüsselt und ausser Haus abgelegt.
  • Wiederherstellungsfenster 30 Tage mit stündlichen Wiederherstellungspunkten (RPO ≤ 1 Stunde).
  • Objektspeicher wird eigenständig gesichert.
  • Vollständiger Datenexport pro Mandant jederzeit über die Verwaltungsoberfläche.
  • Keine geografische Redundanz. Es läuft bewusst eine Produktivinstanz — ein Neustart oder eine Aktualisierung bedeutet eine kurze Unterbrechung. Das ist ein bekannter, angenommener Kompromiss und ohne Architekturänderung nachrüstbar.
⚠️
Wiederherstellungszeiten sind kein Bestandteil dieses Handbuchs. Verbindlich ist allein der Servicevertrag.
↩️

Rollback / Versionen

Checkpoint-Tags, Notfallablauf

Zu jedem Release gehört ein Tag checkpoint-rNNN-deployed im Quellcode-Verwaltungssystem. Damit ist jederzeit belegbar, welcher Stand wann produktiv war.

ℹ️
Rollback: Der vorherige Release wird auf der Instanz vorgehalten und lässt sich in Minuten wieder aktivieren. Eine Datenbank-Migration läuft dabei nicht zurück — wer weiter zurück muss, geht über die Wiederherstellung.
Notfall-SOP
1
Beim Hersteller melden
Rollbacks auf der Instanz führt der Hersteller aus — mit Release-Nummer und Zeitpunkt aus dem Fehlerbild.
2
Browser-Cache leeren
Hartes Reload, ggf. Service Worker aktualisieren.
3
Header verifizieren
curl -I → X-Worker-Version prüfen.
🏢

Multi-Tenant-Isolation

Server-Scope, Logout-Reset, Marker
  • Server-seitige Tenant-Skopierung — tenant_id in jedem Query.
  • In-Memory tenant-Globals werden bei Logout via _resetTenantCalendarData() geleert (6 Kalender-Globals).
  • Cross-Tenant-Leak-Tests fixiert (blockDates-Lesson, vacations-Tenant-Reset).
  • Persist-Trigger über Tenant-Marker companySettingsDirty.
📊

Observability & Logs

Worker-Version, Request-Id, Web Vitals, PII-Scrub
  • X-Worker-Version (r166 A10), X-Request-Id (r166 B1) in jeder Response.
  • Web Vitals (r167 B5) → /api/analytics, keepalive-fetch, DNT respektiert.
  • PII-Scrubbing-Regex (r166 A6) vor Analytics.
  • k-Anonymität ≥ 4 für Aggregate-Charts.
  • Logs liegen auf der Instanz (systemd/journald) und werden vom Hersteller ausgewertet; ein externer Verfügbarkeits-Monitor prüft die Erreichbarkeit und alarmiert.
⚠️
Korrektur zum alten Manual: Observability ist NICHT deaktiviert — sondern aktiv, mit PII-Scrub und DNT-Honor.
⚡

Performance-Budget

LCP / CLS / INP, Lazy-Vendors, Battery-Save
  • LCP / CLS / INP-Ziele als Performance-Budget.
  • CLS-Fix r168 B8: width / height auf <img>-Tags.
  • Lazy-Vendors via _loadVendor — XLSX / html2canvas.
  • Battery-Save: Polling pausiert bei document.hidden (Visibility-Pause, r168 B3).
🔌

Wichtige API-Endpoints

Worker-Routen mit Versions-Header
👥
Stamm & Plan
/api/staff · /api/shift-assignments · /api/vacations
🤒
Absenzen
/api/absences · /api/absences/:id/{approve,reject,cancel} · /api/absence-approval-config
💬
Kommunikation
/api/messages · /api/suggestions
📄
QMS
/api/qms/documents
📋
Tasks
/api/tasks · /api/tasks/templates · /api/tasks/:id/qms-links (PATCH) · /api/tasks/audit
🔄
Mutations / Onboarding
/api/mutations · /api/onboarding/:step
📊
Analytics / Log
/api/analytics · /api/log
👤
Profil
/api/profile
🔐
Monatsabschluss
/r163-monatsabschluss · /r163-monatsabschluss/:year_month (POST / DELETE)
📰
Feed-Proxy
/api/feed-proxy
ℹ️
Jede Response trägt einen Versions-Header (X-Worker-Version) und eine Request-Id (X-Request-Id).
🤖

KI-System & DSG-Firewall

Rate-Limit, PII-Sanitizer, Spracherkennung im Browser
  • KI-Anbieter: pro Mandant zuschaltbar; je Zweck ein fester Dienst, ohne automatischen Ausweichdienst (Fallback). Welcher Anbieter eingesetzt wird, steht im Sub-Bearbeiter-Verzeichnis des AVV — nicht hier, damit diese Seite bei einem Wechsel nicht falsch wird.
  • Rate-Limit: 30 Anfragen pro Stunde pro User.
  • PII-Sanitizer entfernt E-Mail, AHV-Nummer, IBAN, Telefon und Datum vor jedem Aufruf des KI-Dienstes.
  • KI-Cron-Schedules 0 2 / 0 4 für Task-Pattern-Learner — Prompts ohne staff.id.
  • Spracherkennung: übernimmt der Browser (Web Speech API); je nach Browser bzw. Betriebssystem geht die Aufnahme dafür an dessen eigenen Spracherkennungsdienst — ROSIE erhält und speichert keine Audioaufnahmen. Zur Befehls-Erkennung geht nur der erkannte Text an den KI-Dienst, mit Einwilligung (Art. 6 Abs. 6 revDSG).
💡
DSG-Firewall: Anonymisierte Anfragen ohne Identifikatoren; Telefonnummer, AHV-Nummer, IBAN, E-Mail und Datum werden vor dem Versand entfernt, Namen nicht. Für Firewall-Freigaben beim Kunden: die Aufrufe des KI-Dienstes gehen von der Instanz aus, nicht vom Arbeitsplatz. Die Spracherkennung dagegen ruft der Browser vom Arbeitsplatz aus beim Dienst seines Anbieters auf.
🧩

Modul-System

Optionale Lizenz-Module pro Tenant

Optionale Lizenz-Module: Qualitätsmanagement (QMS), Voice-to-Schedule, Lohnvorbereitung & Finanzen, Smart Matchmaker, Belastungs-Radar, Regio-Netzwerk. Aktivierung pro Tenant über Admin → Tools.

♿

A11y & i18n

ESC + Focus-Trap, ARIA, 4 App-Sprachen
  • Globaler ESC + Focus-Trap (r166 A8).
  • ARIA-progressbar (r166 A9).
  • 4 App-Sprachen: DE / FR / IT / EN.
  • 14 Chat-Sprachen für die interne Kommunikation — die Übersetzung läuft im Gerät.
🔑

Secrets-Verwaltung

Secrets auf der Instanz · Rotation · Passwort-Hashing
  • Secrets liegen in /etc/rosie/env auf der Instanz, nur für den Dienstbenutzer lesbar: Signaturschlüssel der Sitzungen, VAPID-Schlüsselpaar, Zugangsdaten für Objektspeicher, SMTP und den KI-Dienst.
  • JWT jährlich rotieren.
  • VAPID-Rotation invalidiert Push-Subs (bekannte Schuld).
  • Passwort-Hashing: PBKDF2-SHA-256 mit Salt, in vier verketteten Runden zu je 100 000 Iterationen (400 000 effektiv).
🚀

Erst-Setup für IT

Was beim Kunden zu tun ist — und was nicht

Die Einrichtung eines Mandanten erfolgt beim Hersteller auf der Schweizer Instanz. Beim Kunden ist keine Installation nötig — keine Server, keine Agenten, keine eingehenden Ports. Was hier steht, ist die Liste der Punkte, die tatsächlich auf der Kundenseite liegen.

Nach dem Onboarding
1
Erreichbarkeit prüfen
curl -I auf die App-Adresse — Header inkl. X-Worker-Version prüfen.
2
Mailzustellung testen
Eine Einladung an eine Kundenadresse senden und die Quarantäne prüfen; support@rosie-app.ch freigeben.
3
AVV unterzeichnen
Auftragsbearbeitungsvertrag mit der Digital Passion GmbH abschliessen — sie ist Anbieterin und Auftragsbearbeiterin zugleich.
4
Admin-Account erstellen
Erster Administrator des Tenants.
🛠️

Troubleshooting & Support

SOPs, Eskalations-Stufen, Antwortzeit

Ablaufbeschreibungen liegen vor für: Anmeldefehler · Datenbankfehler · Deploy-Fehler · E-Mail-Zustellung · KI-Ausfall · Push-Zustellung · Migrationsfehler.

ℹ️
Support: support@rosie-app.ch. Reaktionszeiten regelt der Servicevertrag — nicht dieses Handbuch. Für Sicherheitsmeldungen gilt der Meldeweg unter /.well-known/security.txt.
Eskalations-Stufen
1️⃣
1st Level
Browser / Cache / PWA.
2️⃣
2nd Level
Netzwerk, Mailzustellung, MDM — alles, was auf der Kundenseite liegt.
3️⃣
3rd Level
Hersteller: Server-Logs, Datenbank, Release. Bitte mit X-Request-Id und Zeitpunkt melden.
🔒

Datenschutz-Verifikation

TLS / AES / Region / AVV / SSO-Status
  • Verschlüsselte Übertragung (TLS).
  • Feldweise Verschlüsselung. Vertrauliche Felder wie Diagnosen, Arztzeugnisse, Mutterschutzangaben, AHV-Nummer und IBAN; stündliche Sicherungen verschlüsselt (age).
  • Datenhaltung Schweiz (Infomaniak): Rechenleistung, Datenbank, Objektspeicher und Backups. Der vorgelagerte Schutzdienst der öffentlichen Website und der Zahlungsdienstleister stehen namentlich im Sub-Bearbeiter-Verzeichnis des AVV.
  • AVV vorhanden.
  • Keine Cookies / kein Tracking — DNT respektiert.
  • Schlüsselvernichtung als operativer Widerruf; Löschung innert 30 Tagen nach Vertragsende mit schriftlichem Nachweis.
  • SSO (SAML/OIDC) ist nicht verfügbar und in Evaluation; ein verbindlicher Termin besteht nicht. Anmeldung per E-Mail und Passwort, optional mit TOTP.
❓

FAQ für IT

Die häufigsten IT-Fragen — knapp beantwortet
Wo werden die Daten gespeichert?▶
In der Schweiz bei Infomaniak: Datenbank (libSQL/SQLite) und S3-kompatibler Objektspeicher. Die Übertragung ist verschlüsselt. Vertrauliche Felder wie Diagnosen, Arztzeugnisse, Mutterschutzangaben, AHV-Nummer und IBAN sowie die stündlichen Sicherungen werden verschlüsselt gespeichert. Die Vertragslage regelt der AVV; das Sub-Bearbeiter-Verzeichnis dort nennt alle Beteiligten.
Welche Firewall-Regeln braucht es?▶
Nur ausgehend HTTPS auf Port 443. Keine eingehenden Ports. Freigabe für rosie-app.ch und die App-Subdomäne genügt — Aufrufe an den KI-Dienst gehen von der Instanz aus, nicht vom Arbeitsplatz.
Gibt es Single Sign-On (SSO)?▶
Nein. SSO (SAML/OIDC) ist nicht verfügbar und in Evaluation; ein verbindlicher Termin besteht nicht. Anmeldung per E-Mail und Passwort, optional mit TOTP als zweitem Faktor.
Ist Observability deaktiviert?▶
Korrektur: Observability ist AKTIV — mit PII-Scrub und DNT-Honor. Es werden ausschliesslich anonymisierte Aggregate erhoben.
Wie werden Passwörter gehasht?▶
PBKDF2-SHA-256 mit Salt, in vier verketteten Runden zu je 100 000 Iterationen — 400 000 effektiv.
Warum ist auf iOS-Splash kein WebP erlaubt?▶
iOS akzeptiert für PWA-Splashscreens nur PNG. Seit r168 B8 ist WebP für Splash-Assets gedroppt — iOS-Splash MUSS als PNG vorliegen.
Wie funktioniert Push auf iOS?▶
Web-Push auf iOS funktioniert nur in der installierten PWA. MDM-Empfehlung: Webclip auf Homescreen erzwingen.
Warum ist rosie-planer.com nach Deploy kurz alt?▶
Der 301-Redirect der Aliasdomäne liegt hinter dem vorgelagerten Schutzdienst und kann kurz aus dem Zwischenspeicher kommen. Er konvergiert selbst. Forensik: Origin-Request mit Cache-Buster (?cb=<random>).
Wie identifiziere ich bei einem Incident die laufende Version?▶
curl -I auf die Domain — der Header X-Worker-Version nennt die aktive Release-Nummer, X-Request-Id die einzelne Anfrage für die Korrelation in den Server-Logs.

Rosie IT-Firmen-Handbuch · Version 9.9 · r396
Anbieterin und Auftragsbearbeiterin: Digital Passion GmbH, Haldenstrasse 16, 4600 Olten · CHE-154.512.796
Fragen? support@rosie-app.ch · rosie-app.ch
← Zurück zur Übersicht