aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-07 17:50:28 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-07 17:50:28 +0200
commit36cebf25d0e0f24cf63be4380ccb5d03da726a74 (patch)
tree8509ec4cf68a058f7383299e11bdea97ab06cadf /packages/meshbay-hub/src/meshbay_hub/static/locales/de.js
parent8883d60d0afa2ed9dd1ef68bc21fe1b9a65a59ff (diff)
downloadmeshbay-36cebf25d0e0f24cf63be4380ccb5d03da726a74.tar.gz
feat(chat): encrypt group chat under per-device epoch keys (MNP 2.0)
Chat messages are sealed with AES-256-GCM under a key derived per group, per epoch, per *device*, and signed over the ciphertext with the device key the node pinned. The node relays and archives; it cannot read a message. There is no switch. MNP goes to 2.0 and MNP_MIN_SUPPORTED moves with it, so a 1.x peer is refused at the handshake with `version_too_old` rather than admitted and then unable to speak. An opt-in flag was designed and rejected: every node is a test node, so it would have bought nothing and left a plaintext branch reachable — C6's lesson one feature later. A test reads the source and refuses any code that consults a `chat_encrypted` setting. Not Sender Keys, and `senderkeys.py` is now documented as unused. With distribution under the group key and a node that serves history to devices which were not present, the node must retain each chain's earliest key, and a chain key at iteration i yields every message key from i on by pure HKDF — forward secrecy is zero either way. What the ratchet was left buying was stateful client code with silent failure modes, three of them reproduced: any member could sign as any other, a second device dropped the first's chain, and the skipped-key cache grew without bound. The reasoning is in docs/chat-sender-keys.md, which is the specification and the decision record. Epochs, not rotation: the epoch key is wrapped under the group key at delivery and never stored under it, so `gek_rotate` is a re-wrap. A group-key-derived archive key would have made every message ever sent unreadable on the first `member unpin`, which is the documented step after removing a member. A new epoch opens on member revoke/unpin, device revoke and `gek_rotate`; old epochs are kept and still delivered, so history stays readable to everyone who could already read it, and nothing anywhere deletes one. Three prerequisites this needed, each a live defect on its own: * The peer registry was keyed by user_id, so one account's second device evicted the first and the broadcast skipped recipients by account — a person's phone never saw what they typed on their laptop. * The handshake authenticated an account, never a device. `device_hello` (additive, signed, refused unless the key is a live device of this account in the node's own roster) is what lets the node refuse a member claiming somebody else's key. * `_admin_exec_file_delete` authorized against the exact uploading key, so device linking had already broken deleting your own file from your other device. It now authorizes against any non-revoked device of `uploader_id`. Found by driving the real panel over the real transport, not by reading source: `chat_keys_resp` was routed by arrival order and handed to an unanswered `media_meta_req` — the original frozen-tab defect in a message type that did not exist when that probe was written. And `_asText` had been deleted with an unrelated helper beside it; its only caller sits inside a promise the panel catches, so every conversation rendered empty with nothing in the console. Existing node data is migrated by QE/migration/migrate_chat_encryption.py (not versioned, per the QE rule), run with the node stopped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TZZxYjz8YeWRz13xDi8LJr
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/locales/de.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/locales/de.js12
1 files changed, 12 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js b/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js
index d05d3a3..180c762 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/locales/de.js
@@ -652,6 +652,15 @@ export default {
'chat.unread': 'Neue Nachrichten',
'chat.jump_latest': 'Zu den neuesten springen',
'chat.jump_new': 'Neue Nachrichten',
+ 'chat.unreadable': 'Diese Nachricht konnte nicht gelesen werden',
+ 'chat.unreadable_signature': 'Nicht verifizierte Nachricht — die Signatur passt nicht zum Absender',
+ 'chat.unreadable_epoch': 'Geschrieben, bevor dieses Gerät diese Unterhaltung lesen konnte',
+ 'chat.unreadable_keys': 'Chat-Schlüssel nicht verfügbar — neu verbinden, um dies zu lesen',
+ 'chat.unreadable_decrypt': 'Diese Nachricht konnte nicht entschlüsselt werden',
+ 'chat.unreadable_envelope': 'Diese Nachricht kam unvollständig an',
+ 'chat.unreadable_format': 'Diese Nachricht erfordert eine neuere Version von MeshBay',
+ 'chat.encrypted_needs_newer': 'Diese Unterhaltung ist verschlüsselt und dieser Client kann sie nicht lesen — MeshBay aktualisieren',
+ 'chat.encrypted_cannot_send': 'Diese Unterhaltung ist verschlüsselt und dieses Gerät kann noch nicht darin schreiben',
'group.leave': 'Gruppe verlassen',
'group.leave_confirm': '„{name}“ verlassen? Sie verlieren den Zugang zu ihren Dateien und zum Chat. Hochgeladene Dateien bleiben auf dem Node, und der Node behält die für Sie gemerkte Identität, bis sein Betreiber sie entfernt.',
'group.mute': 'Mute notifications',
@@ -852,6 +861,9 @@ export default {
'settings_app.chat_no_writable_root': 'Diese Gruppe hat kein beschreibbares Verzeichnis, daher sind Anhänge aus.',
'settings_app.chat_link_preview_label': 'Link-Vorschauen',
'settings_app.chat_link_preview_hint': 'Postet ein Mitglied einen Link, holt der Node Titel und Bild der Seite. Das ist eine Anfrage von Ihrem Rechner an eine Website, die jemand anderes gewählt hat.',
+ 'settings_app.chat_encrypted_always': 'Der Chat dieser Gruppe ist immer verschlüsselt. Das lässt sich nicht abschalten.',
+ 'settings_app.chat_rotate_epoch': 'Chat-Schlüssel weiterdrehen',
+ 'settings_app.chat_rotate_epoch_hint': 'Mitglieder lesen weiterhin den gesamten Verlauf. Wer aus der Gruppe entfernt wurde, kann nicht mehr lesen, was ab jetzt geschrieben wird. Ein Mitglied oder Gerät zu entfernen tut das bereits von selbst.',
'settings_app.tmdb_token_prompt': 'Registrieren Sie sich bei TMDB, um einen eigenen API-Schlüssel zu erzeugen.',
'settings_app.tmdb_token_link': 'Schlüssel holen',
'settings_node.roots_offline_hint': 'Nicht mit dem Node verbunden — Änderungen laufen über den lokalen Node und greifen beim nächsten Neuladen.',