Symptom
User accepts invitation to a private room. For ~5-30 seconds afterwards, every message in the room renders as `[Encrypted message - secret v0 not available (have: [])]`. Then the back-fill arrives and messages decrypt.
The placeholder text is alarming — it suggests the room is permanently broken. It's actually a transient sync state.
Root cause
When the invitee accepts:
- GET response for the new room contract arrives. State contains messages + member list. No `encrypted_secrets` blob for the invitee's `member_id` yet — the owner's chat-delegate hasn't issued one yet.
- Invitee's `repopulate_secrets_from_state` runs, decrypts 0 secrets. Local `secrets` HashMap empty.
- Renderer falls back to the "secret vN not available (have: [])" placeholder.
- Invitee PUTs join_event. Owner's delegate sees the new member via `ContractNotification`, runs back-fill, publishes blob.
- Update notification reaches the invitee → `repopulate_secrets_from_state` runs again → blob decrypted → messages decrypt.
The window between (3) and (5) is what users see. It's a real network round-trip — order of seconds in practice.
Fix shape
In the renderer (`ui/src/components/conversation.rs`, message bubble rendering), when:
- room is private AND
- local `room_data.secrets` is empty AND
- the message is private-encrypted
show a friendly placeholder instead:
- First ~30 seconds: "Decrypting your invitation — this should only take a moment" with a spinner.
- After 30 seconds with still no secrets: "Still waiting for the room owner to share keys. Try refreshing if this persists."
Optionally also hide the message list entirely behind a centred "Syncing your invitation…" placeholder until first decryption succeeds. Less jarring when decryption flips on.
Logs (user reproduction, build 94fcd8c)
```
get_response.rs:237 GET response: decrypted 0 room secret(s) for member MemberId(QC2UMYUC)
get_response.rs:257 Private room but no secret available for encrypting nickname, using public
```
Then several seconds of state updates pass. Eventually the user sends a message at `secret_version: 2` — confirming the back-fill landed by then.
Related
[AI-assisted - Claude]
Symptom
User accepts invitation to a private room. For ~5-30 seconds afterwards, every message in the room renders as `[Encrypted message - secret v0 not available (have: [])]`. Then the back-fill arrives and messages decrypt.
The placeholder text is alarming — it suggests the room is permanently broken. It's actually a transient sync state.
Root cause
When the invitee accepts:
The window between (3) and (5) is what users see. It's a real network round-trip — order of seconds in practice.
Fix shape
In the renderer (`ui/src/components/conversation.rs`, message bubble rendering), when:
show a friendly placeholder instead:
Optionally also hide the message list entirely behind a centred "Syncing your invitation…" placeholder until first decryption succeeds. Less jarring when decryption flips on.
Logs (user reproduction, build 94fcd8c)
```
get_response.rs:237 GET response: decrypted 0 room secret(s) for member MemberId(QC2UMYUC)
get_response.rs:257 Private room but no secret available for encrypting nickname, using public
```
Then several seconds of state updates pass. Eventually the user sends a message at `secret_version: 2` — confirming the back-fill landed by then.
Related
[AI-assisted - Claude]