Sicherheitsarchitektur
Heinzel Pro ist so gebaut, dass das Modell vorschlagen darf, aber nur Menschen und Code entscheiden. Diese Seite beschreibt die Kontrollen und ihre Grenzen.
Kontrollen für ein Audit
Verwaltung, Kontrollen ordnet die Schutzmaßnahmen des Produkts (Freigabe, Vier-Augen-Prinzip, Rollen, Anmeldung, Audit-Protokoll, Schlüssel, Änderungsnachweis) Kontrollen aus ISO/IEC 27001:2022 Anhang A, den Reihen der SOC-2-Kriterien und Bausteinen des BSI IT-Grundschutz-Kompendiums zu, jeweils mit dem Stand im Mandanten und einem Verweis auf den Nachweis. Es ist eine Zuordnung für das Gespräch mit einem Prüfer, kein Zertifikat.
Vertrauensgrenzen
- Der Modellanbieter erhält den System-Prompt, die Session und von Geheimnissen bereinigte Befehlsausgaben. Der Anbieter kann ein Server im eigenen Netz sein (Ollama, vLLM); dann verlässt nichts das Intranet. Nie erhält er SSH-Schlüssel, den Vault-Schlüssel, Zugangsdaten von Benutzern oder das Audit-Protokoll.
- Server erhalten genau die Befehle, die in der Oberfläche stehen, über SSH mit einem Schlüssel pro Server, den Heinzel Pro erzeugt hat und verschlüsselt aufbewahrt.
- Der Browser erhält nur, was die Rolle des Benutzers erlaubt.
Was die Installation verlässt
Eine Installation öffnet Verbindungen zu den Stellen unten und zu keiner anderen. Jede haben Sie selbst eingetragen, mit einer Ausnahme, dem Regelwerk. Es gibt keine Telemetrie, keine Nutzungszahlen und keine Lizenzprüfung. Die Liste ist vollständig, und ein Test in der Testsuite des Produkts schlägt fehl, sobald der Code eine Verbindung öffnet, die hier nicht steht.
- Modellanbieter. Die Adresse jedes Anbieters, den Sie anlegen,
voreingestellt
api.anthropic.comoderapi.openai.com, oder ein Server im eigenen Netz. Einer, der über eine VPN-Verbindung oder einen Server erreicht wird, wird innerhalb dieser Verbindung gewählt oder über das SSH dieses Servers weitergeleitet, nie aus dem Netz der Installation. Er erhält, was unter Vertrauensgrenzen steht, sobald eine Session arbeitet. - Ihre Server. SSH zu den Hosts, die Sie anlegen, auf dem Port, den Sie angeben.
- VPN-Verbindungen. WireGuard zur Gegenstelle aus dem Block, den Sie eingefügt haben. Eine Tailscale-Verbindung spricht mit dem Koordinationsserver und den Relays von Tailscale oder mit dem Headscale-Server, den Sie nennen; der Helfer startet mit abgeschaltetem Log-Upload.
- Mail. Der Mailserver oder Maildienst, den Sie eingerichtet haben.
Microsoft 365 ohne SMTP meldet sich bei
login.microsoftonline.coman und sendet übergraph.microsoft.com. - Endpunkte, die Sie eintragen. Der Webhook des Teams, der Kollektor, an den das Audit-Protokoll geht, das Monitoring, das Markierungen annimmt. Jeder bleibt still, bis ein Mandant eine Adresse einträgt.
- Single Sign-on. Der OpenID-Connect-Aussteller, den Sie einrichten, wenn sich jemand darüber anmeldet.
- Regelwerk.
api.github.comundgithub.com, nur wenn ein Administrator der Installation unter Einstellungen, Regelwerk auf Prüfen oder Aktualisieren drückt. Die Anfrage liest das öffentliche Heinzel-Repository ohne Konto und trägt nichts über die Installation; GitHub sieht ihre Adresse. Wer das Archiv hochlädt, öffnet diese Verbindung nie. Die Kopie des Regelwerks, die ein Image mitbringt, wurde beim Bau des Images auf demselben Weg geholt (mix heinzel.rules.sync), vom Entwickler, nie von einer Installation. - Modellkatalog. Wird nie geholt. Der Katalog der Modelle, den ein Image
mitbringt, mit den Tagen, an denen ihr Anbieter sie abschaltet, wurde beim
Erstellen mit Anthropics Abkündigungsseite auf
platform.claude.comverglichen (mix heinzel.catalog check), vom Entwickler, nie von einer Installation. Ein neuerer Katalog zwischen zwei Releases wird von Hand eingefügt.
Docker selbst holt das Image von ghcr.io, wenn Sie es ziehen.
Weg eines Befehls
- Das Modell ruft
run_commandmit Server, Befehl und einer einzeiligen Begründung auf. - Der Classifier stuft den Befehl in eine Risikoklasse ein: nur lesen,
schreibend, Paket, Dienst, Firewall, Neustart, unumkehrbar, gesperrt. Er
zerlegt Pipes,
&&,;, Subshells,sudoundsh -cund fällt im Zweifel zu: Was er nicht lesen kann, ist mindestens „schreibend“. Die Klasse wird im Code bestimmt und dem Operator angezeigt; das Modell kann sie nicht beeinflussen. - Regelwerk: Gesperrte Befehle laufen nie. Gesperrte Server lehnen alles ab. Nur-lesen-Server lehnen alles Schreibende ab. Unbeaufsichtigte Läufe überspringen alles außer Lesebefehlen.
- Autonomie: wie viel ohne einen Menschen läuft, in den Buchstaben eines
Modus:
rw(Befehle, die nur lesen) oderrwx(was die Matrix des Mandanten allein laufen lässt, voreingestellt alles außer Identitäten und Gesperrtem), und eine Session kann wählen, dass jeder Befehl wartet. Eine Stufe dazwischen gibt es nicht: Jede Klasse oberhalb des Lesens enthält Befehle, die andere Programme starten oder die Verbindung kappen. Es zählt das Niedrigste aus mehreren: die Obergrenze, die die Installation dem Mandanten gibt, die Buchstaben der Beteiligten auf dem Server (die des Besitzers deckeln sie), und die Wahl für die Session. Beteiligt sind der Besitzer der Session und wer die gerade bearbeitete Nachricht geschickt hat. Ein Befehl aus mehreren Teilen läuft nur allein, wenn jeder Teil es darf. - Freigabe, für das, was die Stufe nicht selbst ausführt: Die Matrix des Mandanten (Einstellungen, Richtlinie) sagt je Klasse und Stufe, ob der Befehl auf eine Person wartet, auf zwei oder nie läuft; ein Server stellt eine Zelle nur strenger. Voreingestellt brauchen unumkehrbare Befehle und Identitäten zwei Freigaben von zwei verschiedenen Personen, die zweite von einem Freigeber oder Administrator; alles andere braucht eine.
- Ausführung über eine gepoolte SSH-Verbindung mit Zeitlimit. Exit-Code, stdout und stderr werden gespeichert, Operatoren unbereinigt gezeigt und dem Modell bereinigt zurückgegeben.
- Jeder Schritt landet mit Akteur und Zeitstempel im Audit-Protokoll.
Eine Ablehnung ist für diesen Aufruf endgültig: Das Modell erfährt, wer abgelehnt hat und warum, und wird angewiesen, nicht umzuformulieren.
Die eigene Sperrliste eines Mandanten
Neben der Liste im Klassifizierer fügen die Administratoren eines Mandanten Befehle hinzu, die dort nie laufen (Einstellungen, Befehle): überall oder auf einem Server. Eine Regel in Worten sperrt diese Worte in dieser Reihenfolge innerhalb eines Befehls einer Zeile; eine Regel kann auch ein regulärer Ausdruck über die ganze Zeile sein. Statt zu sperren kann eine Regel einen Befehl höher einstufen („zählt als“), nie tiefer: Die Matrix entscheidet dann wie für diese Klasse. Geprüft wird beim Vorschlag eines Befehls und noch einmal unmittelbar vor dem Ausführen, sodass auch eine nach der Freigabe angelegte Regel greift. Eine Regel benennt eine Schreibweise, und ein Befehl lässt sich anders schreiben: Die Liste ist ein Netz für Befehle, die ein Team nie will. Ein Host, der sich gar nicht ändern darf, wird auf „nur lesen“ gestellt.
Server-Sperre
Der Besitzer eines Hosts sperrt ihn gegen Änderungen, ohne Zugang zu Heinzel Pro, mit einer Datei auf dem Host, die auch das offene Heinzel beachtet:
# /etc/heinzel.conf
allow_changes = false
reason = Datenbank-Migration bis 20.10.Bevor ein Befehl, der den Host ändert, vorgeschlagen wird, und noch einmal
direkt bevor ein freigegebener läuft, liest Heinzel Pro die Datei über SSH.
Nur eine fehlende Datei oder allow_changes = true lässt die Änderung
durch; eine leere oder unlesbare Datei, jeder andere Wert oder eine
Prüfung, die nicht antwortet, verweigert sie, mit dem Grund des Besitzers
am Befehl. Lesen läuft wie bisher. Der Klassifikator blockiert jeden
Befehl, der die Datei schreibt, verschiebt oder löscht, also hebt nur der
Besitzer die Sperre auf. Sie hält Heinzel zurück, keinen Menschen mit
root auf dem Host.
Not-Aus
Die Administratoren eines Mandanten haben einen Schalter (Einstellungen, Allgemein), die der Installation einen für alle Mandanten (Mandanten). Das Auslösen verlangt einen Grund. Er stoppt jede Session, nimmt jeden Befehl zurück, der auf Freigabe wartet, bricht auf Hosts laufende Befehle ab, und von da an startet keine Session, läuft kein Befehl, feuert kein Zeitplan und nimmt nach einem Neustart nichts die Arbeit wieder auf, bis er aufgehoben wird. Geprüft wird er dort, wo Arbeit beginnt, und noch einmal unmittelbar bevor ein Befehl läuft. Wer ihn ausgelöst und aufgehoben hat und warum, steht im Audit-Protokoll; ein Banner auf jeder Seite zeigt, dass er an ist.
SSH
- Schlüsselpaare in der Anwendung erzeugt, eines pro Server oder eines für
eine Servergruppe, privater Schlüssel mit AES-256-GCM verschlüsselt. Kein
Import, kein Export. Nichts wird nach
~/.sshgeschrieben. - Ed25519, außer man wählt beim Anlegen oder Rotieren ECDSA (P-256, P-384,
P-521) oder RSA 4096, weil ein Host oder eine Richtlinie es verlangt.
RSA-Schlüssel signieren nur mit SHA-2. Ein Host, der allein
SHA-1-Signaturen (
ssh-rsa) kennt, also OpenSSH vor 7.2, bleibt unerreichbar. - Host-Keys werden bei der ersten Verbindung gespeichert (oder vorab eingetragen). Ein geänderter Host-Key verweigert die Verbindung, markiert den Server und alarmiert Administratoren.
- Nur Public-Key-Authentifizierung; keine Passwörter, kein Agent-Forwarding.
- SSH-Zertifizierungsstellen werden gelesen, nicht betrieben. Der
Verbindungstest hält fest, welcher User-CA ein Host vertraut, wo Principals
und Sperrliste liegen und wann seine Host-Zertifikate ablaufen. Heinzel Pro
signiert nichts, schreibt keine sshd-Direktive und meldet sich mit dem eigenen
Schlüssel an; ein Host, der nur Zertifikate annimmt
(
AuthorizedKeysFile none), lässt sich deshalb nicht verwalten.
Was auf einem Host liegen bleibt
Ein Befehl, der nur liest, läuft in seinem SSH-Kanal und hinterlässt nichts.
Ein Befehl, der etwas ändert oder eine längere Laufzeit bekommen hat, läuft
als Job: ein Verzeichnis ~/.heinzel/jobs/<Befehls-ID> im Konto, unter dem
er läuft, Modus 700, mit dem Befehlstext, der Ausgabe, dem Exit-Code und
zwei Prozessnummern. Heinzel Pro liest das Ergebnis dort, auch nach einem
eigenen Neustart, und löscht das Verzeichnis, sobald das Ergebnis gespeichert
ist. Ein Verzeichnis, das niemand mehr abgeholt hat, verschwindet nach sieben
Tagen beim nächsten Job-Start auf diesem Host.
Ein Befehl, der ein Geheimnis oder den neuen Inhalt einer Datei über seine Eingabe bekommt, bleibt immer im Kanal; dafür landet nichts davon auf der Platte des Hosts. Der Befehlstext eines Jobs liegt auf dem Host, solange der Job läuft; ein Geheimnis steht nie darin, siehe Geheimnisse.
Stopp einer Session, Zeitüberschreitung und Not-Aus beenden den Job über die
Prozessgruppe, die sshd ihm gegeben hat: erst TERM, dann KILL für alles, was
nicht hört. Der Aufbau ist der aus der Regel ssh-connections, Abschnitt 4,
des offenen Heinzel.
VPN
- Jede VPN-Verbindung ist ein eigener WireGuard-Tunnel in einem eigenen
Prozess (
wireproxy, WireGuard im Userspace). Der Container bekommt keine Netzwerkschnittstelle und keine Privilegien dafür; nichts von dieser Maschine wird in einen Tunnel geroutet. - In einen Tunnel gelangt nur, was Heinzel Pro für einen Server anwählt, der diese Verbindung nennt. Der Helfer öffnet dafür eine SOCKS5-Tür auf der Loopback-Adresse, deren Passwort bei jedem Start neu gewürfelt wird und das nur Heinzel Pro und der Helfer kennen.
- Zwei Mandanten mit demselben privaten Netz begegnen sich nicht: Die Tunnel teilen weder Adressen noch Routen, und ein Server kann nur eine Verbindung seines Mandanten nennen (zusammengesetzter Fremdschlüssel).
- Im Tunnel bleibt SSH, was es ist: eigener Schlüssel, gespeicherter Host-Key. Der Tunnel ersetzt keine der beiden Prüfungen.
- Schlüssel liegen verschlüsselt wie alle Geheimnisse. Wählt sich die
Gegenseite ein, erzeugt Heinzel Pro auch deren Schlüssel und behält ihn,
um die fertige Datei erneut zeigen zu können; er öffnet nichts als diesen
einen Tunnel. Die Konfigurationsdatei des Helfers liegt nur während
seines Starts unter
/tmpund wird danach gelöscht. - Eine Verbindung in ein Tailscale-Netz ist ein eigenes
tailscaledim Userspace, also ein eigenes Gerät je Verbindung. Der Auth-Key liegt verschlüsselt vor, bis das Gerät beigetreten ist, und wird dann gelöscht; was das Gerät über sich weiß (sein Zustand mit dem Geräteschlüssel), liegt danach verschlüsselt bei der Verbindung. An Tailscales Log-Server wird nichts gesendet. Anders als bei WireGuard hat die SOCKS5-Tür dieses Helfers kein Passwort: Sie liegt auf der Loopback-Adresse eines Containers, in dem sonst nichts läuft, und die Trennung der Mandanten hängt hier allein am Code, der sie anwählt. - Die Gegenseite schaltet ab, ohne zu fragen: den Dienst stoppen, das Gerät am Router löschen oder aus dem Tailscale-Netz entfernen.
Mandanten
- Jede Tabelle mit Daten eines Mandanten trägt den Mandanten. Die Datenbankschicht bindet jeden Prozess (eine Anfrage, eine LiveView, den Agenten, einen Job, eine SSH-Verbindung) an einen Mandanten und ergänzt ihn bei jedem Lesen, Ändern und Löschen. Ein Prozess ohne Mandant kann eine solche Tabelle gar nicht lesen: Die Abfrage bricht ab. Ein Einfügen ohne Mandant verletzt NOT NULL.
- Verweise zwischen Mandantentabellen tragen den Mandanten im Fremdschlüssel. Die Datenbank selbst verweigert damit einen Server, der auf den Schlüssel eines anderen Mandanten zeigt, oder einen Befehl auf dessen Server.
- Der Agent läuft gebunden an den Mandanten seiner Session. Seine Werkzeuge suchen Server nur innerhalb dieses Mandanten; ein Host eines anderen ist für ihn ein unbekannter Server, und Modellanbieter und API-Schlüssel sind die seines Mandanten.
- Der Mandant einer Sitzung wird bei jeder Anfrage gegen die Mitgliedschaft geprüft und steht ab der ersten Anfrage fest. Ist er gefälscht, geschlossen oder dem Benutzer nicht mehr offen, wird neu gewählt; die Anfrage selbst verfällt. Eine Seite trägt den Mandanten, in dem sie erzeugt wurde, und verbindet sich nicht in einen anderen.
- Jede Kette des Audit-Protokolls wird für sich exportiert: Die Datei eines Mandanten enthält nichts aus dem Protokoll der Installation (Anmeldungen, Adressen von Menschen, die woanders arbeiten).
- Live-Aktualisierungen und Benachrichtigungen werden pro Mandant veröffentlicht. Hintergrundjobs tragen ihren Mandanten und werden abgebrochen, wenn er geschlossen ist.
- Jeder Mandant hat eine eigene Audit-Kette, nummeriert ab eins, und liest, exportiert, prüft und kürzt nur diese; Mandant und Nummer stehen unter dem Hash. Anmeldungen und was sonst außerhalb eines Mandanten geschieht, bilden die Kette der Installation, die deren Administratoren lesen. Kein Mandant erkennt an seinem Protokoll, wie viel ein anderer tut.
- Was ein Konto als solches betrifft (Passkeys, zweiter Faktor, Sitzungen, Sperre), steht in der Kette der Installation, weil ein Konto mehrere Mandanten umfasst. Eine Warnung über fehlgeschlagene Anmeldungen geht an die Mandanten, in denen das Konto arbeitet.
- Ein Konto betritt einen Mandanten erst, nachdem sein Inhaber die Einladung angenommen hat. Bis dahin sieht der einladende Mandant die eingetippte Adresse und nichts vom Konto, und er erkennt nicht, ob die Adresse schon ein Konto hatte.
- Eine Seite, die offen ist, während sich eine Rolle ändert, ein Mitglied entfernt oder ein Mandant geschlossen wird, wird getrennt und kommt mit den neuen Rechten zurück. Das Schließen eines Mandanten stoppt auch seine Agenten und SSH-Verbindungen.
- Adressen, die der Server selbst aufruft (Basis-URL des Modells, Webhook), legen nur die Administratoren der Installation fest. Ein Mandant kann den Server damit nicht in das Netz lenken, in dem er läuft.
Adressen, die ein Mandant einträgt
Ein Webhook, ein Modellanbieter, ein Server: Die Installation wählt, was ein Mandant nennt. Im eigenen Rechenzentrum ist das der Zweck, und eine solche Adresse darf in Ihrem Netz liegen. Eine Installation, die für Mandanten gehostet wird, die ihr Betreiber nicht kennt, lehnt Adressen ab, die zu ihr selbst zurückführen: die Loopback-Adresse, jede Adresse der eigenen Netzwerkschnittstellen, die privaten und link-lokalen Bereiche und Netze, die der Betreiber nennt. Das Formular lehnt eine solche Adresse ab, wenn sie ausgeschrieben ist. Ein Name wird beurteilt, wenn er gewählt wird, nach der Adresse, zu der er in diesem Moment auflöst, und die Verbindung geht an genau diese Adresse; ein Name, der nach dem Speichern umgebogen wird, gewinnt also nichts. Einer Antwort, die weiterleitet, wird nicht gefolgt. Server hinter einer VPN-Verbindung des Mandanten werden durch deren Tunnel erreicht und sind nicht betroffen.
Zwei Grenzen, beide bei VPN-Verbindungen, deren Helfer Namen selbst auflösen. Der Name des Routers oder des Anmeldeservers wird vor jedem Start geprüft, nicht festgelegt. Und ein Server hinter einer Verbindung wird nur abgelehnt, wenn seine Adresse diese Maschine ausschreibt: Ein Name wird im Tunnel aufgelöst, wohin die Installation nicht sehen kann, und was dort antwortet, wird in SSH angesprochen und in nichts sonst.
Benutzer
- Passkeys (WebAuthn) als Anmeldeweg. Gespeichert wird nur der öffentliche Schlüssel. Ein Passkey muss auffindbar sein und seinen Benutzer prüfen, ist damit zwei Faktoren in einem Schritt und überspringt den TOTP-Code; eine Antwort gilt einmal und nur für die konfigurierte öffentliche Adresse, und ein Signaturzähler, der rückwärts läuft, wird als kopierter Schlüssel abgelehnt. Zum Hinzufügen muss die Anmeldung höchstens zehn Minuten alt sein. Es wird keine Attestierung verlangt, jeder Authenticator wird akzeptiert. Ist 2FA Pflicht, richtet trotzdem jeder Benutzer TOTP ein, weil die Anmeldung mit Passwort möglich bleibt.
- Jede Anmeldung ist eine eigene Sitzung, gebunden an einen Browser. Die Kontoseite listet sie mit System, Adresse und letzter Aktivität; ein Benutzer beendet jede davon oder alle außer der aktuellen, und die offenen Seiten des Geräts schließen sich sofort.
- Passwortanmeldung mit bcrypt, Anmeldelinks per Mail oder OpenID Connect. Passwörter lassen sich abschalten, sobald SSO funktioniert.
- TOTP als zweiter Faktor pro Benutzer; kann Pflicht sein.
- Rollen (Betrachter, Operator, Freigeber, Administrator) mit einzelnen Rechten, die je Person gegeben oder genommen werden; eine Person kann nur einen Teil der Server sehen. Rechte zum Ansehen belegen keinen Platz.
- Inaktive Sitzungen enden nach einstellbarer Zeit. Das Deaktivieren eines Benutzers beendet seine Sitzungen sofort.
- Anmeldeversuche sind pro Adresse begrenzt; wiederholte Fehlversuche lösen einen Alarm aus.
Audit-Protokoll
Nur anhängbar auf Datenbankebene (ein Trigger verweigert UPDATE und DELETE),
mit einer SHA-256-Hash-Kette über jede Zeile. „Kette prüfen“ in der Oberfläche
oder bin/heinzel_pro eval HeinzelPro.Release.verify_audit erkennt Lücken und
Änderungen. Das Löschen nach Aufbewahrungsfrist ist, wenn eingerichtet, der
einzige Weg, Zeilen zu entfernen, und wird selbst protokolliert.
Gespeicherte Geheimnisse
API-Schlüssel, OIDC-Client-Secrets, Webhook-URLs, private SSH-Schlüssel und TOTP-Geheimnisse sind mit einem Schlüssel aus der Umgebung verschlüsselt. Die Rotation verschlüsselt alle neu; siehe upgrade.md.
Web
Content Security Policy ohne Inline-Skripte, strikte Referrer-Policy,
CSRF-Schutz auf jedem Formular, HSTS bei FORCE_SSL, Prüfung der
WebSocket-Origins, signierte und verschlüsselte Cookies.
Bekannte Grenzen
- Ein Link zu einer Session ist ein Geheimnis in einer URL: Wer ihn bekommt, liest die Session, bis er endet. Die Seite schwärzt, was die Bereinigung als Geheimnis erkennt, anhand von Mustern; Hostnamen, Befehle und alles, was sie nicht erkennt, bleiben sichtbar. Links sind aus, solange kein Administrator des Mandanten sie erlaubt, und ihre Aufrufe stehen nicht im Request-Log.
- Auf der Stufe „alles allein“ steht zwischen Modell und Server nichts als die Sperrliste und der Modus des Servers. Die Ausgabe eines Befehls ist Text, den das Modell liest; auf einem kompromittierten Host kann dieser Text versuchen, es zu lenken. „Alles allein“ nur Servern und Personen geben, bei denen das vertretbar ist, und die Obergrenze eines Mandanten sonst darunter lassen. Die Vier-Augen-Regel gilt nicht für das, was ohne Freigabe läuft.
- Zwei Dinge lassen einen Befehl unterhalb von „alles allein“ ohne Person laufen: eine Dauerfreigabe, die genau eine Befehlszeile abdeckt und nie eine unumkehrbare, und eine erhöhte Stufe auf einem Server für höchstens vier Stunden. Beide setzt ein Administrator, beide stehen im Audit-Protokoll. Wo die Richtlinie es verlangt, wartet, was allein lief, unter Sessions, Gegenzeichnen auf die Unterschrift einer zweiten Person.
- Ausgaben, die wie Anweisungen an den Agenten klingen, werden dem Modell vorenthalten, bis ein Mensch sie freigibt. Die Prüfung kennt die üblichen Formulierungen; Text, der sie umgeht, kommt durch. Sie senkt das Risiko aus dem Punkt darüber und beseitigt es nicht.
- Der Classifier ist ein Filter, keine Sandbox. Ein Befehl der Klasse „schreibend“ kann Schaden anrichten; deshalb sieht ihn ein Mensch.
- Die Bereinigung von Geheimnissen arbeitet mit Mustern. Ungewöhnliche Ausgabeformate können durchrutschen.
- Mandanten teilen sich eine Datenbank, einen Vault-Schlüssel und einen Anwendungsprozess. Die Trennung erzwingen die Anwendung und Fremdschlüssel, nicht getrennte Datenbanken oder Row-Level-Security in PostgreSQL. Wer die Installation, die Datenbank oder den Vault-Schlüssel verwaltet, erreicht jeden Mandanten.
- Die Sperre für Abfragen sieht Tabellen, die über ihr Schema benannt sind. Rohes SQL und Fragmente liegen außerhalb; der Code enthält keine auf Mandantentabellen.
- Die Lizenz wird offline mit einem eingebauten öffentlichen Schlüssel geprüft. Wer den Container neu baut, kann sie umgehen; sie soll ehrliche Kunden ehrlich halten, nicht einen entschlossenen Angreifer stoppen.