Connections — API-Key-Lebenszyklus
Wie eine Personal-Brain-Instanz sich mit einer Business-Brain-Instanz verbindet und wieder trennt.
Für die architektonische Einordnung siehe ARCHITECTURE.md, für gelockte Entscheidungen ../DECISIONS.md (D24, D25).
1. Ablauf
Admin@Business User@Personal
(z.B. gustavo (z.B. gustavo
im Business-Admin-UI) auf seinem Mac)
│ │
│ 1. Invite generieren │
│ POST /admin/invites │
│ → { code: "KBL-7A3X", api_key: "sk_…" } │
│ (Code ist 24h gültig, one-shot) │
│ │
│ 2. Code an den Eingeladenen senden │
│ (E-Mail, Signal, o.Ä. — out of band) │
│ ────────────────────────────────────────────► │
│ │
│ │ 3. UI: "Business verbinden"
│ │ → URL + Code eingeben
│ │ POST /api/connect
│ │ { business_url, code }
│ ◄───────────────────────────────────────────── │
│ │
│ 4. Business validiert Code │
│ - existiert? │
│ - nicht abgelaufen? │
│ - noch nicht eingelöst? │
│ Bindet Code an callers Identity │
│ Deaktiviert Code (one-shot) │
│ │
│ 5. Response: { │
│ business_id: "kuble", │
│ business_name: "Kuble GmbH", │
│ api_key: "sk_…", │
│ scopes: [...] │
│ } │
│ ────────────────────────────────────────────► │
│ │
│ │ 6. Personal persistiert
│ │ in SQLite (api_keys Tabelle)
│ │ UI: "Verbunden mit Kuble ✓"
│ │
│ │ 7. UI: Brain-Liste laden
│ │ → GET /api/brain/list
│ │ Header: X-GTS-Key
│ ◄───────────────────────────────────────────── │
│ │
│ 8. UI: User haken ab, welche │
│ Projekte/Kunden syncen sollen │
│ │
│ ... ongoing sync (via /api/sync) ... │
│ │
│ n. Admin: "Trennen" │
│ DELETE /admin/connections/<id> │
│ → API-Key revoked │
│ │
│ n+1. Nächster Personal-Sync │
│ Response: 401 Unauthorized │
│ │ Personal UI:
│ │ "Verbindung getrennt durch Admin"
│ │ zeigt Kontakt-Hinweis
2. Zustände einer Connection
Aus Business-Sicht (Spalte status in connections-Tabelle):
| Status | Bedeutung |
|---|---|
invited |
Code ausgestellt, noch nicht eingelöst. Expires in 24h. |
active |
Eingelöst, funktioniert. |
revoked |
Admin hat widerrufen. Key funktioniert nicht mehr. Historisch sichtbar im Audit-Log. |
expired |
Code lief ab, ohne eingelöst zu werden. |
Aus Personal-Sicht analog: connecting, connected, disconnected, failed.
3. Scope (Phase 4+)
API-Keys haben einen Scope-Set. Im MVP der einzige Scope ist sync (Lesen + Schreiben von Brain-Sync-Daten). Erweiterbar:
sync.read— Nur-Lese-Personalsync.write— Bidirektional (Default)admin— Darf auf die Business-Seite zurückschreiben auch ohne Sync (z.B. ein Delegated-Admin-Setup)
Scopes werden in Phase 4 im Detail ausgearbeitet — MVP reicht sync.write.
4. Sicherheits-Constraints
- Code einmalig einlösbar — nach erstem Redeem deaktiviert, unabhängig vom Ergebnis.
- API-Key nie im Klartext loggen — nur das letzte Präfix (
sk_abc…). - Rate-Limit auf
/api/connect— 10 Versuche/IP/10min (verhindert Brute-Force auf Codes). - Key-Rotation: Admin kann einen Key ohne Disconnect rotieren (neuer Key ersetzt alten). Personal bekommt Push-Notification oder schlägt beim nächsten Sync fehl und muss den neuen Key eintragen.
- Offboarding: Bei "Mitarbeiter verlässt Firma" sollte der Admin die Connection revoken. Die historischen Brain-Daten auf der Personal-Instanz bleiben beim Ex-Mitarbeiter (kann nicht verhindert werden — git ist dezentral) — aber Business-Soul-Updates stoppen, und der Ex-Mitarbeiter kann nichts mehr ins Business schreiben.
5. CLI-Äquivalente
Was die Web-UI kann, kann auch die CLI:
# Business (Admin):
gts admin invite --email user@example.com # → Code + URL
gts admin connections list
gts admin connections revoke <id>
gts admin connections rotate-key <id> # neuen Key ausstellen, alten widerrufen
# Personal (User):
gts connect <business-url> <code>
gts connect list
gts connect revoke <business-slug>
gts sync [<business-slug>] # pull/push, logged in git + SQLite