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
This commit is contained in:
Lotus CI
2026-09-23 23:17:53 -04:00
co-authored by Claude Opus 5.5
parent 1dacf29d53
commit 23ad133dc3
3 changed files with 29 additions and 18 deletions
+4 -2
View File
@@ -109,7 +109,9 @@ matrix/
- Monitor state: `/var/lib/cinny-monitor/last-upstream-commit`
- Monitor log: `/var/log/cinny-monitor.log`
- Build log: `/var/log/cinny-build.log`
- Nginx site config: `/etc/nginx/sites-available/cinny`
- Nginx site config: `/etc/nginx/sites-available/cinny` (copy in this repo: `cinny/nginx.conf`, synced with live on 2026-09-23)
- Nginx security headers: `/etc/nginx/snippets/cinny-security-headers.conf` (`cinny/nginx-security-headers.conf`). Included at server level **and** in every `location` that sets its own `add_header`; nginx drops inherited `add_header`s in such blocks, which left static assets without `nosniff` and `/sw.js` without its CSP (cinny #210). Edit the CSP here, not in the site config.
- ⚠️ The `matrix-deploy` hook on 106 has been unreachable since May (webhook bound to `127.0.0.1:9000`), so edits to these files in the repo are **not** auto-deployed there. Apply them by hand (`nginx -t` then `nginx -s reload`) and keep the repo copy in sync.
---
@@ -535,7 +537,7 @@ All custom code lives in `src/app/` on the `lotus` branch of `code.lotusguild.or
| **PiP position persistence + snap** | `src/app/components/CallEmbedProvider.tsx` | PiP position saved to `localStorage` on drag end; restored on next PiP enter (clamped to viewport). Double-click snaps to nearest corner with 180ms CSS transition |
| **Threads (P3-8 + P4-1)** | `src/app/features/room/thread/`, `state/room/thread.ts`, `utils/threadNotifications.ts`, `hooks/useRoomsListener.ts` | Full m.thread support: side panel (own composer, per-thread drafts), "N replies" unread chips, threaded receipts; SDK `threadSupport` on, markAsRead unthreaded; replies no longer render inline. **Slack-style notifications**: default = participating-only, per-thread All/Mentions/Mute in `io.lotus.thread_notifications` account data; muted threads subtracted from room badges client-side |
| **KaTeX math + encrypted-search cache + session hardening + crypto diagnostics** | `utils/{mathParse,searchCache,cryptoDiagLog}.ts`, `state/sessions.ts`, `LOTUS_E2EE_INVESTIGATION.md` | July 2026 batch: `$…$`/`$$…$$` + `data-mx-maths` via lazy KaTeX; opt-in IndexedDB search index for E2EE rooms (wiped on logout); atomic `cinny_session_v1` blob + cross-tab logout sync; KE-1→4 diagnostics capture card in Developer Tools |
| **Inline media embeds** | `src/app/utils/videoEmbed.ts`, `src/app/components/url-preview/{UrlPreviewCard,UrlPreview.css}.tsx` | Media links play/render **in place** behind a click-to-play **facade** (homeserver `og:image` thumbnail; third-party iframe mounts only on Play). 16 providers: video (YouTube/Shorts, Vimeo, Dailymotion, Streamable, Twitch, Loom, Kick), audio (Spotify, SoundCloud, Apple Music, Tidal), self-resizing posts (X/Twitter, Instagram, Reddit, Bluesky). TikTok short links resolve via CORS `oEmbed`; posts self-size via origin-scoped `postMessage`. Sandbox omits `allow-top-navigation`; previews capped at 6/msg. Setting `inlineMediaEmbeds`. **CSP:** every embed host is enumerated in the desktop Tauri `frame-src` (`cinny-desktop/tauri.conf.json`) **and** the deployed web nginx `frame-src` allowlist on LXC 106 (`/etc/nginx/sites-available/cinny` — hand-maintained; the wildcard `frame-src 'self' https:` in this repo's `cinny/nginx.conf` is the looser fallback) |
| **Inline media embeds** | `src/app/utils/videoEmbed.ts`, `src/app/components/url-preview/{UrlPreviewCard,UrlPreview.css}.tsx` | Media links play/render **in place** behind a click-to-play **facade** (homeserver `og:image` thumbnail; third-party iframe mounts only on Play). 16 providers: video (YouTube/Shorts, Vimeo, Dailymotion, Streamable, Twitch, Loom, Kick), audio (Spotify, SoundCloud, Apple Music, Tidal), self-resizing posts (X/Twitter, Instagram, Reddit, Bluesky). TikTok short links resolve via CORS `oEmbed`; posts self-size via origin-scoped `postMessage`. Sandbox omits `allow-top-navigation`; previews capped at 6/msg. Setting `inlineMediaEmbeds`. **CSP:** every embed host is enumerated in the desktop Tauri `frame-src` (`cinny-desktop/tauri.conf.json`) **and** the deployed web nginx `frame-src` allowlist on LXC 106 (`/etc/nginx/snippets/cinny-security-headers.conf` on LXC 106; repo copy `cinny/nginx-security-headers.conf`) |
| **On-device message translation** | `src/app/features/room/message/`, `src/app/hooks/useMessageTranslation.ts`, `src/app/state/settings.ts` | "Translate" button on foreign-language messages renders the translation inline with a "Translated from &lt;lang&gt; · Show original" toggle + optional auto-translate mode. Runs **100% on-device** via the browser's built-in Translator API (Chromium: Chrome/Edge + Lotus desktop app) — message text never leaves the device and never reaches any cloud translation service (Google/DeepL/Microsoft), so it works in **E2EE rooms** without weakening encryption. Target language in Settings → General (default English). Feature-detected — gracefully hidden where unsupported (Firefox/Safari/mobile) |
| **Desktop app (Tauri)** | `cinny-desktop` → `src-tauri/src/native/*.rs`, `src-tauri/src/lib.rs`; cinny `src/app/hooks/useTauri*.ts`, `src/app/components/TauriDesktopFeatures.tsx` | Tauri v2 native shell: rich WinRT toast notifications (click → open room, inline quick reply), Windows Focus Assist → DND sync, taskbar Jump List of recent rooms, taskbar thumbnail + volume-flyout call controls (mute/deafen/end), no-sleep during calls, network-change awareness (`mx.retryImmediately`), opt-in TDS window chrome, recursive folder drag-drop, auto-update toast. Windows-native pieces compile in CI (Gitea `windows` runner + GitHub `windows-latest`); detail in cinny `LOTUS_FEATURES.md` → Desktop App Features |
| **LiveKit codec config** | `/etc/livekit/config.yaml` (LXC 151) | `enabled_codecs`: VP8, H264, VP9, Opus, RED for better quality and redundancy |