diff --git a/API.md b/API.md index c7b6020c..8fcb2e4a 100644 --- a/API.md +++ b/API.md @@ -3597,10 +3597,10 @@ If both `since` and `Last-Event-ID` are present, the larger value is used. --- ### GET /api/docs/{file} -**Purpose**: Serve documentation files from the GitHub repository. +**Purpose**: Serve files from the GitHub repository. **Path Parameter**: -- `file`: Documentation filename (e.g., `README.md`, `FAQ.md`, `API.md`, `sc_short.jpg`, `sc_simple.jpg`) +- `file`: Documentation filename (e.g., `README.md`, `FAQ.md`, `API.md`, `SECURITY.md`, `sc_short.jpg`, `sc_simple.jpg`) **Response**: - File content with appropriate `Content-Type` header (text/markdown for .md, image/jpeg for .jpg, etc.) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c8f776dc..73c1bf97 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,7 +45,12 @@ Before writing any code, **propose your idea** through one of these channels: ```bash git checkout dev git pull origin dev -git checkout -b feature/descriptive-name +git switch -C feature/descriptive-name +``` + +**Run the backend:** +```bash +uv run python -m app.main --dev ``` **Follow project standards:** diff --git a/app/main.py b/app/main.py index 37ed9fa5..48144457 100644 --- a/app/main.py +++ b/app/main.py @@ -12,8 +12,10 @@ sys.path.insert(0, APP_ROOT) +import argparse import asyncio import logging +from collections.abc import Sequence from pathlib import Path import magic @@ -217,6 +219,31 @@ def started(_): ) -if __name__ == "__main__": +def start() -> None: logging.basicConfig(level=logging.DEBUG) Main().start() + + +def run_dev() -> None: + from watchfiles import PythonFilter, run_process + + run_process( + ROOT_PATH, + target=start, + watch_filter=PythonFilter(ignore_paths=(ROOT_PATH / "migrations",)), + ) + + +def main(argv: Sequence[str] | None = None) -> None: + parser = argparse.ArgumentParser(description="Start YTPTube server", allow_abbrev=False) + parser.add_argument("--dev", action="store_true", help="Reload the server when Python files change") + args, _ = parser.parse_known_args(argv) + + if args.dev: + run_dev() + else: + start() + + +if __name__ == "__main__": + main() diff --git a/app/routes/api/docs.py b/app/routes/api/docs.py index 334d6467..92c8cd6d 100644 --- a/app/routes/api/docs.py +++ b/app/routes/api/docs.py @@ -14,7 +14,7 @@ LOG = get_logger() -STATIC_FILES = ["README.md", "FAQ.md", "API.md", "sc_short.jpg", "sc_simple.jpg"] +STATIC_FILES = ["README.md", "FAQ.md", "API.md", "SECURITY.md", "sc_short.jpg", "sc_simple.jpg"] EXT_TO_MIME: dict = { ".md": "text/markdown", ".png": "image/png", diff --git a/app/tests/test_main.py b/app/tests/test_main.py new file mode 100644 index 00000000..32de849f --- /dev/null +++ b/app/tests/test_main.py @@ -0,0 +1,12 @@ +from unittest.mock import Mock + +from app import main + + +def test_accepts_process_arg(monkeypatch): + start = Mock() + monkeypatch.setattr(main, "start", start) + + main.main(["--ytp-process"]) + + start.assert_called_once_with() diff --git a/ui/app/composables/useDocs.ts b/ui/app/composables/useDocs.ts index c8fbf188..0bd56311 100644 --- a/ui/app/composables/useDocs.ts +++ b/ui/app/composables/useDocs.ts @@ -1,4 +1,4 @@ -export type DocsFile = 'README.md' | 'FAQ.md' | 'API.md'; +export type DocsFile = 'README.md' | 'FAQ.md' | 'API.md' | 'SECURITY.md'; export type DocsEntry = { id: string; @@ -44,6 +44,16 @@ const DOCS_ENTRIES: DocsEntry[] = [ icon: 'i-lucide-code-xml', navLabel: 'docs.entries.api.navLabel', }, + { + id: 'docs-security', + title: 'docs.entries.security.title', + description: 'docs.entries.security.description', + file: 'SECURITY.md', + route: '/docs/security', + slug: ['security'], + icon: 'i-lucide-shield-check', + navLabel: 'docs.entries.security.navLabel', + }, ]; const DOCS_ROUTE_BY_FILE = new Map(DOCS_ENTRIES.map((entry) => [entry.file, entry.route])); diff --git a/ui/app/utils/generatedIconCatalog.ts b/ui/app/utils/generatedIconCatalog.ts index 4cb752ec..f7800222 100644 --- a/ui/app/utils/generatedIconCatalog.ts +++ b/ui/app/utils/generatedIconCatalog.ts @@ -161,6 +161,7 @@ export const bundledIconNames = [ "lucide:shapes", "lucide:share", "lucide:shield-alert", + "lucide:shield-check", "lucide:sliders-horizontal", "lucide:split", "lucide:square", @@ -355,6 +356,7 @@ export const bundledUiIconNames = [ "i-lucide-shapes", "i-lucide-share", "i-lucide-shield-alert", + "i-lucide-shield-check", "i-lucide-sliders-horizontal", "i-lucide-split", "i-lucide-square", diff --git a/ui/i18n/locales/ar.json b/ui/i18n/locales/ar.json index c61cf549..70feddb4 100644 --- a/ui/i18n/locales/ar.json +++ b/ui/i18n/locales/ar.json @@ -1288,6 +1288,11 @@ "title": "API", "navLabel": "API", "description": "مرجع HTTP API وسلوك نقاط النهاية." + }, + "security": { + "title": "الأمان", + "navLabel": "الأمان", + "description": "سياسة الأمان وإرشادات الإبلاغ عن الثغرات الأمنية." } } }, diff --git a/ui/i18n/locales/en.json b/ui/i18n/locales/en.json index fc6f6f04..6571978c 100644 --- a/ui/i18n/locales/en.json +++ b/ui/i18n/locales/en.json @@ -1288,6 +1288,11 @@ "title": "API", "navLabel": "API", "description": "HTTP API reference and endpoint behavior." + }, + "security": { + "title": "Security", + "navLabel": "Security", + "description": "Security policy and vulnerability reporting guidance." } } }, diff --git a/ui/i18n/locales/fr.json b/ui/i18n/locales/fr.json index c01b7d72..41b69dcc 100644 --- a/ui/i18n/locales/fr.json +++ b/ui/i18n/locales/fr.json @@ -1286,6 +1286,11 @@ "title": "API", "navLabel": "API", "description": "Référence de l'API HTTP et comportement des points de terminaison." + }, + "security": { + "title": "Sécurité", + "navLabel": "Sécurité", + "description": "Politique de sécurité et consignes de signalement des vulnérabilités." } } }, diff --git a/ui/i18n/locales/ja.json b/ui/i18n/locales/ja.json index ca16aa8a..f629c897 100644 --- a/ui/i18n/locales/ja.json +++ b/ui/i18n/locales/ja.json @@ -1286,6 +1286,11 @@ "title": "API", "navLabel": "API", "description": "HTTP API リファレンスとエンドポイントの動作。" + }, + "security": { + "title": "セキュリティ", + "navLabel": "セキュリティ", + "description": "セキュリティポリシーと脆弱性の報告手順。" } } }, diff --git a/ui/i18n/locales/zh.json b/ui/i18n/locales/zh.json index 90994635..849c39b7 100644 --- a/ui/i18n/locales/zh.json +++ b/ui/i18n/locales/zh.json @@ -1286,6 +1286,11 @@ "title": "API", "navLabel": "API", "description": "HTTP API 参考和端点行为。" + }, + "security": { + "title": "安全", + "navLabel": "安全", + "description": "安全政策和漏洞报告指南。" } } },