Skip to content

Commit 43e47d7

Browse files
@m v2.0.0 — Desktop security architecture overhaul, Android provider fixes, community features
MOBILE APP: - devtools-detector.js stub injection (fixes viduki.net stall — was blocked by ADBLOCK_ENGINE) - disable-devtool patch for zxcstream/vidsrc providers - allowServerRedirects config flag for redirect-mesh providers (viduki.net, videasy.net) - New settings Community section: GitHub Repository, Website links - Star on GitHub card with gradient background - Download Engine v2: live byte tracking, background notifications, storage manager - Theme color token migration across all screens - Runtime version bumped to 59.0.0 (EAS rebuild required) DESKTOP SECURITY (expert-reviewed): - Migrated <webview> → WebContentsView (Electron 42 Phase 3 hybrid) - Ad-blocking engine: @cliqz/adblocker → @ghostery/adblocker (Rust/WASM core) - Config v5 split: blocklist.json → providers.json + filters.txt + Ed25519 signature - Exact/suffix host matching (fixes cloudfront.net substring vulnerability) - OTA config with signature verification + 3-config ring-buffer rollback - CDP Fetch L8 injection (HTML response injection at document_start) - MIME-based session trust acquisition + 15-min sliding TTL - NavGuard bootstrap whitelist fix for server-redirect providers - Structural warnings + local auto-heal telemetry (heal-events.log) FEEDBACK PORTAL: - Cloudflare Workers + D1 production backend (migration 002: v1.0.6 changelog) - 14-layer abuse prevention: Turnstile CAPTCHA, 3-tier rate limiting, spam scoring - Offline submission queue with auto-retry on reconnect - API routes: feedback CRUD, search, vote, roadmap, changelog, FAQ PACKAGES: - adblock-config: v5 schema validation + signature presence - filter-compiler: filters.txt → compiled-engine.bin pipeline - shared: playback engine module, provider registry updates
1 parent 75b10e3 commit 43e47d7

129 files changed

Lines changed: 23458 additions & 16483 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ apps/mobile/ios/
7575
*.mobileprovision
7676
*.orig.*
7777

78+
# config signing — Ed25519 private key NEVER committed; public key is
79+
.keys/*.key
80+
!.keys/filmsnaps-ed25519.pub
81+
7882
# mobile build artifacts
7983
*.log
8084
build_commands.txt

.keys/filmsnaps-ed25519.pub

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MCowBQYDK2VwAyEAuL54sRMa4NpYZnl4TiQgl4Dib93hrSrWxcvqQ78Sv+Y=
3+
-----END PUBLIC KEY-----

CONTRIBUTING.md

Lines changed: 124 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ a provider, and ship changes across web, desktop, and mobile.
1010
3. [Development workflow](#development-workflow)
1111
4. [Project structure](#project-structure)
1212
5. [Adding a new provider](#adding-a-new-provider)
13-
6. [Editing `blocklist.json`](#editing-blocklistjson)
13+
6. [Editing `providers.json` + `filters.txt` (v5)](#editing-providersjson--filterstxt-v5)
1414
7. [Testing](#testing)
1515
8. [Code style](#code-style)
1616
9. [Common pitfalls](#common-pitfalls)
@@ -23,15 +23,17 @@ FilmSnaps is a pnpm + Turborepo monorepo. Read
2323
[docs/architecture.md](docs/architecture.md) for the full picture, and
2424
[docs/security.md](docs/security.md) before touching anything security-related.
2525

26-
| Directory | Package | What it is |
27-
| --- | --- | --- |
28-
| `apps/web` | `@filmsnaps/web` | Next.js web app (discovery + watch UI). |
29-
| `apps/desktop` | `@filmsnaps/desktop` | Electron app wrapping the web app + hardened player. |
30-
| `apps/mobile` | `@filmsnaps/mobile` | Expo / React Native app. |
31-
| `apps/feedback` | `@filmsnaps/feedback` | Feedback portal (Cloudflare Workers + D1). |
32-
| `packages/shared` | `@filmsnaps/shared` | Shared guards, provider registry, types, state. |
33-
| `packages/adblock-config` | `@filmsnaps/adblock-config` | `blocklist.json` schema + validation. |
34-
| `packages/filter-compiler` | `@filmsnaps/filter-compiler` | Adblock engine + mobile pattern artifacts. |
26+
| Directory | Package | What it is |
27+
| -------------------------- | ---------------------------- | -------------------------------------------------------- |
28+
| `apps/web` | `@filmsnaps/web` | Next.js web app (discovery + watch UI). |
29+
| `apps/desktop` | `@filmsnaps/desktop` | Electron app wrapping the web app + hardened player. |
30+
| `apps/mobile` | `@filmsnaps/mobile` | Expo / React Native app. |
31+
| `apps/feedback` | `@filmsnaps/feedback` | Feedback portal (Cloudflare Workers + D1). |
32+
| `packages/shared` | `@filmsnaps/shared` | Shared guards, provider registry, types, state. |
33+
| `packages/adblock-config` | `@filmsnaps/adblock-config` | v5 `providers.json` + `filters.txt` schema + validation. |
34+
| `packages/filter-compiler` | `@filmsnaps/filter-compiler` | `@ghostery/adblocker` engine + mobile pattern export. |
35+
36+
---
3537

3638
## Setting up
3739

@@ -47,6 +49,8 @@ If you change a filter/blocklist config, regenerate the adblock artifacts:
4749
pnpm build:filters # recompiles compiled-engine.bin + android-adblock-patterns.json
4850
```
4951

52+
---
53+
5054
## Development workflow
5155

5256
### Web
@@ -81,6 +85,8 @@ engine — see `apps/desktop/README.md`.
8185
cd apps/feedback && pnpm dev # http://localhost:3001
8286
```
8387

88+
---
89+
8490
## Project structure
8591

8692
```
@@ -91,16 +97,17 @@ apps/
9197
feedback/ Next.js + Workers + D1
9298
packages/
9399
shared/ shared logic (security bundles, providers, state)
94-
adblock-config/ blocklist.json schema + validation
95-
filter-compiler/ engine + pattern export
96-
blocklist.json provider + blocking rules (single source of truth)
100+
adblock-config/ providers.json + filters.txt v5 schema + validation
101+
filter-compiler/ @ghostery/adblocker engine + mobile pattern export
102+
providers.json v5 config (providers) — single source of truth, Ed25519-signed
103+
providers.json.sig Ed25519 signature over providers.json
104+
filters.txt v5 config (uBO/EasyList rules)
105+
blocklist.json legacy v4 fallback (backward compat)
97106
```
98107

99-
## Adding a new provider
108+
---
100109

101-
Providers are **only** registered in the shared package — there is no separate
102-
web/mobile provider list. See `apps/desktop/README.md` and
103-
`apps/mobile/README.md` for per-platform notes.
110+
## Adding a new provider
104111

105112
### Step 1 — Register in `@filmsnaps/shared`
106113

@@ -115,23 +122,89 @@ web/mobile provider list. See `apps/desktop/README.md` and
115122
embed: {
116123
movie: (id: string) => `/embed/movie/${id}`,
117124
tv: (id, season, episode) => `/embed/tv/${id}/${season}/${episode}`,
125+
}
126+
}
127+
```
128+
129+
### Step 2 — Add its domains to `providers.json` (v5)
130+
131+
**File:** `providers.json` (repo root, schema v5)
132+
133+
```json
134+
{
135+
"version": 5,
136+
"providers": [
137+
{
138+
"id": "myprovider",
139+
"embedDomains": ["example.com", "www.example.com"],
140+
"cdnDomains": ["cdn.example.com"],
141+
"enabled": true,
142+
"allowServerRedirects": false,
143+
"blockHomePaths": ["/go-home"],
144+
"apiIntercepts": [],
145+
"cosmeticRules": [],
146+
"adblockDisabled": false
147+
}
148+
],
149+
"providerProfiles": {
150+
"example.com": {
151+
"scripts": ["https://example.com/script.js"],
152+
"iframes": ["https://cdn.example.com/frame.html"],
153+
"images": ["https://example.com/image.png"]
154+
}
118155
},
156+
"navigationGuard": {
157+
"universalBlockPaths": ["/"]
158+
},
159+
"rules": {
160+
"videoDetection": {
161+
"extensions": [".mp4", ".m3u8", ".ts"],
162+
"pathPatterns": ["seg-", "init-", "chunk-"],
163+
"enableSessionTrust": true,
164+
"trustTTLMs": 900000
165+
},
166+
"alwaysBlock": {
167+
"domains": [],
168+
"pathPatterns": []
169+
}
170+
}
119171
}
120172
```
121173

122-
### Step 2 — Add its domains to `blocklist.json`
174+
### Step 3 — Add `filters.txt` entries (optional, for ad blocking)
175+
176+
**File:** `filters.txt` (repo root)
177+
178+
Standard uBO/EasyList syntax. Example rules:
123179

124-
Add a `providers[]` entry with `embedDomains` and `cdnDomains`, and any
125-
`blockHomePaths` for its error-UI "Go Home" links. Run `pnpm build:filters`.
180+
```
181+
@@||example.com^ # allowlist the embed domain
182+
||google-analytics.com^$3p # block 3rd-party trackers
183+
##.ad-banner # cosmetic rule
184+
```
126185

127-
### Step 3 — Test on each platform
186+
### Step 4 — Regenerate compiler artifacts
187+
188+
```bash
189+
pnpm build:filters # rebuilds compiled-engine.bin + android-adblock-patterns.json
190+
```
191+
192+
### Step 5 — Test on each platform
128193

129194
- **Web** — iframe mounts the embed; check the video plays without 404s.
130195
- **Desktop** — full R0–R8 cascade + L5 preload. Verify with
131196
`FILMSNAPS_AUDIT=1` (see `docs/security.md` → Audit & diagnostics).
132197
- **Mobile** — native `PlayerWebView` + `shouldInterceptRequest`. Verify no ads,
133198
popups, or fullscreen issues.
134199

200+
### Step 6 — Sign the config (for OTA)
201+
202+
Run the signing step to generate `providers.json.sig`:
203+
204+
```bash
205+
pnpm sign:providers # Ed25519-signs providers.json; .key in .keys/ (gitignored), .pub committed
206+
```
207+
135208
### Providers needing custom handling
136209

137210
If the provider doesn't work with the standard pipeline (Cloudflare challenge,
@@ -140,12 +213,24 @@ the mobile `VideoWebView.tsx` / `PlayerWebViewOverlayView.kt` and the desktop
140213
preload, then test on all platforms. Do **not** weaken shared guards to make a
141214
provider work — prefer per-provider allowlist entries.
142215

143-
## Editing `blocklist.json`
216+
---
144217

145-
`blocklist.json` is the single source of truth (v4 schema). See
146-
[docs/security.md](docs/security.md) → Configuration for the sections. After
147-
editing, run `pnpm build:filters` so the compiled engine and mobile patterns
148-
regenerate.
218+
## Editing `providers.json` + `filters.txt` (v5)
219+
220+
> The v5 config lives in `providers.json` (app logic) + `filters.txt` (uBO
221+
> syntax), both Ed25519-signed (`providers.json.sig`). A legacy `blocklist.json`
222+
> (v4) is kept for backward compatibility.
223+
224+
**Workflow:**
225+
226+
1. Edit `providers.json` (add/update provider entries, allowlists, nav-guard,
227+
apiIntercepts, cosmetics, `allowServerRedirects`).
228+
2. Edit `filters.txt` (uBO/EasyList rules — exact/suffix matching only, e.g.
229+
`@@||cloudfront.net^`, `||doubleclick.net^$3p`, `##.ad-banner`).
230+
3. Run `pnpm build:filters` — regenerates `compiled-engine.bin` (desktop) and
231+
`android-adblock-patterns.json` (mobile).
232+
4. Run `pnpm sign:providers` — Ed25519-signs `providers.json``providers.json.sig`.
233+
5. Commit all four files. OTA clients will pull and verify the updated config.
149234

150235
**Safety rules:**
151236

@@ -155,6 +240,11 @@ regenerate.
155240
the cascade on every provider.
156241
- `blockHomePaths` are per-provider deny-lists — append new home-page shapes as
157242
discovered.
243+
- `allowServerRedirects: true` is only for redirect-mesh providers (vidsrc→viduki.net,
244+
videasy→videasy.to). Enabling it on a non-redirect provider could let an ad
245+
redirect through.
246+
247+
---
158248

159249
## Testing
160250

@@ -174,6 +264,8 @@ Current suites:
174264
If you change the R0–R8 cascade or the navigation guard, add/extend tests in
175265
these files.
176266

267+
---
268+
177269
## Code style
178270

179271
- TypeScript, Prettier-formatted (`pnpm format`).
@@ -185,10 +277,14 @@ these files.
185277
at runtime — reproduce shared logic there with a comment pointing at the
186278
canonical source (see `provider-config.ts`, `navigation-guard.ts`).
187279

280+
---
281+
188282
## Common pitfalls
189283

190-
- **Forgetting `pnpm build:filters`** after editing `blocklist.json` — the
191-
desktop engine and mobile patterns go stale.
284+
- **Forgetting `pnpm build:filters`** after editing `providers.json` or
285+
`filters.txt` — the desktop engine and mobile patterns go stale.
286+
- **Forgetting `pnpm sign:providers`** after editing `providers.json` — OTA
287+
clients will reject the unsigned config and keep the last-known-good version.
192288
- **Adding a provider to only one platform.** Registration lives in
193289
`@filmsnaps/shared`; each app consumes the same registry.
194290
- **Weakening guards.** If a provider breaks, investigate the allowlist /

README.md

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,30 @@ Expo/React Native mobile app, and a feedback portal.
1616

1717
## Apps
1818

19-
| App | Package | Stack | Description |
20-
| ----------------------------------- | --------------------- | ---------------------------------- | ---------------------------------------- |
21-
| [Web](apps/web/README.md) | `@filmsnaps/web` | Next.js 16 (App Router) + Tailwind | Discovery UI, watch pages, API routes |
22-
| [Desktop](apps/desktop/README.md) | `@filmsnaps/desktop` | Electron 43 + Next.js standalone | Web UI + native hardened player |
23-
| [Mobile](apps/mobile/README.md) | `@filmsnaps/mobile` | Expo SDK 55 / React Native 0.83 | Phone app with downloads + native player |
24-
| [Feedback](apps/feedback/README.md) | `@filmsnaps/feedback` | Next.js 16 + Cloudflare Workers/D1 | Public feedback portal |
19+
| App | Package | Stack | Description |
20+
| ----------------------------------- | --------------------- | ---------------------------------- | -------------------------------------------------------- |
21+
| [Web](apps/web/README.md) | `@filmsnaps/web` | Next.js 16 (App Router) + Tailwind | Discovery UI, watch pages, API routes |
22+
| [Desktop](apps/desktop/README.md) | `@filmsnaps/desktop` | Electron 43 + Next.js standalone | Web UI + native hardened player (WebContentsView hybrid) |
23+
| [Mobile](apps/mobile/README.md) | `@filmsnaps/mobile` | Expo SDK 55 / React Native 0.83 | Phone app with downloads + native player |
24+
| [Feedback](apps/feedback/README.md) | `@filmsnaps/feedback` | Next.js 16 + Cloudflare Workers/D1 | Public feedback portal |
2525

2626
## Packages
2727

28-
| Package | Description |
29-
| ---------------------------- | --------------------------------------------------------------------- |
30-
| `@filmsnaps/shared` | Shared guard scripts, provider registry, types, state, design tokens. |
31-
| `@filmsnaps/adblock-config` | `blocklist.json` schema + validation. |
32-
| `@filmsnaps/filter-compiler` | Adblocker engine + mobile pattern export artifacts. |
28+
| Package | Description |
29+
| ---------------------------- | ------------------------------------------------------------------------------------ |
30+
| `@filmsnaps/shared` | Shared guard scripts, provider registry, types, state, design tokens. |
31+
| `@filmsnaps/adblock-config` | v5 `providers.json` + `filters.txt` schema + validation + Ed25519 OTA config loader. |
32+
| `@filmsnaps/filter-compiler` | Adblocker engine (@ghostery/adblocker WASM) + mobile pattern export. |
3333

3434
---
3535

3636
## Documentation
3737

3838
- **[Security Architecture](docs/security.md)** — the full security stack: R0–R8
39-
rule cascade and L2–L8 desktop layers, mobile native protection, and the
40-
`blocklist.json` configuration.
39+
rule cascade and L2–L8 desktop layers, mobile native protection, WebContentsView hybrid,
40+
and the `providers.json` + `filters.txt` v5 configuration.
41+
- **[Security Expert Review](docs/security-expert-review.md)** — external expert review
42+
and implementation status.
4143
- **[Architecture](docs/architecture.md)** — repository layout, data flow,
4244
builds, and CI.
4345
- **[Contributing](CONTRIBUTING.md)** — how to set up, develop, add a provider,
@@ -79,16 +81,17 @@ build profiles).
7981

8082
## Common commands
8183

82-
| Command | Purpose |
83-
| ------------------------ | ------------------------------------------------------------ |
84-
| `pnpm build` | Build all apps/packages (Turborepo). |
85-
| `pnpm lint` | Lint everything. |
86-
| `pnpm test` | Run the Vitest suites (shared + desktop security). |
87-
| `pnpm typecheck:desktop` | Typecheck the desktop app. |
88-
| `pnpm format` | Prettier across the repo. |
89-
| `pnpm build:filters` | Regenerate adblocker/filter artifacts from `blocklist.json`. |
90-
| `pnpm cf:deploy` | Deploy the web app to Cloudflare Pages. |
91-
| `pnpm dist:desktop` | Build the desktop installer. |
84+
| Command | Purpose |
85+
| ------------------------ | ---------------------------------------------------------------------------- |
86+
| `pnpm build` | Build all apps/packages (Turborepo). |
87+
| `pnpm lint` | Lint everything. |
88+
| `pnpm test` | Run the Vitest suites (shared + desktop security). |
89+
| `pnpm typecheck:desktop` | Typecheck the desktop app. |
90+
| `pnpm format` | Prettier across the repo. |
91+
| `pnpm build:filters` | Regenerate adblocker/filter artifacts from `providers.json` + `filters.txt`. |
92+
| `pnpm sign:providers` | Sign `providers.json` with Ed25519 for OTA. |
93+
| `pnpm cf:deploy` | Deploy the web app to Cloudflare Pages. |
94+
| `pnpm dist:desktop` | Build the desktop installer. |
9295

9396
---
9497

@@ -102,6 +105,11 @@ build profiles).
102105
- **Multi-provider player** — provider registry in `@filmsnaps/shared`; each
103106
platform mounts embeds with native security layers (see
104107
[docs/security.md](docs/security.md)).
108+
- **Native hardened desktop player** — WebContentsView hybrid (Electron 43), L8 `Page.addScriptToEvaluateOnNewDocument` HTML-bytes injection (replaces disabled CDP-Fetch that dropped renderer headers → Cloudflare 403),
109+
`@ghostery/adblocker` (adblock-rs WASM), session trust with MIME-based 15-min TTL, `allowServerRedirects` for redirect-mesh providers.
110+
- **Native hardened mobile player**`PlayerWebView` native Expo module with `shouldInterceptRequest` filtering (Aho-Corasick unified trie), Ed25519-verified OTA config with ring-buffer rollback, 3×-failure watchdog, NavGuard server-redirect fix, session trust with 15-min TTL, and cosmetic rules from config.
111+
- **Signed OTA config**`providers.json` + `filters.txt` v5, Ed25519-signed, ring-buffer rollback (3 configs),
112+
3×-failure watchdog with local `heal-events.log` on both desktop and mobile.
105113
- **Mobile downloads** — SQLite-backed episode/movie downloads with a native
106114
downloader.
107115
- **Feedback portal** — account-free bug reports, feature requests, roadmap,

0 commit comments

Comments
 (0)