docs: complete repository documentation update for v1.0.0-RC5 features

This commit is contained in:
Timo
2026-04-22 11:54:54 +02:00
parent 830f8c44b1
commit 1d2237aab6
5 changed files with 117 additions and 148 deletions
+32 -60
View File
@@ -3,85 +3,57 @@
Welcome to the KoalaSync project. This file is the primary entry point for any developer or AI agent working on this codebase. It defines the architecture, non-negotiables, and workflows required to maintain the stability and security of the system.
> [!IMPORTANT]
> **Privacy & Data Sovereignty**: KoalaSync follows a strict **Zero-External-Requests Policy**: The extension and website must not make requests to any third-party domains (Google Fonts, CDNs, etc.). All assets (fonts, icons, scripts) must be self-hosted or use system defaults.
> - **Font Stack**: Use a modern system font stack (e.g., -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif) to maintain a premium look without external dependencies. Prohibit the use of `@import` or `<link>` for external font services.
> **Privacy & Data Sovereignty**: KoalaSync follows a strict **Zero-External-Requests Policy**: The extension and website must not make requests to any third-party domains. All assets must be self-hosted.
> - **Font Stack**: Use a modern system font stack to maintain a premium look without external dependencies.
---
## 1. Project Overview
KoalaSync is a specialized tool for **synchronized video playback** across multiple remote peers. It supports YouTube, Twitch, and native HTML5 video elements.
- **Users**: Friends or groups wanting to watch synchronized content together.
- **Workflow**: A user creates a room, shares an invite link (RoomID#Password), and all peers in that room are synchronized via a Node.js relay server.
KoalaSync is a specialized tool for **synchronized video playback** across multiple remote peers.
- **Workflow**: A user creates a room, shares an invitation link, and all peers are synchronized via a Node.js relay server.
- **Identity**: Users are identified by a unique hex `peerId` combined with a customizable `username`.
## 2. Repository Structure
- `extension/`: Chrome Extension (Manifest V3). Contains background service worker, content scripts, and popup UI.
- `extension/`: Chrome Extension (Manifest V3).
- `server/`: Node.js Relay Server using Socket.IO (WebSocket-only).
- `website/`: **Landing Page** (Marketing, Tutorials, and Downloads).
- `shared/`: **Single Source of Truth** for protocol constants and event names.
- `scripts/`: Utility scripts (e.g., `sync-constants.sh`).
- `docker-compose.yml`: Root-level orchestration for the relay server.
> [!IMPORTANT]
> `shared/constants.js` and `shared/blacklist.js` must be synchronized to the `extension/shared/` directory after every modification by running `./scripts/sync-constants.sh`.
- `website/`: Landing Page & Invitation Bridge.
- `shared/`: Single Source of Truth for protocol constants and event names.
## 3. Mandatory Reading
Before touching any code, you MUST read the following documents in order:
1. [ARCHITECTURE.md](ARCHITECTURE.md) Detailed communication flows and two-phase sync protocol.
2. [shared/README.md](shared/README.md) Protocol constants and synchronization requirements.
3. [extension/README.md](extension/README.md) Extension components and loading process.
4. [server/README.md](server/README.md) Server setup, Docker configuration, and security.
1. [ARCHITECTURE.md](ARCHITECTURE.md) Communication flows and Dual Heartbeat protocol.
2. [extension/README.md](extension/README.md) UI structure and component overview.
## 4. Design Guidelines
The popup UI follows a strict design system. Do not modify these variables or the layout structure without explicit approval.
- **Font**: System font stack (e.g., `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif`). **MANDATORY**: No external CDNs or Google Fonts to ensure 100% privacy.
- **Popup Width**: Fixed at `320px`.
- **Tab Structure**: Must maintain the **Room**, **Sync**, and **Dev** tabs.
- **CSS Variables**:
| Variable | Value | Purpose |
| :--- | :--- | :--- |
| `--bg` | `#0f172a` | Main background |
| `--card` | `#1e293b` | Form and info cards |
| `--accent` | `#6366f1` | Primary actions and branding |
| `--success` | `#22c55e` | Success states / Online dot |
| `--error` | `#ef4444` | Errors / Offline dot |
- **Tab Structure**: **Room**, **Sync**, **Settings**, and **Dev**.
- **CSS Variables**: Uses the CSS variables defined in `popup.html` for a consistent Dark Mode / Glassmorphic look.
## 5. Non-Negotiables (Core Logic)
The following features are critical and must not be removed or fundamentally altered:
- **Two-Phase Force Sync**: The `Prepare``ACK``Execute` flow ensures all peers are buffered before playback resumes.
- **Platform Specifics**: Specialized click-logic for YouTube (`.ytp-play-button`) and Twitch play/pause buttons in `content.js`.
- **pollSeekReady()**: The polling mechanism that checks `video.readyState` and `currentTime` offset before acknowledging a sync command.
- **SW Keep-alive**: Use of `chrome.alarms` to prevent the Manifest V3 Service Worker from suspending.
- **Exponential Backoff**: Reconnection logic in `background.js` (1s → 30s max).
- **Rate Limiting**: IP-based connection limits (10/min) and socket-based event limits (30/10s) on the server.
- **Security**: Token validation during the initial WebSocket handshake.
- **Persistence**: `peerId` must be stored in `chrome.storage.local` to remain stable across sessions.
- **Two-Phase Force Sync**: `Prepare``ACK``Execute` flow for frame-perfect sync.
- **Dual Heartbeat**:
- **Background Heartbeat (30s)**: Keeps the session alive even without a video.
- **Content Heartbeat (15s)**: Transmits current video metadata (title, time).
- **Dead Peer Pruning**: Server automatically disconnects peers after 5 minutes of total silence.
- **Deduplication**: Server kills old sockets if a user re-joins with the same `peerId`.
- **Diagnostics**: The "Dev" tab provides real-time access to the underlying `<video>` state for troubleshooting.
## 6. Technical Constraints
- **No Bundler**: The extension uses plain ES Modules. Do not introduce build steps or npm packages into the `extension/` folder.
- **Manual Protocol**: `background.js` implements a subset of the Socket.IO wire protocol (e.g., `42[...]` framing) to work with native WebSockets.
- **Server Transport**: Restricted to `websocket` only. Polling is disabled.
- **Docker Context**: The Docker build must run from the **Repo Root**, as it needs access to the `shared/` directory.
- **Manifest Settings**: `run_at` must remain `document_idle`, and `all_frames` must remain `false`.
- **No Bundler**: Plain ES Modules only.
- **Socket.IO Protocol**: Manual implementation of the wire protocol in `background.js`.
- **Docker Context**: Must build from the **Repo Root**.
## 7. Security & Deployment
- **Tokens**: `OFFICIAL_SERVER_TOKEN` and `OFFICIAL_SERVER_URL` are intentionally hardcoded in `constants.js` by design.
- **Environment**: `.env` is excluded via `.gitignore`. Only `.env.example` should be committed.
- **Revocation**: `MIN_VERSION` in the server configuration is the only way to deprecate old extension versions.
- **Token Rotation**: Requires updating `shared/constants.js`, running the sync script, incrementing the extension version, and re-deploying the server.
- **Invitation Links**: Correctly propagate server URLs and room credentials via the URL hash.
- **Rate Limiting**: IP and socket-based limits are enforced server-side.
- **Persistence**: `peerId` and `username` must persist across browser sessions.
## 8. Common Workflows
### Adding a Protocol Event
1. Add the event name to `shared/constants.js`.
2. Run `./scripts/sync-constants.sh`.
3. Implement the handler in `server/index.js` and `background.js`.
### Modifying the Protocol
1. Edit `shared/constants.js`.
2. Run `scripts/sync-constants.bat` (Windows) or `scripts/sync-constants.sh` (POSIX).
3. Restart the server and reload the extension.
### Testing Locally
1. Load `extension/` as an "Unpacked Extension" in Chrome.
2. Start the server from the root: `docker-compose up --build`.
3. Select "Custom" server in the popup and enter `ws://localhost:3000`.
### Locking Old Versions
1. Increase `APP_VERSION` in `shared/constants.js`.
2. Update `MIN_VERSION` in the server's `.env` file.
3. Restart the server.
### Testing
- Use **different browser profiles** or vendors to test multi-peer logic locally.
- Use the **Dev tab** to verify that the extension is correctly detecting the video state.
+29 -43
View File
@@ -3,54 +3,40 @@
This document describes the communication flows and internal logic of the KoalaSync system.
## 1. Extension Startup & Connection
- **Initialization**: On startup, `background.js` reads settings (Server URL, Last Room) from `chrome.storage.sync`.
- **Initialization**: On startup, `background.js` reads settings (Server URL, Username, Last Room) from `chrome.storage.sync`.
- **WebSocket Handshake**:
1. Background creates a `new WebSocket` to `/socket.io/?EIO=4&transport=websocket&version=1.0.0&token=...`.
1. Background creates a `new WebSocket` to `/socket.io/?EIO=4&transport=websocket&version=1.0.0`.
2. Server performs security checks:
- **IP Rate Limit**: Checks if the IP has exceeded 10 connections/min.
- **Auth Token**: If a server token is required, it must match.
- **Version Check**: Client version must be `>= MIN_VERSION`.
3. Server responds with an Engine.IO handshake (packet type `0`).
4. Background sends `40` to join the default Socket.IO namespace.
5. Server responds with `40`.
- **Room Join**: If a Room ID is stored, Background emits `42["join_room", {...}]`.
- **Reconnect Logic**: If the connection drops, Background uses an exponential backoff (1s, 2s, 4s... max 30s) to reconnect.
- **IP Rate Limit**: Checks if the IP has exceeded connection limits.
- **Protocol Version**: Client must match the server's protocol (currently `1.0.0`).
3. Server responds with Engine.IO handshake (`0`) and the client joins the namespace (`40`).
- **Room Join**: Background emits `JOIN_ROOM` containing `roomId`, `password`, `peerId`, and `username`.
- **Deduplication**: If a user joins with a `peerId` that already has an active socket, the server kills the old socket to prevent "Ghost Peers".
## 2. Media Event Synchronization
When a user presses Play/Pause in a synchronized tab:
1. **Detection**: `content.js` listens to native `play`/`pause` events on the `<video>` element.
2. **Reporting**: `content.js` sends a `CONTENT_EVENT` message to `background.js`.
3. **Emission**: `background.js` emits `42["play"|"pause", {...}]` to the server.
4. **Relay**: The Server forwards the event to all other sockets in the same room.
5. **Reception**: Other Extensions receive the event via WebSocket.
6. **Execution**: `background.js` sends a `SERVER_COMMAND` to its `content.js`.
7. **Control**: `content.js` calls `video.play()` or `video.pause()`.
- *Note*: It uses `isProcessingCommand` to prevent feedback loops.
When a user interacts with a video:
1. **Detection**: `content.js` listens to native events (`play`, `pause`, `seeked`) on the `<video>` element.
2. **Prevention of Loops**: Uses `lastTargetState` to distinguish between user actions and programmatic actions triggered by the extension.
3. **Reporting**: `content.js` sends a `CONTENT_EVENT` to `background.js`.
4. **Relay**: The Server forwards the event to all other peers in the room.
5. **Execution**: Remote peers receive the command and call `video.play()`, `video.pause()`, or `video.currentTime = targetTime`.
## 3. Two-Phase Force Sync
This protocol ensures all peers are paused and buffered at the exact same timestamp before resuming playback.
1. **Initiation**: User clicks "Force Sync" in the popup.
2. **Preparation**:
- Popup asks Content Script for the current time.
- Background emits `FORCE_SYNC_PREPARE` with `targetTime`.
3. **Coordination**:
- Peers receive `PREPARE`, `content.js` pauses and seeks.
- Once `video.readyState >= 3` (buffered), `content.js` sends `FORCE_SYNC_ACK`.
- Background forwards ACK to the Initiator via Server.
4. **Execution**:
- Initiator collects ACKs. Once all peers have responded (or 5s timeout), Initiator emits `FORCE_SYNC_EXECUTE`.
- All peers receive `EXECUTE` and call `video.play()`.
Ensures all peers are frame-perfect and buffered before resuming:
1. **Prepare**: Initiator sends `FORCE_SYNC_PREPARE` with the target timestamp.
2. **Buffer**: Peers seek and pause. Once buffered (`readyState >= 3`), they send a `FORCE_SYNC_ACK`.
3. **Execute**: Once the Initiator collects ACKs (or after a 5s timeout), they send `FORCE_SYNC_EXECUTE`.
4. **Resume**: All peers call `play()` simultaneously.
## 4. Peer Lifecycle
- **Join**: Server sends `ROOM_DATA` to the joiner and `PEER_STATUS (joined)` to others.
- **Leave**:
- **Manual**: User clicks "Leave". Popup sends `LEAVE_ROOM` to Background -> Server.
- **Pruning**: If a socket disconnects, the Server automatically broadcasts `PEER_STATUS (left)` and deletes the room if empty.
- **Heartbeat**: `content.js` sends a status heartbeat every 15s to keep the peer list updated with current playback states.
## 4. Peer Lifecycle & Dual Heartbeat
To maintain a clean room state and eliminate "Ghost Peers":
- **Session Heartbeat (Background)**: Every 30 seconds, `background.js` sends an "I'm alive" signal to the server. This keeps you in the room even if no video is playing.
- **Video Heartbeat (Content)**: Every 15 seconds, `content.js` sends current playback metadata (time, title, state) if a video is found.
- **Server Pruning**: The server runs a "Reaper" every 2 minutes. If a peer has sent **zero** activity (no events and no heartbeats) for 5 minutes, they are forcefully disconnected.
- **Immediate Cleanup**: Rooms are deleted instantly when the last peer leaves or disconnects.
## 5. Service Worker Keep-alive
Manifest V3 Service Workers are ephemeral. To keep the connection alive:
1. `chrome.alarms` triggers every 15 seconds.
2. The alarm listener checks the WebSocket `readyState`.
3. If not `OPEN`, it triggers a `connect()` attempt.
4. This keeps the background process "awake" enough to handle incoming WebSocket messages.
## 5. Security & Stability
- **Service Worker Lifecycle**: Uses `chrome.alarms` to prevent the Manifest V3 service worker from suspending while in an active room.
- **Rate Limiting**: Server-side per-socket and per-IP rate limits to prevent sync-spamming or DoS.
- **Noise Filtering**: Uses a curated blacklist of domains (Search Engines, Social Media) to declutter the "Target Tab" selector in the popup.
- **Diagnostics**: A "Dev" tab provides real-time access to the underlying `<video>` state (`readyState`, `paused`, `currentTime`) for easier troubleshooting.
+25 -29
View File
@@ -1,20 +1,28 @@
# KoalaSync
KoalaSync is a Chrome Extension and Relay Server for synchronized video playback (YouTube, Twitch, HTML5).
KoalaSync is a premium, lightweight Chrome Extension and Relay Server for synchronized video playback across any website (YouTube, Twitch, Netflix, and custom HTML5 players).
> [!TIP]
> **New Developers & AI Agents**: Please read [AI_INIT.md](AI_INIT.md) before starting work.
## Repository Structure
- `extension/`: Chrome Extension (Manifest V3).
- `server/`: Node.js + Socket.IO Relay Server.
- `extension/`: Chrome Extension (Manifest V3, Vanilla JS).
- `server/`: Node.js + Socket.IO Relay Server (Containerized).
- `website/`: Static marketing landing page & tutorials.
- `shared/`: Shared protocol constants.
## Key Features
- **Global Synchronization**: Synchronize Play, Pause, and Seeking on any website with a `<video>` tag.
- **Smart Identity**: Customizable usernames combined with unique hexadecimal peer IDs.
- **Dual Heartbeat Architecture**: Robust session tracking that prevents ghost rooms and stale connections.
- **Zero-Latency Relay**: Custom Socket.IO wire protocol implementation for maximum performance.
- **Integrated Diagnostics**: A dedicated "Dev" tab for real-time video state debugging.
- **Seamless Invitations**: Smart invitation links that automatically configure the server and room credentials for your friends.
## Setup Instructions
### 1. Relay Server (Docker)
The server runs on Node.js using Socket.IO but is restricted to WebSocket transport for compatibility with native clients.
The server runs on Node.js using Socket.IO, containerized for easy deployment.
```bash
# From the root directory
@@ -29,35 +37,23 @@ The server will be available at `ws://localhost:3000`.
4. Select the `extension/` folder.
## Usage
1. Open the extension popup.
2. Enter the Server URL (default: `ws://localhost:3000`).
3. Click **Join / Create Room**.
4. In the **Sync** tab, select the tab containing the video you want to sync.
5. Share the **Invite Link** (RoomID#Password) with your friends.
6. When they join, your play/pause/seek actions will be synchronized.
7. Use **Force Sync** to align everyone to your current timestamp.
1. Open the extension and go to the **Settings** tab to set your **Username**.
2. Go to the **Room** tab, enter your Server URL (default: `ws://localhost:3000`), and click **Join / Create Room**.
3. In the **Sync** tab, select the tab containing the video you want to sync.
4. Share the **Invite Link** from the Room tab. When your friends click it, they will automatically join your room and server.
5. Use **Force Sync** to perfectly align everyone to your current timestamp.
## Technical Details
- **Manifest V3**: Uses a Service Worker for background tasks.
- **Native WebSockets**: The extension uses the native `WebSocket` API.
- > [!IMPORTANT]
- > **Socket.IO Compatibility**: The server must use **Socket.IO v4**. The extension implements a subset of the Engine.IO/Socket.IO wire protocol.
- **Keep-Alive**: A `chrome.alarms` mechanism keeps the Service Worker active.
- **Two-Phase Force Sync**: Uses `pollSeekReady` to ensure all peers are synchronized before resuming.
- **Manifest V3**: Uses a persistent Service Worker with Alarm-based keep-alive.
- **Manual Socket.IO Protocol**: The extension implements the Socket.IO v4 wire protocol natively for extreme performance and zero dependencies.
- **Dead Peer Pruning**: The server automatically prunes peers after 5 minutes of total inactivity (detected via dual heartbeats).
- **Two-Phase Sync**: Ensures all peers are buffered (`readyState >= 3`) before resuming playback.
## Security & Privacy
> [!IMPORTANT]
> **Privacy by Design**: KoalaSync is built with extreme data parsimony in mind.
> - **No Databases**: The server stores absolutely nothing on disk. All room states and peer mappings exist only in RAM and are destroyed as soon as a room is empty or inactive.
> - **No Tracking**: There is zero telemetry, analytics, or user tracking in both the extension and the server.
> - **Minimal Logging**: The server logs only technical events (connections, errors, rate-limiting) with no personally identifiable information (PII).
> - **Extension Permissions**: The `<all_urls>` permission is required solely to detect and synchronize HTML5 video elements on any website you visit. No browsing history is ever transmitted or stored.
- > [!WARNING]
> **Invite Links**: Passwords in invite links (e.g., `RoomID#Password`) are shared in plaintext. This is a trade-off for convenience. For higher security, share the password via a secure channel.
> **Privacy First**: KoalaSync stores no data on disk. All room states exist only in RAM and are purged immediately when empty. There is zero telemetry, tracking, or analytics.
## Troubleshooting
- **Logs**: Check the **Dev** tab in the extension popup for detailed connection logs.
- **Handshake**: Look for `Socket.IO Handshake: 0{...}` in the logs to verify successful connection.
- **Permissions**: Ensure you have granted the extension permission to access the video site's tab.
- **Logs**: Check the **Dev** tab in the extension popup for live connection logs and video state diagnostics.
- **Handshake**: Verify you see `Joined Namespace /` in the logs.
- **Permissions**: Ensure the target site hasn't blocked script injection (rare for most video sites).
+9 -3
View File
@@ -1,9 +1,9 @@
# KoalaSync Protocol Synchronization Guide (SYNC_GUIDE.md)
# KoalaSync Protocol Synchronization Guide
## Why do we need to sync?
KoalaSync uses a "Single Source of Truth" for its communication protocol constants located in the `shared/` directory. However, Chrome Extensions (Manifest V3) are strictly sandboxed and **cannot load or import files from outside their root directory**.
KoalaSync uses a "Single Source of Truth" for its communication protocol constants located in the root `shared/` directory. However, Chrome Extensions (Manifest V3) are strictly sandboxed and **cannot load or import files from outside their root directory**.
To ensure that the extension and the relay server are always using the exact same event names and protocol versions, we must maintain a mirrored copy of the shared files within the extension folder.
To ensure that the extension and the relay server are always using the exact same event names and protocol versions, we maintain a mirrored copy of the shared files within the `extension/shared/` folder.
## When should you run the sync script?
You MUST run the synchronization script in any of the following scenarios:
@@ -32,5 +32,11 @@ The script performs the following actions:
2. Copies `shared/constants.js` to `extension/shared/constants.js`.
3. Copies `shared/blacklist.js` to `extension/shared/blacklist.js`.
## Protocol Versioning
As of v1.0.0-RC5, the system enforces a strict `protocolVersion` check during the `JOIN_ROOM` handshake.
- The version is defined in `shared/constants.js`.
- If the extension and server versions mismatch, the server will reject the connection with an `Incompatible protocol version` error.
- **Always run the sync script** after bumping the version number to ensure both components are updated.
> [!CAUTION]
> **NEVER** edit the files inside `extension/shared/` directly. They will be overwritten the next time the sync script is run. Always edit the files in the root `shared/` directory and then run the sync script.
+22 -13
View File
@@ -1,23 +1,32 @@
# KoalaSync Chrome Extension
A Manifest V3 Chrome Extension for synchronized video playback.
A Manifest V3 Chrome Extension for synchronized video playback across any website.
## Key Features
- **Manifest V3**: Using a modern Service Worker architecture.
- **Native WebSockets**: No heavy libraries, uses the browser's native API.
- **Manifest V3**: Optimized Service Worker architecture with session persistence.
- **Pure Vanilla JS**: No external dependencies or heavy libraries.
- **Smart Peer IDs**: Hexadecimal IDs combined with customizable Usernames for easy identification.
- **Dual Heartbeat**: Advanced session tracking (Background) and video synchronization (Content) to prevent ghost sessions.
- **Live Diagnostics**: Built-in "Dev" tab for real-time video state debugging (ReadyState, CurrentTime, etc.).
## Tab Overview
1. **Room**: Manage connections, view active peers, and share invitation links.
2. **Sync**: Control video playback (Play/Pause/Force Sync) and view recent activity.
3. **Settings**: Customize your Username and toggle domain-based Noise Filtering.
4. **Dev**: Monitor connection status and view real-time video element metadata for debugging.
## Privacy & Permissions
KoalaSync requires `<all_urls>` permission to detect and interact with video elements (`<video>`) on any website.
- **No Browsing History**: We do not track which sites you visit.
- **No Telemetry**: There are no analytics or tracking scripts included.
- **Local State**: Settings (Server URL, Room ID, Password) are stored only locally in your browser using `chrome.storage`.
KoalaSync requires `<all_urls>` permission to detect and interact with video elements (`<video>`) on websites.
- **No Browsing History**: We do not track or store your browsing history.
- **State Management**: Sensitive data (Room Passwords) is stored locally using `chrome.storage`.
- **Zero Telemetry**: No analytics or external tracking scripts.
## Installation
1. Go to `chrome://extensions/`.
2. Enable **Developer mode**.
3. Click **Load unpacked** and select this folder.
1. Open Chrome and go to `chrome://extensions/`.
2. Enable **Developer mode** (top right).
3. Click **Load unpacked** and select the `extension` folder from this repository.
## Development
If you change `shared/constants.js`, remember to run the synchronization script:
- Windows: `..\scripts\sync-constants.bat`
- Linux/macOS: `../scripts/sync-constants.sh`
If you modify `shared/constants.js`, you must synchronize the changes across the extension and server:
- **Windows**: Run `scripts\sync-constants.bat`
- **Linux/macOS**: Run `scripts/sync-constants.sh`