Architektur & Schutzmassnahmen
Questi contenuti non sono ancora disponibili nella tua lingua.
Diese Seite richtet sich an IT-Verantwortliche, Treuhänder und Sicherheitsbeauftragte, die einen technischen Überblick benötigen. Wenn Sie Betreiber sind und nur die Kurzfassung wollen, finden Sie diese auf der Übersichtsseite.
Grundsatz
Abschnitt betitelt „Grundsatz“CampOne ist eine mehrmandantenfähige SaaS-Anwendung. Backend (Django 5.2, Python 3.12), Admin-Frontend (React 19, Vite 6) und Datenbank (Supabase PostgreSQL, EU-Region) sind drei klar getrennte Komponenten, die ausschliesslich über verschlüsselte Verbindungen (TLS 1.2+) miteinander reden.
Authentifizierung
Abschnitt betitelt „Authentifizierung“| Element | Wert |
|---|---|
| Token-Verfahren | JWT (RFC 7519), Algorithmus HS256, Bearer-Header |
| Lebensdauer Access-Token | 30 Minuten, ausschliesslich im Speicher des Browsers |
| Lebensdauer Refresh-Token | 7 Tage, in einem HttpOnly; Secure; SameSite=None Cookie |
| Rotation | Refresh-Tokens werden bei jeder Erneuerung ausgetauscht; das alte Token wird sofort gesperrt |
| Abmeldung | Server-seitiges Sperren des Refresh-Tokens plus Cookie-Löschung |
| Passwort-Politik | Mindestlänge, Ähnlichkeitsprüfung, Liste der häufigsten Passwörter, kein rein numerisches Passwort |
| Passwort-Hash | Django-Standardpipeline (PBKDF2 als Primär, Argon2 verfügbar), Cost-Factor rotierbar |
| Passwort-Reset | Einmalig verwendbarer HMAC-Token, Standardgültigkeit 3 Tage |
| Sitzungslimit | Pro Mandant nach Plan begrenzt (z.B. Starter 2, Professional 5) — älteste Sitzungen werden bei Überschreitung abgemeldet |
Mandantentrennung
Abschnitt betitelt „Mandantentrennung“Jede Anfrage wird durch eine TenantMiddleware geschleust, die den Mandanten in dieser Reihenfolge ermittelt:
- Aus dem JWT-Claim
tenant_id(für authentifizierte Aufrufe). - Aus dem
X-Tenant-SlugHeader (für unauthenticierte öffentliche Endpunkte). - Aus der Custom-Domain im Origin-Header (für Gäste-Buchungs-Webseiten).
Anschliessend wendet ein TenantManager automatisch den Filter tenant=<aktueller> auf jede Datenbankabfrage an. Es ist nicht möglich, ohne explizite, im Code grep-bare Mandantenwechsel-Logik auf Daten eines anderen Betriebs zuzugreifen.
Nicht aktive Mandanten (is_active=False) werden nie aufgelöst — die Deaktivierung wirkt sofort als Notausschalter.
Rollen & Berechtigungen
Abschnitt betitelt „Rollen & Berechtigungen“| Rolle | Beschreibung |
|---|---|
| Superadmin | CampOne-interner Support. Kein Mandant zugewiesen. Zugriff auf einen Echt-Mandanten erfordert eine genehmigte Support-Anfrage. |
| Tenant-Admin | Vollzugriff innerhalb des eigenen Mandanten. Kann Mitarbeitende anlegen und Module zuweisen. |
| Staff | Eingeschränkter Zugriff auf zugewiesene Module (z.B. nur Rezeption oder nur Kasse). |
| Customer | Gast mit Zugriff auf eigene Buchungen über das Gästeportal. |
CampOne-Support kann auf einen Echt-Mandanten in drei Modi zugreifen, und dies wird stets im Audit-Log festgehalten:
- Mock: ein gemeinsamer, synthetischer Beispiel-Mandant. Keine Genehmigung nötig.
- Maskiert: Ihr Mandant, aber alle persönlichen Daten der Gäste sind in den Antworten ausgeblendet, und schreibende Aktionen werden serverseitig blockiert. Keine Genehmigung nötig.
- Real: Ihr Mandant mit Vollzugriff. Erfordert eine genehmigte Support-Zugangsanfrage. Token-Lebensdauer 30 Minuten.
Transport & Sicherheits-Header
Abschnitt betitelt „Transport & Sicherheits-Header“| Header | Wert |
|---|---|
Strict-Transport-Security | max-age=31536000; includeSubDomains; preload (1 Jahr, Preload-Liste) |
Content-Security-Policy | mit frame-ancestors 'none' und auf bekannte Quellen beschränkten connect-src und img-src |
X-Frame-Options | DENY |
X-Content-Type-Options | nosniff |
Referrer-Policy | strict-origin-when-cross-origin |
Permissions-Policy | geolocation=(), microphone=(), camera=() |
Alle vier ausgelieferten Web-Frontends (Admin, Marketing, Docs, mandantenspezifische Buchungs-SPAs) setzen diese Header am Vercel-Edge zusätzlich zur Backend-Konfiguration.
Daten in Ruhe
Abschnitt betitelt „Daten in Ruhe“| Datentyp | Speicherort | Schutz |
|---|---|---|
| Datenbank | Supabase PostgreSQL, AWS Frankfurt-Region (eu-west-1) | TLS-Verbindung, tägliche Backups, Point-in-Time-Recovery |
| Datei-Uploads | Supabase S3, EU-Region | private ACL, mandantenspezifische Pfade, signierte URLs für jeden Zugriff |
| Mandanten-Geheimnisse (Stripe-Keys, SMTP-Passwörter) | Datenbank | Anwendungsseitig verschlüsselte Felder, eigener Schlüssel pro Umgebung |
| Logs | Volume des Backend-Hosters | Rotation alle 5 MB, max. 5 Generationen, kein PII in Anfrageparametern |
Drosselung & Missbrauchsschutz
Abschnitt betitelt „Drosselung & Missbrauchsschutz“| Endpunkt | Schwelle |
|---|---|
| Anmeldung | 10 Versuche/Minute pro IP |
| Passwort-Reset | 5 Versuche/Stunde pro IP |
| Konto-Löschung | 3 Versuche/Stunde pro Konto |
| Verfügbarkeitssuche (öffentlich) | 60 Anfragen/Minute pro IP |
| AI-Assistent (anonym) | 20 Anfragen/Stunde pro IP |
| Public API pro Schlüssel | konfigurierbar, Standard 1000/Stunde |
Zusätzlich erzwingt die Anwendung pro Mandant ein Limit gleichzeitiger Sitzungen — älteste Refresh-Tokens werden bei Überschreitung gesperrt.
Schutz öffentlicher Schnittstellen
Abschnitt betitelt „Schutz öffentlicher Schnittstellen“- Public API (
/api/v1/public/): API-Key-Authentifizierung mit Formatck_<prefix><secret>, in der Datenbank wird nur der gesalzene Hash gespeichert, der Klartext ist nach der Erstellung nicht wiederherstellbar. Jeder Aufruf wird inAPICallLogmit Status, Pfad und Latenz protokolliert. Bodies werden nicht geloggt — der Audit-Trail enthält keine personenbezogenen Inhalte. - Webhooks: Stripe-Webhooks werden mit dem mandantenspezifischen Webhook-Secret signaturgeprüft. Der OTA-Webhook (Booking.com) authentifiziert sich per HTTP-Basic über TLS.
- Lead-Formular auf der Marketing-Webseite: Validierung über
react-hook-formundzod, serverseitiges Drosseln auf 20 Anfragen/Stunde pro IP.
Audit-Trail
Abschnitt betitelt „Audit-Trail“Sechs separate, mandantenspezifische und indizierte Tabellen halten relevante Vorgänge fest:
UserLoginLog— jede erfolgreiche Anmeldung mit IP-Adresse und Zeitstempel.BookingAuditLog— jede Änderung an einer Buchung als Diff-Eintrag mit Akteur und Begründung.SupportAuditEvent+SupportAccessSession— jede Support-Sitzung von CampOne in Ihren Mandanten.APICallLog— jeder Aufruf über die Public API.MessageLog— jeder verschickte transaktionale E-Mail-Versand.ErrorLog— unbehandelte Fehler im Backend.
Detaillierte Beschreibung auf der Audit-Trail-Seite.
Software-Stand
Abschnitt betitelt „Software-Stand“CampOne läuft auf den jeweils aktuellen Hauptversionen:
| Komponente | Version |
|---|---|
| Django | 5.2 |
| Django REST Framework | 3.17 |
| SimpleJWT | 5.4 |
| React | 19 |
| Vite | 6 |
| Python | 3.12 |
| PostgreSQL | 15 (Supabase) |
Es gibt keine End-of-Life-Komponenten im produktiven Einsatz. Sicherheitspatches werden in den jeweils nächsten Wartungs-Release übernommen; kritische Updates werden ausserhalb des regulären Release-Zyklus eingespielt.
Verifizierbarkeit
Abschnitt betitelt „Verifizierbarkeit“Diese Seite ist eine Zusammenfassung. Für ein technisches Audit stellen wir auf Anfrage zur Verfügung:
- die interne Sicherheitsposture-Dokumentation mit Verweisen auf jede einzelne Code-Stelle,
- den nDSG-Compliance-Audit-Bericht,
- den aktuellen Sicherheits-Roadmap-Stand mit Risikoeinstufungen,
- Zugriff auf eine Test-Umgebung zur eigenständigen Überprüfung.
Anfragen an security@campone.ch.