wip: Sicherungs-Commit aller Änderungen seit April + Arbeitsstruktur (CLAUDE.md, ROADMAP.md, PROGRESS.md, Autopilot)

6 Wochen uncommittete Arbeit (Voice-Channels, LiveKit-Manager, Settings-Modal u.v.m.)
als ein WIP-Commit gesichert, damit nichts verloren geht und der Pi den aktuellen
Stand klonen kann. Thematische Aufarbeitung: siehe ROADMAP M0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPrAGBxBT6GfPXzeWQ4AXb
This commit is contained in:
Bernd Steckmeister
2026-07-03 05:47:18 +02:00
parent d706ace35f
commit 25ed765a03
195 changed files with 47784 additions and 1236 deletions
@@ -0,0 +1,437 @@
# 13 — Server-Administration: Continuwuity
> **Gilt für:** Continuwuity 0.5.x (Fork von Conduwuit, welches ein Fork von Conduit ist)
> **Homeserver:** `steggi-matrix.work`
> **WICHTIG:** Continuwuity hat KEINE Synapse Admin API (`/_synapse/admin/` existiert nicht!)
---
## Inhaltsverzeichnis
- [Server-Admin vs. Room Power Level](#server-admin-vs-room-power-level)
- [Admin Room — Befehle](#admin-room--befehle)
- [Continuwuity Admin HTTP API](#continuwuity-admin-http-api)
- [Power Level in Räumen erzwingen (als Server-Admin)](#power-level-in-räumen-erzwingen)
- [MSC3083: Restricted Join Rules auf Continuwuity](#msc3083-restricted-join-rules-auf-continuwuity)
- [Diagnose: Warum M_FORBIDDEN?](#diagnose-warum-m_forbidden)
- [User-Admin-Status prüfen/setzen](#user-admin-status-prüfensetzen)
- [Raum-Administration via Matrix API](#raum-administration-via-matrix-api)
- [Wichtige Unterschiede: Continuwuity vs. Synapse](#wichtige-unterschiede-continuwuity-vs-synapse)
- [Continuwuity `homeserver.yaml` — relevante Einstellungen](#continuwuity-homeserveryaml--relevante-einstellungen)
---
## Server-Admin vs. Room Power Level
```
Continuwuity Server-Admin
├── Ermöglicht: Admin-Room-Befehle, Server-API
├── Ermöglicht: User deaktivieren, Räume löschen (Server-Level)
└── NICHT: Automatisch PL 100 in jedem Matrix-Raum!
Matrix Room Power Level 100
├── Gilt pro Raum (in m.room.power_levels State-Event gespeichert)
├── Ermöglicht: Name/Topic/Avatar setzen, Join-Rules ändern, User kicken/bannen
└── Unabhängig vom Server-Admin-Status
```
**Beispiel-Problem:**
- Du bist Server-Admin auf `steggi-matrix.work`
- Du hast PL 100 im Space `!xyz:steggi-matrix.work`
- Du erstellst einen neuen Channel → Server gibt dir PL 100 als Ersteller ✅
- Du versuchst `join_rules: restricted` zu setzen → M_FORBIDDEN ❌
- **Grund:** Continuwuity 0.5.x unterstützt MSC3083 möglicherweise nicht vollständig
---
## Admin Room — Befehle
Continuwuity hat einen speziellen Admin-Raum. Als Server-Admin kannst du dort Befehle eingeben:
```
# Admin-Raum beitreten (normalerweise automatisch eingeladen)
# Raum-Alias: #admins:steggi-matrix.work
# Befehle im Admin-Raum (als Nachricht senden):
!admin help # Alle Befehle anzeigen
!admin make_user_admin @user:server # User zu Server-Admin machen
!admin deactivate_user @user:server # User deaktivieren
!admin list_users # Alle User auflisten
!admin get_room_state !roomId:server # Room-State anzeigen
!admin delete_room !roomId:server # Raum löschen
!admin get_mem_usage # Server-Speicherverbrauch
!admin server_version # Server-Version
```
```bash
# Als curl (Admin-Token erforderlich):
# Admin-Room-ID herausfinden:
curl -s "https://steggi-matrix.work/_matrix/client/v3/directory/room/%23admins%3Asteggi-matrix.work" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
# → {"room_id": "!adminRoomId:steggi-matrix.work", ...}
```
---
## Continuwuity Admin HTTP API
```bash
# Basis-URL: https://steggi-matrix.work/_conduwuit/admin/v1/
# (Nicht /_synapse/admin/ — das ist Synapse-only!)
# User zu Server-Admin machen
curl -X POST "https://steggi-matrix.work/_conduwuit/admin/v1/make_user_admin" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
-H "Content-Type: application/json" \
-d '{"user_id": "@todesneutron:steggi-matrix.work"}'
# Server-Status abfragen
curl "https://steggi-matrix.work/_conduwuit/server/version" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
# Alternativ — Standard Matrix-Whoami (prüft ob Token gültig):
curl "https://steggi-matrix.work/_matrix/client/v3/account/whoami" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
# → {"user_id": "@todesneutron:steggi-matrix.work", "is_guest": false}
# Prüfen ob User Server-Admin ist (Conduwuit-spezifisch):
curl "https://steggi-matrix.work/_conduwuit/admin/v1/users/@todesneutron:steggi-matrix.work" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
```
---
## Power Level in Räumen erzwingen (als Server-Admin)
Als Server-Admin kannst du via Matrix Client API Power Levels in jedem Raum setzen,
**auch wenn du kein Mitglied bist** (Continuwuity erlaubt das für Server-Admins):
```bash
# Schritt 1: Aktuelles Power-Level-Event lesen
ROOM_ID="!raumId:steggi-matrix.work"
TOKEN="J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
SERVER="https://steggi-matrix.work"
curl "${SERVER}/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.power_levels/" \
-H "Authorization: Bearer ${TOKEN}"
# Schritt 2: Power Level setzen (users-Map ändern)
curl -X PUT "${SERVER}/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.power_levels/" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"users": {
"@todesneutron:steggi-matrix.work": 100
},
"users_default": 0,
"events_default": 0,
"state_default": 50,
"ban": 50,
"kick": 50,
"invite": 0,
"redact": 50
}'
```
```dart
// In Flutter / Dart (mit Admin-Token):
// Zuerst aktuellen PL-State lesen:
final currentPl = await client.getRoomStateWithKey(
roomId,
EventTypes.RoomPowerLevels,
'',
);
// Users-Map erweitern und zurückschreiben:
final users = Map<String, dynamic>.from(
(currentPl['users'] as Map?)?.cast<String, dynamic>() ?? {},
);
users['@todesneutron:steggi-matrix.work'] = 100;
await client.setRoomStateWithKey(
roomId,
EventTypes.RoomPowerLevels,
'',
{
...currentPl,
'users': users,
},
);
```
---
## MSC3083: Restricted Join Rules auf Continuwuity
`join_rules: restricted` (MSC3083) erlaubt Räumen, nur Space-Mitglieder beizutreten.
**Continuwuity 0.5.x unterstützt MSC3083 möglicherweise nicht vollständig.**
```bash
# Testen ob restricted join rules funktionieren:
ROOM_ID="!testRaum:steggi-matrix.work"
TOKEN="J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
SPACE_ID="!spaceId:steggi-matrix.work"
curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.join_rules/" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"join_rule": "restricted",
"allow": [
{
"type": "m.room_membership",
"room_id": "'"${SPACE_ID}"'"
}
]
}'
# → 200 OK: Unterstützt!
# → M_FORBIDDEN oder M_UNRECOGNIZED: Nicht unterstützt oder PL zu niedrig
```
**Workaround wenn restricted nicht funktioniert:**
```bash
# Fallback: invite-only (explizit jeden User einladen)
curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.join_rules/" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"join_rule": "invite"}'
```
```dart
// In space_admin_dialog.dart — Fallback wenn restricted nicht supported:
try {
await room.setJoinRules(
JoinRules.restricted,
allow: [
SpaceRoomJoinRulesAllowInner(
roomId: spaceId,
type: SpaceRoomJoinRulesAllowInnerType.mRoomMembership,
),
],
);
} on MatrixException catch (e) {
if (e.error == MatrixError.M_FORBIDDEN || e.error == MatrixError.M_UNKNOWN) {
// Continuwuity unterstützt restricted join rules nicht
// Fallback zu invite-only:
await room.setJoinRules(JoinRules.invite);
} else {
rethrow;
}
}
```
---
## Diagnose: Warum M_FORBIDDEN?
```bash
# 1. Prüfen: Welchen Power Level hat mein User in diesem Raum?
ROOM_ID="!raumId:steggi-matrix.work"
TOKEN="J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
curl "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.power_levels/" \
-H "Authorization: Bearer ${TOKEN}"
# Antwort zeigt 'users' Map — prüfen ob '@todesneutron:steggi-matrix.work' drin ist
# 2. Prüfen: Was ist state_default?
# Im Antwort-JSON: "state_default": 50 bedeutet: PL 50 nötig für State-Events
# "m.room.join_rules": 100 in events-Map = PL 100 für Join-Rule-Änderung
# 3. Prüfen: Bin ich Mitglied des Raums?
curl "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.member/%40todesneutron%3Asteggi-matrix.work/" \
-H "Authorization: Bearer ${TOKEN}"
# → {"membership": "join"} = Mitglied ✅
# → {"errcode": "M_NOT_FOUND"} = Nicht Mitglied ❌ (Server-Admin kann trotzdem State setzen)
# 4. Prüfen: Unterstützt der Server restricted join rules?
curl "https://steggi-matrix.work/_matrix/client/v3/capabilities" \
-H "Authorization: Bearer ${TOKEN}"
# Antwort: capabilities-Objekt — MSC3083 ist nicht explizit gelistet (kein Standard-Capability)
```
**Häufige Ursachen und Lösungen:**
| Fehler | Ursache | Lösung |
|---|---|---|
| M_FORBIDDEN beim State-Event | PL zu niedrig im Raum | Power Level via curl erhöhen (s.o.) |
| M_FORBIDDEN bei join_rules: restricted | MSC3083 nicht unterstützt | Fallback zu `invite` nutzen |
| M_FORBIDDEN beim Channel erstellen | Bug in space_admin_dialog.dart | Raum manuell erstellen, dann Space-Child setzen |
| M_NOT_FOUND | Raum nicht bekannt | Raum beitreten oder Admin-Join |
| M_FORBIDDEN bei Power-Level-Änderung | PL darf nur gleich/höher gesetzt werden | Als Ersteller oder via Admin-API |
---
## User-Admin-Status prüfen/setzen
```bash
# Prüfen ob User Server-Admin ist:
curl "https://steggi-matrix.work/_matrix/client/v3/account/whoami" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
# Auf Pi (SSH): User-Datenbank direkt abfragen (Conduwuit/Continuwuity nutzt RocksDB)
# Alternativ: Über Admin-Room-Befehl
# (Im Admin-Room als Nachricht senden:)
# !admin make_user_admin @todesneutron:steggi-matrix.work
# Über HTTP (Conduwuit Admin-Endpoint):
curl -X POST "https://steggi-matrix.work/_conduwuit/admin/v1/make_user_admin" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
-H "Content-Type: application/json" \
-d '{"user_id": "@todesneutron:steggi-matrix.work"}'
```
---
## Raum-Administration via Matrix API
Da kein Synapse-Admin-API existiert, nutze die Standard-Matrix-Client-API mit Admin-Token:
```bash
# Raum beitreten (als Admin, auch wenn invite-only):
curl -X POST "https://steggi-matrix.work/_matrix/client/v3/join/!roomId%3Asteggi-matrix.work" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
-H "Content-Type: application/json" \
-d '{}'
# User in Raum einladen:
curl -X POST "https://steggi-matrix.work/_matrix/client/v3/rooms/!roomId%3Asteggi-matrix.work/invite" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
-H "Content-Type: application/json" \
-d '{"user_id": "@user:steggi-matrix.work"}'
# Space-Child-Relation setzen (Channel einem Space hinzufügen):
curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/!spaceId%3Asteggi-matrix.work/state/m.space.child/!channelId%3Asteggi-matrix.work/" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
-H "Content-Type: application/json" \
-d '{
"via": ["steggi-matrix.work"],
"suggested": false
}'
# Space-Parent-Relation setzen (im Channel-Raum):
curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/!channelId%3Asteggi-matrix.work/state/m.space.parent/!spaceId%3Asteggi-matrix.work/" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
-H "Content-Type: application/json" \
-d '{
"via": ["steggi-matrix.work"],
"canonical": true
}'
# Alle Mitglieder eines Raums auflisten:
curl "https://steggi-matrix.work/_matrix/client/v3/rooms/!roomId%3Asteggi-matrix.work/members" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
# Raum verlassen (als User, nicht löschen):
curl -X POST "https://steggi-matrix.work/_matrix/client/v3/rooms/!roomId%3Asteggi-matrix.work/leave" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \
-H "Content-Type: application/json" \
-d '{}'
```
---
## Wichtige Unterschiede: Continuwuity vs. Synapse
| Feature | Synapse | Continuwuity 0.5.x |
|---|---|---|
| Admin API URL | `/_synapse/admin/v1/` | `/_conduwuit/admin/v1/` |
| Admin Room | Optional | Standard |
| MSC3083 (restricted join rules) | ✅ Vollständig | ⚠️ Teilweise / experimentell |
| Spaces (MSC1772) | ✅ | ✅ Grundfunktionen |
| MatrixRTC / MSC3401 | ✅ (Element Call) | ⚠️ Eingeschränkt |
| Push-Gateway | ✅ | ✅ |
| Server-side search | ✅ | ✅ Grundfunktionen |
| E2EE / Cross-Signing | ✅ | ✅ |
| Presence | ✅ | ✅ |
| Account Deactivation | Admin API | Admin Room / API |
| Room Deletion/Purge | Admin API | Admin Room / API |
| User Listing | Admin API | Admin Room / API |
| Federation | ✅ | ✅ |
| Application Services | ✅ | ⚠️ Eingeschränkt |
---
## Continuwuity `homeserver.yaml` — relevante Einstellungen
```yaml
# /etc/continuwuity/homeserver.yaml (oder /etc/conduwuit/conduwuit.toml je nach Version)
# Matrix-RTC / LiveKit
# MSC3266: Room Summary
# MSC3401: MatrixRTC
allow_unstable_room_versions: true
# Federation (für Multi-Server-Calls nötig)
allow_federation: true
allow_public_room_directory_without_auth: false
# Push (für Notifications)
# Kein spezieller Config — nutzt Standard-Matrix-Push-API
# TURN-Server für WebRTC
turn_uris:
- "turn:steggi-matrix.work:3478?transport=udp"
- "turn:steggi-matrix.work:3478?transport=tcp"
turn_secret: "dein-turn-secret"
turn_username: "" # leer = HMAC-basiert
turn_password: ""
turn_ttl: 86400
# Registrierung
allow_registration: false # Kein offener Signup
registration_token: "dein-token" # Oder token-basiert
# Log-Level
log: "warn,conduwuit=info"
# Performance
rocksdb_parallelism_threads: 4 # Pi 5 hat 4 Cores
# Unter Continuwuity: Admin-User beim ersten Start setzen
# Erster registrierter User wird automatisch Server-Admin
```
```bash
# Auf dem Pi: Config-Datei editieren
ssh steggi@192.168.178.71
sudo nano /etc/continuwuity/homeserver.yaml
# oder:
sudo nano /etc/conduwuit/conduwuit.toml # Falls TOML-Format
# Service neu starten:
sudo systemctl restart continuwuity
# oder:
sudo systemctl restart conduwuit
# Logs prüfen:
sudo journalctl -u continuwuity -f
```
---
## Schnell-Diagnose Checkliste
Wenn du M_FORBIDDEN bekommst:
```bash
# 1. Token gültig?
curl "https://steggi-matrix.work/_matrix/client/v3/account/whoami" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
# 2. PL im betroffenen Raum prüfen:
curl "https://steggi-matrix.work/_matrix/client/v3/rooms/!ROOM_ID/state/m.room.power_levels/" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
# 3. Mitglied des Raums?
curl "https://steggi-matrix.work/_matrix/client/v3/rooms/!ROOM_ID/state/m.room.member/%40todesneutron%3Asteggi-matrix.work/" \
-H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI"
# 4. Was genau schlägt fehl? (Antwort-Body lesen!)
# M_FORBIDDEN + "Power level too low" → PL erhöhen
# M_FORBIDDEN + "Not a member" → Raum beitreten
# M_UNRECOGNIZED → Feature nicht unterstützt
# M_FORBIDDEN + "..." → join_rules restricted Problem
```