Commit Graph
10 Commits
Author SHA1 Message Date
Lotus CIandClaude Opus 5.5 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
2026-09-29 12:08:45 -04:00
Lotus CIandClaude Opus 5.5 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
2026-09-28 18:47:49 -04:00
Lotus CIandClaude Opus 5.5 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
2026-09-27 11:52:52 -04:00
Lotus CIandClaude Opus 5.5 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
2026-09-26 23:24:32 -04:00
Lotus CIandClaude Opus 5.5 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
2026-09-26 16:53:07 -04:00
Lotus CIandClaude Opus 5.5 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
2026-09-26 15:11:50 -04:00
Lotus CIandClaude Opus 5.5 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
2026-09-25 19:26:52 -04:00
Lotus CIandClaude Opus 5.5 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"): 23ad133
(cinny #210) put the security-headers snippet, including the app CSP, on
every .html response. /public/element-call/index.html then carried
frame-ancestors 'none', so the browser refused to load it inside the app
("Content-Security-Policy ... frame-ancestors 'none'"). Desktop was fine (it
loads Element Call from its own bundle). Before #210 that page had no CSP.

A `location ^~ /public/element-call/` now serves it with
cinny-security-headers-framed.conf: the same headers minus the CSP
(X-Frame-Options SAMEORIGIN still limits framing to chat.lotusguild.org),
and the same caching (HTML no-cache, hashed assets 1 year). Applied live on
LXC 106 (backup sites-available/cinny.bak-ecframe-*), nginx -t ok; verified
from outside: no CSP on the call page, and the live site frames it and it
loads ("Element Call").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-25 19:26:44 -04:00
Lotus CIandClaude Opus 5.5 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
2026-09-23 23:17:53 -04:00
Lotus CIandClaude Opus 5.5 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
2026-09-23 22:29:52 -04:00