feat(cinny-web): serve avatar decorations from chat.lotusguild.org/decorations (#22) #35

Merged
jared merged 1 commits from feat/decorations-package into main 2026-10-19 12:35:22 -04:00
Owner

Fixes #22 (decision 2026-10-19: replace Nextcloud with a package; migrate the current set).

Decorations were served through Nextcloud's public DAV: a new PHP session, four cookies, per image and no cache headers, on every decorated avatar in timelines, member lists and call tiles.

Now

  • Package: Gitea generic package avatar-decorations 1.0.0 (published), the full current set: 629 decorations + 629 thumbnails, 573 MB. It's split into 4 tar parts of ≤150 MB, because the proxy in front of Gitea refuses large uploads. A MANIFEST.sha256 inside covers every file.
  • Pin: cinny/decorations.sha256 holds the sha256 of each part, which also names the version. That's the only thing in git.
  • Deploy (deploy/lxc106-cinny.sh): when the pin changes (or nothing is installed yet), it downloads the parts and verifies them against the pin and then the manifest. It unpacks to /var/www/decorations-<version>, atomically repoints /var/www/decorations, and keeps the previous version. A download or checksum failure leaves the live set unchanged.
  • nginx: location ^~ /decorations/ (alias, outside the web root, so app deploys' rsync --delete don't touch it), with Cache-Control: public, max-age=604800. It's a week rather than immutable, so an image replaced under the same name still updates. MANIFEST.sha256 isn't served.
  • deploy/publish-decorations.sh <folder> <version> publishes a new version and rewrites the pin. The README has the update and rollback steps.

Verified

  • All 1,258 files reassemble from the 4 parts and match the manifest.
  • The install step, run locally against the real registry: fresh install (629 images, symlink live); re-run is a no-op; a bad checksum is refused and the live set is untouched. This caught a real bug: set -e is ignored in a subshell on the left of ||, so each step now checks its own status. Pruning keeps live + previous.
  • nginx harness: /decorations/joystick.png → 200 image/png, the security headers, one Cache-Control: public, max-age=604800, bytes identical. Missing file and manifest → 404.
  • shellcheck is clean for the whole repo, as CI runs it.

Rollout: this merge's deploy still runs the old installed script, which installs the nginx route and the new script. I'll trigger the deploy once more so the new script installs the files. Then cinny and the Element Call fork switch their URL (separate PRs). Nextcloud can be retired once clients have updated.

🤖 Generated with Claude Code

https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5

Fixes #22 (decision 2026-10-19: replace Nextcloud with a package; migrate the current set). Decorations were served through Nextcloud's public DAV: a **new PHP session, four cookies, per image** and **no cache headers**, on every decorated avatar in timelines, member lists and call tiles. **Now** - **Package:** Gitea generic package **`avatar-decorations` 1.0.0** (published), the full current set: **629 decorations + 629 thumbnails, 573 MB**. It's split into 4 tar parts of ≤150 MB, because the proxy in front of Gitea refuses large uploads. A `MANIFEST.sha256` inside covers every file. - **Pin:** `cinny/decorations.sha256` holds the sha256 of each part, which also names the version. That's the only thing in git. - **Deploy (`deploy/lxc106-cinny.sh`):** when the pin changes (or nothing is installed yet), it downloads the parts and verifies them against the pin and then the manifest. It unpacks to `/var/www/decorations-<version>`, atomically repoints `/var/www/decorations`, and keeps the previous version. A download or checksum failure leaves the live set unchanged. - **nginx:** `location ^~ /decorations/` (alias, outside the web root, so app deploys' `rsync --delete` don't touch it), with `Cache-Control: public, max-age=604800`. It's a week rather than immutable, so an image replaced under the same name still updates. `MANIFEST.sha256` isn't served. - **`deploy/publish-decorations.sh <folder> <version>`** publishes a new version and rewrites the pin. The README has the update and rollback steps. **Verified** - All 1,258 files reassemble from the 4 parts and match the manifest. - The install step, run locally against the real registry: fresh install (629 images, symlink live); re-run is a no-op; a **bad checksum is refused** and the live set is untouched. This caught a real bug: `set -e` is ignored in a subshell on the left of `||`, so each step now checks its own status. Pruning keeps live + previous. - nginx harness: `/decorations/joystick.png` → 200 `image/png`, the security headers, one `Cache-Control: public, max-age=604800`, bytes identical. Missing file and manifest → 404. - `shellcheck` is clean for the whole repo, as CI runs it. **Rollout:** this merge's deploy still runs the old installed script, which installs the nginx route and the new script. I'll trigger the deploy once more so the new script installs the files. Then cinny and the Element Call fork switch their URL (separate PRs). Nextcloud can be retired once clients have updated. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared added 1 commit 2026-10-19 12:33:20 -04:00
feat(cinny-web): serve avatar decorations from chat.lotusguild.org/decorations (#22)
Lint / Shell (shellcheck) (push) Successful in 14s
Lint / JS (eslint) (push) Successful in 11s
Lint / No secrets in webhook configs (push) Successful in 5s
Lint / Landing page is rendered (matrix (push) Successful in 4s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 32s
Lint / Secret scan (gitleaks) (push) Successful in 4s
Lint / Shell (shellcheck) (pull_request) Successful in 7s
Lint / JS (eslint) (pull_request) Successful in 5s
Lint / No secrets in webhook configs (pull_request) Successful in 4s
Lint / Landing page is rendered (matrix (pull_request) Successful in 3s
Lint / Python (ruff) (pull_request) Successful in 4s
Lint / Python deps (pip-audit) (pull_request) Successful in 30s
Lint / Secret scan (gitleaks) (pull_request) Successful in 4s
b6380b6c8a
Decorations came through Nextcloud's public DAV: a new PHP session (four
cookies) per image and no cache headers, on every decorated avatar. The
set (629 decorations + thumbnails, 573 MB) is now a versioned Gitea
generic package (avatar-decorations 1.0.0, 4 tar parts), pinned by
sha256 in cinny/decorations.sha256. LXC 106's deploy installs it to
/var/www/decorations-<version> (verified against the pin and the
in-package manifest; previous version kept; failures leave the live set
alone), and nginx serves /decorations/ with a one-week public cache.
deploy/publish-decorations.sh publishes a new version and writes the pin.

Fixes #22

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
jared merged commit adeb872abb into main 2026-10-19 12:35:22 -04:00
Sign in to join this conversation.