4bb2dd4449637a63106710d98660a23b1922caac
26
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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 |
||
|
|
d3f389cab1 |
feat(voice-limit-guard): enforce the limit at connect time too (#25)
Lint / Shell (shellcheck) (push) Successful in 39s
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 5s
Lint / Python deps (pip-audit) (push) Successful in 43s
Lint / Secret scan (gitleaks) (push) Successful in 9s
Lint / Shell (shellcheck) (pull_request) Successful in 13s
Lint / JS (eslint) (pull_request) Successful in 11s
Lint / No secrets in webhook configs (pull_request) Successful in 10s
Lint / Landing page is rendered (matrix (pull_request) Successful in 11s
Lint / Python (ruff) (pull_request) Successful in 10s
Lint / Python deps (pip-audit) (pull_request) Successful in 50s
Lint / Secret scan (gitleaks) (pull_request) Successful in 5s
The limit was only checked at token issue, and lk-jwt tokens last an hour, so a token fetched while there was space could be used to connect once the room was full. The reconcile loop now compares each limited room's distinct Matrix users with max_users and RemoveParticipants the people who arrived since the previous sweep, newest first, until it is back within the limit. People already in the call are never removed (lowering a limit mid-call kicks nobody); extra devices of one person never count twice. Fixes #25 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 |
||
|
|
fa0351084b |
fix(voice-limit-guard): two simultaneous joins can no longer both pass a full room (#25)
Lint / Shell (shellcheck) (pull_request) Successful in 16s
Lint / JS (eslint) (pull_request) Successful in 13s
Lint / No secrets in webhook configs (pull_request) Successful in 8s
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 1m25s
Lint / Secret scan (gitleaks) (pull_request) Successful in 13s
Lint / Shell (shellcheck) (push) Successful in 14s
Lint / JS (eslint) (push) Successful in 7s
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 5s
Lint / Python deps (pip-audit) (push) Successful in 40s
Lint / Secret scan (gitleaks) (push) Successful in 6s
The limit was checked against participants LiveKit already had, so tokens issued but not yet connected were not counted: two users pressing Join together could both get into a 1-person channel. Serialise the check per room and give each admitted user a 30 s reservation, counted like a present user until LiveKit lists them or it expires. Refs #25 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
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 |
||
|
|
076340227f |
docs(livekit): bind lk-jwt-service to 127.0.0.1:8071, not all interfaces (#24)
Lint / Shell (shellcheck) (pull_request) Successful in 19s
Lint / JS (eslint) (pull_request) Successful in 16s
Lint / No secrets in webhook configs (pull_request) Successful in 9s
Lint / Landing page is rendered (matrix (pull_request) Successful in 5s
Lint / Python (ruff) (pull_request) Successful in 5s
Lint / Python deps (pip-audit) (pull_request) Successful in 38s
Lint / Secret scan (gitleaks) (pull_request) Successful in 8s
Lint / Shell (shellcheck) (push) Successful in 14s
Lint / JS (eslint) (push) Successful in 9s
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 6s
Lint / Python deps (pip-audit) (push) Successful in 40s
Lint / Secret scan (gitleaks) (push) Successful in 7s
voice-limit-guard (:8070) is meant to be the only way to get a LiveKit token, but lk-jwt-service bound :8071 on every interface, so any LAN host could mint an unguarded token (no max_users, full publish sources in audio-only rooms). The guard runs on the same LXC: document the loopback bind in the setup steps and the port table. Refs #24 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 |
||
|
|
cf42d0aab0 |
docs: registration is closed (SSO/LLDAP only); note Draupnir encryption status
Lint / Shell (shellcheck) (pull_request) Successful in 10s
Lint / JS (eslint) (pull_request) Successful in 9s
Lint / No secrets in webhook configs (pull_request) Successful in 4s
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) Successful in 52s
Lint / Secret scan (gitleaks) (pull_request) Successful in 6s
Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 8s
Lint / No secrets in webhook configs (push) Successful in 4s
Lint / Landing page is rendered (matrix (push) Successful in 5s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 43s
Lint / Secret scan (gitleaks) (push) Successful in 5s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
cabc393b6b |
Revert Draupnir Rust crypto (#26): it fails to start without a device-bound token
Lint / Shell (shellcheck) (pull_request) Successful in 7s
Lint / JS (eslint) (pull_request) Successful in 6s
Lint / No secrets in webhook configs (pull_request) Successful in 3s
Lint / Landing page is rendered (matrix (pull_request) Successful in 4s
Lint / Python (ruff) (pull_request) Successful in 5s
Lint / Python deps (pip-audit) (pull_request) Successful in 32s
Lint / Secret scan (gitleaks) (pull_request) Successful in 4s
Lint / Shell (shellcheck) (push) Successful in 6s
Lint / JS (eslint) (push) Successful in 5s
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 34s
Lint / Secret scan (gitleaks) (push) Successful in 7s
With experimentalRustCrypto: true, Draupnir 2.9.0 exits on startup with "Encryption not possible: server not revealing device ID": its access token is not bound to a device, which matrix-bot-sdk crypto requires. Restores experimentalRustCrypto: false so the deploy hook brings it back. To enable encryption later, give Draupnir a device-bound access token (a normal password login) first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
d17c40e79f |
landing: describe SSO sign-up, drop dashes and hyphens from the page text
Lint / Shell (shellcheck) (pull_request) Successful in 13s
Lint / JS (eslint) (pull_request) Successful in 17s
Lint / No secrets in webhook configs (pull_request) Successful in 10s
Lint / Landing page is rendered (matrix (pull_request) Successful in 9s
Lint / Python (ruff) (pull_request) Successful in 11s
Lint / Python deps (pip-audit) (pull_request) Successful in 1m11s
Lint / Secret scan (gitleaks) (pull_request) Successful in 6s
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
Lint / No secrets in webhook configs (push) Successful in 4s
Lint / Landing page is rendered (matrix (push) Successful in 5s
Lint / Python (ruff) (push) Successful in 6s
Lint / Python deps (pip-audit) (push) Successful in 39s
Lint / Secret scan (gitleaks) (push) Successful in 6s
The "How to Join" steps still said to register with a token from Jared; accounts now come from LLDAP and people sign in with Lotus SSO. The steps now read: ask Jared for a Lotus Guild account, open chat.lotusguild.org and sign in with Lotus SSO, join the space. The contact line asks "Questions or need an account?" and the server details say "Invite only". Visible text no longer uses em dashes, en dashes or hyphens (dashes became colons, commas, full stops or "to"; compounds became separate words), in the hand-written parts and in data/features.json / comparison.json, with index.html regenerated by build.py. Package names (matrix-js-sdk, matrix-rust-sdk, matrix-dart-sdk, matrix-sdk-crypto-wasm) and D-Bus keep their hyphens; markup, URLs and <code> are untouched. The reviewed date displays as "September 26, 2026" (datetime attribute stays ISO). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 |
||
|
|
77e719183a |
draupnir: enable Rust crypto so it can read commands in the encrypted management room
Lint / Shell (shellcheck) (pull_request) Successful in 10s
Lint / JS (eslint) (pull_request) Successful in 9s
Lint / No secrets in webhook configs (pull_request) Successful in 4s
Lint / Landing page is rendered (matrix (pull_request) Successful in 4s
Lint / Python (ruff) (pull_request) Successful in 5s
Lint / Python deps (pip-audit) (pull_request) Successful in 1m17s
Lint / Secret scan (gitleaks) (pull_request) Successful in 10s
Lint / Shell (shellcheck) (push) Successful in 10s
Lint / JS (eslint) (push) Successful in 7s
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 8s
Lint / Python deps (pip-audit) (push) Successful in 1m13s
Lint / Secret scan (gitleaks) (push) Successful in 6s
The management room is end-to-end encrypted, but Draupnir ran with experimentalRustCrypto: false and Pantalaimon off, so it could post there (its own messages are unencrypted) but never saw commands: its last reply to a command was ~57 days ago, and `!draupnir rooms add …` sent from Lotus on 2026-10-13 was ignored. The same command sent unencrypted worked at once (✅, joined dco-memes-minecraft). Merging deploys via lxc110-draupnir.sh, which restarts draupnir. 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 |
||
|
|
8d47df711d |
fix(lxc106): deploy script merges config.json and updates itself (#13)
Lint / Shell (shellcheck) (push) Successful in 31s
Lint / JS (eslint) (push) Successful in 5s
Lint / No secrets in webhook configs (push) Successful in 4s
Lint / Landing page is rendered (matrix (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 8s
Lint / Python deps (pip-audit) (push) Successful in 1m2s
Lint / Secret scan (gitleaks) (push) Successful in 10s
Lint / Shell (shellcheck) (pull_request) Successful in 12s
Lint / JS (eslint) (pull_request) Successful in 12s
Lint / No secrets in webhook configs (pull_request) Successful in 8s
Lint / Landing page is rendered (matrix (pull_request) Successful in 8s
Lint / Python (ruff) (pull_request) Successful in 8s
Lint / Python deps (pip-audit) (pull_request) Successful in 1m15s
Lint / Secret scan (gitleaks) (pull_request) Successful in 12s
LXC 106's matrix-deploy hook has not fired since May: Gitea posts to 10.10.10.6:9000, which webhook.service binds to 127.0.0.1. The same hooks (same secret) are served by webhook-lotus on :9001; the Gitea hook is being re-pointed there. Before it starts firing again: - cinny/config.json is merged into the live file instead of copied over it. The live file carries gifApiKey (injected by lotus_deploy.sh), empty in git, which a copy would blank. Repo keys win except where the repo value is empty and the live one isn't. Backup goes to /root/config-backups; the live file is left untouched on error. - The script installs its own updates (deploy/lxc106-cinny.sh → /usr/local/bin/matrix-deploy.sh, after bash -n). Until now repo edits to it never reached the server. - A hooks.json change restarts webhook-lotus 15 s after the script exits, since that listener is the one running this script. - README: port 9001, the file list, and the history. 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 |
||
|
|
1dccca914c |
landing: re-verify every client claim (reviewed 2026-09-26)
Lint / Shell (shellcheck) (push) Successful in 21s
Lint / JS (eslint) (push) Successful in 11s
Lint / No secrets in webhook configs (push) Successful in 9s
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 47s
Lint / Secret scan (gitleaks) (push) Successful in 7s
Each client's card and all 64 table cells were checked against its latest release (source at the release tag, changelogs, official docs): Cinny v4.12.7, Element Web v1.12.29, Element X 26.09.2, FluffyChat v2.9.5, Commet v0.5.0, Nheko v0.12.1. ~95 cells corrected, notes tightened, chips made consistent (platforms / SDK / one calling chip). Notable: - Cinny: calls, voice rooms and screenshare via Element Call are stable (card gained the calling chip); ring, who-reacted, read receipts: yes; polls: no. - Element X: cannot START a screenshare (mobile web views have no getDisplayMedia) — chip is now "Voice & Video". - FluffyChat: threads, pinning, media gallery, custom status, QR invites: yes; calls still experimental (DM-only, legacy 1:1). - Commet: web app + Windows/Linux, no macOS; screenshare, widgets (v0.5.0), favourites: yes; "Beta" chip dropped (not self-described). - Nheko: calls are 1:1 only and only in Linux builds; threads: yes; no release since Aug 2025. - Element: no bookmarks or scheduling; custom status is Labs; QR invites and sort order: yes. - Lotus Chat: Vodozemac yes (Rust crypto), widgets yes, push = only while open (no background push yet); desktop app is Windows + Linux (the feature list said macOS). - Vodozemac is yes for every js-sdk client now (Rust crypto). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
f0017f4d5a |
landing: structured feature groups, single-source comparison table (#11)
Lint / Shell (shellcheck) (push) Successful in 17s
Lint / JS (eslint) (push) Successful in 11s
Lint / No secrets in webhook configs (push) Successful in 10s
Lint / Landing page is rendered (matrix (push) Successful in 6s
Lint / Python (ruff) (push) Successful in 11s
Lint / Python deps (pip-audit) (push) Successful in 54s
Lint / Secret scan (gitleaks) (push) Successful in 13s
- The ~1,800-word fork paragraph becomes 7 titled groups, one short line per feature, plus a link to LOTUS_FEATURES.md. - Single source: landing/data/features.json + comparison.json, rendered into index.html by landing/build.py between BEGIN/END markers (all 71 table rows re-render with identical cell text). - CSS moved to landing/style.css; build.py inlines it because the LXC 139 deploy copies index.html only. - "Client comparison last reviewed" stamp driven by comparison.json. - CI job `landing-fresh` fails if index.html drifts from its sources. - Feature list brought up to date: 629 avatar decorations in 28 categories, mic level meter + remembered per-person volume, search operators, paste-as-code, thread "Mark all read", pinch-zoom/swipe media viewer, room widgets with a permission prompt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA |
||
|
|
e28256ab3a |
docs: note the Element Call headers exception
Lint / Shell (shellcheck) (push) Successful in 9s
Lint / JS (eslint) (push) Successful in 7s
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 38s
Lint / Secret scan (gitleaks) (push) Successful in 6s
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 |
||
|
|
1dacf29d53 |
security(deploy): webhook secrets out of git; all exposed ones rotated
Lint / Shell (shellcheck) (push) Successful in 14s
Lint / JS (eslint) (push) Successful in 11s
Lint / No secrets in webhook configs (push) Successful in 7s
Lint / Python (ruff) (push) Successful in 13s
Lint / Python deps (pip-audit) (push) Successful in 1m46s
Lint / Secret scan (gitleaks) (push) Successful in 11s
deploy/hooks-lxc*.json in this public repo held the HMAC secrets for
every auto-deploy webhook (and 106's cinny-build token), readable
anonymously. Six values had been committed: the four matrix-deploy
secrets, 106's lotus-deploy secret (publicly reachable through
chat.lotusguild.org/hooks/lotus-deploy) and the cinny-build token.
- All six rotated on the servers and in Gitea (matrix hooks 6-9,
cinny hook 69). The old values are rejected.
- Secrets now live in /etc/webhook/secrets.env (0600) on each LXC, loaded
by a systemd drop-in that also enables webhook's -template mode; the
hooks files use {{ getenv "NAME" | js }} placeholders.
- The repo hooks files are now exact copies of the live ones, so they
also document the *-config-deploy hooks they were missing. Those
three secrets were never committed and are unchanged.
- README: where the secrets live and how to rotate one.
- CI `hooks-no-secrets` fails if a literal secret lands in a hooks
file again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
|