# KoalaSync Changelog All notable changes to the KoalaSync browser extension and relay server. --- ## [v3.0.0] — 2026-07-26 ### Added - **Extension: Optional encrypted room chat** — Rooms now support live-only, end-to-end encrypted text messages. Chat is disabled and hidden by default and can be enabled explicitly in the extension options. - **Extension: Persistent room chat key** — Every room generates and retains a chat key even while chat is disabled, so chat can be enabled later without creating a new room. - **Extension: Floating player chat** — When enabled, chat is available from a floating control over the selected player and opens in an overlay without replacing the synchronized video. - **Extension: Dedicated chat settings** — Chat now has its own settings section for enablement, left/right/free-floating placement, compact/standard/large/custom sizing, and bubble-versus-open startup behavior. ### Security - **Ciphertext-only relay** — The relay receives and forwards encrypted message payloads without storing chat history or accepting client-supplied plaintext, sender identities, timestamps, or message IDs as authoritative. - **Backward-compatible rollout** — Versioned `chat-v1` capabilities ensure old non-chat extensions never receive unknown chat events, while current extensions continue to work with older chatless relay versions. ### Changed - **Build dependencies** — Updated the supported build and validation toolchain and refreshed compatible transitive dependencies. - **Relay container runtime** — Moved the production container from end-of-life Node.js 20 to Node.js 24 LTS and made production dependency installation deterministic with `npm ci --omit=dev`. ## [v2.6.4] — 2026-07-16 ### Changed - **Extension: Localized store metadata** — Renamed the public extension title to `Watch Party - KoalaSync` and added natural, store-ready descriptions for all 15 supported locales while preserving regional language variants. - **Extension: Locale-based manifest metadata** — The extension name and description now resolve through Chrome/Firefox `_locales` messages instead of being hardcoded in the manifest. ### Fixed - **Build: Extension metadata validation** — Extension builds now fail clearly for invalid locale JSON, missing metadata, an incorrect extension title, or store titles and descriptions that exceed their character limits. ## [v2.6.3] — 2026-07-15 ### Fixed - **Extension: Host-access recovery races** — Prevents stale permission grants, reinjection retries, closed tabs, and rapid target changes from reactivating or clearing the wrong video tab. - **Extension: Cross-browser host patterns** — Uses Firefox-compatible match patterns for local servers while preserving exact Chromium port scopes. - **Extension: Force-sync target integrity** — Keeps sampled playback time and acknowledgements bound to the selected tab during recovery and target changes. ## [v2.6.2] — 2026-07-15 ### Added - **Website: Site-access recovery guide** — Added an English help page and a localized banner across every landing-page language. ### Fixed - **Extension: Withheld website access recovery** — Detects browser-withheld host access, shows a localized allow-access action, requests only the selected website origin, and resumes the selected tab after access is granted. - **Extension: Target-tab reliability** — Hardened permission recovery against rapid tab changes, navigation, closed tabs, service-worker restoration, and stale pending state. - **Browser compatibility** — Uses Chrome's toolbar access request only when available, with a direct user-gesture permission fallback for Firefox and older Chromium browsers. --- ## [v2.6.1] — 2026-07-15 ### Fixed - **Extension: Episode Lobby peer list** — Peer names in the lobby are now rendered as text instead of markup. A peer could previously put HTML in their username and have it rendered in everyone else's popup, which allowed loading remote images (leaking viewer IP addresses) and spoofing the readiness badges. Scripts were already blocked by the extension's content security policy. ### Changed - **Release checks: AMO validation** — `npm run verify` now runs Mozilla's `addons-linter` against the built Firefox artifact with `--warnings-as-errors`, and ESLint enforces `no-unsanitized`, so upload-blocking issues surface locally instead of at submission time. --- ## [v2.6.0] — 2026-07-15 ### Added - **Extension: Appearance controls** — Added localized system, light, and dark theme options with an early theme initializer to avoid flashes during popup startup. ### Changed - **Extension: Popup and settings redesign** — Unified controls, status surfaces, colors, icons, badges, and accessibility behavior; settings are now organized into mutually exclusive accordion groups. ### Fixed - **Extension: Episode Lobby reliability** — Prevented the lobby from remaining stuck in a loading state and stopped episode transitions from triggering on non-episodic media. - **Extension: Tab-title normalization** — Notification counters such as `(14)`, `[7]`, and `(99+)` are removed reliably without stripping legitimate large numeric titles. --- ## [v2.5.4] — 2026-07-08 ### Changed - **Extension: Refined clutter blacklist** — Removed `localhost` and cloud storage providers (`drive.google.com`, `dropbox.com`, `onedrive.live.com`, `icloud.com`) from the domains blacklist so that local web development servers and tabs hosting video files in cloud storage are no longer hidden under "Hide Clutter Tabs". --- ## [v2.5.3] — 2026-07-02 ### Fixed - **Extension: Disney+ force sync and seeking** — Fixed force sync on Disney+ failing or jumping to wrong positions. The extension now relies solely on accurate player-API time and fails cleanly when it isn't available yet, instead of falling back to unreliable raw video data. - **Extension: Force-sync accuracy** — When syncing to the group, peers whose current position isn't known yet (e.g. a Disney+ peer that just loaded) no longer pull the sync target toward the start of the video. - **Extension: Disney+ Host Control Mode** — Regular Disney+ content is no longer misclassified as a live stream, which had silently disabled the desync dialog and snap-back for guests in host-controlled rooms. YouTube and Twitch live detection is unchanged. - **Extension: Disney+ episode auto-sync** — Episode transitions and the "waiting for peers" lobby flow now work reliably on Disney+ again. --- ## [v2.5.2] — 2026-07-02 ### Added - **Extension: Privacy title controls** - Advanced users can now disable sending browser tab titles separately from media titles. Media titles can still be sent in full, reduced to detected episode identifiers such as `S01E04`, or hidden entirely. Defaults remain full titles for backwards compatibility. - **Relay: Cleaner restart handling** — Connected clients are now disconnected explicitly during relay shutdown so reconnects recover more predictably. - **Relay: Stronger abuse protection** — Rapid room-leave spam is now rate-limited. - **Extension: Hidden remote seek diagnostics** — KoalaDev can use the hidden Dev tab to simulate remote seeks and inspect precise native/page-API timing while debugging playback integrations. ### Changed - **Extension: Shared page-API seek bridge** — Netflix and Disney+ now use a common page-level seek bridge so private player APIs can be invoked from the page context while the default HTML5 path stays unchanged. - **Build: Release build timestamp** — Extension builds now inject a build timestamp into the hidden Dev tab for easier local package verification. ### Fixed - **Extension: Disney+ precise sync** — Disney+ now reads time and seeks through the real page media-player API, and the temporary DOM timeline/button scraping fallback has been removed. - **Extension: Netflix seek reliability** — Netflix seeking keeps using the page player API with a safer session lookup path. - **Extension: Tab-title counter cleanup** — Leading browser notification counters such as `(14)` or `[7]` are removed from shared tab titles and matching logic without changing the existing privacy controls. - **Extension: Tab navigation reinjection** — Reinjecting the content script after selected-tab navigation now uses the same page-API-aware injection path. --- ## [v2.5.0] — 2026-06-29 ### Added - **Extension + Relay: Host Control Mode** — Room owners can now switch a room between open playback control and host-controlled playback. In host-only mode, guests stay synchronized but their local play, pause, and seek actions are not rebroadcast to the room. - **Backward-compatible Host Control rollout** — The extension only shows Host Control when the connected relay supports it, so users on older self-hosted servers do not see controls that cannot work yet. - **Extension: Clear host and guest states** — The popup shows the current control mode, host status, peer roles, and localized guest guidance so participants understand when playback is controlled by the host. - **Website: FAQ clarification for streaming access** — The landing page and FAQ structured data now state clearly that KoalaSync does not stream, host, share, or bypass access to video content. Every participant watches locally and needs their own access to services such as Netflix. ### Changed - **Playback sync now follows the room's control setting** — When Host Control is enabled, only the host can drive room-wide playback changes; guests can still watch in sync without accidentally changing playback for everyone. --- ## [v2.4.6] — 2026-06-23 ### Fixed - **Room and settings are no longer stored in `chrome.storage.sync`** — Room ID, password, and username were being resurrected from synced storage on a fresh install (sync survives an uninstall in the user's Google account), which made the extension silently auto-connect to a dead room and appear permanently connected. `getSettings()` and all settings reads are now local-only, and legacy keys are actively purged from sync on install/update/startup. Only `onboardingComplete` and `dismissedHints` remain in sync. - **No server traffic while alone in a room** — When you are the only peer, heartbeats, force-sync, and episode auto-sync are now fully suppressed (previously the keepAlive heartbeat, force-sync, and episode lobby were still broadcast to an empty room). The solo state is re-evaluated live on every event — never cached — so the instant another peer joins, syncing resumes immediately, including an instant state push so the newcomer sees your current position without waiting for the next heartbeat. ## [v2.4.4] — 2026-06-23 ### Changed - **Server: Event rate limit raised 30 → 50 per 10s**, and all connection/event/health rate-limit thresholds and windows extracted into named constants. - **Extension: Reconnect backoff tuned and jittered** — capped at ~8 attempts/60s (under the per-IP connection limit) with ±20% jitter to de-synchronize reconnect herds after a server blip. - **CI: Added a verification workflow** running lint, tests, audits, and builds on every push/PR; the release build now uses `npm ci`. ### Fixed - **Extension: Offline event-queue flush is now paced** (small batches instead of one synchronous burst) so a reconnect after a long outage no longer trips the server event limit and gets disconnected on rejoin. - **Extension: Ping liveness tolerates one missed PONG** — a reconnect is forced only after 2 consecutive misses (~20s) instead of a single 5s timeout, avoiding spurious drops under transient load. - **Extension: `socket.send()` failures are caught and re-queued** instead of losing the event on a disconnect race. ## [v2.4.3] — 2026-06-19 ### Added - **Two new languages: Ukrainian (`uk`) and Chinese (`zh`, Simplified)** — added across the extension (UI strings + Chrome `_locales`) and the website (localized pages, hreflang/Open Graph/schema tags, language selector), bringing the total to 15 languages. ### Changed - **Play/pause sync coalescing** — The content script now collapses rapid bursts of native play/pause events (source swaps, ABR/quality switches, ad transitions, page teardown) into a single relayed command: the first event is sent instantly and a short 150ms window absorbs the rest. This cuts redundant relay traffic and stops bursts from tripping the server's per-socket event rate limit. ### Fixed - **zh/uk translation quality** — Corrected systematic machine-translation word-sense errors in the two new locales (e.g. "Play", "Status", "Leave Room", "Clear", "Open", "peers", and audio compressor terms) and translated the remaining English leftovers. - **Relay logging** — An `EVENT_ACK` aimed at a peer that already left is now logged quietly instead of as a `[SECURITY]` cross-room event, so genuine cross-room attempts stand out in the logs. ## [v2.4.2] — 2026-06-19 ### Changed - **Extension: Optimized uninstall URL registration** — Extracted registration into a reusable, race-condition-protected `initUninstallURL()` helper. It registers the uninstall feedback URL with browser context on both extension installation/update and browser startup to prevent state loss, without storing or sending an installation token. ## [v2.4.1] — 2026-06-19 ### Added - **Extension: Onboarding tour now has a closing step** — The first-run tour ends on a dedicated "You're all set!" card (the `ONBOARDING_5` copy that already existed in all 13 locales but was never shown). The tour no longer stops abruptly on the username step. - **Extension: One-click invite from the empty peer list** — The "No peers yet" state now shows a **📋 Invite Link** button that copies the invite link to the clipboard, so users can share it without hunting for the field. ### Changed - **Extension: Cleaner onboarding welcome** — Step 1 is now a centered welcome card instead of spotlighting the logo title. Added a guard so target-less tour steps center cleanly. - **Website: Mobile comparison table** — The KoalaSync vs Teleparty table stacks into per-feature cards on phones instead of forcing horizontal scrolling; feature descriptions are shown again on mobile. ### Fixed - **Extension: Onboarding step counter/progress placeholders** — Static `Step 1 of 3` / 33% fallbacks in `popup.html` corrected to match the actual 5-step tour (`Step 1 of 5` / 20%). - **Website: Mobile navigation restored** — The header hamburger menu was hidden by a `display:none !important` rule, leaving the nav links unreachable on phones. Re-enabled, with spacing kept comfortable down to ~320px. - **Website: Hero alignment on mobile** — A fixed-width extension mockup forced the hero grid column wider than the container, shifting all hero content off-center (larger left margin than right). The mockup is now responsive (`width:100%/max-width` + `minmax(0,1fr)` grid track). - **Website: Reveal-animation fallback** — Added a `