Avatar decorations are served through Nextcloud's public DAV: no Cache-Control and a new PHP session on every image #22

Closed
opened 2026-10-04 23:14:26 -04:00 by jared · 1 comment
Owner

Lotus Chat loads avatar decorations from the Nextcloud public share (DECORATION_CDN = https://drive.lotusguild.org/public.php/dav/files/<share>/cinny-decorations, cinny src/app/features/lotus/avatarDecorations.ts:6). Every request is answered by Nextcloud's PHP. Headers on a thumbnail (…/thumbs/<slug>.webp):

HTTP/1.1 200 OK
Content-Type: image/webp
Last-Modified / ETag: present
Set-Cookie: oc_sessionPassphrase=…; Set-Cookie: __Host-nc_sameSiteCookielax=…; Set-Cookie: __Host-nc_sameSiteCookiestrict=…; Set-Cookie: oc4y48p5frub=…
(no Cache-Control, no Expires)
  • No cache policy: browsers fall back to heuristic caching. Decorations render on every avatar in the timeline, member lists and call tiles.
  • New session per image: each image creates a fresh Nextcloud session (four cookies). Firefox logs four "Cookie … has been rejected because it is in a cross-site context" errors per image in every Lotus console.
  • Load: the picker is fine (12 thumbnails per category), but timelines and calls fetch full animated PNGs (~1 MB each, per the picker comment) for every decorated member.

Fix: serve the catalogue as static files with a long cache. Either put it next to the web app (nginx on LXC 106, e.g. https://chat.lotusguild.org/decorations/, Cache-Control: public, max-age=604800, immutable) or behind the existing NPM. Then point VITE_DECORATION_CDN (already supported, eafa3533) at it. The Element Call fork pins the same CDN for in-call tiles, so update its pin too.


Found in the October 2026 client audit (Playwright against a local Synapse + LiveKit stack, plus code reading). Code refs are at cinny 30e2dbcd, cinny-desktop 8f67ec7, element-call 3b0050e8.

Lotus Chat loads avatar decorations from the Nextcloud public share (`DECORATION_CDN = https://drive.lotusguild.org/public.php/dav/files/<share>/cinny-decorations`, cinny `src/app/features/lotus/avatarDecorations.ts:6`). Every request is answered by Nextcloud's PHP. Headers on a thumbnail (`…/thumbs/<slug>.webp`): ``` HTTP/1.1 200 OK Content-Type: image/webp Last-Modified / ETag: present Set-Cookie: oc_sessionPassphrase=…; Set-Cookie: __Host-nc_sameSiteCookielax=…; Set-Cookie: __Host-nc_sameSiteCookiestrict=…; Set-Cookie: oc4y48p5frub=… (no Cache-Control, no Expires) ``` - **No cache policy:** browsers fall back to heuristic caching. Decorations render on every avatar in the timeline, member lists and call tiles. - **New session per image:** each image creates a fresh Nextcloud session (four cookies). Firefox logs four "Cookie … has been rejected because it is in a cross-site context" errors per image in every Lotus console. - **Load:** the picker is fine (12 thumbnails per category), but timelines and calls fetch full animated PNGs (~1 MB each, per the picker comment) for every decorated member. **Fix:** serve the catalogue as static files with a long cache. Either put it next to the web app (nginx on LXC 106, e.g. `https://chat.lotusguild.org/decorations/`, `Cache-Control: public, max-age=604800, immutable`) or behind the existing NPM. Then point `VITE_DECORATION_CDN` (already supported, eafa3533) at it. The Element Call fork pins the same CDN for in-call tiles, so update its pin too. --- _Found in the October 2026 client audit (Playwright against a local Synapse + LiveKit stack, plus code reading). Code refs are at cinny `30e2dbcd`, cinny-desktop `8f67ec7`, element-call `3b0050e8`._
jared added the infraenhancementpriority: low labels 2026-10-04 23:14:26 -04:00
jared closed this issue 2026-10-19 12:35:22 -04:00
Author
Owner

Done. Decorations no longer come from Nextcloud.

  • Package: Gitea generic package avatar-decorations 1.0.0, the full current set (629 decorations + thumbnails, 573 MB, byte-identical to the Nextcloud copies) in 4 tar parts, pinned by sha256 in cinny/decorations.sha256 (#35).
  • Served: https://chat.lotusguild.org/decorations/: static files, Cache-Control: public, max-age=604800, no cookies. LXC 106's deploy installs the pinned version with checksum verification and keeps the previous one for rollback.
  • Clients: cinny DECORATION_CDN points there (cinny #425, live on chat.lotusguild.org). The Element Call fork accepts the origin from lotus.26 (EC #56).
  • Rate limits (#36): testing showed the picker would hit the site's 20 r/s limit, and that nginx keyed that limit on the proxy's address, so the whole community shared one bucket (scanner bursts were 503ing everyone). It now uses each client's real address, and /decorations/ has its own budget. On production all 629 thumbnails now load (it refused 500 of them before).
  • Updating the set: GITEA_TOKEN=… deploy/publish-decorations.sh <folder> <version>, then commit the pin. Details in the README, "Avatar decorations".

The Nextcloud share can be retired once desktop users have updated (older desktop builds still point there). The fork still allows drive.lotusguild.org until then.

Done. Decorations no longer come from Nextcloud. - **Package:** Gitea generic package `avatar-decorations` **1.0.0**, the full current set (629 decorations + thumbnails, 573 MB, byte-identical to the Nextcloud copies) in 4 tar parts, pinned by sha256 in `cinny/decorations.sha256` (#35). - **Served:** `https://chat.lotusguild.org/decorations/`: static files, `Cache-Control: public, max-age=604800`, **no cookies**. LXC 106's deploy installs the pinned version with checksum verification and keeps the previous one for rollback. - **Clients:** cinny `DECORATION_CDN` points there (cinny #425, live on chat.lotusguild.org). The Element Call fork accepts the origin from lotus.26 (EC #56). - **Rate limits (#36):** testing showed the picker would hit the site's 20 r/s limit, and that nginx keyed that limit on the proxy's address, so **the whole community shared one bucket** (scanner bursts were 503ing everyone). It now uses each client's real address, and `/decorations/` has its own budget. On production all 629 thumbnails now load (it refused 500 of them before). - **Updating the set:** `GITEA_TOKEN=… deploy/publish-decorations.sh <folder> <version>`, then commit the pin. Details in the README, "Avatar decorations". The Nextcloud share can be retired once desktop users have updated (older desktop builds still point there). The fork still allows `drive.lotusguild.org` until then.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/matrix#22