Architektur — Ground Truth System
Diese Datei beschreibt, wie das System gebaut ist. Für den Plan der Umsetzung siehe ../PLAN.md. Für gelockte Entscheidungen siehe ../DECISIONS.md.
1. Ziel
Ein zentrales, menschen- und agenten-lesbares Gedächtnis pro Unternehmen, mit verteilten persönlichen Gedächtnissen pro Mensch oder Agent — und bewusster, selektiver Synchronisation zwischen beiden Ebenen.
2. Topologie (N:N)
┌─────────────────────────────────────┐
│ Business Brain "kuble" │
│ ground.kuble.com (46.225.238.83) │
│ │
│ • Next.js Web UI + API │
│ • SQLite Metadata │
│ • Git-Repo (brains/) │
│ • MCP Server │
│ • Docker + Traefik │
└─────────────────────────────────────┘
▲ ▲
│ HTTPS+API-Key │
┌────────────────┘ └────────────────┐
│ │
┌──────────────────────┐ ┌──────────────────────┐
│ Personal Brain │ │ Personal Brain │
│ gustavo │ │ maniak (Agent) │
│ Mac Mini │ │ Hermes VPS │
│ │ │ │
│ • Next.js + SQLite │ │ • Next.js + SQLite │
│ • Git-Repo (brains/, │ │ • Git-Repo │
│ soul/private/, │ │ • Key-only API login │
│ soul/business/*) │ │ │
└──────────────────────┘ └──────────────────────┘
Kardinalität: N Personals pro Business, ein Personal mit M Businesses. Jede Verbindung ist eine separate, widerrufbare N:N-Relation.
3. Kernkonzepte
Brain
Eine Sammlung von Markdown-Files mit YAML-Frontmatter, versioniert in git, organisiert in Layern. Jedes File ist ein einzelnes Brain-Dokument (oder kurz: "ein Brain").
Layer
- Slow — stabil, ändert sich selten. Werte, Kultur, Kernwissen, Identität.
- Rapid — dynamisch, ändert sich ständig. Kunden, Projekte, laufende Arbeit.
Domain
- Business — dem Unternehmen gehörend. Zentral gehostet.
- Personal — einer Person oder einem Agent gehörend. Bei ihr/ihm gehostet.
Soul (nur Personal)
- Private Soul (
soul/private/) — persönlich, niemals synced. - Business Soul (
soul/business/<slug>/) — pro verbundenem Business. Read-only auf Personal-Seite, one-way gepullt vom Business. Für Agents: "Wie verhält sich Maniak, wenn er im Auftrag von Kuble agiert?"
Instance
Eine laufende Einheit des Systems. Entweder vom Typ business oder personal. Hat genau eine Identity (z.B. kuble, gustavo, maniak).
Connection
Eine N:N-Beziehung zwischen einer Business- und einer Personal-Instanz, authentifiziert über API-Key, widerrufbar. Siehe CONNECTIONS.md.
4. Daten-Ebenen
| Ebene | Wo | Format | Primär für |
|---|---|---|---|
| Brain-Daten | brains/** + soul/** |
Markdown + Frontmatter | Wissensinhalte — die eigentliche Substanz |
| History | .git/ |
git | Change-Tracking + Rollback |
| Instanz-Metadata | .gts/meta.sqlite |
SQLite | Sessions, Admin-Accounts, Connections, API-Keys, Audit-Log, Mirror-Exclusions, OAuth-State, Chat-History |
| Instanz-Config | .gts/config.yaml |
YAML | Instance-Type, Identity, URLs, Feature-Flags |
Brain-Daten sind Source of Truth (D1). Metadata ist Service-Zustand — nicht teilbar zwischen Instanzen. Config ist Deployment-Setup.
5. ID-Schema
Jedes Brain hat eine global eindeutige id:
<instance-slug>.<type-short>.<slug>[.<subslug>]
Beispiele:
kuble.slow.werte— Werte des Business-Brainskublekuble.projekt.nori-v3— Business-Projektkuble.kunde.beispielgmbh— Business-Kundegustavo.projekt.nori-v3— Personals eigene Sichtgustavo.private.tagebuch.2026-q2— private Notizgustavo.business.kuble.werte— business-soul aus Kuble gepulltmaniak.private.learnings.sync-patterns— Agent-Learning
Der Pfad im Filesystem spiegelt die ID (Linter validiert Konsistenz).
6. Selective Sync
Wer entscheidet was:
- Business definiert, welche Projekte + Kunden existieren, welche Felder (H2-Sektionen) syncable sind.
- Personal entscheidet, welche dieser Projekte/Kunden er syncen will und welche Felder davon.
Mechanik:
- Personal ruft
gts sync <business-slug>(oder Cron). - Personal-Seite sendet Wunsch-Liste:
[{brain_id, fields}]. - Business validiert: API-Key gültig, Brain existiert, Felder syncable.
- Business liefert Content der genehmigten Felder.
- Personal merged in lokale Brains (neue Commits, Sync-Trigger in Message).
- Personal sendet eigene geänderte Felder zurück (wenn bidirectional).
- Business validiert, schreibt, commitet.
Konflikt-Strategie: Wenn beide Seiten denselben Feld-Inhalt seit dem letzten Sync geändert haben, schlägt Sync fehl. User bekommt eine Konflikt-Datei, entscheidet manuell, syncen erneut. Nie automatisches Overwrite.
7. Change Tracking & Rollback
- Jede CLI/MCP/API-Schreibaktion = 1 atomarer Commit.
- Commit-Message-Format:
brain(<domain>/<layer>/<slug>): <action>— normale Schreibvorgänge.sync(<src>→<dst>): fields=[...]— Sync-Operationen.admin(<action>): <detail>— Admin-Operationen (wenn sie git-Änderungen verursachen; Login/Invite gehen in SQLite audit_log).
gts history <brain-id>— lesbarer Wrapper umgit log -- <path>.gts revert <commit>— erstellt einen Revert-Commit, History bleibt erhalten.gts snapshot create "<name>"— benannter git-Tag als Savepoint.
8. Sicherheit
| Vektor | Mechanismus |
|---|---|
| Transport Business↔Personal | HTTPS nur; Let's Encrypt via Traefik auf Business-Server |
| Auth Business-Admin | Email/Passwort + Invite-Flow für weitere Admins (D24) |
| Rollen | admin | member | viewer auf admins.role; last-admin-Guard im UI |
| Auth Personal-User | Username/Passwort oder Google OAuth (Auth.js) |
| Auth Business↔Personal | API-Keys, issued von Admin, revocable (D25) |
| Admin-Brain Access | can_read_admin pro Connection + allowed_users / allowed_connections pro Brain; Remote-Writes auf admin hart blockiert |
| At-Rest Business-Brain | Disk-Encryption auf Server-Host (OS-Verantwortung) |
| At-Rest Personal-Brain | Disk-Encryption auf dem jeweiligen Gerät (User-Verantwortung) |
| Audit | SQLite audit_log (alle Auth/Admin-Ops + MCP-Writes) + git-History (Brain-Ops) |
| Rate-Limit | Auf Auth- und Invite-Endpoints (Phase 4) |
| Secrets | Niemals in Brain-Markdown; .env auf jedem Host; Rotation dokumentiert |
Rollen-Modell:
- admin — Full-Access, darf admin-Kategorie lesen/schreiben, Rollen verwalten, Connections togglen. Mindestens ein Admin pro Instanz (UI-Guard).
- member — Lesen/schreiben in allen Kategorien außer
admin; admin nur lesbar wenn User-Email inallowed_usersdes Brains steht. - viewer — Read-only, sonst gleiche admin-Regeln wie member.
Kein File-Level-Encryption (kein git-crypt) im MVP — D17 supersedet D9.
9. MCP-Integration
Jede Instanz startet einen MCP-Server lokal (packages/mcp/dist/server.js, bin gts-mcp). Agents verbinden sich typischerweise:
- Mit ihrer eigenen Personal-Instanz (per stdio direkt oder via SSH-bridge)
- Mit dem Business-Brain über eine Connection + forced-command SSH-Key mit Env-Vars
MCP-Env-Vars für Access-Control (alle optional):
| Env | Default | Effekt |
|---|---|---|
GTS_MCP_ACTOR_EMAIL / GTS_MCP_ACTOR_NAME |
Instance-Owner | Git-Commit-Author für MCP-Writes |
GTS_MCP_CALLER_SLUG |
unset (= trusted-local) | Remote-Instanz-Slug. Wenn gesetzt → Access-Checks aktiv. |
GTS_MCP_CAN_READ_ADMIN |
0 |
1 erlaubt lesen von admin-Brains (zusätzlich muss Slug in allowed_connections sein) |
GTS_MCP_READONLY_CATEGORIES |
(leer) | Komma-separierte Kategorien wo brain_write/brain_capture abgelehnt wird. Typisch: slow |
Writes auf admin-Kategorie sind für Remote-Caller (GTS_MCP_CALLER_SLUG != unset) immer hart blockiert, unabhängig von Flags.
Audit-Logging: MCP-Writes schreiben einen Row in audit_log mit source: "mcp", actor: "<email> via <slug>", event: mcp-brain-{create,update,capture}, target: <brain-id>, detail: {commit, wasNoOp}. Sichtbar auf /history in der Audit-Events-Spalte.
Tool-Liste siehe ../PLAN.md §10.
9b. Zwei-Ebenen-Modell für Rohtexte (Source + destilliertes Brain)
Ein langer Text (Meeting-Transkript, Email, Dokument) wird nie direkt in ein projekt/kunde/knowledge-Brain reingeschrieben. Stattdessen zwei Writes:
- Source anlegen (
category: source) — Body = voller Originaltext 1:1. Pflichtfeldertype(meeting/email/transcript/document/chat/call) unddate. - Ziel-Brain updaten — neuer Body-Abschnitt mit 3–5 destillierten Bullet Points +
sources[]-Array im Frontmatter um die neue Source-ID erweitern.
Dieses Muster ist in Hermes-SOUL und im MCP-Server instructions-Text verankert, damit Agents es konsistent anwenden. Der destillierte Brain bleibt leserlich; die Source ist jederzeit für Volltext-Suche und Originalzitate verfügbar.
10. Nori als Projekt (Migration)
Nori-Plattform-Daten wandern langfristig vom Standalone-Stack in das GTS:
- Nori-Kunden →
kuble.kunde.<slug>Brains - Nori-Projekte →
kuble.projekt.<slug>Brains - Nori-Agent-Konfigs (SOUL.md, MEMORY.md pro Customer) → Personal-Brain-Instanz pro Agent, verbunden mit dem Kuble-Business
Ziel: ein Business ("Kuble"), viele Personal-Agents (einer pro Nori-Customer), die aus dem Business selective ihre Projekt-Brains pullen.
Zeitlich: Phase 7, nach stabilem MVP.
11. Was NICHT zur Architektur gehört
- Kein Analytics-Cluster. Das System ist Write-Side. Für BI-Dashboards mit aggregierten Daten: separates BI-Tool, das gelegentlich aus git exportiert.
- Kein Real-Time-Collab. Sync ist pull-basiert. Wenn zwei User gleichzeitig schreiben, zählt git-Merge-Logik.
- Kein Multi-Org-Admin. Jedes Business ist eine eigene Instanz. Multi-Business-Verwaltung auf Business-Seite ist aus dem MVP ausgeschlossen (aus Personal-Sicht funktioniert Multi-Business via multiple Connections).