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`._
Package: Gitea generic package avatar-decorations1.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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Lotus Chat loads avatar decorations from the Nextcloud public share (
DECORATION_CDN = https://drive.lotusguild.org/public.php/dav/files/<share>/cinny-decorations, cinnysrc/app/features/lotus/avatarDecorations.ts:6). Every request is answered by Nextcloud's PHP. Headers on a thumbnail (…/thumbs/<slug>.webp):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 pointVITE_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-desktop8f67ec7, element-call3b0050e8.Done. Decorations no longer come from Nextcloud.
avatar-decorations1.0.0, the full current set (629 decorations + thumbnails, 573 MB, byte-identical to the Nextcloud copies) in 4 tar parts, pinned by sha256 incinny/decorations.sha256(#35).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.DECORATION_CDNpoints there (cinny #425, live on chat.lotusguild.org). The Element Call fork accepts the origin from lotus.26 (EC #56)./decorations/has its own budget. On production all 629 thumbnails now load (it refused 500 of them before).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.orguntil then.