52 lines
4.2 KiB
Markdown
52 lines
4.2 KiB
Markdown
# Cordn / MLS / Staircase — UX audit (2026-10-12)
|
|
|
|
Scope: every surface where a skater meets the crew's encrypted chat —
|
|
the crew page (Private chat tab + sidebar card), the Messages hub, Settings →
|
|
Coordinator, and the CrewForm fields — plus the Staircase / Cordn-web hand-offs.
|
|
|
|
The goal was a *coherent* story: two chats exist (built-in NIP-17 "Chat" and the
|
|
real-MLS "Private chat"), and the UI must never make them contradict each other.
|
|
|
|
## Terminology model (the fix that anchors everything)
|
|
| Surface | Name | Protocol | Setup |
|
|
|---|---|---|---|
|
|
| Crew page tab (existing) | **Chat** | NIP-17 giftwrap | always on |
|
|
| Crew page tab (new) | **Private chat** | MLS via coordinator | created once by an admin |
|
|
| Sidebar card | **Encrypted chat** | covers both | — |
|
|
|
|
Rule: never call the sidebar card "Private chat" (collides with the MLS tab), and
|
|
never badge the MLS chat "On" when it hasn't been created.
|
|
|
|
## Findings
|
|
|
|
| # | Sev | Status | Finding |
|
|
|---|---|---|---|
|
|
| 1 | High | **Fixed** | The sidebar card badged **"Private chat · On"** (meaning the NIP-17 Chat tab) while the MLS tab said **"not created yet"** — a direct contradiction. The card now shows two explicit rows, **Chat** (always on) and **Private chat** (On / Set up / Join / Checking), reflecting the real MLS status. |
|
|
| 2 | High | **Fixed** | Name collision: card "Private Crew Chat" vs tab "Private chat". Card retitled **"Encrypted chat"**; row names are Chat / Private chat. |
|
|
| 3 | Med | **Fixed** | The card led with **external** apps ("Cordn (web)", "Copy for Staircase") even though the app now ships its own MLS chat. The **in-app Private chat is now the primary CTA** (one tap → `?tab=mls`); external clients moved under a labelled **"Open in another app"** row. |
|
|
| 4 | Med | **Fixed** | Joining gave no feedback. The panel now says **"Request sent…"** after Ask-to-join and **"No invite waiting yet…"** after Check-for-invite. |
|
|
| 5 | Med | **Fixed** | An admin who created the chat wasn't told how members join. The panel now shows an invite hint while the group has one member. |
|
|
| 6 | Med | **Fixed** | Crews were invisible in the Messages hub. Added a **Crews** section (status badge + deep link to `?tab=mls`). |
|
|
| 7 | Low | **Fixed** | The crew page's tabs weren't deep-linkable; now `?tab=events\|chat\|mls` (explicit param wins over the auto-default). |
|
|
| 8 | Low | Open | `cordnUi.*` / new `crewCoordinator.*` copy exists only in **en/es**; other locales fall back to English. Acceptable for a new feature, worth translating once it has users. |
|
|
| 9 | Low | Open | **Cordn (web) is broken against our coordinator** (upstream issue, drafted). Kept as a secondary link only; prefer the in-app chat or Staircase. |
|
|
| 10 | Low | Open | CrewForm's **"Cordn group"** field is Staircase-era jargon; now that the app creates groups natively it mostly serves importing an external group. Consider moving it under an "Advanced" disclosure. |
|
|
| 11 | Info | By design | **Interactive signer (Amber):** no live updates — the panel shows a hint and the DM pages have a manual Refresh. This is the deliberate "never pop Amber in the background" posture. |
|
|
| 12 | Info | By design | The coordinator sees **ciphertext + metadata only**; the card and the Settings privacy note say so plainly. |
|
|
|
|
## Still open / next
|
|
- **Unread for the Private chat**: ⚠️ needs a **signed fetch** — the MLS messages
|
|
are behind the coordinator's ContextVM RPC, with no cheap metadata peek (that
|
|
was the retired sealed-relay path). Options: a **silent-signers-only** background
|
|
fetch (no dot for Amber), or leave it. A local-only dot would be misleading.
|
|
- ~~Shareable "join this crew's chat" link~~ ✅ **done** — the panel's admin
|
|
**Invite** action shares `…/crew/<pk>/<id>?tab=mls` via the OS share sheet /
|
|
clipboard.
|
|
- ~~i18n drift~~ ✅ **done** — all 20 locales back to 100% (see AGENTS.md).
|
|
- **Persisted DM decrypt cache**: ✅ done (`src/lib/dmDecryptCache.ts`).
|
|
- **Broad polish**: still open — candidates: a "Clear cached messages" action,
|
|
entry-bundle trim, a11y, empty/error-state consistency.
|
|
|
|
## Verified
|
|
`npm test` + `check-i18n` green; `?tab=mls` deep-link wired through the crew page.
|
|
Not click-tested in a real browser this session (no logged-in browser fixture).
|