Files
cinny/LOTUS_TODO.md
T
jared ea15db430c
CI / Build & Quality Checks (push) Successful in 11m51s
Trigger Desktop Build / trigger (push) Failing after 4s
docs: add feature reference, bug tracker, and implementation notes
- LOTUS_FEATURES.md: full reference of every custom Lotus feature with
  implementation details, file paths, and API notes
- LOTUS_BUGS.md: audit of confirmed bugs with root causes and fixes
- LOTUS_TODO_REFERENCE.md: technical implementation notes for backlog items
- LOTUS_TODO.md: trim completed audit results section, link to FEATURES doc
- README.md: rewrite to marketing-friendly feature list format; fix
  incorrect claim that screenshare auto-reverts view to grid (removed)

Fix: auto-revert spotlight on screenshare was removed (600ms grid-click
caused fullscreen to show avatars); corrected in LOTUS_FEATURES.md and
removed from README.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 18:41:24 -04:00

438 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Lotus Chat — Work Backlog
**Repo:** `lotus` branch at `https://code.lotusguild.org/LotusGuild/cinny`
**Deploy:** push to `lotus` → CI → auto-deploy to `chat.lotusguild.org` (~11 min)
---
## ⚠️ TDS DESIGN LAW — READ BEFORE TOUCHING ANY UI
> **ALL Lotus Terminal Design System (TDS) styling — colors, animations, glows, borders, fonts, spacing — MUST come exclusively from `/root/code/web_template/base.css` CSS variables.**
> Do NOT hardcode hex values. Do NOT invent new variable names. Do NOT deviate from the design tokens defined in that file.
> The canonical variable reference: `--lt-accent-orange`, `--lt-accent-cyan`, `--lt-accent-green`, `--lt-glow-orange`, `--lt-box-glow-*`, `--lt-border-color`, etc.
> Reference implementation for code patterns: `/root/code/tinker_tickets/` (markdown.js, base.js, ticket.css)
> This rule applies to EVERY task in this file without exception.
---
Completed features are documented in [LOTUS_FEATURES.md](./LOTUS_FEATURES.md).
---
Legend:
- `[AUDIT REQUIRED]` — at least one assumption needs code/server verification before implementing
- `[SERVER CHECK]` — depends on a Synapse feature or MSC; verify on `matrix.lotusguild.org`
- `[LOW PRIORITY]` — implement after all higher-priority items
- `[EXTREME COMPLEXITY]` — multi-sprint, plan separately before touching
- `[BLOCKED]` — cannot build until a server upgrade, upstream MSC, or dependency resolves
- `[IMPROVE]` — feature exists in upstream Cinny; this task enhances it for Lotus Chat
Status: `[ ]` pending · `[~]` in progress · `[x]` completed
---
## Server Capabilities (as of June 2026)
- **Homeserver:** `matrix.lotusguild.org`
- **Synapse version:** `1.153.0` (2026-05-19) — fully up to date
- **Matrix spec:** up to `v1.12` formally; newer MSC features via `unstable_features`
### Confirmed facts
| Finding | Impact |
| ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| **MSC flags ON:** `msc4140` · `msc3771` · `msc3440.stable` · `msc4133.stable` · `simplified_msc3575` | All safe to use now |
| **MSC flags OFF:** `msc4306` (thread subscriptions) · `msc3882` · `msc3912` · `msc4155` | These features are BLOCKED |
| **MSC3266** room summary: returns 404 | Room Preview feature BLOCKED |
| **MSC3892** relation redaction: not in flags | Reaction Redaction feature BLOCKED |
| **MSC4260** report user: server at v1.12, endpoint may not exist | Report User feature BLOCKED |
| **MSC4151** report room: HTTP 405 on GET = endpoint exists (POST only) | Report Room live ✅ |
| `folds AvatarImage` does NOT accept children | Add frame/overlay inside `UserAvatar.tsx` itself — optional `frameName` prop |
| No in-app toast system exists (was) | Built `ToastProvider` + Jotai queue; at `App.tsx:65` |
| `useUnverifiedDeviceCount()` hook exists | `src/app/hooks/useDeviceVerificationStatus.ts:65-106` |
| Voice player: `AudioContent.tsx:44-223` | Playback rate on hidden `<audio>` at line 217 |
| `CallControl.setMicrophone(bool)` at `CallControl.ts:206-212` | For AFK auto-mute |
| `CallControl.toggleSound()` at `CallControl.ts:230-251` | Push-to-deafen — just wire a hotkey to this |
| matrix-js-sdk has NO arbitrary profile field methods | Use `mx.http.authedRequest()` for MSC4133 |
| Sanitizer (`sanitize.ts`) allows table, div, span, a, code, hr | LFG HTML card is safe locally; test on Element/FluffyChat |
| Sanitizer STRIPS `<math>`/MathML tags | Math/LaTeX task must also modify sanitizer |
| Service worker EXISTS at `src/sw.ts` | Quick-reply task: add `notificationclick` handler |
| `knockSupported()` utility exists at `matrix.ts:376-391` | Knock UX: only need "Request to Join" in `RoomIntro.tsx` |
| `KeywordMessages.tsx` already has custom keyword push rules | Full push rule editor: only non-keyword rule types need new UI |
| `getMatrixToRoom()` in `matrix-to.ts` generates invite URLs | Invite link: just add QR code to room settings |
| Cindy CANNOT inject audio into EC call stream | In-call soundboard must be redesigned as local-only |
| Folds uses vanilla-extract in non-TDS, NOT CSS custom properties | Custom accent color: must create new vanilla-extract theme variant dynamically |
| Theme presets need ~50 CSS custom properties each | Significant design work before coding |
| `useCallSpeakers.ts` CSS MutationObserver polling | Visual speaking indicator: TDS ring animation on top of existing data |
| MSC3489/3672 live location: BOTH false on server | Live Location BLOCKED |
---
## Key File Reference
| What you need | File | Lines |
| -------------------------------- | ------------------------------------------------------------- | ------------------- |
| Global keydown hook | `src/app/hooks/useKeyDown.ts` | whole file |
| Room navigation | `src/app/hooks/useRoomNavigate.ts` | 19-72 |
| All room IDs atom | `src/app/state/room-list/roomList.ts` | `allRoomsAtom` |
| Room unread counts | `src/app/state/room/roomToUnread.ts` | `roomToUnreadAtom` |
| Overlay portal provider | `src/app/pages/App.tsx` | 65 |
| Portal container div | `index.html` | 101 |
| Room settings tabs | `src/app/features/room-settings/RoomSettings.tsx` | 27-56 |
| State event read/write pattern | `src/app/features/common-settings/general/RoomEncryption.tsx` | 42-52 |
| Power level checker | `src/app/hooks/usePowerLevels.ts` | whole file |
| Slash command registration | `src/app/hooks/useCommands.ts` | 140-537 |
| Chat background picker | `src/app/features/settings/general/General.tsx` | 945-981 |
| Chat backgrounds definition | `src/app/features/lotus/chatBackground.ts` | whole file |
| Matrix.to URL builder | `src/app/plugins/matrix-to.ts` | `getMatrixToRoom()` |
| Media event content types | `src/app/types/matrix/common.ts` | 46-91 |
| Media URL conversion | `src/app/utils/matrix.ts` | `mxcUrlToHttp()` |
| Message pagination (search) | `src/app/features/message-search/useMessageSearch.ts` | 74-121 |
| Infinite pagination pattern | `src/app/features/message-search/MessageSearch.tsx` | 234-365 |
| Poll event format | `src/app/components/message/content/PollContent.tsx` | 1-320 |
| Theme class application | `src/app/hooks/useTheme.ts` | 25-60 |
| Animations file | `src/app/styles/Animations.css.ts` | whole file |
| Message status (EventStatus) | `src/app/features/room/message/Message.tsx` | 84-142 |
| Call member change events | `src/app/hooks/useCall.ts` | 37-52 |
| Mic control in calls | `src/app/plugins/call/CallControl.ts` | 206-212 |
| Device verification hook | `src/app/hooks/useDeviceVerificationStatus.ts` | 65-106 |
| Knock room support check | `src/app/utils/matrix.ts` | 376-391 |
| Room join button location | `src/app/components/room-intro/RoomIntro.tsx` | 25-119 |
| Notification mute via push rules | `src/app/hooks/useRoomsNotificationPreferences.ts` | 110-150 |
| Message text body CSS | `src/app/components/message/layout/layout.css.ts` | 182-205 |
---
## Known Bugs
### [!] BUG · Drag-and-drop file overlay doesn't dismiss on hover-away
**Confirmed bug** — drag a file over the window without dropping: the drop overlay persists.
**Fix:** Ensure `dragleave` fires correctly at the window/document level. Child element boundaries can cause spurious `dragleave` — use a counter or `relatedTarget` check.
**[AUDIT REQUIRED]** Find the drag-and-drop overlay component in `RoomInput.tsx` or the room view. Confirm the exact event listener structure.
**Complexity:** Low (bug fix).
---
## Priority 3 — Higher complexity / lower daily frequency
### [ ] P3-4 · Accessibility Improvements (WCAG 2.1 AA)
**What:** Comprehensive audit and fix pass targeting the critical user paths:
- Room list navigation (keyboard-only)
- Reading messages in the timeline (screen reader announces new messages)
- Composing and sending a reply
- Opening and closing modals (focus trap, return focus)
- ARIA labels on all icon-only buttons
**Scope:** Do NOT attempt to make every corner of the app AA-compliant in one pass — focus on the golden path (open app → find room → read → reply → send).
**[AUDIT REQUIRED]** — Run an automated audit first: `npx axe-core` or browser DevTools accessibility tree. Document every violation before writing a single line of code. Prioritize by severity (critical > serious > moderate).
**Complexity:** Medium-High (audit is the main work).
---
### [ ] P3-6 · Configurable Composer Toolbar
**What:** Let users rearrange or hide individual composer toolbar buttons (GIF, Sticker, Emoji, File, Voice, Location). Changes stored in `settingsAtom`. Access via a small "⚙ Customize toolbar" option in toolbar overflow.
**[AUDIT REQUIRED]** — Audit the current toolbar button rendering in `RoomInput.tsx`. Understand the layout system (is it a fixed array or already mapped from config?). Drag-to-reorder may require a DnD library; consider whether reorder is worth the complexity vs just toggle-visibility.
**Complexity:** Medium-High (drag reorder adds significant complexity).
---
### [ ] P3-8 · Thread Panel (full side drawer)
**⚠️ LARGEST FEATURE — requires its own planning session before implementation.**
**What:** A right-side drawer for threaded conversations. Currently "Reply in Thread" exists but there is no panel to read or write thread replies.
Features:
- Click "Reply in Thread" → opens thread drawer on the right
- Thread root event shown at the top of the panel
- Full message rendering for all in-thread replies (reuse timeline components)
- Reply input at the bottom (full composer with formatting, emoji, etc.)
- Unread count badge on the thread button in the main timeline
- Keyboard shortcut to close thread panel
**Architecture:**
- New Jotai atom: `activeThreadEventId: string | null`
- New component: `src/app/features/room/thread/ThreadPanel.tsx`
- Rendered alongside `RoomView` as a conditional right panel (mirror the members drawer pattern)
- Filter events in timeline to `m.thread` relation for the active root event ID
- Shares the same `mx` client and room reference as the main timeline
**[AUDIT REQUIRED]** — Deeply audit how `m.thread` relation events are currently stored and retrieved in the matrix-js-sdk. Understand the thread aggregation API: `GET /rooms/{roomId}/relations/{eventId}/m.thread`. Check if `RoomTimeline.tsx` currently filters out thread replies from the main timeline (it should — confirm).
**Complexity:** High.
---
## Priority 4 — Specialized, high complexity, or low priority
### [ ] P4-1 · Thread Notification Mode Per-Thread (MSC3771)
**Spec:** MSC3771 (stable). Depends on Thread Panel (#P3-8).
**What:** Per-thread notification toggle: "All messages" vs "Mentions only". Accessible from the thread panel header. Tracks unread counts separately per thread.
**[AUDIT REQUIRED]** — Implement after Thread Panel. Requires understanding how the SDK tracks per-thread unread counts.
**Complexity:** Medium (after thread panel exists).
---
### [ ] P4-2 · Thread Subscriptions (MSC4306) [BLOCKED]
**Spec:** MSC4306 (Synapse experimental). Depends on Thread Panel (#P3-8).
**What:** "Follow thread" button to receive notifications for a thread you haven't posted in. Uses MSC4306 subscription endpoint.
**[SERVER CHECK]** — `org.matrix.msc4306 = false` on `matrix.lotusguild.org` — BLOCKED until server enables it.
**Complexity:** Medium (after thread panel exists).
---
### [ ] P4-3 · Knock-to-join Notifications for Admins
**Note:** The basic knock-to-join UX is covered in P1-11 (completed). This task adds the admin notification side.
**What:** Space/room admins see a notification badge when there are pending knock requests. A "Pending Join Requests" section in the members drawer or room settings. Approve (invite) or deny (kick) each knock.
**Complexity:** Medium.
---
### [ ] P4-4 · Math / LaTeX Rendering in Messages (LOW PRIORITY)
**Spec:** CS-API §11.5 (stable) — `formatted_body` can contain LaTeX.
**What:** Render `$...$` or `$$...$$` LaTeX expressions in message bodies. Use KaTeX (lightweight, ~100KB, renders server-side-compatible CSS). Must gracefully fall back to raw LaTeX text if KaTeX fails.
**Note:** This is LOW PRIORITY — only useful for academic/technical communities. Implement last.
**[AUDIT REQUIRED]** — Confirm KaTeX bundle size impact on the Vite bundle. Check if matrix-js-sdk's HTML sanitizer strips LaTeX before it reaches the renderer. The formatted_body sanitization pipeline is the main risk here.
**Complexity:** Low-Medium.
---
### [ ] P4-5 · Live Location Sharing (MSC3489 + MSC3672) (LOW PRIORITY, HIGH COMPLEXITY) [BLOCKED]
**Spec:** MSC3489 + MSC3672. Implemented in Element Web.
**Note:** Static location sharing is already implemented. This adds live/real-time GPS beacons. Very low priority per user preference.
**What:** Start sharing live location → creates `m.beacon_info` state event → client posts `m.beacon` events on a timer → other users see your position update live on a map.
**[SERVER CHECK]** — `org.matrix.msc3489 = false` AND `org.matrix.msc3672 = false` on `matrix.lotusguild.org` — BLOCKED.
**Complexity:** High. Requires background geolocation API + live map rendering.
---
### [ ] P4-6 · OIDC / SSO Next-Gen Auth (MSC3861) (EXTREME COMPLEXITY, LOW PRIORITY)
**Spec:** MSC3861, merged Matrix spec v1.15. Uses Matrix Authentication Service (MAS).
**Context:** ~80% of homeserver users have LLDAP/Authelia/SSO accounts. SSO is currently enabled on `matrix.lotusguild.org` but accounts are not yet linked. This would allow users to log in via their SSO credentials.
**What:** OAuth 2.0 / OIDC login flow, token refresh, account management page linking Matrix identity to SSO identity.
**EXTREME COMPLEXITY** — requires: MAS deployment/configuration on the homeserver, significant auth flow changes in the client, token refresh handling, session management overhaul.
**[SERVER CHECK]** — Before any client work, audit whether MAS is already deployed on `compute-storage-01`. Check: `pct exec 151 -- systemctl status matrix-authentication-service` or similar.
**Complexity:** Extreme. Multi-sprint project. Plan separately.
---
## Priority 5 — Gamer / Aesthetic / Customization
### [ ] P5-1 · Custom Accent Color Picker (non-TDS mode only)
**What:** A hex/HSL color picker in Settings → Appearance. Chosen color replaces the primary accent throughout the UI: buttons, badges, active states, highlights, presence dot, links. Applied via a CSS custom property override injected into `<head>`.
**IMPORTANT:** This feature is completely inactive when TDS is enabled — TDS has its own fixed palette. Add this setting under a "Non-TDS Themes" section that is hidden when TDS is active.
**[AUDIT REQUIRED]** Identify all CSS custom properties that constitute the "accent color" in non-TDS mode. Map them to the folds/vanilla-extract token names.
**Complexity:** Medium.
---
### [ ] P5-2 · Additional Color Theme Presets
**What:** 5 new one-click theme presets alongside TDS. Each must be a complete, polished system with proper contrast ratios (WCAG AA). All implemented as vanilla-extract themes matching the existing TDS pattern.
Themes:
1. **Cyberpunk** — deep navy bg (`#0a0015`), electric purple (`#bf5fff`) + hot pink (`#ff2d9b`) accents, neon glow
2. **Ocean** — deep sea blue bg (`#020b18`), teal (`#00c9b1`) + aqua (`#0096d6`) accents, soft feel
3. **Blood Red** — near-black bg (`#0d0203`), deep crimson (`#7a0010`) + bright red (`#ff2233`) accents
4. **Classic Matrix** — pure black bg (`#000000`), phosphor green (`#00ff41`) text + accents
5. **Midnight** — dark charcoal (`#111827`), cool blue-grey (`#6b7ca8`) accents, clean minimal
**[AUDIT REQUIRED]** Study `src/lotus-terminal.css.ts` for the full token list before designing themes. All tokens must be covered.
**Complexity:** Medium (design effort is the main cost).
---
### [ ] P5-9 · LFG (Looking for Group) Slash Command
**What:** `/lfg` generates a formatted LFG post visible on ALL Matrix clients using standard `m.room.message` HTML. Fields: Game, Players Needed, Platform, Skill Level, Description, DM link. Other clients see clean formatted HTML; Lotus Chat renders an enhanced styled card.
**[AUDIT REQUIRED]** Test which HTML tags survive Matrix HTML sanitization on Element/FluffyChat before designing the card structure. Test with minimal HTML.
**Complexity:** Medium.
---
### [ ] P5-10 · Voice Channel User Limit
**What:** Admins set max participants via custom state event `io.lotus.voice_limit: { max_users: N }`. Show "Channel Full (5/5)" to users over the limit. Local enforcement only.
**[AUDIT REQUIRED]** Check if Element Call has its own participant limit that should be integrated with rather than duplicated.
**Complexity:** Medium.
---
### [ ] P5-11 · AFK / Idle Auto-Mute in Voice
**What:** Auto-mute mic after X minutes of silence (detected via Web Audio AnalyserNode). Show "You were auto-muted due to inactivity" toast with click-to-unmute. Admin-configurable via `io.lotus.afk_timeout` state event. Disableable in Settings → Calls.
**[AUDIT REQUIRED]** Verify auto-mute must go through the same CallControl bridge as manual mute.
**Complexity:** Medium.
---
### [ ] P5-12 · Seasonal / Event Themes
**What:** Automatic + manually toggleable seasonal overlays with CSS particle effects and accent color variants:
- **Halloween** (Oct 15Nov 1): purple particles, orange accents, spider web pattern
- **Christmas** (Dec 10Jan 2): snow fall, red/green accents, snowflake pattern
- **New Year** (Dec 31Jan 1): firework burst animation, gold accents
- **Pride** (June): rainbow gradient accent cycle
All toggleable manually in Settings → Appearance regardless of date. Respects `prefers-reduced-motion`.
**[AUDIT REQUIRED]** Design against existing CSS animation system in `lotus-terminal.css.ts`.
**Complexity:** Medium.
---
### [ ] P5-13 · Avatar Frame / Border Decorations
**What:** Decorative CSS rings/frames rendered around user avatars. Built-in options: TDS Glow (animated orange pulsing), Cyberpunk (rotating gradient), Minimal (thin ring), Gold (supporter cosmetic). Stored in Matrix account data `io.lotus.avatar_frame`. Only visible in Lotus Chat.
**[AUDIT REQUIRED]** Verify folds Avatar component allows overlay decoration without breaking child-type constraints (see previous white-circle avatar bug).
**Complexity:** Medium.
---
### [ ] P5-14 · Animated Avatar Overlay Decorations (Discord-style)
**What:** Animated WebM/GIF overlays that float around avatars (transparent center showing avatar). Curated built-in set OR user-uploaded mxc:// overlay. Stored in account data. Only Lotus Chat users see them.
**[AUDIT REQUIRED]** See #P5-13 audit. Also decide: curated set only vs user-uploadable.
**Complexity:** Medium.
---
### [ ] P5-15 · In-Call Soundboard
**What:** Grid of short audio clips playable into the call audio stream via Web Audio API (AudioBufferSourceNode → MediaStreamDestinationNode → mixed with mic). Built-in clips + user-uploadable custom clips (stored as mxc://). Accessible from call controls bar.
**[AUDIT REQUIRED]** Verify the Element Call integration exposes the mic MediaStream for mixing. This is the highest-risk part of this feature.
**Complexity:** High.
---
### [ ] P5-16 · Custom Join / Leave Sound Effects
**What:** Local-only sounds when participants join/leave a call you're in. Built-in options + per-user settable. Detect via Element Call participant list change events.
**[AUDIT REQUIRED]** Find how Element Call exposes join/leave participant events to the parent window via postMessage bridge.
**Complexity:** Medium.
---
### [ ] P5-20 · Quick Reply from Browser Notification
**What:** Inline reply field in browser notification toasts via Notification Actions API. Reply sends as threaded reply to the triggering message.
**[AUDIT REQUIRED]** (1) Verify browser Notification Actions API support in target browsers. (2) This requires a Service Worker to handle the reply event — confirm if Lotus Chat has one or needs one.
**Complexity:** Medium-High.
---
### [ ] P5-21 · Custom @Mention Highlight Color
**What:** Each user sets their own mention highlight color in Settings → Appearance. Applied as `--user-mention-color` CSS property override on mention-highlighted message rows.
**Complexity:** Low.
---
### [ ] P5-22 · Font Selector for the UI
**What:** Font picker in Settings → Appearance. Options: JetBrains Mono, Inter, Geist, Fira Code, OpenDyslexic, System Default. Applied via CSS custom property overrides.
**[AUDIT REQUIRED]** Check if any fonts are already globally loaded to avoid double-loading.
**Complexity:** Low-Medium.
---
### [ ] P5-27 · Notification Profile Presets (Gaming / Work / Sleep)
**What:** Saved presets that change all notification settings atomically. Gaming (mentions only), Work (DMs + mentions), Sleep (all off). Quick-switch from sidebar or settings.
**Complexity:** Medium.
---
## Blocked Features
These features are confirmed desirable but cannot be built until the listed dependency is resolved.
Check back after each Synapse upgrade — re-run `/matrix/client/versions` and `unstable_features` to see if they've become available.
### [BLOCKED] · Live Location Sharing (MSC3489 + MSC3672)
**Blocked by:** `org.matrix.msc3489 = false` AND `org.matrix.msc3672 = false` on `matrix.lotusguild.org` (confirmed from unstable_features).
**What it would do:** Real-time GPS beacon streaming upgrading the existing static location share.
**Action when unblocked:** Both MSCs must be enabled on the homeserver before any client work.
### [BLOCKED] · Reaction / Relation Redaction (MSC3892)
**Blocked by:** `org.matrix.msc3892` = false on `matrix.lotusguild.org`
**What it would do:** Cleanly remove a reaction without redacting the parent message.
**Current behavior:** Full event redaction — acceptable fallback, no user-facing issue.
**Action when unblocked:** Find `onReactionToggle` redaction call site; swap in MSC3892 endpoint with fallback.
### [BLOCKED] · Room Preview Before Joining (MSC3266)
**Blocked by:** `GET /v1/rooms/{id}/summary` returns 404 — endpoint not available on this server
**What it would do:** Show room name, topic, avatar, member count before joining.
**Action when unblocked:** Build pre-join preview card; trigger on unjoined room navigation.
### [BLOCKED] · Thread Subscriptions (MSC4306)
**Blocked by:** `org.matrix.msc4306` = false on `matrix.lotusguild.org`
**What it would do:** Follow a thread without posting; get notifications for replies.
**Action when unblocked:** Add "Follow thread" button in the thread panel header (depends on #P3-8 Thread Panel).
### [BLOCKED] · Report User (MSC4260)
**Blocked by:** Server declares only spec v1.12; MSC4260 merged in v1.14 — endpoint may not exist
**What it would do:** Report a specific user to homeserver admins (separate from reporting a message).
**Note:** Report Message already exists in upstream Cinny. This would add Report User to the profile panel.
**Action when unblocked:** Test `POST /_matrix/client/v3/users/{userId}/report`; if 200, add button to user profile.
---
## Pending Audits
### [ ] Audit-3 · Profile banner image — Matrix protocol support
Research whether Matrix spec or MSC4133 (v1.16) defines a standard profile banner field. `uk.tcpip.msc4133.stable = true` on our server — check if a `banner_url` or similar field is defined. If no cross-client standard exists, do not implement.
---
## Implementation Notes
### ⚠️ TDS DESIGN LAW (repeated here for emphasis)
> Every TDS color, animation, glow, border, shadow, and font value MUST come from `/root/code/web_template/base.css`.
> Never hardcode hex values. Never invent CSS variable names.
> Key variables: `--lt-accent-orange` · `--lt-accent-cyan` · `--lt-accent-green` · `--lt-glow-*` · `--lt-box-glow-*` · `--lt-border-color` · `--lt-font-mono`
> Reference implementation: `/root/code/tinker_tickets/` (markdown.js, base.js, ticket.css)
> This applies without exception to every task marked `[IMPROVE]`, `[Build]`, or any UI change.
### Design Rules
- All new components must respect both TDS dark (`LotusTerminalTheme`) and TDS light (`LotusTerminalLightTheme`) modes
- Non-TDS theme work (custom accent color, theme presets) uses vanilla-extract theme files — match the pattern in `src/lotus-terminal.css.ts`
- Code syntax highlighting token classes: `.tok-kw .tok-str .tok-num .tok-cmt .tok-fn` (defined in `web_template/base.css`)
- `folds AvatarImage` does NOT accept children — wrap Avatar components externally for overlays/frames/borders
### CI/CD Pipeline
```
edit → commit → git push origin lotus
→ Gitea Actions: tsc --noEmit, eslint, prettier (~3 min)
→ Webhook: lotus_deploy.sh on LXC 106 polls CI, then npm ci && npm run build → rsync
→ Live at chat.lotusguild.org (~11 min total)
```
### Per-Feature Checklist (before marking complete)
- [ ] `npx tsc --noEmit` — zero TypeScript errors
- [ ] `npx eslint src/` — zero new errors (warnings OK if pre-existing)
- [ ] `npx prettier --check src/` — formatting passes
- [ ] `README.md` updated (Lotus-custom features only — not upstream Cinny features)
- [ ] `landing/index.html` updated if the feature appears in the comparison table
- [ ] Visually tested at `chat.lotusguild.org` after CI deploys
### Homeserver Access (for server audits)
- **Synapse (Matrix):** LXC 151 on `compute-storage-01``pct exec 151 -- bash`
- **Config:** `/etc/matrix-synapse/homeserver.yaml`
- **Version check:** `curl -s https://matrix.lotusguild.org/_matrix/client/versions`