Datenschutz¶
Wo personenbezogene Daten in einem Deployment liegen, was es verlässt und unter welcher Konfiguration, welche Kontrollen im Code existieren und einen Test hinter sich haben und welche noch offene Issues sind. Geschrieben für den, der eine Datenschutzprüfung eines Deployments beantwortet — einen Datenschutzbeauftragten, einen Sicherheitsverantwortlichen, einen Betreiber — und ehrlich gehalten über den Unterschied zwischen dem, was die Software kann, und dem, was ein Deployment tatsächlich entschieden hat.
Eine Seite ist keine Compliance
Nichts hier ist ein Nachweis, dass ein Deployment die DSGVO einhält. Die Codebasis lässt sich innerhalb einer konformen Umgebung betreiben; ob eine solche es ist, hängt von den konfigurierten Providern ab, von der entschiedenen Aufbewahrung, den unterzeichneten Verträgen und dem Betreiber, der sie führt. Jede dieser Bedingungen ist unten als etwas benannt, das zu beschaffen und zu prüfen ist, nie als etwas Angenommenes.
Standardmäßig verlässt nichts das System¶
Ein frisches Deployment hält alles in seinem eigenen PostgreSQL und auf seiner eigenen Platte und sendet nirgendwohin etwas. Jeder Sprung nach außen ist eine Zeile oder eine Einstellung, die jemand danach hinzufügt: ein Model-Profil, das einen Provider benennt, eine Collection, die einen Parser wählt, eine Suchmethode auf einem Spec, ein Logfire-Token, ein mem0-Host, ein MCP-Server, ein Kanal-Bot. Entfernen Sie die Zeile, und der Sprung ist weg.
Ein Deployment, das keine dritte Partei in der Kette will, konfiguriert sich entsprechend, und die Software macht mit:
| Thema | Die lokale Antwort |
|---|---|
| Das Chat-Model | Ein ollama- oder litellm-Profil — schlüssellos, auf einen Endpunkt gerichtet, den Sie selbst betreiben. Jeder der 28 Provider mit base_url nimmt auch ein Gateway von Ihnen |
| Dokumenten-Parsing | pymupdf, der Standard, läuft im Worker. LiteParse-OCR läuft ebenfalls im Worker oder an einem OCR-Server, den Sie als lokalen Dienst registrieren. LlamaParse ist eine Wahl je Collection und braucht einen Vault-Schlüssel; ohne einen wird nichts außer Haus geparst |
| Embeddings | Ein Ollama, das Sie betreiben, unter Knowledge → Integrations als lokaler Dienst registriert und je Collection als Provider ollama gewählt. Schlüssellos, und der einzige Provider, den eine app-scoped Collection nutzen darf |
| Traces | Lassen Sie LOGFIRE_TOKEN ungesetzt und binden Sie kein observability-Token an einen Spec oder ein Environment. Runs halten die Trace-Id weiterhin lokal fest |
| Suche, Browsing, Memory, Tools | Binden Sie kein search-Secret, keine Capability web_fetch, browser_use oder memory_mem0, keine MCP-Verbindung. Der Webbrowser kann bleiben, wenn jede Seite, die er öffnen darf, auf allowed_domains steht und seine Schritte an ein Modell gehen, das Sie selbst betreiben |
| Ihr eigenes SMTP-Relay | |
| Sprache, Bilder und Video | Für Spracherkennung gar kein Provider: Diktat auf off oder browser lassen und Kanal-Bots ausschalten, denn ein selbst gehosteter Spracherkennungsserver lässt sich noch nicht benennen (ein geplanter Folgeschritt). Für Sprachausgabe und Video keine Capability text_to_speech oder video_generation. Für Bilder ein Profil bei einem Provider, den Sie betreiben, oder gar kein solches Profil |
Embeddings eingeschlossen: Der Katalog nennt OpenRouter und OpenAI, die eine
Collection mit einem Vault-Schlüssel erreicht, und ollama, das eine Collection
an einem lokalen Dienst erreicht — einer Zeile, die einen Server benennt, den die
Organisation oder das Deployment betreibt. Eine Collection auf ollama schickt
ihre Chunks und Anfragen an keinen anderen Host und zahlt niemandem etwas. Ein
Deployment, das Dokumente auf eigener Hardware halten muss, legt dort jede
Collection an.
Wer wofür verantwortlich ist¶
| Partei | Rolle | Was das hier bedeutet |
|---|---|---|
| Die Organisation, die es betreibt (eine Stadt, ein Unternehmen) | Verantwortlicher | Entscheidet über Zwecke, Aufbewahrung, welche Provider ein Agent erreichen darf, und unterzeichnet die Verträge mit ihnen |
| Vstorm als Autor der Software | Keines von beiden, bei einem selbst gehosteten Deployment | Der Code läuft auf Ihrer Infrastruktur, und nichts telefoniert nach Hause. Vstorm sieht Ihre Daten nie |
| Vstorm, wenn es das Deployment für Sie betreibt | Auftragsverarbeiter | Ein Auftragsverarbeitungsvertrag ist ein Vertrag zwischen uns, keine Einstellung. Er muss vor dem ersten veröffentlichten Agent existieren |
| Ein Model-, Embedding-, Parsing-, Such- oder Observability-Provider | Unterauftragsverarbeiter, per Konfiguration gewählt | Die Plattform hält fest, welchen Provider und welchen Endpunkt jeder Agent nutzt. Deren Standort, Aufbewahrung und Trainingsbedingungen sind ihre und werden je Deployment geprüft |
Die Plattform trainiert und finetunt nichts. Sie sendet Prompts, Dokumente und Tool-Ergebnisse an die Provider, die ein Deployment konfiguriert, und speichert, was zurückkommt. Ob ein Provider API-Verkehr zum Training verwendet, ist eine Eigenschaft seines Kontos und seiner Bedingungen, und die Checkliste am Ende verlangt die Erklärung, statt sie anzunehmen.
Wo personenbezogene Daten liegen¶
Alles unten liegt im eigenen PostgreSQL des Deployments, auf seiner eigenen
Platte oder in einem Dienst, den das Deployment gewählt hat. Jede Tabelle, die
einer Organisation gehört, trägt eine organization_id; eine Kindzeile — eine
Nachricht, ein Anhang, eine Bewertung — ist über die Conversation oder den
Benutzer gescoped, an dem sie hängt, und der Lesezugriff geht über die Prüfung
des Elternteils.
Die Datenbank¶
| Speicher | Hält | Personenbezogene Daten darin | Zweck |
|---|---|---|---|
users, sessions, organization_members |
Konten und Anmeldungen | E-Mail, Name, Avatar, gehashtes Passwort oder die Google-Konto-Id, Refresh-Token-Hash, IP-Adresse und User-Agent je Session; was die Person Agents über sich gesagt hat - Sprache der Konsole, Zeitzone, Rolle, woran sie arbeitet, Arbeitszeiten - und die ersten Nachrichten, die für ihren leeren Chat geschrieben wurden | Authentifizierung und Autorisierung; was jeder Agent über die Person erfährt |
browser_sign_ins |
Gespeicherte Anmeldungen einer Person bei Websites, für den Webbrowser | Die Website, die Organisation, wann sie zuletzt genutzt wurde, und die Sitzung selbst (Cookies und der localStorage der Website), über den Vault im eigenen Bereich der Person versiegelt |
Ein späterer Durchlauf in ihrem Namen beginnt bereits angemeldet. Der Export personenbezogener Daten nennt die Websites, nie die Sitzung |
conversations, messages, tool_calls |
Jeder Chat auf jeder Oberfläche | Der Text, den Menschen geschrieben haben, die Antworten und das Reasoning des Models, Tool-Argumente und -Ergebnisse, eine fortlaufende Zusammenfassung langer Threads | Die Kernfunktion des Produkts; die Historie, zu der ein Mensch zurückkehrt |
voice_calls |
Jede Verbindung eines Sprachanrufs | Die Benutzer-ID des Anrufers (keine bei einem Besucher), der Agent, der Run, die Conversation und das Embed, zu denen er gehörte, Provider und Modell, die Anruf-ID des Providers, die ID des Vault-Schlüssels, mit dem er gehalten wurde, der Worker, der ihn hält, sein Heartbeat, die Zeiten von Beginn, Ende und Auflegen, seine Kosten, Sekunden und die Zahl der Guardrail-Treffer. Kein Audio und kein Transkript - die Worte des Anrufs sind gewöhnliche Zeilen in messages, jede mit einer turn_id markiert und, wenn der Anrufer dazwischengesprochen hat, mit interrupted |
Einen Anruf auflegen, dessen Prozess gestorben ist, und die monatlichen Anrufminuten der Organisation zählen |
chat_files |
Anhänge an einer Nachricht | Dateiname, Typ, Größe, der extrahierte Text (parsed_content) und der Pfad der Bytes auf der Platte |
Antworten über eine Datei |
generated_media |
Eine Zeile je Bild, Sprachclip oder Video, das ein Agent erzeugt hat | Die Organisation, die Conversation, in der es entstand, sofern der Run eine hatte, Dateiname, Speicherpfad und Größe - nicht der Inhalt, der eine Datei unter MEDIA_DIR ist |
Die erzeugten Medien jeder Organisation gegen ihr Kontingent zählen und sie mit ihrer Conversation oder nach ihrer Aufbewahrungsfrist löschen |
context_files |
Dauerhaftes Wissen, das ein Builder für Agents geschrieben hat | Was der Autor dort hineingeschrieben hat — und es erreicht den Prompt wörtlich. Siehe Kontextdateien | Anweisungen und Fakten, die ein Agent immer kennen soll |
artifacts, artifact_versions und ihre Dateien |
Seiten, die Agents veröffentlicht haben — Berichte, Dashboards | Was auch immer die Seite zeigt, die der Run aus dem gebaut hat, was er lesen konnte; der Besitzer, der Run, der jede Version geschrieben hat, und, wenn einer aktiv ist, der Schlüssel des öffentlichen Links, seine Einstellungen (ein Passwort als bcrypt-Hash) und wie oft er geöffnet wurde — eine Zahl und ein Zeitpunkt, nichts über die Besucher. Siehe Apps | Ein Ergebnis unter einem stabilen Link teilen |
agent_memory_files |
Notizen, die ein Agent über eine Person oder einen Gruppenchat geschrieben hat | Was der Agent für merkenswert hielt, geschlüsselt auf person:<user_id> oder einen Chatraum |
Kontinuität zwischen Conversations |
rag_documents, knowledge_bases und eine Vektortabelle je Collection |
Hochgeladene und synchronisierte Dokumente, ihre Chunks und Embeddings | Der Dokumenttext und seine Vektoren, der ursprüngliche Pfad der Datei in der Quelle | Retrieval |
agent_runs, tool_approvals, run_manifests |
Was jeder Run gekostet und getan hat | Der System-Prompt und die letzte an das Model übergebene Anfrage, Tool-Argumente, die auf Freigabe warten, die entscheidende Person und ihre Notiz | Budgets, Freigaben, Run-Historie |
agent_triggers |
Geplante und ereignisgesteuerte Runs | Der Prompt sowie Konfiguration und Filter der Ereignisquelle | Einen Agent ohne Menschen laufen lassen |
app_admin_audit_logs |
Wer Zugriff geändert oder Geld ausgegeben hat — die Spur der Organisation und die des Deployment-Administrators teilen sich eine Tabelle | Akteur, Impersonator, IP-Adresse, die Aktion und eine details-Map. Die Map benennt meist Felder, aber manche Einträge halten Werte: die E-Mail des impersonierten Kontos, die E-Mail eines vom Administrator gelöschten Kontos, eine Veröffentlichungsnotiz |
Rechenschaft. Siehe Governance |
notifications, notification_deliveries |
Jede an jemanden adressierte Benachrichtigung und ihre E-Mail-Zustellung. Eine Zeile wird auch dann geschrieben, wenn der Empfänger für dieses Ereignis jeden Kanal abgeschaltet hat - sie ist es, die verhindert, dass dasselbe Vorkommnis zweimal geschrieben wird - und wird dann einfach nie gezeigt oder gesendet; nur die Zustellungszeile ist bedingt | Der Empfänger, eine vorgerenderte Zusammenfassung (nie ein roher Kommentar oder Secret-Wert) und die typisierten Variablen, aus denen eine E-Mail neu rendert; eine Zustellungszeile fügt ihren Kanal, Status, die Versuche und einen bereinigten Fehlgrund hinzu — nie den Fehlertext des Providers | Warnungen, die eine Person einmal liest, unbeaufsichtigt. Siehe Governance |
notification_preferences, announcements |
Kanal-Umschalter je Ereignis, und die eigenen Ankündigungen eines App-Administrators | Eine Benutzer-Id je Umschalter; der Absender einer Ankündigung, ihr Text sowie die Organisationen und die Rolle, an die sie adressiert war — nie die aufgelöste Empfängerliste, die aus notifications nur rekonstruierbar ist, solange diese Zeile nicht durch den Retention-Sweep für Benachrichtigungen verfällt — danach hält der Audit-Eintrag dahinter nur noch eine Zahl, nie die Empfänger |
Opt-out, und der eigene Nachweis des Verfassers |
embed_visitors, channel_identities, channel_sessions |
Fremde auf einer gehosteten Seite und Menschen auf Slack, Teams, Telegram oder Mattermost | Ein zufälliger Besucherschlüssel; eine Plattform-Benutzer-Id, ein Benutzername und ein Anzeigename; die Chat-Id | Den richtigen Thread fortsetzen |
message_ratings |
Daumen und Kommentare zu Antworten | Der Bewertende und sein Kommentar | Qualitätsprüfung |
suggestions |
Was die Arbeit aus eigener Initiative einer Person vorgeschlagen hat, und ob sie es angenommen hat | Die Person, ein Titel und eine Zeile Detail aus ihren letzten Anfragen, der Routine-Prompt oder das Profil, das er setzen würde, und ein Schlüssel, der verhindert, dass ein verworfener Vorschlag wiederkommt | Vorschläge, über die die Person entscheidet |
watches |
Was eine Person die Arbeit aus eigener Initiative in ihren eigenen Verbindungen beobachten lässt | Die Person, welche ihrer Verbindungen, wonach gesucht und was ausgelassen wird in ihren eigenen Worten, wie oft und wann zuletzt nachgesehen wurde | Beobachtungen, die die Person einrichtet |
ml_service_calls |
Jeder Aufruf der ML-Dienste und jede Transkription: Diktat, eine Sprachnachricht in einem Kanal, die API, das Diktat eines Besuchers auf einer gehosteten Seite oder in einem Widget | Die Organisation, wer gefragt hat, welcher Dienst, Byte- und Einheitenzahlen, die Dauer und wie es endete; bei einer Transkription außerdem Provider und Modell, die ID des Vault-Schlüssels, mit dem sie gesendet wurde, woher sie kam, der Agent und der Kanal-Bot, für die sie war, und die Länge der Aufnahme. Die Zeile einer Sprachnachricht in einem Kanal nennt die Person, mit der das Konto des Absenders verknüpft ist, und bei einem nicht verknüpften Absender niemanden. Die Zeile eines Besuchers nennt niemanden - weder den Besucher, der kein Konto hat, noch den, der die Seite veröffentlicht hat. Das Löschen der Person, des Agents, des Bots oder des Schlüssels entfernt die Verknüpfung und behält die Zeile - nichts von dem, was eingereicht wurde, und nichts von dem, was zurückkam | Nutzungsberichte und der Blick eines Betreibers auf eine Integration, die scheitert |
agent_workspaces, sandbox_operations |
Dateien, an denen ein Agent gearbeitet hat, und das Log dessen, was er ausgeführt hat | Beim state-Backend die Dateien selbst, als JSON; bei einem Container die Session-Id und jedes Kommando, Ziel und Ergebnis-Resümee |
Die Sandbox. Siehe Die Sandbox |
organization_secrets, model_profiles, mcp_connections, channel_bots |
Zugangsdaten und wohin sie zeigen | Nur versiegelter Chiffretext, mit einem Hinweis; Provider, Model und base_url im Klartext |
Provider erreichen. Siehe Secrets |
messages.search_vector ist ein Volltextindex über denselben Inhalt, und
conversations.summary_messages ist eine vom Model geschriebene Verdichtung
davon. Beides sind Kopien des Chats und gehen mit ihm.
Erzeugte Medien¶
Ein Bild, ein Sprachclip oder ein Video, das ein Agent erzeugt, ist eine Datei
unter generated_<org>/ und eine generated_media-Zeile, die sie benennt. Die
Zeile hält die Organisation fest, die Conversation, sofern der Run eine hatte, und
die Größe - so ist die Summe der Organisation durch GENERATED_MEDIA_QUOTA_MB
(5120) begrenzt, geprüft vor jedem bezahlten Erzeugungsaufruf. Jede Datei zählt,
auch eine ohne Conversation: aus einer Vorschau oder einem Testlauf, aus einem
/btw-Einschub in einem Kanal, aus einem API-Run, der keine Conversation nennt,
oder eine Datei, deren Conversation über einen Weg gelöscht wurde, der sie
zurückließ.
Die Datei wird mit ihrer
Conversation gelöscht, mit dem Konto, dem diese Conversation gehörte, vom
täglichen Job sweep-generated-media, sobald sie älter als
GENERATED_MEDIA_RETENTION_DAYS (90) ist, auch wenn ihre Conversation noch
existiert, und per Präfix mit ihrer Organisation. 0 schaltet jede der beiden
Grenzen ab. Eine Datei ohne Conversation kann kein Mitglied löschen, um Platz zu
schaffen, daher löscht derselbe Job sie nach 7 Tagen, unabhängig von
GENERATED_MEDIA_RETENTION_DAYS, auch bei 0. Ein Link darauf - in einer
Kanalantwort oder einer API-Antwort - funktioniert dann nicht mehr.
Das Löschen einer Conversation, eines Kontos oder einer Organisation entfernt die
Zeilen in seiner eigenen Transaktion und reiht das Lösen der Bytes in derselben
Transaktion als Hintergrundjob ein - die Bytes gehen also nur, wenn die Zeilen
gehen, und ein Neustart nach dem Commit verliert das Lösen nicht. Dieser Job
wiederholt ein Präfix, das der Speicher nicht ganz entfernt - das einer
Organisation -, und eine einzelne Datei einer gelöschten Conversation oder eines
gelöschten Kontos, die der Speicher verweigert, weil nichts anderes diese Bytes
je wiederfinden könnte. Eine Datei, die der Speicher auch beim letzten Versuch
des Jobs verweigert, bleibt ohne Zeile unter generated_<org>/, bis ihre
Organisation geht, und der Bericht unten zählt sie.
Der Sweep löscht zuerst die Datei und ihre Zeile erst, wenn die Datei weg ist; eine Datei, die der Speicher verweigert, behält ihre Zeile, und der nächste Sweep versucht es erneut.
Dateien, die erzeugt wurden, bevor es die Tabelle gab, haben keine Zeile. Sie werden weiter ausgeliefert, zählen aber nicht gegen das Kontingent, und der Sweep sieht sie nicht: Sie gehen mit ihrer Organisation oder von Hand, und der Datenschutzbericht zählt sie zu den Dateien ohne Zeile.
Außerhalb der Datenbank¶
| Speicher | Hält | Gelöscht, wenn |
|---|---|---|
MEDIA_DIR auf dem API-Host (Volume media_data) |
Chat-Anhänge unter <user_id>/, Avatare, Embed-Logos, die von Agenten erzeugten Bilder, Sprachclips und Videos unter generated_<org>/ und eine temporäre Kopie jedes Dokuments unter _rag_tmp, solange es geparst wird |
Ein Dokument über das Produkt gelöscht wird. Die Bytes eines Chat-Anhangs werden nach dem Commit gelöst, der seine Conversation oder seinen Besitzer löscht. Eine erzeugte Datei geht mit der Conversation, in der sie entstand, nach GENERATED_MEDIA_RETENTION_DAYS (90) unabhängig davon, was aus der Conversation wurde - nach 7 Tagen, wenn sie keine Conversation hat -, und mit ihrer Organisation; siehe Erzeugte Medien. Siehe Was das Löschen erreicht |
SANDBOXD_WORKSPACE_ROOT auf dem Sandbox-Host |
Die Dateien jedes containergestützten Workspace | Die Conversation gelöscht wird oder SANDBOXD_WORKSPACE_TTL sie wegräumt; ungesetzt bleiben sie unbegrenzt. Siehe Wie lange etwas überlebt |
| Redis | Rate-Limit-Buckets, geschlüsselt auf den Aufrufer — bei einer öffentlichen Oberfläche ist das die IP-Adresse im Klartext, im Schlüssel, für die TTL des Fensters; Dedup-Schlüssel für Trigger und Kanäle; OAuth-Austauschzustand; vorgemerkte Einladungen; die Live-Ansicht eines Browsens — sein letzter Screenshot, seine Schritte und was die Person, die den Browser hält, geklickt und getippt hat, bis das Browsen es liest; die wiederholbaren Browse-Schritte einer Person — Adressen und Beschriftungen dessen, was ihre abgeschlossenen Browses gedrückt haben, nie das Getippte | Beim Ablauf: eine Live-Ansicht eine Stunde nach dem letzten Frame des Browsens, wiederholbare Schritte zwei Wochen nach der letzten Erledigung der Aufgabe, alles andere binnen Minuten |
background_jobs in PostgreSQL |
Der Payload jedes Hintergrund-Jobs, sein letzter Fehler und die Antwort eines asynchronen API-Runs | Der Aufbewahrungs-Sweep entfernt einen beendeten Job nach BACKGROUND_JOB_RETENTION_DAYS (14). Payloads sind Ids und Pfade, mit zwei Ausnahmen: der event_context eines ereignisgesteuerten Auslösens — Absender, Betreff und Text einer Gmail-Nachricht, eines GitHub-Issues, eines Webhook-Payloads — sowie Prompt und Antwort eines asynchronen API-Runs bleiben bis dahin im Job. Die Logs des Workers laufen durch denselben Redaktionsfilter wie die der API |
| Logfire, wenn konfiguriert | Traces jedes Runs | Die Aufbewahrung des Providers. Heute trägt ein Trace den vollen Prompt, die Ausgabe und die Tool-Argumente — siehe Traces |
| Ihr SMTP-Relay | Einladungen, Magic Links, Freigabeanfragen, Budget-Warnungen, Nutzungsberichte, und die eigene Mail des Benachrichtigungs-Postfachs - ein Run, der unbeaufsichtigt fertig wird oder scheitert, die Ingestion eines Dokuments, die abschließt oder scheitert, ein Sicherheitsereignis oder eine Konfigurationsänderung, die eigene Ankündigung eines Admins | Was das Relay aufbewahrt. Eine Freigabe-Mail nennt den Agent, das Tool und einen Link, nicht die Argumente des Tools |
| Backups | Ein pg_dump ist die ganze Datenbank; das Media-Volume sind die Dateien |
Ihr Backup-Ablauf. Eine Löschung erreicht ein bereits gezogenes Backup nie — siehe Backups |
Was das Deployment verlässt¶
Nichts geht hinaus, solange nicht eine Zeile oder eine Einstellung ein Ziel benennt. Dies ist die vollständige Liste der Ziele, mit der Konfiguration, die über jedes entscheidet.
| Ziel | Was gesendet wird | Entschieden durch | Standort und Bedingungen |
|---|---|---|---|
| Das Chat-Model | Die bisherige Conversation, eingefügte oder beschriebene Anhänge, abgerufene Chunks, Tool-Ergebnisse; einmal pro Nacht, für die Arbeit aus eigener Initiative, die letzten Anfragen einer Person, ihr Profil und was ihr Agent über sie notiert hat | Ein Model-Profil: provider, model, base_url und ein versiegelter Schlüssel. Siebenundzwanzig Provider; ollama und litellm sind schlüssellos und werden an einem Endpunkt erreicht, den Sie betreiben, und openai, anthropic, google, huggingface und andere akzeptieren eine base_url, ein EU-Endpunkt oder ein Gateway ist also ein Feld und keine Abzweigung. Ein openai- oder azure-Profil auf der Responses-API sendet store: false, der Provider behält also keine gespeicherte, abrufbare Antwort, sofern das Profil nicht openai_store setzt; die Aufbewahrung von OpenAI zur Missbrauchsüberwachung gilt weiterhin, sofern das Konto keine Zero Data Retention hat |
Die des Providers. Je Profil prüfen |
| Das Embedding-Model | Jeder Chunk jedes Dokuments einer Collection und jede Retrieval-Anfrage | Je Collection, und nur dort: embedding_provider (openrouter, openai oder ollama, aus dem Katalog) und, für die ersten beiden, der Vault-Schlüssel embedding_secret_id, der zahlt. Einen deploymentweiten Embedding-Schlüssel gibt es nicht; eine schlüsselpflichtige Collection ohne einen verweigert Indexierung und Suche. ollama ist schlüssellos und wird an dem lokalen Dienst erreicht, den die Collection benennt (embedding_endpoint_id), einem Host, den Sie betreiben |
Die des Providers oder Ihr eigener Host. Eine dauerhafte Wahl |
| LlamaCloud | Das ganze Dokument | Eine Collection, deren pdf_parser llamaparse ist; sie muss einen Vault-Schlüssel benennen (llamaparse_secret_id), einen Deployment-Schlüssel gibt es nicht. Der Standard pymupdf parst im Worker |
Die von LlamaCloud, falls genutzt |
| Ein OCR-Server | Gerenderte Seiten eines Dokuments | Eine Collection, deren pdf_parser liteparse ist und deren ocr_endpoint_id einen lokalen Dienst benennt; ohne einen läuft OCR im Worker |
Ihr eigener Host — ein lokaler Dienst liegt konstruktionsbedingt im Netz des Deployments |
| Ein Bildbeschreibungs-Model | Bilder in Dokumenten | Das image_description_model einer Collection |
Die dieses Model-Providers |
| Web-Recherche | Die Suchanfrage, die der Agent formuliert hat | web_research.method auf dem Spec: duckduckgo (kein Schlüssel), tavily, brave oder exa (je ein search-Secret), oder native, wobei der Provider des Chat-Models sucht |
Die des Suchanbieters oder des Model-Providers |
| Web-Fetch und der Webbrowser | Die URL; beim Browser, was er auf den geöffneten Seiten eintippt | Die Capability auf dem Spec; der Browser braucht zusätzlich einen CDP-Endpunkt auf BROWSER_CDP_ALLOWED_HOSTS, standardmäßig leer |
Die abgerufene Seite; der Browser-Host und die Seiten, die er öffnet |
| Proxy oder gehosteter Browser eines Agents | Alles, was der Browser lädt und sendet, wie es sonst der Browser im Deployment täte - Seiten, Formularinhalte, Cookies, Anmeldungen - samt der eigenen Aufzeichnung des Proxys oder Dienstes | browser_use.connection in der Spec (#2130); standardmäßig built_in |
Der Proxy oder der gehostete Browser-Dienst (Browserbase, Steel oder ein anderer), unter dem eigenen Vertrag der Organisation |
| Die Schritte des Webbrowsers | Jeder Schritt eines Durchlaufs geht an das eigene Modell des Agenten: die URL der Seite, ihr Titel, die Beschriftungen der sichtbaren Elemente und bis zu 4.000 Zeichen ihres sichtbaren Texts, mit vision auch ein Screenshot — was der Inhalt eines internen Systems sein kann. Was ein Feld enthält, wird nicht wiederholt: Die Elementtabelle sagt nur, dass ein Feld gefüllt ist |
Die Capability browser_use auf dem Spec |
Der Modellanbieter des Agenten, wie beim Gespräch |
| Die Sandbox, ausgehend | Alles im Workspace, an jeden beliebigen Host — die Runtime workbench hat ein Netz, eine Shell und curl |
Die Capability sandbox und eine Runtime mit needs_network; die Kommandofreigabe steuert, was läuft, nicht wohin es sich verbindet |
Wohin das Kommando ging. Egress-Kontrolle ist die Firewall des Sandbox-Hosts, keine Einstellung hier |
| Ein MCP-Server | Tool-Argumente und -Ergebnisse | mcp_connections.url, je Organisation oder je Person |
Die des Serverbetreibers |
| mem0 | Die für eine Person oder einen Chat geschriebenen Memories | Die base_url der Capability memory_mem0, die in MEM0_ALLOWED_HOSTS stehen muss |
Die des mem0-Hosts, den Sie zulassen |
| Logfire | Spans für jede Anfrage und jeden Run | LOGFIRE_TOKEN deploymentweit; ein observability-Token auf einem Spec oder logfire_token_secret_id auf einem Environment lenkt diese Runs in ein anderes Projekt. LOGFIRE_BASE_URL wählt das US- oder EU-Deployment. Überall ungesetzt wird nichts gesendet |
Die von Pydantic, US oder EU |
| Speech-to-Text, Bildgenerierung | Eine Sprachnachricht aus einem Kanal, eine in /chat diktierte Aufnahme oder die Aufnahme eines anonymen Besuchers auf einer gehosteten Seite oder in einem Widget; der Prompt |
Der Provider, auf den sich eine Aufnahme auflöst - das eigene Paar des Bots, die Überschreibung des Agents oder die Voreinstellung der Organisation, die ein Bot erbt, sofern er nicht ausgeschaltet ist -, gesendet mit dem neben diesem Paar benannten Vault-Schlüssel - einem API-Schlüssel für groq, mistral oder openai, auf Organisations- und Bot-Ebene organisationsweit sichtbar; beim Diktieren in /chat zusätzlich die Engine der Organisation auf server, und bei einer Seite oder einem Widget deren eigenes dictation: server. Ein Profil für google oder openai für Bilder. Das Audio eines Diktats wird hier nicht gespeichert. Mit browser auf einer Seite oder in einem Widget schickt der Browser des Besuchers das Audio an seinen Anbieter, und nichts davon geht durch dieses Deployment |
Die des Providers, oder für Bilder Ihr eigener Host; bei browser die des Browser-Anbieters |
| Ein Realtime-Sprach-Provider | Während eines Sprachanrufs: das Audio des Anrufers, die Anweisungen und Tool-Definitionen des Agents, Tool-Ergebnisse und die früheren Züge der Unterhaltung als Text, wenn ein Anruf beginnt oder sich neu verbindet | Der Abschnitt „Sprachgespräche“ (Voice conversations) auf der Karte Stimme des Agents: provider, model (oder ein Azure-Deployment) und der Vault-Schlüssel secret_id, veröffentlicht; ohne den Abschnitt nimmt der Agent keine Anrufe an. Über WebRTC (OpenAI) fließt das Audio direkt zwischen Browser und Provider; über das Relay (Azure, Gemini, xAI) geht es durch dieses Deployment, ohne gespeichert zu werden. Hier wird kein Audio behalten, und die Sitzung behält nur Transkripte |
Die des Providers |
| Sprachausgabe | Der zu sprechende Text und eine etwaige Anweisung, wie er gesprochen wird | Der provider der Capability text_to_speech: openai, elevenlabs oder google, mit dem Schlüssel des Bindings |
Die des Providers |
| Videoerzeugung | Der Prompt und ein etwaiges Startbild | Der provider der Capability video_generation: google, byteplus, xai oder alibaba, mit dem Schlüssel des Bindings. google speichert die Interaktion (store: true), weil Gemini einen Clip nur aus einer gespeicherten per Adresse liefert; die anderen drei werden nicht darum gebeten |
Die des Providers |
| Slack, Teams, Telegram, Mattermost | Die Antworten des Agents; die E-Mail-Adresse eines neuen Mitglieds, um es für eine Begrüßung in Slack, Mattermost oder Teams zu finden | Eine channel_bots-Zeile mit ihrem Token im Vault |
Der Messaging-Anbieter hält den Chat ohnehin schon |
| Google-Anmeldung | Nichts ausgehend; Google liefert E-Mail, Name, Bild und Konto-Id zurück | GOOGLE_CLIENT_ID |
Die von Google |
| Ihr SMTP-Relay | Die oben genannte Post | SMTP_HOST, SMTP_TLS |
Ihre |
Sync-Konnektoren laufen andersherum: Eine Google-Drive- oder S3-Quelle zieht
Dokumente herein, authentifiziert durch ein connector-Secret, und von da an
sind die Dokumente die Kopie des Deployments und folgen den Regeln oben. Wer
lesen kann, was eine Quelle aufgenommen hat, ist
eine Entscheidung der Quellzeile.
Kontrollen, und wo jede nachgewiesen ist¶
Jede Zeile benennt den Mechanismus im Code und den Test oder die Seite, die ihn festnagelt, oder das Issue, das es tun wird. Eine Zeile, deren letzte Spalte ein Issue ist, ist eine Lücke und steht als solche da.
| Kontrolle | Mechanismus | Nachgewiesen durch |
|---|---|---|
| Mandantentrennung | organization_id auf jeder Tabelle, die einer Organisation gehört, bei jeder Anfrage aus X-Organization-Id auf eine Mitgliedschaft aufgelöst; Kindzeilen nur über die Prüfung ihres Elternteils erreichbar |
tests/integration/test_conversation_tenant_isolation.py und Geschwister; Berechtigungen |
| Zugriff auf eine Zeile | Drei Schichten: Deployment-Administrator, Rolle in der Organisation, Grant je Ressource über resolve_access. Ein Bedienelement, das der Aufrufer nicht nutzen darf, wird nicht gerendert |
Ablehnungstests in tests/api/; Berechtigungen |
| Den Chat einer anderen Person lesen | Besitzer, eine ausdrückliche Freigabe oder der App-Administrator des Deployments — nie eine Rolle in der Organisation. Der Chat eines Projekts wird nur über das Projekt gelesen: von allen, die das Projekt sehen dürfen, die Person, die ihn begonnen hat, eingeschlossen, und von niemandem mehr, der es nicht mehr darf. Conversations haben ihre eigene Prüfung, ConversationService._may_read, statt der Grant-Formel |
admin_conversations.py verlangt is_app_admin; tests/integration/test_conversation_tenant_isolation.py |
| Zugangsdaten im Ruhezustand | Envelope-Verschlüsselung je Organisation, versionierte Masterschlüssel, Rotation mit Trockenlauf | Secrets, vier durch Tests festgenagelte Garantien |
| Inhalte im Ruhezustand | Von der Anwendung nicht verschlüsselt. Die Postgres-Daten, media_data und das Workspace-Wurzelverzeichnis der Sandbox verlassen sich auf die Platten- oder Volume-Verschlüsselung, die Sie bereitstellen. Ausnahme sind hochgeladene und Chat-Dateien bei FILE_STORAGE_BACKEND=s3 und FILE_STORAGE_S3_ENCRYPTION auf sse-s3 (der Voreinstellung) oder sse-kms unter einem Schlüssel, den Sie halten: Jeder Schreibvorgang bittet den Store dann, sie zu verschlüsseln. Der dritte Modus, none, sendet keinen Verschlüsselungs-Header und existiert für einen S3-kompatiblen Store ohne KMS |
Sache des Betreibers. Konfiguration; agenticos cmd doctor nennt das Backend, auf dem ein laufendes Deployment steht |
| Auf dem Transportweg, eingehend | HTTPS an Ihrem Proxy; Strict-Transport-Security, wenn ENVIRONMENT=production; Session-Cookies httpOnly, und secure aus dem Schema der Anfrage bei Anmeldung und Refresh. Die Route für den Passwortwechsel setzt secure nur in einem Produktions-Build |
Deploy; frontend/src/app/api/auth/login/route.ts |
| Auf dem Transportweg, zu den Speichern | POSTGRES_SSLMODE und REDIS_SSL; agenticos cmd doctor meldet, ob die hergestellte Verbindung verschlüsselt war |
Verschlüsselte Verbindungen; tests/integration/test_store_tls.py |
| Auf dem Transportweg, zu den Providern | HTTPS zu jedem katalogisierten Endpunkt. Eine eigene base_url wird ohne Host oder mit Zugangsdaten darin abgelehnt, aber http:// wird akzeptiert, für ein Ollama oder ein Gateway im Netz des Deployments selbst; ein Klartext-HTTP-Profil, das aus diesem Netz hinauszeigt, sendet Prompts und Schlüssel im Klartext. Punkt 4 der Checkliste listet jedes solche Profil |
refused_field("base_url", ...) im Model-Profile-Service; das Schema ist Sache des Betreibers |
| Secrets in Antworten, Logs, Audit, Exporten | Kein Endpunkt gibt einen Klartext zurück; SecretStr überall; Specs referenzieren Secrets per Id |
Secrets |
| Personenbezogene Daten in Logs | app/core/logging.py redigiert E-Mail-Adressen, JWTs, API-Schlüssel, Bearer-Token und password=-Paare aus jedem Log-Record, in API wie Worker |
tests/test_logging.py; der Worker installiert es in app/worker/__main__.py, jeder Kindprozess der Ingestion in app/worker/child.py (#440) |
| Personenbezogene Daten, die das Model erreichen | Die Capability guardrails redigiert IBANs, Kartennummern, US-Sozialversicherungsnummern, Telefonnummern und E-Mail-Adressen aus Prompts, Antworten, Tool-Ergebnissen und Tool-Argumenten, sofern konfiguriert |
Capabilities; ihre Tests unter tests/ |
| Personenbezogene Daten in einer Fehlerspalte | rag_documents.error_message und Verwandte halten Stufe und Klasse fest, nie den Text des Kunden |
app/services/rag/failures.py (#423) |
| Rechenschaft | Audit-Einträge teilen die handelnde Transaktion und scheitern geschlossen; Impersonation nennt beide Personen; Massenexporte werden festgehalten | Governance |
| Audit-Export | GET /audit/export, CSV oder JSONL über ein Fenster, auf audit:read gegated und in der Spur selbst festgehalten |
Governance (#1422) |
| Manipulationsnachweis der Spur | Jeder Eintrag gehört zu einer Hash-Kette je Organisation, und jede Kette trägt einen Checkpoint auf ihrem höchsten Stand, damit ein umgeschriebener Eintrag, ein gekapptes Ende und eine gelöschte Kette allesamt erkennbar sind. agenticos cmd audit-verify läuft sie ab und endet bei einem Bruch mit einem Exit-Code ungleich null |
Governance (#1622, #1648). Erkennung, keine Verhinderung: wer die Zugangsdaten der Datenbank selbst hat, schmiedet eine Kette neu oder entfernt den Trigger, der den Checkpoint schützt |
| Traces | observability.content je Agent: full zeichnet alles auf, none nur Zeit, Tokens, Kosten und Tool-Namen, und ein Spezialist dieses Agents erbt den Modus |
Umgebungen (#1413); ein redacted-Dazwischen wurde verworfen, #1616 |
| Aufbewahrung nach Zeitplan | Je Organisation und je Klasse — Gespräche und ihre Dateien, Runs und Manifeste, Workspaces, das Gedächtnis von Agenten, hochgeladene Dokumente und Audit — innerhalb einer deploymentweiten Vorgabe, Obergrenze und Audit-Untergrenze. Ein täglicher Sweep löscht hart und hält Zähler fest, nie Inhalte. Backups und alles bereits an einen externen Collector Geschickte liegen außerhalb. notifications gehört nicht zu diesen Klassen: Es wird stattdessen nach einem eigenen festen Zeitplan geräumt — eine gelesene Zeile nach 90 Tagen, jede Zeile nach einem Jahr in jedem Fall. announcements selbst sind ausgenommen, sodass das Gesendete über die Audit-Spur beantwortbar bleibt, nachdem seine Zustellungen gealtert sind. Ebenso wenig erzeugte Medien, die nach dem deploymentweiten GENERATED_MEDIA_RETENTION_DAYS gehen |
Aufbewahrung; test_retention.py, tests/integration/test_retention_sweep.py; der Notification-Sweep ist tests/integration/test_notification_retention.py (#1598, Decision 8); erzeugte Medien sind test_generated_media.py und tests/integration/test_generated_media.py (#2310) |
| Löschung einer Person | Die Kontolöschung bereinigt, was sie blockieren würde, löst die Anhang-Bytes nach dem Commit und räumt weg, was keine Kaskade erreicht - die Notizen, die Agents über die Person geschrieben haben, ihre Plattform-Identitäten, ihre Workspaces. Die Löschung des Gedächtnisses ist ebenfalls ein eigener Aufruf und erreicht mem0 | Was eine Löschung erreicht für das bewusst Aufbewahrte; test_personal_data.py |
| Zugang zu den eigenen Daten | Eine Person liest unter Einstellungen → Gedächtnis alles, was jeder Agent hier über sie aufgeschrieben hat, und kann eine Notiz stilllegen, wiederherstellen oder löschen. Den Speicher einer anderen Person zu lesen steht allein der Deployment-Administratorin zu - keiner Organisationsrolle - und wird mit Akteurin, Tenant, Person und Begründung auditiert, nie mit Inhalt. Externe Speicher (mem0) werden genannt statt gelistet | Lesen und löschen; test_memory_self_service.py. Alles andere, was über sie gehalten wird, kommt aus GET /me/data/export zurück, begrenzt und auditiert (#1421) |
| Unternehmensidentität | Google-Anmeldung, Passwörter, generisches OIDC gegen den Provider, den Sie ohnehin betreiben - allein per Discovery aus OIDC_ISSUER konfiguriert - und Ihr eigenes Verzeichnis über LDAP oder Kerberos. Adresse, Anzeigename und stabile Kennung aus dem Verzeichnis werden am Konto gehalten; seine Gruppen werden bei jeder Anmeldung gelesen und nicht gespeichert, nur die Mitgliedschaften, die die Zuordnungen der Organisationen daraus machen. Kein SAML, kein SCIM |
Verzeichnisanmeldung und Gruppen; OIDC_ISSUER, LDAP_URL |
| Die Kontrollmatrix, die eine Sicherheitsprüfung liest | Sicherheit ordnet jeder Kontrolle ihren Mechanismus und den Test zu, der ihn hält, im Rahmen von HIPAA §164.312 und SOC 2 CC6–CC8; diese Seite und Einführen sind der Rest | Sicherheit (#1412) |
| Öffentliche Oberflächen | Der Besucherschlüssel einer gehosteten Seite ist zufällig, nie aus der Person abgeleitet; Einlass und Uploads sind je Adresse ratenbegrenzt, die Adresse liegt für die Dauer des Fensters in einem Redis-Schlüssel und sonst nirgends | Kanäle |
| Rechtliche Hinweise | Die eigenen AGB- und Datenschutz-URLs des Deployments ersetzen die eingebauten Seiten | Das Deployment |
Traces¶
instrument_pydantic_ai() läuft mit dem Standard der Bibliothek, ein Span hält
also die Nachricht des Benutzers, die Antwort des Models und jedes Tool-Argument
und -Ergebnis. Mit ungesetztem LOGFIRE_TOKEN, ohne observability-Token auf
irgendeinem Spec und ohne logfire_token_secret_id auf irgendeinem Environment
wird nichts gesendet, und die Trace-Id wird trotzdem lokal festgehalten. Ein
Deployment, das Traces ohne den Inhalt braucht, setzt observability.content des
Agents auf none: aufgezeichnet werden Zeit, Tokens, Kosten und Tool-Namen, und
kein Nachrichtentext verlässt die Maschine — und ein Spezialist dieses Agenten
erbt den Modus, ob sein Autor ihn inline geschrieben oder das Model des Runs ihn
erfunden hat.
Einen dritten Modus dazwischen gibt es nicht. Ein durch einen PII-Filter bereinigter Export ist eine Zusicherung, die niemand prüfen kann — ein Identifikator, den der Filter übersieht, ist bereits draußen, und der Betreiber glaubt das Gegenteil —, die Wahl steht also bewusst zwischen dem ganzen Inhalt und keinem (#1616).
Was das Löschen erreicht¶
Löschen ist das, was das Produkt heute tut, wenn jemand darum bittet; geplante Aufbewahrung ist #1420.
| Aktion | Entfernt | Lässt zurück |
|---|---|---|
DELETE /conversations/{id} (der Besitzer) |
Die Conversation, ihre Nachrichten, Tool-Aufrufe, Bewertungen, Freigaben und chat_files-Zeilen per Kaskade - darunter das Transkript eines Sprachanrufs, da seine Züge Nachrichten sind; die Anhang-Bytes unter MEDIA_DIR, vor dem Löschen eingesammelt und nach dessen Commit gelöst; die von ihren Agenten erzeugten Bilder, Sprachclips und Videos - die Zeilen beim Löschen, die Bytes über einen mit ihm eingereihten Job; die aus diesem Thread ausgelagerten Medienobjekte per Präfix; ein Container-Workspace über purge_for_conversation |
Run-Zeilen und Manifeste, die die Conversation benannten, behalten ihre Prompt-Kopie; eine voice_calls-Zeile behält ihre Zeiten und Kosten, mit geleerter Verknüpfung zur Conversation |
DELETE /memory/person/{user_id} (die Person oder members:manage) |
Jede agent_memory_files-Zeile, die auf die Person geschlüsselt ist, über alle Agents der Organisation hinweg, und dasselbe in jedem gebundenen mem0-Speicher |
Notizen, die auf einen Gruppenchat geschlüsselt sind, in dem die Person gesprochen hat |
DELETE /users/{id} |
Das Konto, seine Sessions, seine persönliche Organisation und persönliche Collections samt Vektortabellen und Dateien per ausdrücklichem Teardown; Conversations außerhalb eines Projekts und Chat-Dateien per Kaskade; deren Bytes, nach dem Commit gelöst; die von Agenten in diesen Conversations erzeugten Bilder, Sprachclips und Videos - die Zeilen beim Löschen, die Bytes über einen mit ihm eingereihten Job; und was keine Kaskade erreicht - die Notizen, die Agents über die Person geschrieben haben (owner_key ist ein String, kein Fremdschlüssel), ihre Plattform-Identitäten und ihre nutzergebundenen Workspaces |
Audit-Einträge, die die Actor-Id und bei manchen Aktionen die E-Mail nennen - bewusst aufbewahrt, denn ein Eintrag ohne seinen Actor ist schlimmer als einer, der ein gelöschtes Konto nennt. Nachrichten in Conversations, die jemand anderem gehören, und die Projekt-Chats, die die Person begonnen hat - für das Team behalten, ohne Urheber, mit den darin erzeugten Medien; ihre Nachrichten darin erscheinen als die eines ehemaligen Mitglieds. Die Medien, die die Person ohne Conversation erzeugt hat - Vorschauen und Testläufe, /btw-Einschübe in Kanälen, API-Runs ohne Conversation -, die keine Zeile mit ihr verknüpft; sie gehen nach 7 Tagen |
| Ein Dokument oder eine Collection löschen | Die Zeilen, die Vektortabelle und die gespeicherte Datei, über einen dauerhaften Flow nach dem Commit | Nichts, sobald der Flow gelaufen ist; die Zählstände in sync_logs bleiben |
| Eine Organisation löschen | Alles, was auf sie gescoped ist, mit demselben aufgeschobenen Abbau - ihre erzeugten Medien per Präfix, einschließlich der Dateien, die geschrieben wurden, bevor sie erfasst wurden | Persönliche Collections, die die Id lediglich mitführten |
Keines davon erreicht ein Backup. Eine Wiederherstellung bringt zurück, was gelöscht wurde, der Backup-Ablauf gehört also zur Aufbewahrungsrichtlinie und wird mit ihr zusammen niedergeschrieben.
Was ein Deployment entscheiden und beschaffen muss¶
Die Software kann nichts davon liefern. Jedes ist ein Nachweis, den die Prüfung verlangen wird, und etwas anderes als die technische Fähigkeit, die ihn möglich macht.
- Ein Auftragsverarbeitungsvertrag mit jedem konfigurierten
Unterauftragsverarbeiter — jedem Provider, den eine Zeile in
model_profilesoderorganization_secretsbenennt, dem Embedding-Provider, LlamaCloud, falls eine Collection es nutzt, dem Suchanbieter, den diemethodeines Agents benennt, dem mem0-Host, Logfire, dem SMTP-Relay und Google, falls die Anmeldung aktiviert ist. - Eine Erklärung zum Datenstandort je Provider, abgeglichen mit der
base_url, die jedes Profil tatsächlich nutzt. Ein Provider mit EU-Endpunkt ist nur dann in der EU, wenn das Profil es sagt. - Ein Trainingsausschluss je Provider: die Kontoeinstellung oder Vertragsklausel, unter der API-Daten nicht zum Training verwendet werden. Die eigene Position der Plattform ist ein Satz — sie trainiert nichts — und der Rest ist deren Sache.
- Ein Auftragsverarbeitungsvertrag mit Vstorm, nur wenn Vstorm das Deployment betreibt.
- Ein Aufbewahrungsplan für Conversations, Dateien, Memory, Dokumente, Runs und Audit, und daneben der Backup-Ablauf. Bis #1420 einen erzwingt, ist Aufbewahrung manuelles Löschen.
- Platten- oder Volume-Verschlüsselung auf dem Datenbank-Host, dem Media-Volume und dem Sandbox-Host, da die Anwendung Inhalte nicht selbst verschlüsselt — und eine Egress-Regel auf dem Sandbox-Host, wenn Agents Kommandos ausführen dürfen.
- Die Rechtsseiten, auf die das Deployment verlinkt, und wer eine Auskunfts-
oder Löschanfrage beantwortet. Die Mechanismen stehen hier -
GET /me/data/exportund die Kontolöschung - aber wer die Anfrage entgegennimmt und in welcher Frist, ist Sache des Verantwortlichen.
Ein Deployment prüfen¶
Wiederholbare Prüfungen, vom Host aus, gegen das laufende Deployment. Jede gibt
Fakten aus, die die Prüfung anhängen kann; keine gibt ein Zugangsdatum oder die
Daten einer Person aus. Führe sie aus backend/ aus, oder über
docker compose exec api.
# 1. Läuft es überhaupt, und sind die Verbindungen zu den Speichern
# verschlüsselt? `postgres` meldet den TLS-Zustand der Verbindung, die der
# Doctor selbst aufgebaut hat.
uv run agenticos cmd doctor
# 2. Jedes versiegelte Zugangsdatum öffnet sich weiterhin unter den
# konfigurierten Master Keys.
uv run agenticos cmd vault-rotate --dry-run
# 3. Die Hash-Ketten der Audit-Spur und ihre Checkpoints, neu berechnet. Endet
# mit einem Exit-Code ungleich null, wenn eine Kette verändert wurde.
uv run agenticos cmd audit-verify
# 4. Alles, was dieses Deployment tatsächlich konfiguriert hat: die
# Einstellungen, die entscheiden, was hinausgeht, jeden Provider und
# Endpunkt, den ein Agent erreichen kann, die gehaltenen Zugangsdaten nach
# Zweck, die Collections und wer sie einbettet, die Server im eigenen Netz,
# die MCP-Server, Trigger-Portale, Sync-Quellen und Channel-Bots, die
# Capabilities, die eine eigene Adresse erreichen, wohin Runs getraced werden
# und wie viel Inhalt ein Span trägt, wie viel jedes Speichers eine
# Aufbewahrungsfrist erfassen würde, und die Dateien unter `MEDIA_DIR`, auf
# die keine Zeile mehr zeigt.
uv run agenticos cmd data-protection-report --older-than 365
Punkt 4 ist der, den man anhängt. Er gibt Konfiguration und Zählungen aus und
niemals Inhalt: keinen Nachrichtentext, kein Dokument, keinen Secret-Wert und
keinen Hinweis darauf, und eine Einstellung, die ein Zugangsdatum hält, wird als
gesetzt oder ungesetzt gemeldet statt ausgegeben. --older-than ist die
betrachtete Aufbewahrungsfrist in Tagen, und die letzte Spalte seiner
Aufbewahrungstabelle ist das, was diese Frist bereits entfernt hätte.
Sein letzter Abschnitt zählt die Bytes, die keine Zeile mehr benennt. Das Löschen einer Konversation oder eines Kontos löst deren Anhänge jetzt nach dem Commit, so dass dieser Weg nichts mehr hinzufügt; was er noch findet, stammt aus der Zeit vor diesen Löschungen oder aus einem Lösen, das ein Best-Effort-Sweep nicht zu Ende gebracht hat.
Das Parse-Arbeitsverzeichnis ist ausgenommen - es hat von
vornherein keine Zeile. Erzeugte Medien werden gezählt, seit generated_media
jede Datei festhält, daher ist, was unter einem Verzeichnis generated_<org>
erscheint, meist eine Datei, die vor dieser Tabelle erzeugt wurde und nur mit
ihrer Organisation geht. Es kann auch eine Datei sein, deren Lösen nach dem
Löschen ihrer Zeile fehlschlug, oder eine, die noch gespeichert wird, bevor ihre
Zeile geschrieben ist. Alles andere, was dort gezählt wird, sind Bytes, die das
Produkt nicht mehr findet und nicht löschen kann. Er meldet ein Verzeichnis und eine Zahl statt eines Dateinamens, denn ein
gespeicherter Pfad behält den Namen, unter dem die Datei hochgeladen wurde.
Zwei Abschnitte werden aus dem gelesen, was läuft, und nicht aus einer Tabelle.
Capability-Ziele listet die an einen Agenten gebundenen Capabilities auf, die
eine eigene Adresse erreichen - web_research sucht ohne jedes Zugangsdatum über
DuckDuckGo und damit ohne Zeile irgendwo sonst im Bericht - und Tracing wird
aus jeder lauffähigen Version gelesen: der Standardversion und der, die jede
benannte Umgebung anheftet, denn ein Run über diese Umgebung
nutzt die Observability jener Version und nicht die der Standardversion.
Was kein Befehl erzeugen kann, ist die andere Hälfte dieser Seite: die Vereinbarungen, Standorte und Trainingsausschlüsse des vorherigen Abschnitts. Hänge sie neben die Ausgabe.
Offene Bedingungen für eine erste Einführung¶
Festgehalten für das Deployment, für das diese Seite geschrieben wurde, und wahr für jedes Deployment, bis jede von ihnen geschlossen ist.
Im Code, und bleibend:
- Traces tragen vollen Inhalt, sofern ein Agent
observability.contentnicht aufnonesetzt. Ein gefiltertes Dazwischen gibt es nicht und wird es nicht geben: ein teilweise bereinigter Export ist eine Zusage, die niemand prüfen kann (#1616). - Inhalte im Ruhezustand gehören dem Betreiber. Nachrichtentexte, Dokumente und ihre Vektoren sowie Sandbox-Workspaces sind gewöhnliche Spalten und Dateien; der Vault versiegelt Zugangsdaten, nicht Inhalte. Hochgeladene Dateien können in einen S3-kompatiblen Store gehen, der sie serverseitig verschlüsselt, aber Datenbank und Medien-Volume schützt die Platten- oder Volume-Verschlüsselung - oder gar nichts.
Geschlossen, und oben statt hier beantwortet: der Manipulationsnachweis der
Audit-Spur (#1622, #1648), der Trace-Inhaltsmodus je Agent und sein Erben durch Spezialisten (#1413, #1699), das Tracing in dem Prozess, der einen
gefeuerten Agent ausführt (#1700), die
Kontrollmatrix für HIPAA und SOC 2 unter
Sicherheit (#1412), Löschung und Export der Daten
einer Person (#1421), das S3-Backend mit serverseitiger Verschlüsselung (#1423)
und generisches OIDC-Sign-in (#1419). Traces haben kein gefiltertes
Dazwischen und bekommen keines
(#1616); für ein
Deployment, das keinen Inhalt exportieren darf, ist none die Antwort.
Im Deployment, von seinem Betreiber entschieden: die Vereinbarungen,
Standorte, Trainingsausschlüsse, der Aufbewahrungsplan, die Backup-Frist, die
Plattenverschlüsselung, der Sandbox-Ausgangsverkehr und die Rechtsseiten des
vorherigen Abschnitts. Jedes davon ist der Nachweis, den
data-protection-report bewusst nicht erzeugt.
Eine Prüfung, die jede Zeile oben entweder geschlossen oder schriftlich akzeptiert vorfindet, hat, was diese Seite ihr geben kann. Der Rest gehört dem Deployment.