xPulse
🇩🇪 DE

Profile – Concept

Status: CONCEPT · Erstellt April 2026 Übergeordnet: TOOL_chat_roadmap.md Verwandt: TOOL_chat_concept-peer-sync.md Geplant ab: v1.8.0


Warum ein eigenes Konzept?

Das Profil ist mehr als ein Login-Name. Ab v1.8.0 kann der User entscheiden wie er sich gegenüber seinen Peers präsentiert – und was davon überhaupt sichtbar ist. Dieses Konzept legt fest welche Felder existieren, was davon gesynct wird, und wie der User die Sichtbarkeit steuert.


Profil-Struktur

{
// Technisch – nie gesynct, nie öffentlich
login: String, // interner Identifier, unveränderlich
clientId: String, // technische Peer-ID
createdAt: Number, // Unix ms – Zeitpunkt der Profil-Erstellung
// Sync-Basis
updatedAt: Number, // Unix ms – letzte Änderung, Grundlage für Sync-Vergleich
// Öffentliche Felder
displayName: String|null, // frei wählbarer Anzeigename ≠ Login
avatar: String|null, // Base64 Thumbnail
bio: String|null, // kurze Beschreibung – max. 500 Zeichen
mood: String|null, // Freitext – Motto / Current Mood – max. 250 Zeichen
pronouns: String|null, // Freitext – z.B. "he/him", "she/her", "they/them"
// UI zeigt Info-Hinweis mit Beispielen
// Status
status: String, // vom User wählbar: 'away' | 'busy'
// vom System gesetzt: 'online' | 'offline'
// Sichtbarkeitssteuerung – alle false by default
public: {
displayName: Boolean, // default: false
avatar: Boolean, // default: false
bio: Boolean, // default: false
mood: Boolean, // default: false
pronouns: Boolean, // default: false
status: Boolean, // default: false
},
// Lokal – nie gesynct
preferences: {
notifications: Boolean, // Benachrichtigungen ein/aus
defaultStatus: String, // 'away' – gesetzt bei Tab-Unfocus + 5min Inaktivität
}
}

Status

Prioritäts-Hierarchie

System (höchste Priorität):
offline → immer wenn nicht verbunden – überschreibt alles
User (mittlere Priorität):
busy → manuell gesetzt – bleibt bis manuell geändert
away → manuell gesetzt – bleibt bis manuell geändert
System-Automatik (niedrigste Priorität):
away → Tab-Unfocus ODER 5min Inaktivität
→ nur wenn kein User-Status gesetzt
online → Tab-Focus + Aktivität
→ nur wenn kein User-Status gesetzt

User-gesetzter Status gewinnt immer gegen System-Automatik:

Vom System ermittelt – nicht wählbar

Vom User wählbar

Der User-Status wird nur angezeigt wenn der Peer online ist. Ist der Peer offline, zeigt das System immer offline.

System-Automatik (`preferences.defaultStatus`)

Tab verliert Fokus → Status: 'away' (wenn kein User-Status gesetzt)
5min keine Aktivität → Status: 'away' (wenn kein User-Status gesetzt)
Tab bekommt Fokus → Status: 'online' (wenn kein User-Status gesetzt)

Nicht stören (`busy`)

Wenn status === 'busy':


Sichtbarkeitssteuerung (`public`)

Jedes öffentliche Feld hat einen eigenen public-Flag. Der ProfileProvider schaut beim Sync-Collect ausschließlich in public und baut daraus das Sync-Payload – nur Felder mit true werden an den Peer übertragen.

// Beispiel: nur displayName und status sind öffentlich
public: {
displayName: true,
avatar: false,
bio: false,
mood: true,
pronouns: false,
status: true,
}

Der Peer sieht dann nur displayName, mood und status – alles andere bleibt lokal.


Was nie gesynct wird

Unabhängig von public-Einstellungen werden folgende Felder niemals gesynct:


Comparator – Konfliktbehandlung

Beim Profile Sync gilt: updatedAt neuer → gewinnt.

sync:response:profile empfangen →
eingehendes updatedAt > lokales updatedAt → übernehmen
eingehendes updatedAt < lokales updatedAt → ignorieren
eingehendes updatedAt === lokales updatedAt → lokaler Stand gewinnt

Migration (altes Format)

// Alt (vor v1.8.0)
{ login, clientId, createdAt, preferences }
// Migration
updatedAt: createdAt // beste Annäherung
displayName: null
avatar: null
bio: null
mood: null
pronouns: null
status: 'online' // Default
public: { // alle false – User entscheidet bewusst
displayName: false,
avatar: false,
bio: false,
mood: false,
pronouns: false,
status: false
}
preferences: {
notifications: true, // bestehender Wert übernehmen
defaultStatus: 'away' // neuer Default
}

Offene Punkte

Thema Stand
Avatar-Größenlimit (Base64, DataChannel ~256KB chunks) TBD – relevant ab v1.8.0
de/concept/profile.md 2026-04-17