From 32791a62a7358f93d3f423748c7fe8f8809f5e75 Mon Sep 17 00:00:00 2001 From: kuekhaoyang Date: Thu, 16 Apr 2026 20:41:18 +0800 Subject: [PATCH] Remediate audit findings across runtime and platforms --- CONTRIBUTING.md | 951 +- README.md | 1196 +- SECURITY.md | 44 +- android-tv/app/build.gradle.kts | 14 +- android-tv/app/src/main/AndroidManifest.xml | 10 +- .../main/java/com/kvideo/tv/MainActivity.kt | 103 +- .../app/src/main/res/layout/activity_main.xml | 15 +- .../app/src/main/res/values/strings.xml | 14 +- app/api/app-update/route.ts | 2 +- app/api/auth/accounts/[accountId]/route.ts | 8 +- app/api/auth/accounts/route.ts | 7 +- app/api/auth/route.ts | 43 +- app/api/auth/session/route.ts | 2 +- app/api/config/route.ts | 2 +- app/api/danmaku/route.ts | 89 +- app/api/detail/route.ts | 84 +- app/api/douban/image/route.ts | 115 +- app/api/douban/recommend/route.ts | 18 +- app/api/douban/tags/route.ts | 2 +- app/api/iptv/route.ts | 58 +- app/api/iptv/stream/route.ts | 207 +- app/api/ping/route.ts | 132 +- app/api/premium/category/route.ts | 52 +- app/api/premium/types/route.ts | 26 +- app/api/probe-resolution/route.ts | 133 +- app/api/proxy/route.ts | 232 +- app/api/search-parallel/route.ts | 267 +- app/api/user/config/route.ts | 18 +- app/api/user/sync/route.ts | 22 +- app/globals.css | 15 + app/layout.tsx | 8 +- app/page.tsx | 59 +- app/player/page.tsx | 6 +- app/settings/hooks/useSettingsPage.ts | 10 +- app/settings/page.tsx | 2 +- apple-tv/KVideoTV/KVideoTV/ContentView.swift | 53 - apple-tv/KVideoTV/KVideoTV/KVideoTVApp.swift | 11 - apple-tv/README.md | 41 +- components/AutoSync.tsx | 17 +- components/PasswordGate.tsx | 33 +- components/ThemeProvider.tsx | 132 +- components/VideoTogetherController.tsx | 46 +- components/favorites/FavoritesItem.tsx | 14 +- components/history/HistoryItem.tsx | 7 +- components/history/PosterImage.tsx | 14 +- components/home/MovieCard.tsx | 2 - components/home/MovieGrid.tsx | 2 +- components/home/PopularFeatures.tsx | 31 +- .../hooks/usePersonalizedRecommendations.ts | 18 +- components/home/hooks/usePopularMovies.ts | 14 +- components/home/hooks/useTagManager.ts | 45 +- components/iptv/IPTVChannelGrid.tsx | 6 +- components/iptv/IPTVPlayer.tsx | 110 +- components/player/DanmakuCanvas.tsx | 34 +- components/player/EpisodeList.tsx | 16 +- components/player/SourceSelector.tsx | 63 +- components/player/VideoMetadata.tsx | 17 +- components/player/VideoPlayer.tsx | 21 +- components/player/desktop/DesktopMoreMenu.tsx | 43 +- .../player/desktop/DesktopSpeedMenu.tsx | 43 +- .../player/hooks/desktop/useCastControls.ts | 99 +- .../hooks/desktop/useProgressControls.ts | 43 +- .../player/hooks/desktop/useVolumeControls.ts | 18 +- components/player/hooks/useAutoSkip.ts | 57 +- components/player/hooks/useHlsPlayer.ts | 43 +- components/player/hooks/useResolutionBadge.ts | 18 +- components/player/hooks/useStallDetection.ts | 5 +- components/premium/PremiumContent.tsx | 25 +- components/premium/PremiumContentGrid.tsx | 9 +- components/search/VideoCard.tsx | 17 +- components/search/VideoGrid.tsx | 32 +- components/search/VideoGroupCard.tsx | 14 +- components/settings/AddSourceModal.tsx | 24 +- components/settings/AppVersionSettings.tsx | 10 +- components/settings/DataSettings.tsx | 11 +- components/settings/DisplaySettings.tsx | 2 +- components/settings/ExportModal.tsx | 30 +- components/settings/ImportModal.tsx | 42 +- components/settings/UserDanmakuSettings.tsx | 39 +- components/settings/UserSourceSettings.tsx | 17 +- components/settings/hooks/useAddSourceForm.ts | 49 +- components/ui/RemotePosterImage.tsx | 43 + docker-compose.yml | 2 - lib/api/http-utils.ts | 11 +- lib/hooks/mobile/useDeviceDetection.ts | 7 +- lib/hooks/mobile/useScreenOrientation.ts | 27 +- lib/hooks/useFloatingButtonPosition.ts | 28 +- lib/hooks/useHomePage.ts | 27 +- lib/hooks/useLanguageBadges.ts | 33 +- lib/hooks/useLatencyPing.ts | 59 +- lib/hooks/useParallelSearch.ts | 11 +- lib/hooks/usePremiumContent.ts | 22 +- lib/hooks/usePremiumHomePage.ts | 51 +- lib/hooks/useSearchAction.ts | 16 +- lib/hooks/useSearchCache.ts | 34 +- lib/hooks/useSourceBadges.ts | 33 +- lib/hooks/useSubscriptionSync.ts | 2 +- lib/hooks/useTVDetection.ts | 60 +- lib/hooks/useTypeBadges.ts | 34 +- lib/server/api-access.ts | 79 + lib/server/auth-rate-limit.ts | 138 + lib/server/auth.ts | 60 +- lib/server/outbound-policy.ts | 293 + lib/server/redis-client.ts | 19 + lib/server/source-validation.ts | 82 + lib/store/history-store.ts | 11 +- lib/store/premium-mode-settings.ts | 6 +- lib/store/settings-store.ts | 54 +- lib/utils/danmaku-utils.ts | 46 +- lib/utils/fetch-with-retry.ts | 65 +- lib/utils/grouped-sources-cache.ts | 6 +- lib/utils/latency-source-map.ts | 19 + lib/utils/m3u8-utils.ts | 2 +- lib/utils/search-stream.ts | 22 +- lib/utils/sort.ts | 31 +- next.config.ts | 75 - open-next.config.ts | 3 + package-lock.json | 16181 ++++++++++------ package.json | 36 +- public/offline.html | 71 + public/sw.js | 107 +- wrangler.toml | 17 +- 122 files changed, 13341 insertions(+), 9985 deletions(-) delete mode 100644 apple-tv/KVideoTV/KVideoTV/ContentView.swift delete mode 100644 apple-tv/KVideoTV/KVideoTV/KVideoTVApp.swift create mode 100644 components/ui/RemotePosterImage.tsx create mode 100644 lib/server/api-access.ts create mode 100644 lib/server/auth-rate-limit.ts create mode 100644 lib/server/outbound-policy.ts create mode 100644 lib/server/redis-client.ts create mode 100644 lib/server/source-validation.ts create mode 100644 lib/utils/latency-source-map.ts create mode 100644 open-next.config.ts create mode 100644 public/offline.html diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d5d9d5c..b78e40e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,930 +1,77 @@ -# 贡献指南 (Contributing Guide) +# Contributing -欢迎来到 **KVideo** 项目!我们非常感谢你愿意为这个项目做出贡献。无论是修复 Bug、添加新功能、改进文档,还是提出建议,你的每一份贡献都将让这个项目变得更好。 +## Baseline -为了确保协作顺畅、代码质量一致,请在提交贡献前仔细阅读本指南。 +Contributions are expected to preserve the post-audit behavior of this repository: -## 📋 目录 +- secure outbound request policy +- private-by-default relay endpoints +- explicit auth secret requirements +- Workers/OpenNext Cloudflare path +- Android TV-only wrapper scope +- Apple TV unsupported -- [行为准则](#行为准则) -- [快速开始](#快速开始) -- [开发环境设置](#开发环境设置) -- [代码规范](#代码规范) -- [Git 工作流程](#git-工作流程) -- [提交规范](#提交规范) -- [Pull Request 指南](#pull-request-指南) -- [设计系统规范](#设计系统规范) -- [测试要求](#测试要求) -- [常见问题](#常见问题) +Do not reintroduce permissive relay behavior, wildcard CORS, cookie forwarding, TLS verification bypasses, or public private-network fetches. -## 🤝 行为准则 +## Prerequisites -我们致力于构建一个开放、友好、包容的社区环境。请在参与项目时: +- Node.js 22+ +- npm 10+ +- Java 17 for Android builds +- Android SDK for Android TV validation +- Docker if you need to run the image/build checks locally -- ✅ 保持尊重和礼貌 -- ✅ 欢迎不同的观点和经验 -- ✅ 接受建设性的批评 -- ✅ 专注于对社区最有利的事情 -- ❌ 不要使用性别化的语言或图像 -- ❌ 不要进行人身攻击或政治攻击 -- ❌ 不要骚扰或歧视他人 - -详细的行为准则请参阅 [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)。 - -## 🚀 快速开始 - -### 我能贡献什么? - -以下是一些你可以做出贡献的方式: - -1. **🐛 报告 Bug**:发现了问题?请提交 Issue -2. **💡 提出新功能**:有好想法?在 Discussions 或 Issues 中分享 -3. **📝 改进文档**:发现文档不清晰或有错误?帮助我们改进 -4. **🎨 优化 UI/UX**:让界面更美观、更易用 -5. **⚡ 性能优化**:让应用运行得更快 -6. **🔧 修复 Bug**:解决现有的问题 -7. **✨ 添加功能**:实现新的特性 - -### 第一次贡献? - -如果这是你第一次为开源项目做贡献,我们推荐: - -1. 浏览 [GitHub Issues](https://github.com/KuekHaoYang/KVideo/issues) -2. 寻找标记为 `good first issue` 的问题 -3. 在 Issue 中评论,表明你想要解决这个问题 -4. 按照本指南进行开发和提交 - -## 🛠 开发环境设置 - -### 系统要求 - -确保你的开发环境满足以下要求: - -| 工具 | 最低版本 | 推荐版本 | 检查命令 | -|------|----------|----------|----------| -| **Node.js** | 20.0.0 | 22.x LTS | `node --version` | -| **npm** | 9.0.0 | 10.x | `npm --version` | -| **Git** | 2.30.0 | 最新版本 | `git --version` | - -### 详细设置步骤 - -#### 1. Fork 仓库 - -点击 GitHub 页面右上角的 "Fork" 按钮,将项目 Fork 到你的账号下。 - -#### 2. 克隆仓库 - -```bash -# 克隆你 Fork 的仓库 -git clone https://github.com/YOUR_USERNAME/KVideo.git -cd KVideo - -# 添加上游仓库 -git remote add upstream https://github.com/KuekHaoYang/KVideo.git -``` - -#### 3. 安装依赖 +Install dependencies: ```bash npm install ``` -#### 4. 启动开发服务器 +## Development Commands ```bash npm run dev -``` - -访问 `http://localhost:3000` 查看应用。 - -#### 5. 验证环境 - -确保以下命令都能正常运行: - -```bash -# 代码检查 npm run lint - -# 构建测试 +npm test +npm run test:e2e npm run build +npm run cf:build +docker compose config +docker build -t kvideo . +cd android-tv && ./gradlew --no-daemon lint test assembleDebug assembleRelease ``` -## 📏 代码规范 +## Required Checks Before a PR -### 核心规范 +At minimum, run the checks relevant to the code you changed. For broad or infrastructure-facing work, run the full matrix: -#### 1. 文件长度限制 ⚠️ +- `npm run lint` +- `npm test` +- `npm run build` +- `npm run cf:build` +- `npm audit --omit=dev` +- `docker compose config` +- `docker build -t kvideo .` +- `cd android-tv && ./gradlew --no-daemon lint test assembleDebug assembleRelease` -> [!CAUTION] -> **这是项目的硬性规则!所有项目文件必须保持在 150 行以内(除系统文件外)。** +If you touch user flows, add or update Playwright smoke coverage in [`playwright`](/Users/haoyangkuek/development/KVideo/playwright). -**检查命令:** +## Style Expectations -```bash -find . -type f -not -path "*/node_modules/*" -not -path "*/.next/*" -not -path "*/.git/*" -not -name "package-lock.json" -not -name "*.png" -not -name "*.md" | xargs wc -l | awk '$1 > 150 && $2 != "total" {print $2 " - " $1 "行"}' -``` +- Keep changes scoped and intentional. +- Prefer testable extraction over speculative abstraction. +- Do not add fake compatibility aliases for insecure legacy behavior. +- Do not depend on arbitrary file-length limits. CI-backed quality gates matter; line counts do not. +- Keep documentation accurate to the actual runtime behavior of the branch. -**如果命令有输出,说明有文件超过 150 行,必须重构!** +## Pull Requests -**重构策略:** +Each PR should include: -如果文件超过 150 行,请使用以下方法重构: +- what changed +- why it changed +- risk areas +- validation performed +- any deployment/env var changes -##### A. 提取组件 - -**问题:** 一个组件太长,包含太多 JSX - -**解决方案:** 将大组件拆分为多个小组件 - -```typescript -// ❌ 不好:一个 200 行的大组件 -export function VideoPlayer() { - // 150+ 行代码 - return ( -
- {/* 大量 JSX */} -
- ); -} - -// ✅ 好:拆分为多个小组件 -export function VideoPlayer() { - return ( -
- - - -
- ); -} - -// PlayerControls.tsx (单独文件) -export function PlayerControls() { /* ... */ } - -// ProgressBar.tsx (单独文件) -export function ProgressBar() { /* ... */ } - -// VolumeControl.tsx (单独文件) -export function VolumeControl() { /* ... */ } -``` - -##### B. 提取自定义 Hook - -**问题:** 组件包含大量状态逻辑 - -**解决方案:** 将逻辑提取到自定义 Hook - -```typescript -// ❌ 不好:组件内有大量状态逻辑 -export function SearchPage() { - const [query, setQuery] = useState(''); - const [results, setResults] = useState([]); - const [loading, setLoading] = useState(false); - // ... 大量逻辑 - - const handleSearch = async () => { - // ... 50+ 行逻辑 - }; - - return
{/* JSX */}
; -} - -// ✅ 好:提取到自定义 Hook -export function SearchPage() { - const { query, results, loading, handleSearch } = useSearch(); - return
{/* JSX */}
; -} - -// useSearch.ts (单独文件) -export function useSearch() { - // ... 所有状态逻辑 - return { query, results, loading, handleSearch }; -} -``` - -##### C. 提取工具函数 - -**问题:** 文件包含大量辅助函数 - -**解决方案:** 将工具函数移到 `lib/utils/` - -```typescript -// ❌ 不好:组件文件包含工具函数 -export function VideoCard() { - const formatDuration = (seconds: number) => { - // ... 格式化逻辑 - }; - - const formatDate = (date: Date) => { - // ... 格式化逻辑 - }; - - // ... 更多工具函数 - - return
{/* JSX */}
; -} - -// ✅ 好:提取到工具文件 -import { formatDuration, formatDate } from '@/lib/utils/format-utils'; - -export function VideoCard() { - return
{/* JSX */}
; -} - -// lib/utils/format-utils.ts -export function formatDuration(seconds: number) { /* ... */ } -export function formatDate(date: Date) { /* ... */ } -``` - -##### D. 模块化 - -**问题:** 单个文件处理多个相关功能 - -**解决方案:** 按功能拆分文件并使用桶文件(barrel exports) - -```typescript -// ❌ 不好:player-utils.ts 包含 200 行 -export function parseHLS() { /* ... */ } -export function handlePlayback() { /* ... */ } -export function manageQuality() { /* ... */ } -// ... 更多函数 - -// ✅ 好:拆分为多个文件 -// lib/utils/player/index.ts -export * from './hls-parser'; -export * from './playback-manager'; -export * from './quality-manager'; - -// lib/utils/player/hls-parser.ts -export function parseHLS() { /* ... */ } - -// lib/utils/player/playback-manager.ts -export function handlePlayback() { /* ... */ } - -// lib/utils/player/quality-manager.ts -export function manageQuality() { /* ... */ } -``` - -#### 2. TypeScript 规范 - -**类型安全** - -```typescript -// ❌ 避免使用 any -function processData(data: any) { - return data.value; -} - -// ✅ 使用具体类型 -interface VideoData { - id: string; - title: string; - url: string; -} - -function processData(data: VideoData) { - return data.title; -} - -// ✅ 或使用 unknown(需要类型检查) -function processData(data: unknown) { - if (typeof data === 'object' && data !== null && 'value' in data) { - return (data as { value: string }).value; - } - throw new Error('Invalid data'); -} -``` - -**函数返回类型** - -```typescript -// ❌ 缺少返回类型 -function calculateTotal(items) { - return items.reduce((sum, item) => sum + item.price, 0); -} - -// ✅ 明确返回类型 -function calculateTotal(items: Item[]): number { - return items.reduce((sum, item) => sum + item.price, 0); -} -``` - -**接口定义** - -```typescript -// ✅ 使用 interface 定义对象类型 -interface VideoCardProps { - video: Video; - onPlay: (id: string) => void; - className?: string; -} - -// ✅ 使用 type 定义联合类型 -type ThemeMode = 'light' | 'dark' | 'system'; -``` - -#### 3. React 组件规范 - -**函数组件** - -```typescript -// ✅ 标准函数组件结构 -interface ButtonProps { - variant?: 'primary' | 'secondary'; - children: React.ReactNode; - onClick?: () => void; -} - -export function Button({ variant = 'primary', children, onClick }: ButtonProps) { - return ( - - ); -} -``` - -**组件文件组织** - -```typescript -// 1. 导入 -import React from 'react'; -import { useState } from 'react'; -import { useRouter } from 'next/navigation'; - -// 2. 类型定义 -interface ComponentProps { - // ... -} - -// 3. 组件定义 -export function Component({ prop1, prop2 }: ComponentProps) { - // 4. Hooks - const [state, setState] = useState(); - const router = useRouter(); - - // 5. 事件处理函数 - const handleClick = () => { - // ... - }; - - // 6. 渲染 - return ( -
{/* JSX */}
- ); -} -``` - -**单一职责原则** - -```typescript -// ❌ 组件做太多事情 -export function VideoSection() { - // 获取数据 - // 处理搜索 - // 渲染列表 - // 处理分页 - // 处理过滤 -} - -// ✅ 拆分为专注的组件 -export function VideoSection() { - const videos = useVideos(); - return ( -
- - - - -
- ); -} -``` - -#### 4. 样式规范 - -**Tailwind CSS 优先** - -```typescript -// ✅ 使用 Tailwind 类名 -export function Card({ children }: { children: React.ReactNode }) { - return ( -
- {children} -
- ); -} -``` - -**遵循 Liquid Glass 设计系统** - -```typescript -// ✅ 正确使用圆角 -
{/* 容器:大圆角 */} -
{/* 小元素:完全圆形 */} - -// ❌ 不要使用其他圆角值 -
{/* 错误! */} -
{/* 错误! */} -``` - -**响应式设计** - -```typescript -// ✅ 移动优先的响应式设计 -
-``` - -#### 5. 命名规范 - -**文件命名** - -- 组件文件:`PascalCase.tsx`(例如:`VideoCard.tsx`) -- Hook 文件:`camelCase.ts`(例如:`useVideoPlayer.ts`) -- 工具文件:`kebab-case.ts`(例如:`format-utils.ts`) -- 类型文件:`kebab-case.ts`(例如:`video-types.ts`) - -**变量命名** - -```typescript -// ✅ 清晰的命名 -const videoList = [...]; -const isLoading = false; -const handleSubmit = () => {}; - -// ❌ 模糊的命名 -const data = [...]; -const flag = false; -const fn = () => {}; -``` - -**常量命名** - -```typescript -// ✅ 全大写 + 下划线 -const MAX_VIDEO_DURATION = 7200; -const API_BASE_URL = 'https://api.example.com'; -``` - -#### 6. 导入顺序 - -```typescript -// 1. React 和 Next.js -import React from 'react'; -import { useState } from 'react'; -import Link from 'next/link'; - -// 2. 第三方库 -import { create } from 'zustand'; - -// 3. 项目别名导入 -import { Button } from '@/components/ui/Button'; -import { formatDate } from '@/lib/utils/date-utils'; - -// 4. 相对路径导入 -import { LocalComponent } from './LocalComponent'; - -// 5. 类型导入 -import type { Video } from '@/lib/types/video'; -``` - -## 🔄 Git 工作流程 - -### 分支策略 - -**主分支** - -- `main`:稳定的生产分支,只接受 PR 合并 - -**功能分支命名** - -遵循以下命名规范: - -- `feat/功能名称`:新功能(例如:`feat/add-playlist`) -- `fix/问题描述`:错误修复(例如:`fix/search-crash`) -- `docs/文档修改`:文档更新(例如:`docs/update-readme`) -- `refactor/重构名称`:代码重构(例如:`refactor/player-controls`) -- `perf/优化内容`:性能优化(例如:`perf/image-loading`) -- `style/样式修改`:样式调整(例如:`style/button-spacing`) -- `test/测试内容`:测试相关(例如:`test/add-unit-tests`) -- `chore/其他修改`:构建或工具变动(例如:`chore/update-deps`) - -### 开发流程 - -#### 1. 同步上游仓库 - -在开始新工作前,先同步最新的代码: - -```bash -# 获取上游更新 -git fetch upstream - -# 切换到主分支 -git checkout main - -# 合并上游更新 -git merge upstream/main - -# 推送到你的 Fork -git push origin main -``` - -#### 2. 创建功能分支 - -```bash -# 从 main 创建新分支 -git checkout -b feat/your-feature-name - -# 确认当前分支 -git branch -``` - -#### 3. 进行开发 - -在开发过程中: - -- 频繁提交小的、原子性的改动 -- 编写清晰的提交信息 -- 定期运行 `npm run lint` 检查代码 - -#### 4. 提交前检查 - -**必须通过的检查:** - -```bash -# 1. 代码规范检查 -npm run lint - -# 2. 文件长度检查 -find . -type f -not -path "*/node_modules/*" -not -path "*/.next/*" -not -path "*/.git/*" -not -name "package-lock.json" -not -name "*.png" -not -name "*.md" | xargs wc -l | awk '$1 > 150 && $2 != "total" {print $2 " - " $1 "行"}' - -# 3. 构建测试 -npm run build -``` - -**如果任何检查失败,必须先修复!** - -#### 5. 推送分支 - -```bash -# 推送到你的 Fork -git push origin feat/your-feature-name -``` - -## 📝 提交规范 - -### Conventional Commits - -我们使用 [Conventional Commits](https://www.conventionalcommits.org/) 规范: - -``` -(): - - - -