Files
pyramid/docs/matrix-sdk
Bernd Steckmeister fe6427bfba security: geleakte Secrets aus Repo entfernen (Review-Befund k)
Secret-Scan im Fable-5-Review fand vier aktive Zugangsdaten im
oeffentlich erreichbaren Gitea-Repo. Gefahrlos entfernbare Stellen:
- scripts/release.ps1: Gitea-Token -> Umgebungsvariable PYRAMID_GITEA_TOKEN
- docs/matrix-sdk/13-server-admin: 19x Admin-Token -> <ADMIN_TOKEN>

Client-eingebettete Secrets (LiveKit apiSecret, Admin-Token im
E2EE-Diagnose-Upload, Giphy-Key) brauchen Rotation + Server-Umbau
und stehen als neue M0-ROADMAP-Punkte (nicht blind auf dem Pi fixbar).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 03:32:37 +02:00
..

Matrix SDK — Pyramid Entwicklungsreferenz

Basis: package:matrix (Dart/Flutter Matrix SDK)
Ziel: Vollständige Landkarte aller Matrix-Funktionen mit Code-Snippets für den Pyramid-App-Bau.
Referenz-Implementierung: FluffyChat (https://gitlab.com/famedly/fluffychat)


Navigation

# Thema Beschreibung
01 Authentifizierung Login, Logout, Register, SSO, Token-Management
02 Räume & Spaces Erstellen, Beitreten, Verlassen, Spaces, Suche
03 Nachrichten & Events Senden, Timeline, Reaktionen, Edits, Threads, Polls
04 Direct Messages DM-Räume finden, starten, verwalten
05 Medien & Dateien Upload, Download, Thumbnails, verschlüsselte Medien
06 E2EE Verschlüsselung Keys, Verifizierung, Cross-Signing, Key-Backup
07 Push & Notifications Pusher, Push Rules, FCM, lokale Benachrichtigungen
08 VoIP & Calls MatrixRTC, Legacy m.call, Klingel-Flow
08b LiveKit Streaming Vollständige Server-Anleitung + Flutter-Implementierung
09 Profil & Präsenz Avatar, Displayname, Presence, Account-Daten
10 Raum-Administration Power Levels, Moderierung, Einstellungen, Bans
11 Suche & Discovery Nachrichten-Suche, User-Suche, Raum-Verzeichnis
12 Schnellreferenz Alle Enums, Widget-Patterns, Fehlerhandling
13 Server-Admin Continuwuity Admin API, Power Levels erzwingen, MSC3083, Diagnose
CHECKLIST Feature-Checklist Implementierungsstand + Roadmap

Schnellreferenz: Client-Initialisierung

import 'package:matrix/matrix.dart';

final client = Client(
  'MeinApp',                              // App-Name (User-Agent)
  database: MatrixSdkDatabase(...),       // Persistenz (sqflite)
  nativeImplementations: NativeImplementationsIsolate(compute), // E2EE
  logLevel: Level.warning,
);

// Initialisieren (lädt gespeicherten Session-State)
await client.init(
  waitForFirstSync: false,               // UI nicht blockieren
  waitUntilLoadCompletedLoaded: false,
);

Architektur-Überblick

Client
├── rooms: List<Room>               // alle bekannten Räume
├── userID: String?                 // eigene MXID (@user:server)
├── accessToken: String?            // Bearer-Token
├── homeserver: Uri                 // https://matrix.example.org
│
├── Room
│   ├── id: String                  // !roomId:server
│   ├── getTimeline()               // Event-Stream
│   ├── sendTextEvent()
│   ├── sendEvent()
│   ├── members                     // Map<String, User>
│   └── states                      // Map<String, Map<String, StrippedStateEvent>>
│
├── Event
│   ├── type: String                // m.room.message, m.reaction, …
│   ├── content: Map<String, dynamic>
│   ├── body: String                // text body (decrypted)
│   └── messageType: String?        // m.text, m.image, m.file, …
│
└── User
    ├── id: String                  // MXID
    ├── displayName: String?
    └── avatarUrl: Uri?

Wichtige Streams / Provider-Hooks

// Auf Sync-Events reagieren
client.onSync.stream.listen((SyncUpdate update) { ... });

// Neue/geänderte Räume
client.onRoomUpdate.stream.listen((String roomId) { ... });

// Verbindungsstatus
client.onConnectionStateChanged.stream.listen((ConnectionState s) { ... });

// Eigener User geändert
client.onUserEvent.stream.listen((EventUpdate update) { ... });

// Benachrichtigungs-Events (gefiltert nach Push-Rules)
client.onNotification.stream.listen((Event event) { ... });

Tipps für Riverpod-Integration

// Matrix-Client als Provider
final matrixClientProvider = FutureProvider<Client>((ref) async {
  final client = Client('Pyramid', ...);
  await client.init(waitForFirstSync: false);
  return client;
});

// Raumliste reaktiv
final roomsProvider = StreamProvider<List<Room>>((ref) async* {
  final client = await ref.watch(matrixClientProvider.future);
  yield client.rooms;
  await for (final _ in client.onSync.stream) {
    yield client.rooms;
  }
});