Add 1:1 voice and video calling over the existing SAS-verified peer connection. Audio and video tracks ride the same RTCPeerConnection as the chat, bundled onto one DTLS-SRTP transport, so media inherits the session's end-to-end encryption. SDP offer/answer is renegotiated in-band over the verified data channel — no signalling server, so the media's DTLS fingerprints are authenticated end-to-end. Calls are gated on a connected, SAS-verified session. Codecs & adaptation: - Opus tuned for lossy links (in-band FEC, DTX, RED redundancy); audio is bandwidth-prioritised and never throttled. - VP9/AV1 single-encoding SVC with H.264/VP8 fallback; video degrades by spatial/temporal layer. - Runtime NetworkAdaptationController trims video bitrate on loss/RTT and recovers as the link clears — no renegotiation. Live connection-quality indicator (Excellent/Good/Fair/Weak) in the call UI. In-call controls: mute, camera on/off (voice→video upgrade in-band), camera flip, minimize-to-widget, hang up, and accept/decline for incoming calls. Production logging disabled (DEBUG_MODE=false); temporary call diagnostic logger removed. Codec rationale in docs/webrtc-config.md.
204 lines
6.5 KiB
ApacheConf
204 lines
6.5 KiB
ApacheConf
# SecureBit.chat - Apache Configuration
|
|
# Comprehensive caching configuration for forced updates
|
|
|
|
# ============================================
|
|
# MIME TYPES - MUST BE FIRST (before other rules)
|
|
# ============================================
|
|
# Critical: Set MIME types BEFORE any other rules to ensure correct Content-Type headers
|
|
<IfModule mod_mime.c>
|
|
# JavaScript modules - explicit order matters
|
|
AddType application/javascript .jsx
|
|
AddType application/javascript .mjs
|
|
AddType application/javascript .js
|
|
AddType application/json .json
|
|
|
|
# Fonts
|
|
AddType font/woff .woff
|
|
AddType font/woff2 .woff2
|
|
AddType application/font-woff .woff
|
|
AddType application/font-woff2 .woff2
|
|
|
|
# Service Worker
|
|
AddType application/manifest+json .webmanifest
|
|
</IfModule>
|
|
|
|
# Force Content-Type headers (override any server defaults)
|
|
<IfModule mod_headers.c>
|
|
# All JavaScript files including JSX - CRITICAL for ES modules
|
|
<FilesMatch "\.(js|mjs|jsx)$">
|
|
Header always set Content-Type "application/javascript; charset=utf-8"
|
|
</FilesMatch>
|
|
</IfModule>
|
|
|
|
# Enable mod_rewrite
|
|
<IfModule mod_rewrite.c>
|
|
RewriteEngine On
|
|
RewriteBase /
|
|
</IfModule>
|
|
|
|
# ============================================
|
|
# CRITICAL FILES - NO CACHING
|
|
# ============================================
|
|
|
|
# meta.json - versioning file (never cache)
|
|
<FilesMatch "meta\.json$">
|
|
<IfModule mod_headers.c>
|
|
Header set Cache-Control "no-cache, no-store, must-revalidate, max-age=0"
|
|
Header set Pragma "no-cache"
|
|
Header set Expires "0"
|
|
Header set X-Content-Type-Options "nosniff"
|
|
</IfModule>
|
|
</FilesMatch>
|
|
|
|
# HTML files - always fresh
|
|
<FilesMatch "\.(html|htm)$">
|
|
<IfModule mod_headers.c>
|
|
Header set Cache-Control "no-cache, no-store, must-revalidate, max-age=0"
|
|
Header set Pragma "no-cache"
|
|
Header set Expires "0"
|
|
# Remove ETag for validation
|
|
Header unset ETag
|
|
FileETag None
|
|
</IfModule>
|
|
</FilesMatch>
|
|
|
|
# Service Worker - no cache
|
|
<FilesMatch "sw\.js$">
|
|
<IfModule mod_headers.c>
|
|
Header set Cache-Control "no-cache, no-store, must-revalidate, max-age=0"
|
|
Header set Pragma "no-cache"
|
|
Header set Expires "0"
|
|
Header set Service-Worker-Allowed "/"
|
|
</IfModule>
|
|
</FilesMatch>
|
|
|
|
# manifest.json - no cache
|
|
<FilesMatch "manifest\.json$">
|
|
<IfModule mod_headers.c>
|
|
Header set Cache-Control "no-cache, no-store, must-revalidate, max-age=0"
|
|
Header set Pragma "no-cache"
|
|
Header set Expires "0"
|
|
</IfModule>
|
|
</FilesMatch>
|
|
|
|
# ============================================
|
|
# STATIC RESOURCES - AGGRESSIVE CACHING
|
|
# ============================================
|
|
|
|
# JavaScript files in dist/ - no cache (for updates)
|
|
<FilesMatch "^dist/.*\.(js|mjs)$">
|
|
<IfModule mod_headers.c>
|
|
Header set Cache-Control "no-cache, no-store, must-revalidate, max-age=0"
|
|
Header set Pragma "no-cache"
|
|
Header set Expires "0"
|
|
Header set X-Content-Type-Options "nosniff"
|
|
</IfModule>
|
|
</FilesMatch>
|
|
|
|
# JavaScript files with hashes in other locations - long cache
|
|
<FilesMatch "\.(js|mjs)$">
|
|
<IfModule mod_headers.c>
|
|
# Files with hashes in name - cache for one year
|
|
Header set Cache-Control "public, max-age=31536000, immutable"
|
|
Header set X-Content-Type-Options "nosniff"
|
|
</IfModule>
|
|
</FilesMatch>
|
|
|
|
# CSS files - long cache
|
|
<FilesMatch "\.css$">
|
|
<IfModule mod_headers.c>
|
|
Header set Cache-Control "public, max-age=31536000, immutable"
|
|
</IfModule>
|
|
</FilesMatch>
|
|
|
|
# Images - long cache
|
|
<FilesMatch "\.(jpg|jpeg|png|gif|webp|svg|ico)$">
|
|
<IfModule mod_headers.c>
|
|
Header set Cache-Control "public, max-age=31536000, immutable"
|
|
</IfModule>
|
|
</FilesMatch>
|
|
|
|
# Fonts - long cache
|
|
<FilesMatch "\.(woff|woff2|ttf|otf|eot)$">
|
|
<IfModule mod_headers.c>
|
|
Header set Cache-Control "public, max-age=31536000, immutable"
|
|
Header set Access-Control-Allow-Origin "*"
|
|
</IfModule>
|
|
</FilesMatch>
|
|
|
|
# Audio/Video - long cache
|
|
<FilesMatch "\.(mp3|mp4|webm|ogg)$">
|
|
<IfModule mod_headers.c>
|
|
Header set Cache-Control "public, max-age=31536000, immutable"
|
|
</IfModule>
|
|
</FilesMatch>
|
|
|
|
# ============================================
|
|
# SECURITY
|
|
# ============================================
|
|
|
|
# XSS Protection
|
|
<IfModule mod_headers.c>
|
|
Header set X-XSS-Protection "1; mode=block"
|
|
Header set X-Content-Type-Options "nosniff"
|
|
Header set Referrer-Policy "strict-origin-when-cross-origin"
|
|
Header set X-Frame-Options "DENY"
|
|
# Force HTTPS (2 years + preload) to close the first-visit SSL-strip window.
|
|
Header set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
|
|
# Restrict powerful features; camera + microphone kept for QR scanning and calls.
|
|
Header set Permissions-Policy "camera=(self), microphone=(self), geolocation=(), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=()"
|
|
</IfModule>
|
|
|
|
# Content Security Policy (frame-ancestors and report-uri only work in HTTP headers, not meta tags)
|
|
<IfModule mod_headers.c>
|
|
Header set Content-Security-Policy "frame-ancestors 'none'; report-uri /csp-report; report-to csp-endpoint;"
|
|
</IfModule>
|
|
|
|
# ============================================
|
|
# GZIP COMPRESSION
|
|
# ============================================
|
|
|
|
<IfModule mod_deflate.c>
|
|
# Compress text files
|
|
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json application/xml
|
|
|
|
# Compress fonts
|
|
AddOutputFilterByType DEFLATE font/woff font/woff2 application/font-woff application/font-woff2
|
|
</IfModule>
|
|
|
|
|
|
# ============================================
|
|
# CLOUDFLARE RULES
|
|
# ============================================
|
|
|
|
# Cloudflare can cache static files, but should not cache:
|
|
# - meta.json
|
|
# - index.html
|
|
# - sw.js
|
|
# - manifest.json
|
|
|
|
# These rules are applied at Cloudflare Page Rules level
|
|
# (see CLOUDFLARE_SETUP.md documentation)
|
|
|
|
# ============================================
|
|
# SPA FALLBACK
|
|
# ============================================
|
|
|
|
# If file not found, redirect to index.html (for SPA routing)
|
|
<IfModule mod_rewrite.c>
|
|
RewriteCond %{REQUEST_FILENAME} !-f
|
|
RewriteCond %{REQUEST_FILENAME} !-d
|
|
RewriteCond %{REQUEST_URI} !^/meta\.json$
|
|
RewriteCond %{REQUEST_URI} !^/sw\.js$
|
|
RewriteCond %{REQUEST_URI} !^/manifest\.json$
|
|
RewriteRule ^(.*)$ /index.html [L]
|
|
</IfModule>
|
|
|
|
# ============================================
|
|
# LOGGING (optional)
|
|
# ============================================
|
|
|
|
# Uncomment for debugging
|
|
# LogLevel rewrite:trace3
|
|
|