[QA] §O July batch: thread panel, per-thread notifications, math, encrypted search cache, session hardening, audit-wave fixes, E2EE call-key cluster #184

Closed
opened 2026-09-17 23:24:09 -04:00 by jared · 1 comment
Owner

Migrated from LOTUS_TESTING.md §O on 2026-09-17 — the file is now reference-only.

How to report: tick each item as it passes; on FAIL comment with what you saw vs expected, browser/OS, web (chat.lotusguild.org) vs desktop (Tauri), theme, and any browser-console errors. Screenshots for anything visual.

Checklist

  • O1. Thread Panel (P3-8) — 👥 2 people help for live replies
  • O2. Per-thread notifications (P4-1, Slack-style) — 👥 2 people
  • O3. Math / LaTeX (P4-4)
  • O4. Encrypted search cache (P4-8) — opt-in
  • O5. Session hardening (N97a) — cross-tab
  • O6. Audit-wave correctness fixes (AW-1)
  • O8. E2EE / call-key cluster (KE-1→4) — 👥 2 people, during a real call

Everything landed after the OIDC work. These mirror the checklists in LOTUS_TODO.md (§P3-8, §P4-1) and the outstanding-verification backlog below (P3-8/P4-1/P4-4/P4-8/N97a/AW-1…4). ⚠️ Threads change the main timeline — thread replies no longer render inline; that's intended (see O1).

O1. Thread Panel (P3-8) — 👥 2 people help for live replies

  1. Hover a message → Reply in Thread (message menu). The right-side thread panel opens with that message as the root.
  2. Send text, an emoji, and a file upload into the thread; have the second person reply too.
  3. Reply to a reply inside the panel.

Expected: the panel shows the root at top + an "N replies" divider + the reply timeline (own composer at the bottom). Your sends appear immediately (pending → confirmed). A reply-to-a-reply is a proper thread reply. In the main timeline the replies do not appear inline — the root message instead shows a "N replies · time" chip. Clicking the chip (or a reply's thread indicator) opens the panel. × or Escape closes it; on mobile the panel is fullscreen. Scrolled up in a long thread → a Jump to Latest chip appears. Reload the page → the root/reply split persists; in an encrypted room the thread replies decrypt (not "Unable to decrypt").

O2. Per-thread notifications (P4-1, Slack-style) — 👥 2 people

  1. Have the second person reply in a thread you have posted in → expect a notification + sound.
  2. Have them reply in a thread you have never touched and don't @mention you → expect silence (only the chip's unread badge updates).
  3. Have them @mention you in any thread → expect a notification regardless of participation.
  4. Open the panel's bell menu (header) → set the thread to Mute → expect no notifications, the chip's unread badge gone (bell-mute glyph shown), and the room's sidebar badge drops by that thread's count. Try All (every reply notifies) and Mentions only (only @mentions).
  5. On a second device, confirm the same per-thread modes are set (they sync via account data).
  6. Room-level Mute (room context menu) still silences everything, including thread overrides.

Known caveat: Mentions-only can under-notify in E2EE rooms (the decision runs before decryption). Muted-thread badge subtraction is Lotus-only.

O3. Math / LaTeX (P4-4)

Send each and confirm rendering: $x^2 + y^2$ (inline), $$\int_0^1 f(x)\,dx$$ (block, centered), $5 and $10 for lunch (stays plain text — currency guard), and a code block containing $x$ (stays literal inside the code block). Expected: the first two render as math (KaTeX); the last two are untouched. First math of the session may show the raw $…$ for a beat while the KaTeX chunk lazy-loads, then renders.

O4. Encrypted search cache (P4-8) — opt-in

In an encrypted room's message search, enable "Persist search index on this device" (Encrypted Rooms panel). Search, then reload and search the same term. Expected: coverage survives the reload (results without re-paginating everything). Clear cached index empties it. Log out → the cache is wiped (privacy). Toggling the setting OFF does not wipe (only Clear/logout do).

O5. Session hardening (N97a) — cross-tab

  1. Log in on a build that predates the change, then load this build → you stay logged in (legacy keys migrate to the cinny_session_v1 blob; check DevTools → Application → Local Storage).
  2. Open the app in two tabs; log out in tab A → tab B reloads to the auth screen within a moment. Log in again in one tab → the other reloads too.

O6. Audit-wave correctness fixes (AW-1)

  • Scheduled-message cancel: schedule a message, then cancel it with the network cut (DevTools offline) → the item stays with an inline error (it does not silently disappear and still send). Restore network, retry → cancels cleanly.
  • Escape coordination: in a thread panel, open the mention autocomplete or set a reply draft, press Escape → it dismisses the autocomplete/reply without closing the panel. A bare Escape (nothing to dismiss) still marks the room read / closes the panel as before.
  • Panel exclusivity: on mobile, opening a thread while the media gallery (or members drawer) is open shows only one right panel (thread wins), not stacked fullscreen overlays.
  • Emoji board (AW-2): the first time you open the emoji board / autocomplete in a session, the grid and search populate with unicode emoji (they don't stay empty). Reactions still show a label.

O8. E2EE / call-key cluster (KE-1→4) — 👥 2 people, during a real call

We shipped the diagnostics kit + a Crypto Diagnostics card (Settings → Developer Tools). During your next call that glitches (audio cutouts, "Unable to decrypt"), open it and Download report, and note whether the symptoms even still occur now that we're on matrix-js-sdk 41.7.0 (crypto-wasm 18.3.1). Send me the report; the KE-1..4 diagnosis + capture guidance is in LOTUS_TODO.md (Encryption / E2EE), with the full original runbook in git history.


_Migrated from `LOTUS_TESTING.md` §O on 2026-09-17 — the file is now reference-only._ **How to report:** tick each item as it passes; on FAIL comment with what you saw vs expected, browser/OS, web (chat.lotusguild.org) vs desktop (Tauri), theme, and any browser-console errors. Screenshots for anything visual. **Checklist** - [ ] O1. Thread Panel (P3-8) — 👥 2 people help for live replies - [ ] O2. Per-thread notifications (P4-1, Slack-style) — 👥 2 people - [ ] O3. Math / LaTeX (P4-4) - [ ] O4. Encrypted search cache (P4-8) — opt-in - [ ] O5. Session hardening (N97a) — cross-tab - [ ] O6. Audit-wave correctness fixes (AW-1) - [ ] O8. E2EE / call-key cluster (KE-1→4) — 👥 2 people, during a real call --- Everything landed after the OIDC work. These mirror the checklists in `LOTUS_TODO.md` (§P3-8, §P4-1) and the outstanding-verification backlog below (P3-8/P4-1/P4-4/P4-8/N97a/AW-1…4). **⚠️ Threads change the main timeline** — thread replies no longer render inline; that's intended (see O1). ### O1. Thread Panel (P3-8) — 👥 2 people help for live replies 1. Hover a message → **Reply in Thread** (message menu). The right-side **thread panel** opens with that message as the root. 2. Send text, an emoji, and a file upload into the thread; have the second person reply too. 3. Reply to a reply _inside_ the panel. **Expected:** the panel shows the root at top + an "N replies" divider + the reply timeline (own composer at the bottom). Your sends appear immediately (pending → confirmed). A reply-to-a-reply is a proper thread reply. In the **main** timeline the replies do **not** appear inline — the root message instead shows a **"N replies · time"** chip. Clicking the chip (or a reply's thread indicator) opens the panel. **×** or **Escape** closes it; on mobile the panel is fullscreen. Scrolled up in a long thread → a **Jump to Latest** chip appears. Reload the page → the root/reply split persists; in an **encrypted** room the thread replies decrypt (not "Unable to decrypt"). ### O2. Per-thread notifications (P4-1, Slack-style) — 👥 2 people 1. Have the second person reply in a thread **you have posted in** → expect a notification + sound. 2. Have them reply in a thread **you have never touched** and don't @mention you → expect **silence** (only the chip's unread badge updates). 3. Have them **@mention** you in any thread → expect a notification regardless of participation. 4. Open the panel's **bell menu** (header) → set the thread to **Mute** → expect no notifications, the chip's unread badge gone (bell-mute glyph shown), and the room's **sidebar badge drops** by that thread's count. Try **All** (every reply notifies) and **Mentions only** (only @mentions). 5. On a **second device**, confirm the same per-thread modes are set (they sync via account data). 6. Room-level **Mute** (room context menu) still silences everything, including thread overrides. **Known caveat:** Mentions-only can under-notify in E2EE rooms (the decision runs before decryption). Muted-thread badge subtraction is Lotus-only. ### O3. Math / LaTeX (P4-4) Send each and confirm rendering: `$x^2 + y^2$` (inline), `$$\int_0^1 f(x)\,dx$$` (block, centered), `$5 and $10 for lunch` (**stays plain text** — currency guard), and a code block containing `$x$` (**stays literal** inside the code block). **Expected:** the first two render as math (KaTeX); the last two are untouched. First math of the session may show the raw `$…$` for a beat while the KaTeX chunk lazy-loads, then renders. ### O4. Encrypted search cache (P4-8) — opt-in In an **encrypted** room's message search, enable **"Persist search index on this device"** (Encrypted Rooms panel). Search, then **reload** and search the same term. **Expected:** coverage survives the reload (results without re-paginating everything). **Clear cached index** empties it. **Log out** → the cache is wiped (privacy). Toggling the setting OFF does **not** wipe (only Clear/logout do). ### O5. Session hardening (N97a) — cross-tab 1. Log in on a build that predates the change, then load this build → you stay logged in (legacy keys migrate to the `cinny_session_v1` blob; check DevTools → Application → Local Storage). 2. Open the app in **two tabs**; **log out** in tab A → tab B reloads to the auth screen within a moment. Log in again in one tab → the other reloads too. ### O6. Audit-wave correctness fixes (AW-1) - **Scheduled-message cancel:** schedule a message, then cancel it **with the network cut** (DevTools offline) → the item **stays** with an inline error (it does **not** silently disappear and still send). Restore network, retry → cancels cleanly. - **Escape coordination:** in a thread panel, open the mention autocomplete or set a reply draft, press **Escape** → it dismisses the autocomplete/reply **without** closing the panel. A bare Escape (nothing to dismiss) still marks the room read / closes the panel as before. - **Panel exclusivity:** on mobile, opening a thread while the media gallery (or members drawer) is open shows only **one** right panel (thread wins), not stacked fullscreen overlays. - **Emoji board (AW-2):** the **first** time you open the emoji board / autocomplete in a session, the grid **and search** populate with unicode emoji (they don't stay empty). Reactions still show a label. ### O8. E2EE / call-key cluster (KE-1→4) — 👥 2 people, during a real call We shipped the diagnostics kit + a **Crypto Diagnostics** card (**Settings → Developer Tools**). During your next call that glitches (audio cutouts, "Unable to decrypt"), open it and **Download report**, and note whether the symptoms even still occur now that we're on **matrix-js-sdk 41.7.0** (crypto-wasm 18.3.1). Send me the report; the KE-1..4 diagnosis + capture guidance is in `LOTUS_TODO.md` (Encryption / E2EE), with the full original runbook in git history. ---
jared added this to the Manual QA backlog milestone 2026-09-17 23:24:09 -04:00
jared added the securityarea: threadsarea: notificationsqa labels 2026-09-17 23:24:09 -04:00
Author
Owner

Verified on the local dev homeserver with Playwright (alice in the browser, bob over the API). Three bugs found and fixed on lotus, one of them a crash.

item result
O1 thread panel chip "N replies · time" on the root, panel shows root + divider + reply timeline + own composer; own reply appears in the panel and is not inlined in the main timeline (chip count updates) ✓
O1 — CRASH (fixed, 58a716c7) opening a thread on a pristine main composer took the whole app to "Something went wrong — Unable to find the path for Slate node". Root cause: one module-level initialValue array shared by every <Slate>; mounting the thread composer re-mapped the shared nodes and the main editor died on its next render. Anything that had edited the main editor first (typing, a restored draft) masked it, which is why it looked intermittent. Now one initial value per editor instance.
O2 per-thread notifications bob replies in a thread alice posted in → toast + sound ✓; thread alice never touched → silent ✓; @mention in that thread → toast + sound ✓; main-timeline baseline ✓; bell menu → Mute writes io.lotus.thread_notifications ({mode:"mute"} keyed by room/thread) and bob's next reply is silent ✓. Second-device sync = that account-data write. Room-level mute not exercised.
O3 math $x^2 + y^2$ inline KaTeX ✓, $$\int…$$ block (katex-display) ✓, $5 and $10 stays text ✓. $x$ inside a typed ``` fence rendered as math — the outgoing serializer converted math per paragraph line before the block-markdown parser saw the fence; fixed in 22371f81 (fences and backtick spans are literal; unit-tested).
O4 encrypted search cache persist toggle on → search → reload → same 9 hits / 10 cached ✓. "Clear cached index" did nothing observable: the active search re-ran and wrote the in-memory rows straight back (IDB still 12 rows). Fixed in the next commit — after Clear the stores are 0/0 until a new search. Logout deletes the lotus-search-cache database ✓. (Label nit: the per-room "N messages cached" line counts in-memory timeline events, not the disk index.)
O5 cross-tab logout two tabs, logout in A → B is on the login page within seconds ✓; cinny_session_v1 blob present alongside the legacy keys (dual-write) ✓
O6 scheduled cancel offline with the network cut, Cancel keeps the row and shows "Could not cancel this message. Try again."; back online, Cancel removes it ✓ (dev homeserver needed max_event_delay_duration — added to scripts/dev-homeserver.sh)
O6 emoji board first open of the session: 850 emoji rendered, search works ✓
O6 Escape coordination / mobile panel exclusivity not exercised here (mobile panels partly covered by the #175 members fix)
O7 desktop CSP cinny-desktop #12
O8 E2EE call-key cluster needs a real call — #201

Closing this one; the remaining rows have their own issues.

Verified on the local dev homeserver with Playwright (alice in the browser, bob over the API). **Three bugs found and fixed on `lotus`**, one of them a crash. | item | result | |---|---| | **O1 thread panel** | chip "N replies · time" on the root, panel shows root + divider + reply timeline + own composer; own reply appears in the panel and is **not** inlined in the main timeline (chip count updates) ✓ | | **O1 — CRASH (fixed, `58a716c7`)** | opening a thread on a **pristine** main composer took the whole app to "Something went wrong — Unable to find the path for Slate node". Root cause: one module-level `initialValue` array shared by every `<Slate>`; mounting the thread composer re-mapped the shared nodes and the main editor died on its next render. Anything that had edited the main editor first (typing, a restored draft) masked it, which is why it looked intermittent. Now one initial value per editor instance. | | **O2 per-thread notifications** | bob replies in a thread alice posted in → toast + sound ✓; thread alice never touched → **silent** ✓; @mention in that thread → toast + sound ✓; main-timeline baseline ✓; bell menu → **Mute** writes `io.lotus.thread_notifications` (`{mode:"mute"}` keyed by room/thread) and bob's next reply is silent ✓. Second-device sync = that account-data write. Room-level mute not exercised. | | **O3 math** | `$x^2 + y^2$` inline KaTeX ✓, `$$\int…$$` block (`katex-display`) ✓, `$5 and $10` stays text ✓. **`$x$` inside a typed ``` fence rendered as math** — the outgoing serializer converted math per paragraph line before the block-markdown parser saw the fence; fixed in `22371f81` (fences and backtick spans are literal; unit-tested). | | **O4 encrypted search cache** | persist toggle on → search → reload → same 9 hits / 10 cached ✓. **"Clear cached index" did nothing observable**: the active search re-ran and wrote the in-memory rows straight back (IDB still 12 rows). Fixed in the next commit — after Clear the stores are 0/0 until a new search. Logout deletes the `lotus-search-cache` database ✓. (Label nit: the per-room "N messages cached" line counts in-memory timeline events, not the disk index.) | | **O5 cross-tab logout** | two tabs, logout in A → B is on the login page within seconds ✓; `cinny_session_v1` blob present alongside the legacy keys (dual-write) ✓ | | **O6 scheduled cancel offline** | with the network cut, Cancel keeps the row and shows "Could not cancel this message. Try again."; back online, Cancel removes it ✓ (dev homeserver needed `max_event_delay_duration` — added to `scripts/dev-homeserver.sh`) | | **O6 emoji board** | first open of the session: 850 emoji rendered, search works ✓ | | O6 Escape coordination / mobile panel exclusivity | not exercised here (mobile panels partly covered by the #175 members fix) | | O7 desktop CSP | cinny-desktop #12 | | O8 E2EE call-key cluster | needs a real call — #201 | Closing this one; the remaining rows have their own issues.
jared closed this issue 2026-09-18 18:34:58 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#184