5268156e48512df7c006175ab0dcdc1cf7354f88
36
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5268156e48 |
cinny: point the status banner at Kuma's public page
Lint / JS (eslint) (pull_request) Successful in 30s
Lint / No Hookshot webhook IDs in README (pull_request) Successful in 15s
Lint / No secrets in webhook configs (pull_request) Successful in 15s
Lint / Landing page is rendered (matrix (pull_request) Successful in 5s
Lint / Python (ruff) (pull_request) Successful in 8s
Lint / Python deps (pip-audit) (pull_request) Successful in 1m9s
Lint / Secret scan (gitleaks) (pull_request) Successful in 9s
Lint / Shell (shellcheck) (push) Successful in 13s
Lint / JS (eslint) (push) Successful in 11s
Lint / No Hookshot webhook IDs in README (push) Successful in 16s
Lint / Landing page is rendered (matrix (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 6s
Lint / Shell (shellcheck) (pull_request) Successful in 22s
Lint / Python deps (pip-audit) (push) Successful in 1m34s
Lint / No secrets in webhook configs (push) Successful in 7s
Lint / Secret scan (gitleaks) (push) Successful in 7s
The "matrix" status page was merged into "public" on 2026-10-11, so the banner has read a 404 and stayed silent since. Kuma's Matrix group on "public" is now split into Homeserver / Voice calls / Discord, and notices are scoped with noticePrefix "Matrix:" (cinny #486, already live), so other services' maintenance and incidents don't reach Lotus users. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
ad7d735739 |
fix(cinny-nginx): give content-hashed app files their own rate budget
Lint / Shell (shellcheck) (pull_request) Successful in 15s
Lint / JS (eslint) (pull_request) Successful in 10s
Lint / No secrets in webhook configs (pull_request) Successful in 5s
Lint / Landing page is rendered (matrix (pull_request) Successful in 5s
Lint / Python (ruff) (pull_request) Successful in 6s
Lint / Python deps (pip-audit) (pull_request) Failing after 57s
Lint / Secret scan (gitleaks) (pull_request) Successful in 11s
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 9s
Lint / No secrets in webhook configs (push) Successful in 5s
Lint / Landing page is rendered (matrix (push) Successful in 5s
Lint / Python (ruff) (push) Successful in 8s
Lint / Python deps (pip-audit) (push) Failing after 51s
Lint / Secret scan (gitleaks) (push) Successful in 6s
A cold page load fires ~75 requests within a second and the service worker precaches all ~126 build files at once (every deploy renames them), both past chat_limit's burst of 60. The excess got 503 "limiting requests": a fresh visit to /register/matrix.org rendered blank (4 chunks refused), and precache installs could fail after deploys. Like decorations (matrix #22), hashed js/css/fonts/images/wasm now use assets_limit (100 r/s, burst 400); pages and the webhook keep chat_limit. The deploy validates with nginx -t and restores the old config on failure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
8aea38fc67 |
feat(cinny-deploy): fail and alert when a deployed page references missing files
Lint / No secrets in webhook configs (pull_request) Successful in 24s
Lint / Landing page is rendered (matrix (pull_request) Successful in 18s
Lint / Python (ruff) (pull_request) Successful in 10s
Lint / Python deps (pip-audit) (pull_request) Successful in 1m0s
Lint / Secret scan (gitleaks) (pull_request) Successful in 8s
Lint / Shell (shellcheck) (push) Successful in 15s
Lint / JS (eslint) (push) Successful in 16s
Lint / No secrets in webhook configs (push) Successful in 10s
Lint / Landing page is rendered (matrix (push) Successful in 9s
Lint / Python (ruff) (push) Successful in 10s
Lint / Python deps (pip-audit) (push) Successful in 1m17s
Lint / Shell (shellcheck) (pull_request) Successful in 13s
Lint / JS (eslint) (pull_request) Successful in 7s
Lint / Secret scan (gitleaks) (push) Successful in 5s
After copying, check every script/stylesheet the app and call pages reference (src/href in both index.html files) exists in the webroot. If any is missing, log it, post an alert with the upstream checker's Matrix credentials (/etc/cinny-monitor.env, best effort) and exit 1. This would have caught the 2026-10-20 call-page outage at deploy time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
85c58d5ed0 |
fix(cinny-deploy): the call page's scripts are deployed again
Lint / No secrets in webhook configs (pull_request) Successful in 11s
Lint / Landing page is rendered (matrix (pull_request) Successful in 8s
Lint / Python (ruff) (pull_request) Successful in 7s
Lint / Python deps (pip-audit) (pull_request) Successful in 44s
Lint / Secret scan (gitleaks) (pull_request) Successful in 9s
Lint / Shell (shellcheck) (push) Successful in 14s
Lint / JS (eslint) (push) Successful in 9s
Lint / No secrets in webhook configs (push) Successful in 6s
Lint / Landing page is rendered (matrix (push) Successful in 5s
Lint / Python (ruff) (push) Successful in 7s
Lint / Python deps (pip-audit) (push) Successful in 40s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Lint / Shell (shellcheck) (pull_request) Successful in 14s
Lint / JS (eslint) (pull_request) Successful in 10s
#30 added `rsync --exclude assets/` to keep old app assets, but an unanchored exclude matches every directory named assets, including public/element-call/assets/. Each deploy then updated the call page's index.html but not its hashed scripts, so after the lotus.28 deploy the call page requested files that did not exist (66 x 404 from 00:05 on 2026-10-20 until the assets were copied in by hand). The excludes are now anchored (/assets/, /public/element-call/assets/), and both asset directories get the same treatment: copied without --delete, pruned after 14 days, so an open call page keeps its scripts across a deploy. config.json stays unanchored on purpose (the production call config lives at public/element-call/config.json). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
a52d6a89bc |
fix(cinny-web): per-client rate limits; own budget for decorations
Lint / Shell (shellcheck) (pull_request) Successful in 7s
Lint / JS (eslint) (pull_request) Successful in 7s
Lint / No secrets in webhook configs (pull_request) Successful in 3s
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 49s
Lint / Secret scan (gitleaks) (pull_request) Successful in 5s
Lint / Shell (shellcheck) (push) Successful in 7s
Lint / JS (eslint) (push) Successful in 6s
Lint / No secrets in webhook configs (push) Successful in 4s
Lint / Landing page is rendered (matrix (push) Successful in 4s
Lint / Python (ruff) (push) Successful in 4s
Lint / Python deps (pip-audit) (push) Successful in 30s
Lint / Secret scan (gitleaks) (push) Successful in 4s
Every request reaches LXC 106 from Nginx Proxy Manager (10.10.10.27), and nginx had no realip config, so chat_limit (20 r/s, burst 60, keyed by $binary_remote_addr) was ONE bucket for the whole community: a scanner burst 503ed real users. Trust X-Real-IP from the proxy only, in both server blocks. Decorations (#22) now come from this host, and the profile picker can fetch all 629 thumbnails: ~500 of them 503ed in testing. /decorations/ gets its own zone (100 r/s, burst 700) instead of chat_limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
b6380b6c8a |
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
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 |
||
|
|
0aa34123a8 |
Merge pull request 'fix(cinny-web): CSP for mozilla.org discovery and TikTok oEmbed; featured communities (#18, #20, #21)' (#32) from fix/web-config-csp into main
Lint / Shell (shellcheck) (push) Successful in 12s
Lint / JS (eslint) (push) Successful in 10s
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 1m7s
Lint / Secret scan (gitleaks) (push) Successful in 6s
|
||
|
|
61ed3c64e3 |
feat(cinny-web): featured communities on Explore, matching the desktop app (#20)
Lint / JS (eslint) (push) Successful in 11s
Lint / No secrets in webhook configs (push) Successful in 6s
Lint / Landing page is rendered (matrix (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 16s
Lint / Python deps (pip-audit) (push) Successful in 1m9s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Lint / Shell (shellcheck) (pull_request) Successful in 15s
Lint / JS (eslint) (pull_request) Successful in 14s
Lint / No secrets in webhook configs (pull_request) Successful in 9s
Lint / Landing page is rendered (matrix (pull_request) Successful in 10s
Lint / Python (ruff) (pull_request) Successful in 11s
Lint / Python deps (pip-audit) (pull_request) Successful in 1m7s
Lint / Secret scan (gitleaks) (pull_request) Successful in 8s
Lint / Shell (shellcheck) (push) Successful in 11s
chat.lotusguild.org's config.json has never had featuredCommunities, so Explore → Featured was empty on the web while the desktop app showed the Lotus Guild space, Homelab, Jellyfin and matrixrooms.info. Add the same set (decided 2026-10-04). Fixes #20 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
be0ff3b854 |
fix(cinny-web): allow the TikTok oEmbed lookup in connect-src (#18)
TikTok short links (vm.tiktok.com/…, tiktok.com/t/…) resolve their video id via https://www.tiktok.com/oembed, which the CSP refused, so their cards always failed on the web. The player itself was already allowed (frame-src https:). Fixes #18 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
93078858c1 |
fix(cinny-web): allow www.mozilla.org in connect-src so mozilla.org login can discover its homeserver (#21)
mozilla.org/.well-known/matrix/client 301s to www.mozilla.org, which the CSP refused, so choosing mozilla.org always said "Failed to connect". Fixes #21 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
bf770fed83 |
fix(cinny-web): no-cache for the app shell on SPA routes; keep old hashed assets 14 days (#23)
Lint / Shell (shellcheck) (push) Successful in 24s
Lint / JS (eslint) (push) Successful in 15s
Lint / No secrets in webhook configs (push) Successful in 7s
Lint / Landing page is rendered (matrix (push) Successful in 42s
Lint / Python (ruff) (push) Successful in 11s
Lint / Python deps (pip-audit) (push) Successful in 40s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Lint / Shell (shellcheck) (pull_request) Successful in 9s
Lint / JS (eslint) (pull_request) Successful in 7s
Lint / No secrets in webhook configs (pull_request) Successful in 5s
Lint / Landing page is rendered (matrix (pull_request) Successful in 4s
Lint / Python (ruff) (pull_request) Successful in 6s
Lint / Python deps (pip-audit) (pull_request) Successful in 1m59s
Lint / Secret scan (gitleaks) (pull_request) Successful in 15s
SPA URLs (/, /home/…, /login/…) are rewritten to /index.html inside location /, which set no cache headers, so browsers heuristically reused a stale shell after a deploy, and rsync --delete had just removed the assets it referenced: a blank app until the shell expired. Send no-cache for the rewritten shell (map on $uri; location / now includes the security headers, since add_header drops the inherited ones), and stop deleting previous builds' hashed assets: prune after 14 days. Fixes #23 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
8d80ebf4c2 |
cinny config: status banner from the Kuma page (cinny #124)
Lint / Shell (shellcheck) (push) Successful in 15s
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 6s
Lint / Python (ruff) (push) Successful in 9s
Lint / Python deps (pip-audit) (push) Successful in 1m1s
Lint / Secret scan (gitleaks) (push) Successful in 8s
Lint / Shell (shellcheck) (pull_request) Successful in 14s
Lint / JS (eslint) (pull_request) Successful in 11s
Lint / No secrets in webhook configs (pull_request) Successful in 6s
Lint / Landing page is rendered (matrix (pull_request) Successful in 6s
Lint / Python (ruff) (pull_request) Successful in 6s
Lint / Python deps (pip-audit) (pull_request) Successful in 44s
Lint / Secret scan (gitleaks) (pull_request) Successful in 7s
Adds `statusPages` for matrix.lotusguild.org → the Kuma status page https://isitup.lotusguild.org/status/matrix (groups Homeserver, Voice calls, Login). The banner code (cinny #255) and the CSP (#16) are already live; production's config.json comes from this file, so without this entry the client never asks Kuma. The LXC 106 deploy merges it into the live file and keeps server-only values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
9fcbd410f2 |
cinny CSP: allow the app to read the Kuma status page (cinny #124)
Lint / Shell (shellcheck) (push) Successful in 17s
Lint / JS (eslint) (push) Successful in 12s
Lint / No secrets in webhook configs (push) Successful in 7s
Lint / Landing page is rendered (matrix (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 7s
Lint / Python deps (pip-audit) (push) Successful in 45s
Lint / Secret scan (gitleaks) (push) Successful in 7s
Lint / Shell (shellcheck) (pull_request) Successful in 12s
Lint / JS (eslint) (pull_request) Successful in 11s
Lint / No secrets in webhook configs (pull_request) Successful in 7s
Lint / Landing page is rendered (matrix (pull_request) Successful in 10s
Lint / Python (ruff) (pull_request) Successful in 8s
Lint / Python deps (pip-audit) (pull_request) Successful in 57s
Lint / Secret scan (gitleaks) (pull_request) Successful in 8s
Add https://isitup.lotusguild.org to connect-src so the client can fetch the public status JSON (GET /api/status-page/matrix and /api/status-page/heartbeat/matrix) for the homeserver status banner. Read-only public JSON, no credentials; nothing else changes. The live snippet (/etc/nginx/snippets/cinny-security-headers.conf on LXC 106) was identical to this file before the change; install it by hand with a backup and `nginx -t` (the deploy script only handles cinny/nginx.conf). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
9baafd4928 |
cinny: load Element Call from call.chat.lotusguild.org (cinny #43)
Lint / Shell (shellcheck) (push) Successful in 50s
Lint / JS (eslint) (push) Successful in 10s
Lint / No secrets in webhook configs (push) Successful in 8s
Lint / Landing page is rendered (matrix (push) Successful in 11s
Lint / Python (ruff) (push) Successful in 10s
Lint / Python deps (pip-audit) (push) Successful in 48s
Lint / Secret scan (gitleaks) (push) Successful in 8s
Sets elementCallUrl so the web app frames the call page on its own origin (desktop keeps its bundled copy). Applied on LXC 106 in place (the live file also carries the injected gifApiKey; backup in /root/config-backups/), since the matrix-deploy webhook there has not fired since May. Rollback: remove this key (live: restore the backup) and new calls use the bundled same-origin page again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
9c5a183025 |
feat(cinny): nginx for Element Call on call.chat.lotusguild.org (cinny #43)
Lint / Shell (shellcheck) (push) Successful in 21s
Lint / JS (eslint) (push) Successful in 14s
Lint / No secrets in webhook configs (push) Successful in 6s
Lint / Landing page is rendered (matrix (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 7s
Lint / Python deps (pip-audit) (push) Successful in 52s
Lint / Secret scan (gitleaks) (push) Successful in 8s
Lint / Shell (shellcheck) (pull_request) Successful in 17s
Lint / JS (eslint) (pull_request) Successful in 13s
Lint / No secrets in webhook configs (pull_request) Successful in 6s
Lint / Landing page is rendered (matrix (pull_request) Successful in 6s
Lint / Python (ruff) (pull_request) Successful in 8s
Lint / Python deps (pip-audit) (pull_request) Successful in 53s
Lint / Secret scan (gitleaks) (pull_request) Successful in 8s
- cinny/nginx.conf: a call.chat.lotusguild.org server block that serves ONLY /public/element-call/ (the same files chat.lotusguild.org already serves there) and 404s everything else, including source maps and dotfiles. - cinny/nginx-security-headers-call.conf (new snippet): frame-ancestors https://chat.lotusguild.org instead of X-Frame-Options SAMEORIGIN, which would block the now cross-origin parent. - cinny/nginx-security-headers.conf: the app's Permissions-Policy delegates autoplay/camera/display-capture/microphone to the call origin (without it the cross-origin frame's getUserMedia is refused). Outer quotes switched to single: the inner "origin" quotes broke nginx parsing. Nothing changes for users until config.json sets elementCallUrl (separate step). Snippets are installed by hand on LXC 106; nginx.conf deploys on merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
d4fd1d0b8e |
fix(cinny/nginx): let the app frame its bundled Element Call again
Lint / Shell (shellcheck) (push) Successful in 20s
Lint / JS (eslint) (push) Successful in 13s
Lint / No secrets in webhook configs (push) Successful in 4s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 44s
Lint / Secret scan (gitleaks) (push) Successful in 8s
Web calls broke ("nobody can join calls from the web version"):
|
||
|
|
23ad133dc3 |
cinny(nginx): security headers on every location; sync repo with live (cinny #210, #214, #155)
Lint / Shell (shellcheck) (push) Successful in 13s
Lint / JS (eslint) (push) Successful in 12s
Lint / No secrets in webhook configs (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 9s
Lint / Python deps (pip-audit) (push) Successful in 1m9s
Lint / Secret scan (gitleaks) (push) Successful in 10s
Applied on LXC 106 (backed up, `nginx -t`, reloaded) and recorded here: - Security headers (incl. CSP) moved to snippets/cinny-security-headers.conf and included at server level plus in the /sw.js, static-asset and json/html locations. nginx drops inherited add_header in any block that sets its own, so static assets were served without nosniff and /sw.js without a CSP (a service worker takes its CSP from its own script). Now every path carries all seven headers. Verified: the SW installs and controls the page under the CSP with no violations. - #214: CSP no longer allows fonts.googleapis.com / fonts.gstatic.com (VT323 is self-hosted since cinny 6f250353). - #155: the /share-target → /share 303 is now live (it was only in the repo; the 106 matrix-deploy hook has been dead since May, so repo edits never reached it). absolute_redirect off makes it relative. - README: the snippet, and that 106 needs these applied by hand. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
a16cc85420 |
cinny: 303 /share-target → /share for the PWA share target (#155)
The service worker normally answers the share-sheet POST itself; this keeps a POST that reaches nginx before the worker controls the page from returning 405. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
c553c28957 |
cinny nginx: drop fonts.googleapis.com / fonts.gstatic.com from the CSP
Lotus Chat 6f250353 self-hosts VT323, so nothing legitimate loads from Google any more; keeping the hosts allowed would let a regression pass silently. NOTE: the live config is hand-maintained at /etc/nginx/sites-available/cinny on LXC 106 — apply the same two edits there after the cinny deploy lands. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
b6ea4a333e |
fix(cinny-deploy): queue a trigger that arrives mid-deploy instead of dropping it
lotus_deploy.sh took an flock and exited if a deploy was already running. The poll loop only retargets origin/lotus while it is still waiting on CI; a push that lands during npm ci / npm run build was silently never deployed until the next unrelated push (cinny 81a6d9c9 — the MSC4515 call fix — passed CI but never reached the web root). A concurrent trigger now leaves a .pending marker and the running deploy re-execs itself once at the end, which re-fetches and re-gates on CI as usual. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
67a08c7402 |
fix(cinny): upstream-merge script pushes and hands off to CI instead of deploying
lotus-build.sh merged the latest upstream tag, then built, copied to the web root, reloaded nginx and only then pushed — the one path that could change production without any CI gate (cinny#98). It now merges, runs the same local gates CI runs (npm ci, typecheck, eslint, prettier, tests), and pushes; the push triggers Gitea CI and lotus_deploy.sh deploys once "Build & Quality Checks" is green, like every other lotus commit. A failed gate leaves the merge local for inspection and notifies the room. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
c15a48971d |
deploy(cinny): follow origin/lotus HEAD while gating on CI
Companion to cinny's `concurrency: cancel-in-progress`. The poll loop latched origin/lotus once at startup; with CI cancel-in-progress a superseded run's status flips to error/failure, so polling the latched (now-cancelled) SHA would abort and — with the flock skipping the newer push's deploy — strand the newest commit undeployed (a deploy freeze, the exact class this script fought before). - Re-resolve origin/lotus each poll iteration; retarget the CI gate to HEAD if it advanced (fresh MAX_WAIT window). - On a failure/error status, re-check HEAD before aborting — only a genuine failure of the CURRENT HEAD aborts; a superseded/blip SHA is followed instead. - Reset to the gated $COMMIT_SHA (not a bare origin/lotus that may have advanced past the gate after the loop) so we build exactly what passed CI. shellcheck clean; reviewed (SHIP). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
d9dfc54200 |
fix(cinny): restore gifApiKey placeholder + redact leaked key from README
The production config.json (cp'd from cinny/config.json by deploy/lxc106-cinny.sh)
lost its "gifApiKey": "" placeholder, so lotus_deploy.sh's sed injection had no
field to fill -> the GIF composer button disappeared (it renders only when
gifApiKey is non-empty). Restore the placeholder so future deploys inject the key.
Also redact the real Giphy key that was committed in the README (it belongs only in
/etc/lotus-deploy.env on LXC 106). NOTE: the key remains in git history (commit
|
||
|
|
b72d6620cc |
chore(nginx): widen CSP frame-src to https: for room widgets (MSC1236)
Room widgets embed arbitrary third-party https pages in a sandboxed iframe; frame-src was 'self' + openstreetmap only. Apply + nginx -s reload. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
64262b39ec |
chore(nginx): drop api.qrserver.com from CSP (invite QR now generated locally)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
6293a62e47 |
feat(nginx): add HSTS + Permissions-Policy to chat.lotusguild.org (P6-4)
Adds Strict-Transport-Security (2y, includeSubDomains, preload) and a Permissions-Policy that allows only the features the app uses (camera/mic/ display-capture for calls, geolocation for location share, autoplay/fullscreen/ encrypted-media) and denies the rest. Complements the existing X-Frame/CSP/ Referrer headers. Apply: reload nginx on the LXC. TLS terminates upstream (listen 80), so verify the header reaches the browser (front proxy must pass it through) — else set HSTS at the TLS terminator. Verify a call + location share still work. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
d344b9b4b5 |
fix(ci): make the SC1091 suppression in lotus_deploy.sh actually apply
Shellcheck directives bind to the NEXT command; on the compound line
`set -a; source /etc/lotus-deploy.env; set +a` the existing
`# shellcheck disable=SC1091` bound to `set -a`, so the info-level SC1091
finding on the runtime-only env file still failed the lint workflow
(find -exec shellcheck exits non-zero on any finding). Split the line so the
directive sits directly above `source` (as `source=/dev/null`, the standard
idiom for host-only env files). Verified with CI's exact invocation:
`find . -name "*.sh" -exec shellcheck {} +` now exits 0 (shellcheck 0.9.0).
No runtime behavior change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
c13549f3da |
cinny: harden + version-control the webhook web-deploy (lotus_deploy.sh)
The live /usr/local/bin/lotus_deploy.sh (the `lotus-deploy` webhook target) was never under version control and had rotted into two deploy-killing bugs that froze chat.lotusguild.org on an old build: 1. CI gate: it waited on the WHOLE workflow run with a 15-min cap. Web CI shares the single act_runner with the slow Tauri desktop builds, so a web run could sit queued >15 min -> "result: timeout" -> deploy aborted. Now it gates only on the "Build & Quality Checks" commit-status context (build + unit tests), decoupled from "Trigger Desktop Build", and waits up to 45 min. 2. Dead element-call copy: `cp node_modules/@element-hq/element-call-embedded/...` under `set -e` aborted every deploy after the widget was forked to @lotusguild/element-call-embedded. The build already emits dist/public/ element-call; replaced the copy with a presence check. Also: rsync now excludes config.json so the app deploy stops clobbering the production runtime config (homeserver list / allowCustomHomeservers) that the matrix repo owns. lxc106-cinny.sh now installs this script (syntax-checked). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
d6fd323262 |
cinny: enable mozilla.org (OIDC/next-gen-auth homeserver)
Now that the client supports MSC3861 OIDC login, add mozilla.org to the homeserverList and its origins to the CSP. mozilla delegates: homeserver -> mozilla.modular.im, OIDC issuer -> chat.mozilla.org, identity -> vector.im. - connect-src += mozilla.org mozilla.modular.im chat.mozilla.org vector.im - img-src += mozilla.org mozilla.modular.im Applied live to LXC 106 and synced here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
b39e3594d5 |
cinny: allow matrix.org media in CSP img-src
Federated matrix.org users load avatars/images from their own media endpoint (matrix-client.matrix.org), which img-src still blocked — so every avatar tripped a CSP violation. Add https://matrix.org + https://*.matrix.org to img-src to match connect-src. (media-src already allows https: so video/audio were fine.) Applied live to LXC 106 and synced here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
40ceb43672 |
cinny: version-control the production nginx site config
The chat.lotusguild.org nginx config (LXC 106) was edited directly on the box and never tracked — which is how its CSP drifted (kept a dead Sentry URL and blocked matrix.org logins). Snapshot it as cinny/nginx.conf (verbatim from prod, incl. the corrected connect-src that now allows matrix.org/*.matrix.org) and deploy it via lxc106-cinny.sh: back up the live file, swap, `nginx -t`, and reload only on success (auto-restore the backup if validation fails, so a bad config can't take the site down). TLS terminates at the NPM proxy, so this is a plain HTTP server block with no secrets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
45444e5118 |
cinny: allow matrix.org logins on the Lotus client
Add matrix.org to homeserverList so federated friends with matrix.org accounts can sign into chat.lotusguild.org. defaultHomeserver stays 0 (lotusguild), and allowCustomHomeservers stays false — only the two listed servers are selectable, so the client isn't opened up to arbitrary homeservers. Deploys via lxc106-cinny.sh (cp -> /var/www/html/config.json); lotus-build.sh preserves the live config across app rebuilds, so this is the authoritative copy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
ffff199b7f |
Fix NODE_OPTIONS heap size for Vite build (896MB → 6144MB)
OOM observed during rendering-chunks phase at 896MB and 3072MB. 6144MB heap with 8GB LXC memory is confirmed working. Also update README rebuild command to match. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
7f7ddd3e3c |
Switch Lotus Cinny from nightly dev to stable-release fork workflow
- Replace nightly build script with daily upstream release checker (cinny/upstream-check.sh) — posts to Matrix as LotusBot when a new cinnyapp/cinny stable release is published - Add cinny/lotus-build.sh — merges latest release tag into the lotus branch, builds, deploys; triggered via !cinny-update webhook - Fork lives at code.lotusguild.org/LotusGuild/cinny (lotus branch, v4.11.1) - deploy/hooks-lxc106.json — adds cinny-build webhook endpoint (port 9000) - Update landing page: "dev branch / nightly" → "Lotus fork / stable releases" - Set LotusBot avatar on @hookshot_tinker-tickets Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
735c1eb30e |
ci: add lint workflow, shellcheck fixes, and CI failure hookshot alert
- .gitea/workflows/lint.yml: new workflow running shellcheck on .sh files
and eslint on hookshot/ JS transform scripts
- hookshot/.eslintrc.json: declare data/result as hookshot globals
- hookshot/ci-alert.js: new Matrix hookshot transform for CI failure alerts
- hookshot/deploy.sh: fix SC2155 (split local/assign), SC2034 (remove unused var)
- systemd/livekit-clear-port.sh: fix SC2148 (invalid shebang escape)
- cinny/dev-update.sh: fix SC2115 (use ${WEB_ROOT:?} to guard rm -rf)
- deploy/lxc151-hookshot.sh: add shellcheck source=/dev/null for sourced file
- .gitignore: ignore node_modules/
- package.json + package-lock.json: eslint@8 dev dependency
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
||
|
|
0e275d725e |
refactor: replace old bot code with Matrix infra configs and scripts
- Remove obsolete Python bot (Wordle, commands, callbacks, welcome) - Add hookshot/ — all 11 webhook transformation functions + deploy.sh - Add cinny/ — config.json and dev-update.sh (nightly dev branch build) - Add landing/ — matrix.lotusguild.org landing page HTML - Add systemd/ — livekit-server, draupnir, cinny cron unit files - Add draupnir/ — production config (access token redacted) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |