Commit Graph

522 Commits

Author SHA1 Message Date
Timo e2bba04efd docs: update README language count to 15 (add zh, uk)
The localization section still listed 13 languages; Ukrainian (uk) and
Chinese Simplified (zh) were added in v2.4.3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 16:49:34 +02:00
GitHub Action c7b29c277c chore(release): update versions to v2.4.3 [skip ci] 2026-06-19 14:39:06 +00:00
Timo e06965b95c docs: add v2.4.3 entry to CHANGELOG.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v2.4.3
2026-06-19 16:38:49 +02:00
Timo 23d43741ce chore: replace Ko-Fi with Support links, drop uninstall token
Switch the Ko-Fi support links to https://support.koalastuff.net across the
README badge, the extension footer (popup.html/template.html, label
"Support KoalaSync") and remove the now-unused KOFI_URL constant. Stop
generating/sending the anonymous uninstall token: initUninstallURL() now
registers the feedback URL without the `t` parameter or storage write.
CHANGELOG updated to match.

Also guard the client CMD_ACK path: only ACK a command sender that is still
a known peer in the room, so we don't emit ACKs to peers that already left
(which the server now drops as absent-peer ACKs anyway).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 16:26:54 +02:00
Timo 027d2dbde5 fix(sync): coalesce play/pause bursts and quiet absent-peer ACK logs
Media players fire bursts of native play/pause events (source swaps, ABR,
ads, teardown). Each was relayed as a distinct command, spamming peers and
tripping the relay's event rate limit. Add leading+trailing coalescing in
the content script: emit the first event instantly (zero added latency) and,
on a 150ms window, collapse a burst to its final state. Echo-suppression and
seek-flush stay synchronous on event arrival; the trailing send is never
deduped against the leading one (a remote command may change shared state
mid-window — re-sending is the safe, idempotent choice).

Server: split the EVENT_ACK handler's logging so only a genuine different-room
ACK is logged as [SECURITY]; an ACK to a peer that already left is logged
quietly as [ACKDROP] (verbose-only), so real signals are no longer drowned out.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 16:26:31 +02:00
Timo a0c16df664 feat(i18n): add Ukrainian & Chinese, fix zh/uk translation quality
Add two new languages (uk, zh / zh_CN) across the extension and website:
register them in SUPPORTED_LANGUAGES, the Chrome _locales map, the website
build/lang-init/app routing, hreflang/og/schema tags and language selectors.

Fix systematic machine-translation word-sense errors in the new zh/uk
locales (e.g. zh "Status"=地位→状态, "Leave Room"=留出空间→离开房间,
"Play"=玩→播放, "Seek"=寻找→跳转, audio Attack/Release/Knee; uk "Play"=Грати
→Відтворити, "Clear"=ЯСНО→Очистити, "Open"=ВІДЧИНЕНО→Відкрити, peers
"Однолітки"→"Учасники"), translate remaining English leftovers (Room ID,
Custom) and normalise terminology. All 15 locales pass test-locales.cjs.

Note: popup.html and website/template.html also carry the language-selector
additions here; their Ko-Fi→Support label text is part of the branding change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 16:26:20 +02:00
KoalaDev 8fd866f20a feat(website): add canonicals, hreflangs, meta descriptions, and localized schema descriptions 2026-06-19 12:10:08 +02:00
KoalaDev 8f72c238a2 docs: add v2.4.2 entry to CHANGELOG.md 2026-06-19 11:58:06 +02:00
GitHub Action 24ad7c3732 chore(release): update versions to v2.4.2 [skip ci] 2026-06-19 09:54:42 +00:00
KoalaDev 32fd677a31 feat: optimize extension uninstall URL registration with anonymous token and startup hardening v2.4.2 2026-06-19 11:54:07 +02:00
KoalaDev fb22700268 docs: revert completed milestones in ROADMAP.md 2026-06-19 11:39:50 +02:00
KoalaDev 59b675ce17 docs: audit and update script references, supported languages, and completed milestones 2026-06-19 11:35:49 +02:00
KoalaDev 8a9293280b chore: harden version substitution in release workflow and fix supply chain security version in README 2026-06-19 11:12:48 +02:00
KoalaDev 450f715874 ci(release): update actions to Node 24 versions & optimize workflow
- Bump all actions off the deprecated Node 20 runtime: checkout v4->v7,
  upload-artifact v4->v7, setup-node added@v6, action-gh-release v1->v3,
  docker build-push v5->v7, login v3->v4, metadata v5->v6, buildx v3->v4
  (verified latest majors via GitHub API; no breaking input/output changes)
- Add npm dependency caching via setup-node (cache: npm)
- Add GHA layer caching for the multi-arch Docker build (cache-from/to gha)
- Add concurrency group so a release run is never interrupted, only dedupes
  re-pushes of the same tag
- Tighten release-server permissions to contents: read (it never writes to the repo)

Version-injection and commit-back logic unchanged. First exercised on the next v* tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 10:59:30 +02:00
GitHub Action b4c00f36a0 chore(release): update versions to v2.4.1 [skip ci] 2026-06-19 08:50:27 +00:00
KoalaDev 36f494fa55 feat(extension): one-click invite button in empty peer list + v2.4.1 changelog
- "No peers yet" state now shows a localized "Copy invite link" button (reuses BTN_COPY_INVITE, present in all 13 locales) so users can share without hunting for the field
- Add v2.4.1 changelog entry covering the onboarding tour improvements, empty-state action, and the mobile landing-page fixes from this session

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v2.4.1
2026-06-19 10:50:04 +02:00
KoalaDev b5b3885d19 feat(extension): finish onboarding tour with closing step & cleaner welcome
- Add the previously-orphaned 5th onboarding step (ONBOARDING_5) so the tour ends on a closing card instead of stopping at the username field
- Make step 1 a centered welcome card instead of spotlighting the logo; guard querySelector for target-less steps
- Fix stale static placeholders in popup.html (Step 1 of 3 -> 5, progress 33% -> 20%)

Verified ONBOARDING_5/DONE exist across all 13 locales; rendered with the longest (German) copy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 10:40:40 +02:00
KoalaDev 373f2d127a fix(website): mobile comparison cards, hamburger nav, hero symmetry & reveal fallback
- Comparison table: stack into per-feature cards on phones (no more horizontal scroll); bring feature descriptions back
- Re-enable mobile hamburger menu (was hidden via display:none !important); keep logo/language/button uncrowded down to ~320px
- Fix hero asymmetry: extension mockup forced the grid column wider than the container; make it width:100%/max-width:320px and use minmax(0,1fr)
- Add IntersectionObserver guards + <noscript> fallback so reveal-animated content never stays hidden

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 10:27:07 +02:00
KoalaDev 3ebe80aab2 refactor: replace dynamic GitHub API badges with static shields.io badges 2026-06-17 06:39:42 +02:00
Timo e7b59d61ac docs: update all docs for lazy-connect, refactor, and .cjs rename
- ARCHITECTURE.md: startup -> lazy connect, reconnect when in room
- HOW_IT_WORKS.md: on-demand connection, heartbeat while connected
- PRIVACY.md: clarify alarms only during active sessions
- SYNC_GUIDE.md: build-extension.cjs + episode-utils injection
- StoreDescription.md: on-demand relay, no persistent connection
- README.md + extension/README.md: npm run build:extension
- extension/README.md: replace Dual Heartbeat with On-Demand Connection
- website/privacy.html: add lazy-connect privacy note
2026-06-16 14:17:19 +02:00
GitHub Action 71f7ac425a chore(release): update versions to v2.4.0 [skip ci] 2026-06-16 12:00:03 +00:00
Timo 394b9ba474 Merge branch 'refactor/split-monoliths' v2.4.0 2026-06-16 13:58:32 +02:00
Timo 526736b045 fix(ci): update website build path to .cjs after rename 2026-06-16 13:54:57 +02:00
Timo 86112057b4 test: add names generator unit tests (getAvatarForName + generateUsername)
Tests: 20 deterministic avatar assertions (exact match, case insensitive,
longest-match-wins, ZWJ sequences, fallback), 30 randomized username format
checks, and validation that every noun in the list has an emoji mapping.
2026-06-16 13:53:19 +02:00
Timo c56fcfd281 test(server): add 13 WebSocket integration tests covering all server features
Tests: connect, room create/join, password auth, play/pause/seek relay,
force_sync, event_ack, episode_lobby, peer leave, ping/pong, room list,
protocol version check, deduplication, health HTTP endpoint.
All 13 tests pass as part of npm run verify.
2026-06-16 13:48:21 +02:00
Timo 5c43fc6236 docs: add v2.4.0 changelog entries for lazy-connect and refactor 2026-06-16 13:23:53 +02:00
Timo 101761e984 chore: add type:module, fix npm audit, rename CJS files, document module structure
- package.json: add type: module to silence ESM warnings
- server: npm audit fix (0 vulnerabilities, ws vuln resolved)
- Rename 4 CJS files to .cjs: build-extension, test-content-video-finder,
  test-locales, website/build
- Update eslint.config.mjs for .cjs glob patterns
- extension/README.md + server/README.md: document module structure
2026-06-16 13:22:45 +02:00
Timo 3bc68a5713 test: add unit tests for rate-limiter and episode-utils
- test-rate-limiter.mjs: 12 test groups covering all rate-limit
  functions, Maps, cleanup, and double-start guard
- test-episode-utils.mjs: 30+ assertions covering SxxExx patterns,
  6 separator types (dash/dot/slash/colon/comma/space), German/English,
  edge cases (null/undefined/empty), and sameEpisode matching logic
- verify-release.mjs: added 2 test suites + 1 syntax check to pipeline
2026-06-16 13:15:25 +02:00
Timo 6c96dd6344 chore(refactor): remove orphaned comment, add double-start guard to rate-limiter 2026-06-16 13:10:37 +02:00
Timo d7bb8dc97c refactor(extension): extract episode-utils from background.js + content.js
Move extractEpisodeId() and sameEpisode() to shared episode-utils.js.
background.js imports via ES module. content.js (IIFE) receives injected
copy via build-extension.js marker replacement, eliminating duplication.
2026-06-16 12:48:11 +02:00
Timo d38a840114 refactor(server): extract rate-limiter module from index.js
Move 6 rate-limit functions, all rate-limit Maps, cleanup intervals,
and denial counter to server/rate-limiter.js. 149 lines extracted.
Index.js re-exports what tests and ops.js need.
npm run verify passes.
2026-06-16 12:44:43 +02:00
Timo e7d2d76ba3 fix(eslint): add missing browser globals history and location 2026-06-16 10:50:40 +02:00
Timo 5277cd0f21 fix(eslint): add missing browser globals history and location 2026-06-16 10:50:32 +02:00
Timo 4d7cbfe347 Merge branch 'feature/lazy-connect' 2026-06-16 10:47:46 +02:00
Timo 91aa76e842 fix: revert premature isConnecting reset + remove popup disconnected flicker
- background.js: remove isConnecting=false at line 608 (was set before
  WebSocket handshake completed, defeating the guard for the entire
  CONNECTING phase). isConnecting is already properly reset in onclose,
  onopen/40 handler, catch block, and socket guard path.
- background.js: restore isConnecting=false in forceDisconnect() so
  subsequent connect() calls can proceed after intentional disconnect.
- popup.js: remove hardcoded applyConnectionStatus('disconnected') that
  caused a guaranteed red flicker on every popup open. Status is now
  set only by the async GET_STATUS response.
2026-06-16 10:44:57 +02:00
Timo 5f0a189451 fix(popup): trigger CONNECT when popup opens with saved roomId
If user has a room configured but the background is not connected
(e.g. service worker was killed, startup race, or stale state), the
popup now sends CONNECT on open. Previously it only called GET_STATUS
and showed 'disconnected' with 0 logs — the user had no way to know
whether the extension was working.
2026-06-16 10:35:13 +02:00
KoalaDev 312d4f2cf7 chore: update sitemap lastmod dates, automate in release CI
- Update all sitemap <lastmod> entries from 2026-06-09 to 2026-06-16.
- Add sed step in release workflow to auto-update sitemap dates on every
  tagged release, so the sitemap never goes stale.
2026-06-16 06:11:13 +02:00
KoalaDev 884feb982d fix(website): smooth anchor scrolling, language-switch scroll position, lang select UX
- Replace JS scrollIntoView handler with CSS scroll-behavior:smooth for
  native anchor navigation. Fixes #hash-based scroll position surviving
  language switches since the hash stays in the URL.
- Auto-update URL hash via IntersectionObserver as user scrolls through
  sections, so manual scrolling also sets the anchor for language switch.
- Preserve window.location.hash across all language-switch navigations.
- Fix Chrome double-arrow on language select by limiting appearance:base-select
  to ::picker(select) only, keeping the custom SVG chevron.
- Make chevron absolutely positioned over the select with pointer-events:none
  so clicks anywhere on the container open the dropdown.
- Remove max-width constraint on language select so longer names fit.
- Add scroll-margin-top to section[id] and header[id] so anchored sections
  clear the fixed navbar (100px offset).
- Add header[id] to scroll-margin-top for keyboard skip-link accessibility.

Thanks to Taradal from Reddit
2026-06-16 06:05:49 +02:00
KoalaDev b2da17ab62 fix(lazy-connect): harden connection lifecycle against race conditions and edge cases
- Prevent concurrent connect() by removing isConnecting reset from
  forceDisconnect(); the guard in connect() now reliably blocks
  re-entry since no external caller can defeat it.
- Reset isConnecting at end of connect() so subsequent calls can
  proceed without waiting for the async '40' handler.
- Clear connectIntent and cancel reconnect timer on server ERROR
  when no currentRoom exists, preventing infinite reconnect loops
  after failed join attempts (e.g. wrong password via invite link).
- Move connectIntent assignment after !roomId guard in
  WEB_JOIN_REQUEST to avoid clobbering existing intent on invalid
  input.
- Broadcast JOIN_STATUS failure to popup and bridge tabs when
  WEB_JOIN_REQUEST receives an invalid room ID, so the website
  join page receives feedback instead of hanging forever.
- Clear joinBtnTimeout on CONNECTION_STATUS connected/disconnected
  to avoid stale timeout error messages in the popup.
2026-06-16 05:39:17 +02:00
KoalaDev b518685e2c merge: bring main (v2.3.2) changes into lazy-connect 2026-06-16 04:59:13 +02:00
GitHub Action b7a7a14a35 chore(release): update versions to v2.3.2 [skip ci] 2026-06-16 02:29:41 +00:00
KoalaDev 9ee22d985f docs: remove transient _locales fix from changelog (never released) v2.3.2 2026-06-16 04:28:30 +02:00
KoalaDev 2070e701de docs: add v2.3.2 changelog entry (translations, locale fixes, timing leak) 2026-06-16 04:26:07 +02:00
KoalaDev dd8eefe3f9 fix(security): actually prevent timing leak — eagerly evaluate timingSafeEqual
The previous fix had a subtle bug: JavaScript && short-circuits,
so crypto.timingSafeEqual() was skipped when buffer lengths differed
(sameLength was false). The dummy buffer was allocated but never
compared, leaving the original length-based timing leak intact.

Now timingSafeEqual is eagerly assigned to a const before the &&
guard, guaranteeing it runs in constant time on every auth attempt
regardless of whether the length guess was correct.
2026-06-16 04:23:20 +02:00
KoalaDev cc97e0d371 fix(security): prevent admin token length leak via timing side-channel
isAdminMetricsAuthorized() returned early when buffer lengths differed,
allowing an attacker to discover the token length by measuring response
time. Now always calls crypto.timingSafeEqual (using a zeroed dummy
buffer on length mismatch) so every auth attempt takes constant time
regardless of whether the length guess was correct.

Reported-by: Kaia-Alenia
2026-06-16 04:21:15 +02:00
KoalaDev 7571f1986d fix: restore _locales key names, remove orphan pt/ dir, fix locale typos
- _locales/es, pt_BR: renamed appDescription → appDesc (Chrome matches by key name)
- _locales/es, pt_BR: removed extra key contextMenu_syncVideo not in baseline
- _locales/pt_PT: merged Kaia's improved translation, deleted orphan pt/ duplicate
- locales/ko: fixed BTN_REFRESH (Refreschi → 새로고침) and STATUS_CONNECTING corrupted char
- locales/ja: fixed Korean character (의 → の) in LABEL_PUBLIC_ROOMS_TOOLTIP
- locales/nl: fixed typo cmmuniceren → communiceren
2026-06-16 04:19:53 +02:00
KoalaDev bb1a88c085 Merge pull request #8 from Kaia-Alenia/feat/complete-spanish-translation
i18n: complete and refined Spanish translation for extension and website
2026-06-16 03:43:54 +02:00
Kaia-Alenia 07863bdad6 docs: credit Alenia Studios for PT and PT-BR translations 2026-06-15 13:10:55 -06:00
Kaia-Alenia 5e6306432f i18n: complete and refined Portuguese (PT and BR) translations 2026-06-15 13:10:35 -06:00
Kaia-Alenia fa5dfc1cf1 docs: credit Alenia Studios for ES and IT translations 2026-06-15 11:19:52 -06:00