teampulse/docs/superpowers/specs/2026-05-16-teampulse-design.md
Oliver Hofmann 3ba945f283 Add TeamPulse design spec
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 17:05:58 +02:00

133 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# TeamPulse — Design-Dokument
**Datum:** 2026-05-16
**Status:** Zur Implementierung freigegeben
---
## Ziel
Ein Python-Script, das den Chat eines laufenden Microsoft Teams-Meetings überwacht, alle Personen erfasst, die in einem definierten Zeitfenster eine Nachricht gepostet haben, und ein Memo mit Name und E-Mail-Adresse der Teilnehmer erzeugt.
Ausgangslage: Nutzer ohne Admin-Rechte, kein Zugriff auf Microsoft Graph API / Azure AD App-Registrierung.
---
## Architektur
```
main.py
├── auth.py — Playwright-Session verwalten (Login, Persistenz)
├── monitor.py — Teams-Chat pollen, Trigger erkennen, Nachrichten sammeln
├── resolver.py — Sender-Name → E-Mail via Profilkarte (mit lokalem Cache)
└── memo.py — Markdown-Memo erzeugen und speichern
```
---
## Komponenten
### `auth.py`
- Startet Playwright mit persistentem User-Data-Verzeichnis (`~/.teampulse/session`)
- Beim ersten Start: sichtbares Browser-Fenster für manuellen SSO/MFA-Login
- Bei bekannter Session: headless, unsichtbar im Hintergrund
- Erkennt Session-Ablauf (Login-Redirect) und öffnet Browser-Fenster zur Re-Authentifizierung
- Liest beim Start den Display-Namen des eingeloggten Nutzers aus → wird als „Moderator" gespeichert
### `monitor.py`
- Öffnet Teams Web im Hintergrund-Browser
- Nutzer navigiert einmalig manuell zur Meeting-Chat-URL
- Pollt den Chat-DOM alle ~2 Sekunden auf neue Nachrichten
- Erkennt Trigger-Befehle (nur wenn gepostet vom eingeloggten Nutzer):
- `!start "Name des Vortragenden"` → startet Zeitfenster, speichert Vortragendenname
- `!stop` → beendet Zeitfenster
- Fallback: Enter-Taste in der Konsole als alternativer Trigger
- Sammelt während des Zeitfensters: `{ sender: str, timestamp: str }`
- Reconnect-Logik bei Seitenreload oder Verbindungsverlust (gesammelte Daten bleiben erhalten)
### `resolver.py`
- Iteriert nach `!stop` über alle eindeutigen Sender
- Prüft `~/.teampulse/cache.json` — bekannte Namen werden nicht erneut aufgelöst
- Für unbekannte Sender: klickt Profilkarte im Teams-Web → extrahiert E-Mail
- Fehlerbehandlung:
- Profilkarte nicht ladbar → `<nicht auflösbar>`
- Externer Gast → als Gast markieren: `<gast@extern.com>` oder `<externer Gast>`
- Cache wird bei jedem neuen Eintrag sofort geschrieben
### `memo.py`
- Filtert Vortragenden und Moderator aus der Teilnehmerliste
- Sortiert verbleibende Einträge nach E-Mail-Adresse
- Erzeugt Markdown-Ausgabe (siehe Format unten)
- Speichert Datei als `audit_YYYYMMDD_HHMM.md` im aktuellen Verzeichnis
- Gibt Inhalt zusätzlich in der Konsole aus
---
## Trigger-Verhalten
| Aktion | Chat-Befehl | Konsole |
|---|---|---|
| Zeitfenster starten | `!start "Anna Bauer"` | Enter drücken |
| Zeitfenster beenden | `!stop` | Enter drücken |
- Nur Befehle vom eingeloggten Nutzer werden als Trigger akzeptiert
- `!start` ohne Anführungszeichen oder ohne Namen → Warnung, Zeitfenster startet mit Platzhalter „Unbekannter Vortragender"
- Mehrfaches `!start` ohne `!stop` → zweites `!start` überschreibt das erste (kein Fehler)
---
## Ausgabeformat
```markdown
# Meeting Chat Audit
Zeitfenster: 10:03:42 10:47:15
## Teilnehmer am Vortrag von Anna Bauer (4)
_Moderator: Oliver Hofmann — Vortragender und Moderator ausgeschlossen_
- Klaus Huber <k.huber@company.com>
- Max Mustermann <m.mustermann@company.com>
- Sandra Vogel <s.vogel@company.com>
- Thomas Wolf <t.wolf@company.com>
_Sortiert nach E-Mail-Adresse. Erstellt: 2026-05-16 10:51_
```
- Keine Nachrichten im Zeitfenster → Hinweis „Keine Chat-Aktivität in diesem Zeitfenster"
- Nicht auflösbare E-Mails → Eintrag trotzdem aufgeführt, E-Mail als `<nicht auflösbar>`
---
## Technologie-Stack
| Komponente | Wahl |
|---|---|
| Sprache | Python 3.11+ |
| Browser-Automation | Playwright (sync API) |
| Cache | JSON-Datei (`~/.teampulse/cache.json`) |
| Ausgabe | Markdown |
| Plattform | Mac, Windows, Linux |
---
## Randfälle
| Situation | Verhalten |
|---|---|
| Session abgelaufen | Sichtbarer Browser für Re-Auth, danach wieder headless |
| Profilkarte nicht ladbar | `<nicht auflösbar>`, kein Absturz |
| Externer Gast | Als Gast markiert |
| `!start` ohne Namen | Warnung + Platzhalter |
| `!start` von anderem Nutzer | Ignoriert |
| Seitenreload während Monitoring | Automatischer Reconnect, keine Datenverlust |
| Keine Nachrichten im Fenster | Memo mit entsprechendem Hinweis |
---
## Nicht im Scope
- Graph API / Azure AD Integration
- GUI / Web-Dashboard
- Mehrere gleichzeitige Zeitfenster
- Historische Chat-Auswertung (vergangene Meetings)