From 678ade462056413bf43fd00971e174d332d1eece Mon Sep 17 00:00:00 2001 From: sprooty Date: Mon, 3 Aug 2026 11:40:13 +0000 Subject: [PATCH] T27: Apply GPL-3.0 headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit D3 resolved: **GPL-3.0**. **Acceptance:** headers applied consistently; CI check optional but preferred. Reviewed: not yet — this is a checkpoint taken after the cheap gates passed and before review. harness-item: T27 --- .github/workflows/ci.yml | 2 + CONTRIBUTING.md | 14 +++ client/eslint.config.js | 3 + client/public/sw.js | 3 + client/src-tauri/build.rs | 3 + client/src-tauri/src/lib.rs | 3 + client/src-tauri/src/main.rs | 3 + client/src/App.tsx | 3 + client/src/api.ts | 3 + client/src/components/ActivityIndicator.tsx | 3 + client/src/components/DiscoverGrid.tsx | 3 + client/src/components/ErrorBoundary.tsx | 3 + client/src/components/MediaRow.tsx | 3 + client/src/components/NotificationBell.tsx | 3 + .../src/components/NotificationDropdown.tsx | 3 + client/src/components/NotificationItem.tsx | 3 + client/src/components/ProgressReporter.tsx | 3 + client/src/components/RatingStars.tsx | 3 + client/src/components/RequestCard.tsx | 3 + client/src/components/Skeleton.tsx | 3 + client/src/components/StreamStats.tsx | 3 + client/src/components/TmdbRow.tsx | 3 + client/src/components/WatchlistButton.tsx | 3 + client/src/context/AuthContext.tsx | 3 + client/src/globals.d.ts | 3 + client/src/hooks/useApi.ts | 3 + client/src/hooks/useAuth.ts | 3 + client/src/hooks/useMobile.ts | 3 + client/src/main.tsx | 3 + client/src/pages/AccountPage.tsx | 3 + client/src/pages/Browse.tsx | 3 + client/src/pages/CalendarPage.tsx | 3 + client/src/pages/DiscoverPage.tsx | 3 + client/src/pages/HistoryPage.tsx | 3 + client/src/pages/HomePage.tsx | 3 + client/src/pages/LoginPage.tsx | 3 + client/src/pages/MovieView.tsx | 3 + client/src/pages/Player.tsx | 3 + client/src/pages/QueuePage.tsx | 3 + client/src/pages/RegisterPage.tsx | 3 + client/src/pages/RequestsPage.tsx | 3 + client/src/pages/SeriesView.tsx | 3 + client/src/pages/ServerConnect.tsx | 3 + client/src/pages/WatchlistPage.tsx | 3 + client/src/styles/forms.ts | 3 + client/vite.config.ts | 3 + .../src/comparator.rs | 3 + crates/stackarr-cardigann-parity/src/main.rs | 3 + .../src/provisioner.rs | 3 + .../src/prowlarr_api.rs | 3 + .../stackarr-cardigann-parity/src/report.rs | 3 + crates/stackarr-cardigann/src/categories.rs | 3 + crates/stackarr-cardigann/src/definition.rs | 3 + crates/stackarr-cardigann/src/filters.rs | 3 + crates/stackarr-cardigann/src/lib.rs | 3 + crates/stackarr-cardigann/src/search.rs | 3 + crates/stackarr-cardigann/src/selector.rs | 3 + crates/stackarr-cardigann/src/template.rs | 3 + crates/stackarr-core/src/auth.rs | 3 + crates/stackarr-core/src/config.rs | 3 + crates/stackarr-core/src/dav_db.rs | 3 + crates/stackarr-core/src/db.rs | 3 + crates/stackarr-core/src/error.rs | 3 + crates/stackarr-core/src/lib.rs | 3 + crates/stackarr-core/src/log_buffer.rs | 3 + crates/stackarr-core/src/models.rs | 3 + crates/stackarr-core/src/models/discover.rs | 3 + crates/stackarr-core/src/models/download.rs | 3 + crates/stackarr-core/src/models/history.rs | 3 + .../src/models/import_candidate.rs | 3 + crates/stackarr-core/src/models/media.rs | 3 + crates/stackarr-core/src/models/quality.rs | 3 + crates/stackarr-core/src/models/rss.rs | 3 + crates/stackarr-core/src/models/user.rs | 3 + crates/stackarr-core/src/notifications.rs | 3 + crates/stackarr-core/src/test_helpers.rs | 3 + crates/stackarr-download/src/client.rs | 3 + .../stackarr-download/src/embedded_torrent.rs | 3 + .../stackarr-download/src/embedded_usenet.rs | 3 + crates/stackarr-download/src/factory.rs | 3 + crates/stackarr-download/src/lib.rs | 3 + crates/stackarr-download/src/manager.rs | 3 + crates/stackarr-download/src/nzbget.rs | 3 + crates/stackarr-download/src/qbittorrent.rs | 3 + crates/stackarr-download/src/sabnzbd.rs | 3 + crates/stackarr-download/src/transmission.rs | 3 + crates/stackarr-import/src/lib.rs | 3 + crates/stackarr-import/src/naming.rs | 3 + crates/stackarr-import/src/recycle_bin.rs | 3 + crates/stackarr-import/src/tmdb_match.rs | 3 + crates/stackarr-import/src/upgrade.rs | 3 + crates/stackarr-indexer/src/indexarr.rs | 3 + crates/stackarr-indexer/src/lib.rs | 3 + crates/stackarr-indexer/src/manager.rs | 3 + crates/stackarr-indexer/src/newznab.rs | 3 + crates/stackarr-indexer/src/search.rs | 3 + crates/stackarr-media/src/import_lists.rs | 3 + crates/stackarr-media/src/lib.rs | 3 + crates/stackarr-metadata/src/lib.rs | 3 + crates/stackarr-migrate/src/lib.rs | 3 + crates/stackarr-migrate/src/prowlarr.rs | 3 + crates/stackarr-migrate/src/radarr.rs | 3 + crates/stackarr-migrate/src/sonarr.rs | 3 + crates/stackarr-migrate/src/writer.rs | 3 + .../stackarr-migrate/tests/import_fixtures.rs | 3 + crates/stackarr-notify/src/lib.rs | 3 + crates/stackarr-parser/src/episode.rs | 3 + crates/stackarr-parser/src/language.rs | 3 + crates/stackarr-parser/src/lib.rs | 3 + crates/stackarr-parser/src/quality.rs | 3 + crates/stackarr-parser/src/release.rs | 3 + crates/stackarr-parser/src/title.rs | 3 + crates/stackarr-plex/src/api.rs | 3 + crates/stackarr-plex/src/guid.rs | 3 + crates/stackarr-plex/src/lib.rs | 3 + crates/stackarr-plex/src/scanner.rs | 3 + crates/stackarr-plex/src/sync.rs | 3 + crates/stackarr-plex/src/types.rs | 3 + crates/stackarr-postgres/src/config.rs | 3 + crates/stackarr-postgres/src/error.rs | 3 + crates/stackarr-postgres/src/lib.rs | 3 + crates/stackarr-postgres/src/lifecycle.rs | 3 + crates/stackarr-postgres/src/provision.rs | 3 + crates/stackarr-quality/src/custom_formats.rs | 3 + crates/stackarr-quality/src/lib.rs | 3 + crates/stackarr-scheduler/src/auto_search.rs | 3 + crates/stackarr-scheduler/src/health.rs | 3 + crates/stackarr-scheduler/src/lib.rs | 3 + crates/stackarr-scheduler/src/rss.rs | 3 + .../stackarr-scheduler/src/task_registry.rs | 3 + crates/stackarr-stream/src/direct.rs | 3 + crates/stackarr-stream/src/error.rs | 3 + crates/stackarr-stream/src/ffmpeg.rs | 3 + crates/stackarr-stream/src/ffprobe.rs | 3 + crates/stackarr-stream/src/hls.rs | 3 + crates/stackarr-stream/src/lib.rs | 3 + crates/stackarr-stream/src/provision.rs | 3 + crates/stackarr-stream/src/session.rs | 3 + crates/stackarr-stream/src/subtitle.rs | 3 + crates/stackarr-stream/src/types.rs | 3 + crates/stackarr-web/src/dav_manager.rs | 3 + crates/stackarr-web/src/embedded_ui.rs | 3 + crates/stackarr-web/src/lib.rs | 3 + crates/stackarr-web/src/middleware.rs | 3 + crates/stackarr-web/src/openapi.rs | 3 + crates/stackarr-web/src/routes/activities.rs | 3 + crates/stackarr-web/src/routes/admin.rs | 3 + crates/stackarr-web/src/routes/auth.rs | 3 + crates/stackarr-web/src/routes/backup.rs | 3 + crates/stackarr-web/src/routes/blocklist.rs | 3 + crates/stackarr-web/src/routes/bootstrap.rs | 3 + crates/stackarr-web/src/routes/calendar.rs | 3 + crates/stackarr-web/src/routes/dav.rs | 3 + crates/stackarr-web/src/routes/discover.rs | 3 + .../src/routes/downloadclients.rs | 3 + crates/stackarr-web/src/routes/episodes.rs | 3 + crates/stackarr-web/src/routes/filebrowser.rs | 3 + crates/stackarr-web/src/routes/general.rs | 3 + crates/stackarr-web/src/routes/health.rs | 3 + crates/stackarr-web/src/routes/history.rs | 3 + crates/stackarr-web/src/routes/images.rs | 3 + .../src/routes/import_candidates.rs | 3 + crates/stackarr-web/src/routes/importlists.rs | 3 + crates/stackarr-web/src/routes/indexarr.rs | 3 + crates/stackarr-web/src/routes/indexers.rs | 3 + crates/stackarr-web/src/routes/logs.rs | 3 + .../stackarr-web/src/routes/manual_import.rs | 3 + .../src/routes/medialibraryfolders.rs | 3 + .../src/routes/mediamanagement.rs | 3 + crates/stackarr-web/src/routes/mod.rs | 3 + crates/stackarr-web/src/routes/movies.rs | 3 + crates/stackarr-web/src/routes/naming.rs | 3 + .../src/routes/notification_providers.rs | 3 + .../stackarr-web/src/routes/notifications.rs | 3 + crates/stackarr-web/src/routes/plex.rs | 3 + crates/stackarr-web/src/routes/progress.rs | 3 + crates/stackarr-web/src/routes/quality.rs | 3 + crates/stackarr-web/src/routes/queue.rs | 3 + crates/stackarr-web/src/routes/releases.rs | 3 + crates/stackarr-web/src/routes/remote.rs | 3 + crates/stackarr-web/src/routes/requests.rs | 3 + crates/stackarr-web/src/routes/rss.rs | 3 + crates/stackarr-web/src/routes/scheduler.rs | 3 + crates/stackarr-web/src/routes/search.rs | 3 + crates/stackarr-web/src/routes/series.rs | 3 + crates/stackarr-web/src/routes/stream.rs | 3 + crates/stackarr-web/src/routes/stremio.rs | 3 + crates/stackarr-web/src/routes/system.rs | 3 + crates/stackarr-web/src/routes/tags.rs | 3 + crates/stackarr-web/src/routes/torrent.rs | 3 + crates/stackarr-web/src/routes/usenet.rs | 3 + crates/stackarr-web/src/routes/user.rs | 3 + crates/stackarr-web/src/routes/wanted.rs | 3 + crates/stackarr-web/src/routes/watchlist.rs | 3 + crates/stackarr-web/src/state.rs | 3 + docker/build-test.sh | 3 + docker/init-indexarr-db.sh | 3 + docker/run-tests.sh | 3 + scripts/check_dependency_sources.py | 3 + scripts/check_license_headers.py | 113 ++++++++++++++++++ scripts/check_workspace_docs.py | 3 + scripts/convert_sql_placeholders.py | 3 + src/main.rs | 3 + tests/e2e/common.sh | 3 + tests/e2e/setup-existing.sh | 3 + tests/e2e/test-existing.sh | 3 + tests/e2e/test-fresh.sh | 3 + tests/e2e/test-import.sh | 3 + tests/e2e/test-quality-parity.sh | 3 + ui/e2e/calendar.spec.ts | 3 + ui/e2e/connection-error.spec.ts | 3 + ui/e2e/discover.spec.ts | 3 + ui/e2e/docker-live.spec.ts | 3 + ui/e2e/first-boot.spec.ts | 3 + ui/e2e/fixtures.ts | 3 + ui/e2e/history.spec.ts | 3 + ui/e2e/live-auth.spec.ts | 3 + ui/e2e/live-discover.spec.ts | 3 + ui/e2e/live-download-clients.spec.ts | 3 + ui/e2e/live-indexers.spec.ts | 3 + ui/e2e/live-movies.spec.ts | 3 + ui/e2e/live-quality-tags-folders.spec.ts | 3 + ui/e2e/live-series.spec.ts | 3 + ui/e2e/live-settings-misc.spec.ts | 3 + ui/e2e/live-torrent.spec.ts | 3 + ui/e2e/live-usenet.spec.ts | 3 + ui/e2e/live.spec.ts | 3 + ui/e2e/login.spec.ts | 3 + ui/e2e/logs.spec.ts | 3 + ui/e2e/manage-test-env.sh | 3 + ui/e2e/movies.spec.ts | 3 + ui/e2e/navigation.spec.ts | 3 + ui/e2e/queue.spec.ts | 3 + ui/e2e/search.spec.ts | 3 + ui/e2e/series.spec.ts | 3 + ui/e2e/settings.spec.ts | 3 + ui/e2e/torrents.spec.ts | 3 + ui/e2e/usenet.spec.ts | 3 + ui/e2e/users.spec.ts | 3 + ui/e2e/watchlist.spec.ts | 3 + ui/eslint.config.js | 3 + ui/playwright.config.ts | 3 + ui/src/App.tsx | 3 + ui/src/api/client.ts | 3 + ui/src/api/types.ts | 3 + .../components/ActivityNotificationBell.tsx | 3 + .../components/ActivityNotificationPopup.tsx | 3 + ui/src/components/ActivityPanel.tsx | 3 + ui/src/components/ActivityTab.tsx | 3 + ui/src/components/AddToLibraryModal.tsx | 3 + ui/src/components/BulkEditBar.tsx | 3 + ui/src/components/BulkImportModal.tsx | 3 + ui/src/components/EventsTab.tsx | 3 + ui/src/components/GenreSlider.tsx | 3 + ui/src/components/HistoryDetailModal.tsx | 3 + ui/src/components/InteractiveSearchModal.tsx | 3 + ui/src/components/Layout.tsx | 3 + ui/src/components/ManualImportModal.tsx | 3 + ui/src/components/MediaCard.tsx | 3 + ui/src/components/MediaFileDetailModal.tsx | 3 + ui/src/components/MediaSlider.tsx | 3 + ui/src/components/MovieBrowse.tsx | 3 + ui/src/components/NotificationTab.tsx | 3 + ui/src/components/SeriesBrowse.tsx | 3 + ui/src/components/Sidebar.tsx | 3 + ui/src/components/VideoPlayer.tsx | 3 + ui/src/hooks/useApi.ts | 3 + ui/src/index.css | 3 + ui/src/main.tsx | 3 + ui/src/pages/Blocklist.tsx | 3 + ui/src/pages/Calendar.tsx | 3 + ui/src/pages/Discover.tsx | 3 + ui/src/pages/FileBrowser.tsx | 3 + ui/src/pages/FirstBoot.tsx | 3 + ui/src/pages/History.tsx | 3 + ui/src/pages/Import.tsx | 3 + ui/src/pages/LiveStream.tsx | 3 + ui/src/pages/Login.tsx | 3 + ui/src/pages/Logs.tsx | 3 + ui/src/pages/Migrate.tsx | 3 + ui/src/pages/MovieDetail.tsx | 3 + ui/src/pages/MovieList.tsx | 3 + ui/src/pages/Notifications.tsx | 3 + ui/src/pages/Player.tsx | 3 + ui/src/pages/PlexActivity.tsx | 3 + ui/src/pages/Queue.tsx | 3 + ui/src/pages/Requests.tsx | 3 + ui/src/pages/Rss.tsx | 3 + ui/src/pages/Search.tsx | 3 + ui/src/pages/SeriesDetail.tsx | 3 + ui/src/pages/SeriesList.tsx | 3 + ui/src/pages/ServerConnect.tsx | 3 + ui/src/pages/Settings.tsx | 3 + ui/src/pages/Streaming.tsx | 3 + ui/src/pages/Torrents.tsx | 3 + ui/src/pages/Usenet.tsx | 3 + ui/src/pages/Users.tsx | 3 + ui/src/pages/Wanted.tsx | 3 + ui/src/pages/Watchlist.tsx | 3 + ui/src/utils/clipboard.ts | 3 + ui/src/utils/date.ts | 3 + ui/vite.config.ts | 3 + 302 files changed, 1026 insertions(+) create mode 100644 scripts/check_license_headers.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a49ebab3..27b9eeb5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,8 @@ jobs: run: python3 scripts/check_dependency_sources.py - name: Verify workspace documentation run: python3 scripts/check_workspace_docs.py + - name: Verify GPL-3.0 source headers + run: python3 scripts/check_license_headers.py - run: cargo fmt --all -- --check - run: cargo clippy --workspace --all-features --locked -- -D warnings diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a4bd6922..1f23cfed 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,6 +33,20 @@ only with executable evidence against the governing specification. - A new `#[allow(...)]` must have an adjacent comment that names the concrete reason it is necessary. +## Licensing + +StackArr is GPL-3.0-only. Every first-party source file starts with the SPDX +header, below any shebang and before the rest of the file: + +``` +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors +``` + +Use `#` comments in shell and Python and `/* */` in CSS. New files are covered +by `python3 scripts/check_license_headers.py`, which CI runs and which inserts +missing headers when passed `--fix`. + ## Required gates The repository toolchain is pinned in `rust-toolchain.toml`. Before every diff --git a/client/eslint.config.js b/client/eslint.config.js index 5e6b472f..bdb4a366 100644 --- a/client/eslint.config.js +++ b/client/eslint.config.js @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import js from '@eslint/js' import globals from 'globals' import reactHooks from 'eslint-plugin-react-hooks' diff --git a/client/public/sw.js b/client/public/sw.js index 2ca9102e..b080b30a 100644 --- a/client/public/sw.js +++ b/client/public/sw.js @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + const CACHE_NAME = 'stackarr-shell-v1'; const SHELL_URLS = [ '/app/', diff --git a/client/src-tauri/build.rs b/client/src-tauri/build.rs index 261851f6..47adaa01 100644 --- a/client/src-tauri/build.rs +++ b/client/src-tauri/build.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + fn main() { tauri_build::build(); } diff --git a/client/src-tauri/src/lib.rs b/client/src-tauri/src/lib.rs index 3b48e91a..24929562 100644 --- a/client/src-tauri/src/lib.rs +++ b/client/src-tauri/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() diff --git a/client/src-tauri/src/main.rs b/client/src-tauri/src/main.rs index b5e3ed9d..cfe9113f 100644 --- a/client/src-tauri/src/main.rs +++ b/client/src-tauri/src/main.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + // Prevents additional console window on Windows in release #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] diff --git a/client/src/App.tsx b/client/src/App.tsx index f8b5c238..112cfdc6 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useCallback } from 'react' import { Routes, Route, NavLink, useLocation, useNavigate } from 'react-router-dom' import { Tv, Film, Home, LogOut, User, Search, ListChecks, Bookmark, Settings, Calendar, Download, Clock } from 'lucide-react' diff --git a/client/src/api.ts b/client/src/api.ts index 67a52d11..b35ecd87 100644 --- a/client/src/api.ts +++ b/client/src/api.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + // ── Connection management ─────────────────────────────────────────────────── export interface ServerConnection { diff --git a/client/src/components/ActivityIndicator.tsx b/client/src/components/ActivityIndicator.tsx index 276e8ce2..45d1af9d 100644 --- a/client/src/components/ActivityIndicator.tsx +++ b/client/src/components/ActivityIndicator.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { Loader2 } from 'lucide-react' import { useRunningActivities } from '../hooks/useApi' diff --git a/client/src/components/DiscoverGrid.tsx b/client/src/components/DiscoverGrid.tsx index 42571612..d2cae6b1 100644 --- a/client/src/components/DiscoverGrid.tsx +++ b/client/src/components/DiscoverGrid.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { Check, Clock, Library, Plus, X } from 'lucide-react' import { imageUrl, type DiscoverResult } from '../api' import { useMobile } from '../hooks/useMobile' diff --git a/client/src/components/ErrorBoundary.tsx b/client/src/components/ErrorBoundary.tsx index 9d29c1d9..891dc557 100644 --- a/client/src/components/ErrorBoundary.tsx +++ b/client/src/components/ErrorBoundary.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { Component, type ReactNode } from 'react' import type { ErrorInfo } from 'react' diff --git a/client/src/components/MediaRow.tsx b/client/src/components/MediaRow.tsx index 657b6e03..3f1a86f2 100644 --- a/client/src/components/MediaRow.tsx +++ b/client/src/components/MediaRow.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useNavigate } from 'react-router-dom' import { imageUrl, type ContinueWatchingItem } from '../api' import { useMobile } from '../hooks/useMobile' diff --git a/client/src/components/NotificationBell.tsx b/client/src/components/NotificationBell.tsx index 112f70cb..1d02a4ae 100644 --- a/client/src/components/NotificationBell.tsx +++ b/client/src/components/NotificationBell.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useRef, useCallback } from 'react' import { useNavigate } from 'react-router-dom' import { Bell } from 'lucide-react' diff --git a/client/src/components/NotificationDropdown.tsx b/client/src/components/NotificationDropdown.tsx index ab201d86..fd406e00 100644 --- a/client/src/components/NotificationDropdown.tsx +++ b/client/src/components/NotificationDropdown.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import type { UserNotification } from '../api' import NotificationItem from './NotificationItem' import { useMobile } from '../hooks/useMobile' diff --git a/client/src/components/NotificationItem.tsx b/client/src/components/NotificationItem.tsx index aeaafefd..d167b1af 100644 --- a/client/src/components/NotificationItem.tsx +++ b/client/src/components/NotificationItem.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import type { UserNotification } from '../api' function relativeTime(dateStr: string): string { diff --git a/client/src/components/ProgressReporter.tsx b/client/src/components/ProgressReporter.tsx index 39628540..6ff17cab 100644 --- a/client/src/components/ProgressReporter.tsx +++ b/client/src/components/ProgressReporter.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useEffect, useRef, useCallback } from 'react' import { api } from '../api' diff --git a/client/src/components/RatingStars.tsx b/client/src/components/RatingStars.tsx index ede16d75..786d3387 100644 --- a/client/src/components/RatingStars.tsx +++ b/client/src/components/RatingStars.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { Star } from 'lucide-react' import { useRating, useSetRating, useDeleteRating } from '../hooks/useApi' diff --git a/client/src/components/RequestCard.tsx b/client/src/components/RequestCard.tsx index 878a8f6a..fffbcb8e 100644 --- a/client/src/components/RequestCard.tsx +++ b/client/src/components/RequestCard.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { Clock, Check, X, Library } from 'lucide-react' import { imageUrl, type MediaRequest } from '../api' diff --git a/client/src/components/Skeleton.tsx b/client/src/components/Skeleton.tsx index fcd92588..95ac275c 100644 --- a/client/src/components/Skeleton.tsx +++ b/client/src/components/Skeleton.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + const shimmerBg = 'linear-gradient(90deg, #1e293b 25%, #334155 50%, #1e293b 75%)' const shimmerSize = '200% 100%' const shimmerAnim = 'shimmer 1.5s infinite' diff --git a/client/src/components/StreamStats.tsx b/client/src/components/StreamStats.tsx index 9c864f92..0917e587 100644 --- a/client/src/components/StreamStats.tsx +++ b/client/src/components/StreamStats.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useEffect, useState, useRef } from 'react' import Hls from 'hls.js' diff --git a/client/src/components/TmdbRow.tsx b/client/src/components/TmdbRow.tsx index 1e4dddc6..56f1ea7b 100644 --- a/client/src/components/TmdbRow.tsx +++ b/client/src/components/TmdbRow.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { Film } from 'lucide-react' import { imageUrl } from '../api' import { useMobile } from '../hooks/useMobile' diff --git a/client/src/components/WatchlistButton.tsx b/client/src/components/WatchlistButton.tsx index dc3df1e5..268dc1e1 100644 --- a/client/src/components/WatchlistButton.tsx +++ b/client/src/components/WatchlistButton.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect } from 'react' import { Bookmark } from 'lucide-react' import { api } from '../api' diff --git a/client/src/context/AuthContext.tsx b/client/src/context/AuthContext.tsx index 4d9036f7..27b966ea 100644 --- a/client/src/context/AuthContext.tsx +++ b/client/src/context/AuthContext.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /* eslint-disable react-refresh/only-export-components -- context files co-export provider + context value */ import { createContext, useState, useEffect, useCallback, type ReactNode } from 'react' diff --git a/client/src/globals.d.ts b/client/src/globals.d.ts index e042dcc5..694bd1be 100644 --- a/client/src/globals.d.ts +++ b/client/src/globals.d.ts @@ -1 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + declare const __APP_VERSION__: string diff --git a/client/src/hooks/useApi.ts b/client/src/hooks/useApi.ts index 0524b2fc..8472f1d0 100644 --- a/client/src/hooks/useApi.ts +++ b/client/src/hooks/useApi.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { api } from '../api' diff --git a/client/src/hooks/useAuth.ts b/client/src/hooks/useAuth.ts index 7b506c80..91a662de 100644 --- a/client/src/hooks/useAuth.ts +++ b/client/src/hooks/useAuth.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useContext } from 'react' import { AuthContext } from '../context/AuthContext' import type { AuthContextValue } from '../context/AuthContext' diff --git a/client/src/hooks/useMobile.ts b/client/src/hooks/useMobile.ts index fd13349f..c13e7859 100644 --- a/client/src/hooks/useMobile.ts +++ b/client/src/hooks/useMobile.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useSyncExternalStore } from 'react' const MOBILE_BREAKPOINT = 768 diff --git a/client/src/main.tsx b/client/src/main.tsx index 48a5f96e..008b591f 100644 --- a/client/src/main.tsx +++ b/client/src/main.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /* eslint-disable react-refresh/only-export-components -- entry point, no HMR exports needed */ import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' diff --git a/client/src/pages/AccountPage.tsx b/client/src/pages/AccountPage.tsx index 1cd370a1..f70ec062 100644 --- a/client/src/pages/AccountPage.tsx +++ b/client/src/pages/AccountPage.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { Monitor, Smartphone, Globe, Trash2, LogOut } from 'lucide-react' import { useAuth } from '../hooks/useAuth' diff --git a/client/src/pages/Browse.tsx b/client/src/pages/Browse.tsx index 9b211e94..67eadb1d 100644 --- a/client/src/pages/Browse.tsx +++ b/client/src/pages/Browse.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useMemo } from 'react' import { useNavigate } from 'react-router-dom' import { Search, Play, Film } from 'lucide-react' diff --git a/client/src/pages/CalendarPage.tsx b/client/src/pages/CalendarPage.tsx index 9be6295f..aa1e28b6 100644 --- a/client/src/pages/CalendarPage.tsx +++ b/client/src/pages/CalendarPage.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useMemo, useState } from 'react' import { useNavigate } from 'react-router-dom' import { ChevronLeft, ChevronRight, Check, Clock } from 'lucide-react' diff --git a/client/src/pages/DiscoverPage.tsx b/client/src/pages/DiscoverPage.tsx index d6f2a000..429f424b 100644 --- a/client/src/pages/DiscoverPage.tsx +++ b/client/src/pages/DiscoverPage.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useCallback, useRef, useEffect } from 'react' import { useNavigate, useSearchParams } from 'react-router-dom' import { Search, Film, Tv } from 'lucide-react' diff --git a/client/src/pages/HistoryPage.tsx b/client/src/pages/HistoryPage.tsx index 24d7798a..dd737b61 100644 --- a/client/src/pages/HistoryPage.tsx +++ b/client/src/pages/HistoryPage.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { useNavigate } from 'react-router-dom' import { ChevronLeft, ChevronRight, Download, Upload, Search, Trash2, RotateCcw, Clock } from 'lucide-react' diff --git a/client/src/pages/HomePage.tsx b/client/src/pages/HomePage.tsx index 1f1f6463..c3dfbef1 100644 --- a/client/src/pages/HomePage.tsx +++ b/client/src/pages/HomePage.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useMemo, useCallback } from 'react' import { useNavigate } from 'react-router-dom' import { Play } from 'lucide-react' diff --git a/client/src/pages/LoginPage.tsx b/client/src/pages/LoginPage.tsx index 78dc732e..b92cfd70 100644 --- a/client/src/pages/LoginPage.tsx +++ b/client/src/pages/LoginPage.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { useAuth } from '../hooks/useAuth' import { labelStyle, inputStyle, buttonStyleDisabled } from '../styles/forms' diff --git a/client/src/pages/MovieView.tsx b/client/src/pages/MovieView.tsx index 619db9d4..94c49959 100644 --- a/client/src/pages/MovieView.tsx +++ b/client/src/pages/MovieView.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useCallback } from 'react' import { useParams, useNavigate } from 'react-router-dom' import { ArrowLeft, Play, Film } from 'lucide-react' diff --git a/client/src/pages/Player.tsx b/client/src/pages/Player.tsx index fef622a1..6991815d 100644 --- a/client/src/pages/Player.tsx +++ b/client/src/pages/Player.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useEffect, useRef, useState, useCallback } from 'react' import { useParams, useNavigate, useLocation } from 'react-router-dom' import { ArrowLeft, Maximize, Minimize, RotateCcw, RotateCw, PictureInPicture2, Play, Pause } from 'lucide-react' diff --git a/client/src/pages/QueuePage.tsx b/client/src/pages/QueuePage.tsx index 38d504f2..de31d7a1 100644 --- a/client/src/pages/QueuePage.tsx +++ b/client/src/pages/QueuePage.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useNavigate } from 'react-router-dom' import { Download, Trash2, AlertCircle, ArrowDown, ArrowUp } from 'lucide-react' import type { QueueItem } from '../api' diff --git a/client/src/pages/RegisterPage.tsx b/client/src/pages/RegisterPage.tsx index 1ad63e24..2638eef7 100644 --- a/client/src/pages/RegisterPage.tsx +++ b/client/src/pages/RegisterPage.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { useAuth } from '../hooks/useAuth' import { labelStyle, inputStyle, buttonStyleDisabled } from '../styles/forms' diff --git a/client/src/pages/RequestsPage.tsx b/client/src/pages/RequestsPage.tsx index 2f7ecbd8..d5826cd3 100644 --- a/client/src/pages/RequestsPage.tsx +++ b/client/src/pages/RequestsPage.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useMemo } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { Check, X } from 'lucide-react' diff --git a/client/src/pages/SeriesView.tsx b/client/src/pages/SeriesView.tsx index 55f99ab4..55fca227 100644 --- a/client/src/pages/SeriesView.tsx +++ b/client/src/pages/SeriesView.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useCallback } from 'react' import { useParams, useNavigate } from 'react-router-dom' import { ArrowLeft, Play, ChevronDown, ChevronRight } from 'lucide-react' diff --git a/client/src/pages/ServerConnect.tsx b/client/src/pages/ServerConnect.tsx index e691d155..1fc95ba8 100644 --- a/client/src/pages/ServerConnect.tsx +++ b/client/src/pages/ServerConnect.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { redeemClaimCode, saveConnection, assetUrl, type ServerConnection } from '../api' import { labelStyle, inputStyle, buttonStyleDisabled } from '../styles/forms' diff --git a/client/src/pages/WatchlistPage.tsx b/client/src/pages/WatchlistPage.tsx index f6e7d62f..96a7c257 100644 --- a/client/src/pages/WatchlistPage.tsx +++ b/client/src/pages/WatchlistPage.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useMemo } from 'react' import { useNavigate } from 'react-router-dom' import { Bookmark, X, Tv, Film } from 'lucide-react' diff --git a/client/src/styles/forms.ts b/client/src/styles/forms.ts index da785d9b..f6e29376 100644 --- a/client/src/styles/forms.ts +++ b/client/src/styles/forms.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import type { CSSProperties } from 'react' export const labelStyle: CSSProperties = { diff --git a/client/vite.config.ts b/client/vite.config.ts index 7b4e8179..63d5f14b 100644 --- a/client/vite.config.ts +++ b/client/vite.config.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' diff --git a/crates/stackarr-cardigann-parity/src/comparator.rs b/crates/stackarr-cardigann-parity/src/comparator.rs index fcc05602..19dedcc7 100644 --- a/crates/stackarr-cardigann-parity/src/comparator.rs +++ b/crates/stackarr-cardigann-parity/src/comparator.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Compare Prowlarr search results with StackArr Cardigann engine results. use std::collections::HashMap; diff --git a/crates/stackarr-cardigann-parity/src/main.rs b/crates/stackarr-cardigann-parity/src/main.rs index d957d524..e146e029 100644 --- a/crates/stackarr-cardigann-parity/src/main.rs +++ b/crates/stackarr-cardigann-parity/src/main.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Cardigann parity test harness. //! //! Spins up a dedicated Prowlarr instance, provisions all public indexers, diff --git a/crates/stackarr-cardigann-parity/src/provisioner.rs b/crates/stackarr-cardigann-parity/src/provisioner.rs index b7a6f1df..5bc6f407 100644 --- a/crates/stackarr-cardigann-parity/src/provisioner.rs +++ b/crates/stackarr-cardigann-parity/src/provisioner.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Auto-provision all public Cardigann indexers in a Prowlarr instance. use anyhow::{Context, Result}; diff --git a/crates/stackarr-cardigann-parity/src/prowlarr_api.rs b/crates/stackarr-cardigann-parity/src/prowlarr_api.rs index 33830f25..ad99dfad 100644 --- a/crates/stackarr-cardigann-parity/src/prowlarr_api.rs +++ b/crates/stackarr-cardigann-parity/src/prowlarr_api.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Prowlarr REST API client for the parity test harness. use std::time::Duration; diff --git a/crates/stackarr-cardigann-parity/src/report.rs b/crates/stackarr-cardigann-parity/src/report.rs index 807ee533..e501dbbd 100644 --- a/crates/stackarr-cardigann-parity/src/report.rs +++ b/crates/stackarr-cardigann-parity/src/report.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Parity report generation. use std::path::Path; diff --git a/crates/stackarr-cardigann/src/categories.rs b/crates/stackarr-cardigann/src/categories.rs index f40cdc52..eb228df7 100644 --- a/crates/stackarr-cardigann/src/categories.rs +++ b/crates/stackarr-cardigann/src/categories.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Category mapping between Cardigann indexer categories and Newznab standard categories. use std::collections::HashMap; diff --git a/crates/stackarr-cardigann/src/definition.rs b/crates/stackarr-cardigann/src/definition.rs index 6b64b7f5..318430d6 100644 --- a/crates/stackarr-cardigann/src/definition.rs +++ b/crates/stackarr-cardigann/src/definition.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Serde structs for Cardigann YAML definitions. //! //! These mirror Prowlarr's `CardigannDefinition.cs` types and are deserialized diff --git a/crates/stackarr-cardigann/src/filters.rs b/crates/stackarr-cardigann/src/filters.rs index 2e5a4292..2fbfdbf2 100644 --- a/crates/stackarr-cardigann/src/filters.rs +++ b/crates/stackarr-cardigann/src/filters.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Filter implementations for Cardigann field value transforms. //! //! Each filter takes an input string and optional arguments and returns diff --git a/crates/stackarr-cardigann/src/lib.rs b/crates/stackarr-cardigann/src/lib.rs index febb4287..dcad849c 100644 --- a/crates/stackarr-cardigann/src/lib.rs +++ b/crates/stackarr-cardigann/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Cardigann YAML definition engine for StackArr. //! //! Interprets Prowlarr-compatible Cardigann YAML indexer definitions, diff --git a/crates/stackarr-cardigann/src/search.rs b/crates/stackarr-cardigann/src/search.rs index 20e76bcf..bacfa0b6 100644 --- a/crates/stackarr-cardigann/src/search.rs +++ b/crates/stackarr-cardigann/src/search.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Search execution: load definition → build URL → fetch → parse → return releases. use std::collections::HashMap; diff --git a/crates/stackarr-cardigann/src/selector.rs b/crates/stackarr-cardigann/src/selector.rs index 60d19cae..a5342676 100644 --- a/crates/stackarr-cardigann/src/selector.rs +++ b/crates/stackarr-cardigann/src/selector.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! HTML and JSON selector engine for extracting values from responses. //! //! HTML mode uses the `scraper` crate for CSS selectors. diff --git a/crates/stackarr-cardigann/src/template.rs b/crates/stackarr-cardigann/src/template.rs index ea2aef03..b4c9047d 100644 --- a/crates/stackarr-cardigann/src/template.rs +++ b/crates/stackarr-cardigann/src/template.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Go-template-like expression evaluator for Cardigann YAML paths and values. //! //! Supports the subset of Go templates actually used across Prowlarr's 549 diff --git a/crates/stackarr-core/src/auth.rs b/crates/stackarr-core/src/auth.rs index 5d04a917..130baef5 100644 --- a/crates/stackarr-core/src/auth.rs +++ b/crates/stackarr-core/src/auth.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use argon2::password_hash::SaltString; use argon2::password_hash::rand_core::OsRng; use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier}; diff --git a/crates/stackarr-core/src/config.rs b/crates/stackarr-core/src/config.rs index c6e2301c..7547f146 100644 --- a/crates/stackarr-core/src/config.rs +++ b/crates/stackarr-core/src/config.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use serde::{Deserialize, Serialize}; use std::path::{Path, PathBuf}; diff --git a/crates/stackarr-core/src/dav_db.rs b/crates/stackarr-core/src/dav_db.rs index b4831a30..60083a1d 100644 --- a/crates/stackarr-core/src/dav_db.rs +++ b/crates/stackarr-core/src/dav_db.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! `PostgresDavDatabase` — implements nzbdav-core's `DavDatabase` trait for PostgreSQL. use chrono::{DateTime, NaiveDateTime, Utc}; diff --git a/crates/stackarr-core/src/db.rs b/crates/stackarr-core/src/db.rs index d08d57c4..e7f46151 100644 --- a/crates/stackarr-core/src/db.rs +++ b/crates/stackarr-core/src/db.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::time::Duration; use chrono::{DateTime, Utc}; diff --git a/crates/stackarr-core/src/error.rs b/crates/stackarr-core/src/error.rs index 616e2200..4a66bb17 100644 --- a/crates/stackarr-core/src/error.rs +++ b/crates/stackarr-core/src/error.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use thiserror::Error; pub type Result = std::result::Result; diff --git a/crates/stackarr-core/src/lib.rs b/crates/stackarr-core/src/lib.rs index 21f06ef2..4f6bd888 100644 --- a/crates/stackarr-core/src/lib.rs +++ b/crates/stackarr-core/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod auth; pub mod config; pub mod dav_db; diff --git a/crates/stackarr-core/src/log_buffer.rs b/crates/stackarr-core/src/log_buffer.rs index 9f127046..a6569f9e 100644 --- a/crates/stackarr-core/src/log_buffer.rs +++ b/crates/stackarr-core/src/log_buffer.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! In-memory ring buffer for application log entries. //! //! A custom `tracing::Layer` captures log events into a bounded buffer. diff --git a/crates/stackarr-core/src/models.rs b/crates/stackarr-core/src/models.rs index a50843c8..c3e0dd40 100644 --- a/crates/stackarr-core/src/models.rs +++ b/crates/stackarr-core/src/models.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod discover; pub mod download; pub mod history; diff --git a/crates/stackarr-core/src/models/discover.rs b/crates/stackarr-core/src/models/discover.rs index 7c02cf48..039f2080 100644 --- a/crates/stackarr-core/src/models/discover.rs +++ b/crates/stackarr-core/src/models/discover.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::FromRow; diff --git a/crates/stackarr-core/src/models/download.rs b/crates/stackarr-core/src/models/download.rs index 23304859..478413f5 100644 --- a/crates/stackarr-core/src/models/download.rs +++ b/crates/stackarr-core/src/models/download.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::FromRow; diff --git a/crates/stackarr-core/src/models/history.rs b/crates/stackarr-core/src/models/history.rs index 09467316..264c947f 100644 --- a/crates/stackarr-core/src/models/history.rs +++ b/crates/stackarr-core/src/models/history.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::FromRow; diff --git a/crates/stackarr-core/src/models/import_candidate.rs b/crates/stackarr-core/src/models/import_candidate.rs index 7fde94d5..60ae849c 100644 --- a/crates/stackarr-core/src/models/import_candidate.rs +++ b/crates/stackarr-core/src/models/import_candidate.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::FromRow; diff --git a/crates/stackarr-core/src/models/media.rs b/crates/stackarr-core/src/models/media.rs index 2e989325..770333f4 100644 --- a/crates/stackarr-core/src/models/media.rs +++ b/crates/stackarr-core/src/models/media.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use chrono::{DateTime, NaiveDate, NaiveTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::FromRow; diff --git a/crates/stackarr-core/src/models/quality.rs b/crates/stackarr-core/src/models/quality.rs index 4194b1b7..962cf5df 100644 --- a/crates/stackarr-core/src/models/quality.rs +++ b/crates/stackarr-core/src/models/quality.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use serde::{Deserialize, Serialize}; use sqlx::FromRow; diff --git a/crates/stackarr-core/src/models/rss.rs b/crates/stackarr-core/src/models/rss.rs index beed9d02..6a5942e0 100644 --- a/crates/stackarr-core/src/models/rss.rs +++ b/crates/stackarr-core/src/models/rss.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::FromRow; diff --git a/crates/stackarr-core/src/models/user.rs b/crates/stackarr-core/src/models/user.rs index 3d683c44..be2c5ca2 100644 --- a/crates/stackarr-core/src/models/user.rs +++ b/crates/stackarr-core/src/models/user.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::FromRow; diff --git a/crates/stackarr-core/src/notifications.rs b/crates/stackarr-core/src/notifications.rs index 216fe364..6a4028ce 100644 --- a/crates/stackarr-core/src/notifications.rs +++ b/crates/stackarr-core/src/notifications.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use crate::db::Database; /// High-level helpers for creating notifications. diff --git a/crates/stackarr-core/src/test_helpers.rs b/crates/stackarr-core/src/test_helpers.rs index e8bc2ac2..f9a8ab28 100644 --- a/crates/stackarr-core/src/test_helpers.rs +++ b/crates/stackarr-core/src/test_helpers.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Test utilities for database-backed integration tests. //! //! Requires a running PostgreSQL instance (e.g. `docker compose -f docker/docker-compose.dev.yml up -d`). diff --git a/crates/stackarr-download/src/client.rs b/crates/stackarr-download/src/client.rs index 6f47bc76..9fa17494 100644 --- a/crates/stackarr-download/src/client.rs +++ b/crates/stackarr-download/src/client.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use async_trait::async_trait; diff --git a/crates/stackarr-download/src/embedded_torrent.rs b/crates/stackarr-download/src/embedded_torrent.rs index 830f40b9..83e673fa 100644 --- a/crates/stackarr-download/src/embedded_torrent.rs +++ b/crates/stackarr-download/src/embedded_torrent.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use std::sync::Arc; diff --git a/crates/stackarr-download/src/embedded_usenet.rs b/crates/stackarr-download/src/embedded_usenet.rs index 087ccdb5..2f3fdac0 100644 --- a/crates/stackarr-download/src/embedded_usenet.rs +++ b/crates/stackarr-download/src/embedded_usenet.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use std::sync::Arc; diff --git a/crates/stackarr-download/src/factory.rs b/crates/stackarr-download/src/factory.rs index 21625cfe..ddcbc36b 100644 --- a/crates/stackarr-download/src/factory.rs +++ b/crates/stackarr-download/src/factory.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use crate::client::DownloadClient; /// Build a download client instance from a `client_type` string and JSON config. diff --git a/crates/stackarr-download/src/lib.rs b/crates/stackarr-download/src/lib.rs index be3b48d1..9ad623e3 100644 --- a/crates/stackarr-download/src/lib.rs +++ b/crates/stackarr-download/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod client; pub mod embedded_torrent; pub mod embedded_usenet; diff --git a/crates/stackarr-download/src/manager.rs b/crates/stackarr-download/src/manager.rs index a38d3243..025108e2 100644 --- a/crates/stackarr-download/src/manager.rs +++ b/crates/stackarr-download/src/manager.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use anyhow::bail; use tracing::{debug, info, warn}; diff --git a/crates/stackarr-download/src/nzbget.rs b/crates/stackarr-download/src/nzbget.rs index fa424621..49620d8a 100644 --- a/crates/stackarr-download/src/nzbget.rs +++ b/crates/stackarr-download/src/nzbget.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use anyhow::{Context, bail}; diff --git a/crates/stackarr-download/src/qbittorrent.rs b/crates/stackarr-download/src/qbittorrent.rs index c7cb0896..2cb4aadd 100644 --- a/crates/stackarr-download/src/qbittorrent.rs +++ b/crates/stackarr-download/src/qbittorrent.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use std::sync::Arc; diff --git a/crates/stackarr-download/src/sabnzbd.rs b/crates/stackarr-download/src/sabnzbd.rs index 90e86cae..937b0853 100644 --- a/crates/stackarr-download/src/sabnzbd.rs +++ b/crates/stackarr-download/src/sabnzbd.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use anyhow::{Context, bail}; diff --git a/crates/stackarr-download/src/transmission.rs b/crates/stackarr-download/src/transmission.rs index cacbd3b3..f5bfb1eb 100644 --- a/crates/stackarr-download/src/transmission.rs +++ b/crates/stackarr-download/src/transmission.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use anyhow::{Context, bail}; diff --git a/crates/stackarr-import/src/lib.rs b/crates/stackarr-import/src/lib.rs index a8a844f7..0ce041e1 100644 --- a/crates/stackarr-import/src/lib.rs +++ b/crates/stackarr-import/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod naming; pub mod recycle_bin; pub mod tmdb_match; diff --git a/crates/stackarr-import/src/naming.rs b/crates/stackarr-import/src/naming.rs index 3822bace..f31bfe64 100644 --- a/crates/stackarr-import/src/naming.rs +++ b/crates/stackarr-import/src/naming.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use once_cell::sync::Lazy; use regex::Regex; use stackarr_parser::Quality; diff --git a/crates/stackarr-import/src/recycle_bin.rs b/crates/stackarr-import/src/recycle_bin.rs index 70ca952a..f896d06c 100644 --- a/crates/stackarr-import/src/recycle_bin.rs +++ b/crates/stackarr-import/src/recycle_bin.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::{Path, PathBuf}; use anyhow::Result; diff --git a/crates/stackarr-import/src/tmdb_match.rs b/crates/stackarr-import/src/tmdb_match.rs index 6b8da9f4..25c99a16 100644 --- a/crates/stackarr-import/src/tmdb_match.rs +++ b/crates/stackarr-import/src/tmdb_match.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! TMDB fuzzy-match helper for the import-candidates pipeline. //! //! Given a parsed title (and optional year) that the disk scanner could not diff --git a/crates/stackarr-import/src/upgrade.rs b/crates/stackarr-import/src/upgrade.rs index 4094c8db..0e798df5 100644 --- a/crates/stackarr-import/src/upgrade.rs +++ b/crates/stackarr-import/src/upgrade.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use anyhow::Result; diff --git a/crates/stackarr-indexer/src/indexarr.rs b/crates/stackarr-indexer/src/indexarr.rs index 5e8704b3..d379a8d2 100644 --- a/crates/stackarr-indexer/src/indexarr.rs +++ b/crates/stackarr-indexer/src/indexarr.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::HashMap; use anyhow::{Context, bail}; diff --git a/crates/stackarr-indexer/src/lib.rs b/crates/stackarr-indexer/src/lib.rs index 376a4554..6501db7d 100644 --- a/crates/stackarr-indexer/src/lib.rs +++ b/crates/stackarr-indexer/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod indexarr; pub mod manager; pub mod newznab; diff --git a/crates/stackarr-indexer/src/manager.rs b/crates/stackarr-indexer/src/manager.rs index d571594d..69567473 100644 --- a/crates/stackarr-indexer/src/manager.rs +++ b/crates/stackarr-indexer/src/manager.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::HashMap; use std::sync::Arc; diff --git a/crates/stackarr-indexer/src/newznab.rs b/crates/stackarr-indexer/src/newznab.rs index a1ac38f0..ad6cb4cb 100644 --- a/crates/stackarr-indexer/src/newznab.rs +++ b/crates/stackarr-indexer/src/newznab.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use anyhow::{Context, bail}; use chrono::{DateTime, Utc}; use quick_xml::events::Event; diff --git a/crates/stackarr-indexer/src/search.rs b/crates/stackarr-indexer/src/search.rs index 25808362..da6c9cef 100644 --- a/crates/stackarr-indexer/src/search.rs +++ b/crates/stackarr-indexer/src/search.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::{HashMap, HashSet}; use std::sync::Arc; diff --git a/crates/stackarr-media/src/import_lists.rs b/crates/stackarr-media/src/import_lists.rs index fdc84599..49a6a349 100644 --- a/crates/stackarr-media/src/import_lists.rs +++ b/crates/stackarr-media/src/import_lists.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; use sqlx::PgPool; diff --git a/crates/stackarr-media/src/lib.rs b/crates/stackarr-media/src/lib.rs index c9602e33..6b4135cc 100644 --- a/crates/stackarr-media/src/lib.rs +++ b/crates/stackarr-media/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod import_lists; use anyhow::Result; diff --git a/crates/stackarr-metadata/src/lib.rs b/crates/stackarr-metadata/src/lib.rs index 4d2fc3e5..b79acf01 100644 --- a/crates/stackarr-metadata/src/lib.rs +++ b/crates/stackarr-metadata/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::num::NonZeroUsize; use std::sync::Arc; use std::time::{Duration, Instant}; diff --git a/crates/stackarr-migrate/src/lib.rs b/crates/stackarr-migrate/src/lib.rs index cc056148..651cabdc 100644 --- a/crates/stackarr-migrate/src/lib.rs +++ b/crates/stackarr-migrate/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod prowlarr; pub mod radarr; pub mod sonarr; diff --git a/crates/stackarr-migrate/src/prowlarr.rs b/crates/stackarr-migrate/src/prowlarr.rs index 0d410806..c1c5494d 100644 --- a/crates/stackarr-migrate/src/prowlarr.rs +++ b/crates/stackarr-migrate/src/prowlarr.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::Path; use anyhow::{Context, Result}; diff --git a/crates/stackarr-migrate/src/radarr.rs b/crates/stackarr-migrate/src/radarr.rs index c34e1844..b93e9194 100644 --- a/crates/stackarr-migrate/src/radarr.rs +++ b/crates/stackarr-migrate/src/radarr.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::Path; use anyhow::{Context, Result}; diff --git a/crates/stackarr-migrate/src/sonarr.rs b/crates/stackarr-migrate/src/sonarr.rs index 3ee7eda5..958e9a6e 100644 --- a/crates/stackarr-migrate/src/sonarr.rs +++ b/crates/stackarr-migrate/src/sonarr.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::Path; use anyhow::{Context, Result}; diff --git a/crates/stackarr-migrate/src/writer.rs b/crates/stackarr-migrate/src/writer.rs index 7460f2d0..48296595 100644 --- a/crates/stackarr-migrate/src/writer.rs +++ b/crates/stackarr-migrate/src/writer.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::HashMap; use anyhow::{Context, Result}; diff --git a/crates/stackarr-migrate/tests/import_fixtures.rs b/crates/stackarr-migrate/tests/import_fixtures.rs index 4e202951..fcb20b7a 100644 --- a/crates/stackarr-migrate/tests/import_fixtures.rs +++ b/crates/stackarr-migrate/tests/import_fixtures.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Integration test: import real Sonarr, Radarr, Prowlarr backups. //! //! Requires: diff --git a/crates/stackarr-notify/src/lib.rs b/crates/stackarr-notify/src/lib.rs index 41d6952b..b18617ed 100644 --- a/crates/stackarr-notify/src/lib.rs +++ b/crates/stackarr-notify/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use anyhow::Result; use serde::{Deserialize, Serialize}; diff --git a/crates/stackarr-parser/src/episode.rs b/crates/stackarr-parser/src/episode.rs index b308fc98..eb728141 100644 --- a/crates/stackarr-parser/src/episode.rs +++ b/crates/stackarr-parser/src/episode.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use chrono::NaiveDate; use once_cell::sync::Lazy; use regex::Regex; diff --git a/crates/stackarr-parser/src/language.rs b/crates/stackarr-parser/src/language.rs index c6e94575..3c39334a 100644 --- a/crates/stackarr-parser/src/language.rs +++ b/crates/stackarr-parser/src/language.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use once_cell::sync::Lazy; use regex::Regex; use serde::{Deserialize, Serialize}; diff --git a/crates/stackarr-parser/src/lib.rs b/crates/stackarr-parser/src/lib.rs index 38b5a38a..f873eb5d 100644 --- a/crates/stackarr-parser/src/lib.rs +++ b/crates/stackarr-parser/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod episode; pub mod language; pub mod quality; diff --git a/crates/stackarr-parser/src/quality.rs b/crates/stackarr-parser/src/quality.rs index 973f7c67..590f34b5 100644 --- a/crates/stackarr-parser/src/quality.rs +++ b/crates/stackarr-parser/src/quality.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use once_cell::sync::Lazy; use regex::Regex; use serde::{Deserialize, Serialize}; diff --git a/crates/stackarr-parser/src/release.rs b/crates/stackarr-parser/src/release.rs index 43e146ce..1537b4bf 100644 --- a/crates/stackarr-parser/src/release.rs +++ b/crates/stackarr-parser/src/release.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use once_cell::sync::Lazy; use regex::Regex; use serde::{Deserialize, Serialize}; diff --git a/crates/stackarr-parser/src/title.rs b/crates/stackarr-parser/src/title.rs index 7f059ba1..3d869f96 100644 --- a/crates/stackarr-parser/src/title.rs +++ b/crates/stackarr-parser/src/title.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use once_cell::sync::Lazy; use regex::Regex; diff --git a/crates/stackarr-plex/src/api.rs b/crates/stackarr-plex/src/api.rs index 592d2250..c75d36c1 100644 --- a/crates/stackarr-plex/src/api.rs +++ b/crates/stackarr-plex/src/api.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use anyhow::{Context, Result}; use reqwest::header::{HeaderMap, HeaderValue}; diff --git a/crates/stackarr-plex/src/guid.rs b/crates/stackarr-plex/src/guid.rs index 6fcbec00..c11ef1ba 100644 --- a/crates/stackarr-plex/src/guid.rs +++ b/crates/stackarr-plex/src/guid.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use regex::Regex; use std::sync::LazyLock; diff --git a/crates/stackarr-plex/src/lib.rs b/crates/stackarr-plex/src/lib.rs index ecac5a0a..56633e9c 100644 --- a/crates/stackarr-plex/src/lib.rs +++ b/crates/stackarr-plex/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod api; pub mod guid; pub mod scanner; diff --git a/crates/stackarr-plex/src/scanner.rs b/crates/stackarr-plex/src/scanner.rs index adccb5f0..8d5377f1 100644 --- a/crates/stackarr-plex/src/scanner.rs +++ b/crates/stackarr-plex/src/scanner.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use anyhow::Result; diff --git a/crates/stackarr-plex/src/sync.rs b/crates/stackarr-plex/src/sync.rs index 29383ed2..235f4e3a 100644 --- a/crates/stackarr-plex/src/sync.rs +++ b/crates/stackarr-plex/src/sync.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use anyhow::Result; use sqlx::PgPool; diff --git a/crates/stackarr-plex/src/types.rs b/crates/stackarr-plex/src/types.rs index 5777d6f3..c210d7bf 100644 --- a/crates/stackarr-plex/src/types.rs +++ b/crates/stackarr-plex/src/types.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::FromRow; diff --git a/crates/stackarr-postgres/src/config.rs b/crates/stackarr-postgres/src/config.rs index 41acd589..3b0f5dee 100644 --- a/crates/stackarr-postgres/src/config.rs +++ b/crates/stackarr-postgres/src/config.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; /// Resolved paths to PostgreSQL binaries and directories. diff --git a/crates/stackarr-postgres/src/error.rs b/crates/stackarr-postgres/src/error.rs index 1934c769..7bda3745 100644 --- a/crates/stackarr-postgres/src/error.rs +++ b/crates/stackarr-postgres/src/error.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /// PostgreSQL management errors. #[derive(Debug, thiserror::Error)] pub enum PostgresError { diff --git a/crates/stackarr-postgres/src/lib.rs b/crates/stackarr-postgres/src/lib.rs index 557e9d0b..b8d168f8 100644 --- a/crates/stackarr-postgres/src/lib.rs +++ b/crates/stackarr-postgres/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Managed PostgreSQL for StackArr. //! //! This crate provides automatic provisioning and lifecycle management of a diff --git a/crates/stackarr-postgres/src/lifecycle.rs b/crates/stackarr-postgres/src/lifecycle.rs index 89820d83..5a4be40f 100644 --- a/crates/stackarr-postgres/src/lifecycle.rs +++ b/crates/stackarr-postgres/src/lifecycle.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::{Path, PathBuf}; use crate::config::PgPaths; diff --git a/crates/stackarr-postgres/src/provision.rs b/crates/stackarr-postgres/src/provision.rs index 5aa12e0b..1ccd39f1 100644 --- a/crates/stackarr-postgres/src/provision.rs +++ b/crates/stackarr-postgres/src/provision.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::{Path, PathBuf}; use crate::config::{PgPaths, PgVersionInfo}; diff --git a/crates/stackarr-quality/src/custom_formats.rs b/crates/stackarr-quality/src/custom_formats.rs index 2a2684eb..9f345573 100644 --- a/crates/stackarr-quality/src/custom_formats.rs +++ b/crates/stackarr-quality/src/custom_formats.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::HashMap; use std::sync::{LazyLock, Mutex}; diff --git a/crates/stackarr-quality/src/lib.rs b/crates/stackarr-quality/src/lib.rs index d68f383b..b1481b24 100644 --- a/crates/stackarr-quality/src/lib.rs +++ b/crates/stackarr-quality/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod custom_formats; use anyhow::Result; diff --git a/crates/stackarr-scheduler/src/auto_search.rs b/crates/stackarr-scheduler/src/auto_search.rs index edf06649..2f64c7cc 100644 --- a/crates/stackarr-scheduler/src/auto_search.rs +++ b/crates/stackarr-scheduler/src/auto_search.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Automatic search for missing/wanted media. //! //! Provides the canonical `search_and_grab` implementation used by both the diff --git a/crates/stackarr-scheduler/src/health.rs b/crates/stackarr-scheduler/src/health.rs index 072d5ea8..7488e4aa 100644 --- a/crates/stackarr-scheduler/src/health.rs +++ b/crates/stackarr-scheduler/src/health.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use std::time::Duration; diff --git a/crates/stackarr-scheduler/src/lib.rs b/crates/stackarr-scheduler/src/lib.rs index aae11c0a..ae4e8b09 100644 --- a/crates/stackarr-scheduler/src/lib.rs +++ b/crates/stackarr-scheduler/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use std::time::Duration; diff --git a/crates/stackarr-scheduler/src/rss.rs b/crates/stackarr-scheduler/src/rss.rs index 98cc8940..35fc16f1 100644 --- a/crates/stackarr-scheduler/src/rss.rs +++ b/crates/stackarr-scheduler/src/rss.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use anyhow::{Context, Result}; diff --git a/crates/stackarr-scheduler/src/task_registry.rs b/crates/stackarr-scheduler/src/task_registry.rs index 98dff873..fdecb525 100644 --- a/crates/stackarr-scheduler/src/task_registry.rs +++ b/crates/stackarr-scheduler/src/task_registry.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use chrono::{DateTime, Utc}; diff --git a/crates/stackarr-stream/src/direct.rs b/crates/stackarr-stream/src/direct.rs index a188fbbe..a41f66d1 100644 --- a/crates/stackarr-stream/src/direct.rs +++ b/crates/stackarr-stream/src/direct.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::Path; use tokio::io::{AsyncReadExt, AsyncSeekExt}; diff --git a/crates/stackarr-stream/src/error.rs b/crates/stackarr-stream/src/error.rs index a498acbb..a3717dfc 100644 --- a/crates/stackarr-stream/src/error.rs +++ b/crates/stackarr-stream/src/error.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /// Streaming-specific errors. #[derive(Debug, thiserror::Error)] pub enum StreamError { diff --git a/crates/stackarr-stream/src/ffmpeg.rs b/crates/stackarr-stream/src/ffmpeg.rs index 379e1877..bada640c 100644 --- a/crates/stackarr-stream/src/ffmpeg.rs +++ b/crates/stackarr-stream/src/ffmpeg.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::{Path, PathBuf}; use std::process::Stdio; diff --git a/crates/stackarr-stream/src/ffprobe.rs b/crates/stackarr-stream/src/ffprobe.rs index a209d517..753db6cd 100644 --- a/crates/stackarr-stream/src/ffprobe.rs +++ b/crates/stackarr-stream/src/ffprobe.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::Path; use crate::error::{StreamError, StreamResult}; diff --git a/crates/stackarr-stream/src/hls.rs b/crates/stackarr-stream/src/hls.rs index 82db0912..5c5ea889 100644 --- a/crates/stackarr-stream/src/hls.rs +++ b/crates/stackarr-stream/src/hls.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::Path; use std::time::Duration; diff --git a/crates/stackarr-stream/src/lib.rs b/crates/stackarr-stream/src/lib.rs index 759ea244..f65fda42 100644 --- a/crates/stackarr-stream/src/lib.rs +++ b/crates/stackarr-stream/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod direct; pub mod error; pub mod ffmpeg; diff --git a/crates/stackarr-stream/src/provision.rs b/crates/stackarr-stream/src/provision.rs index 5833e71f..a7e86246 100644 --- a/crates/stackarr-stream/src/provision.rs +++ b/crates/stackarr-stream/src/provision.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::{Path, PathBuf}; use crate::error::{StreamError, StreamResult}; diff --git a/crates/stackarr-stream/src/session.rs b/crates/stackarr-stream/src/session.rs index 5dc4fce2..4cda6d84 100644 --- a/crates/stackarr-stream/src/session.rs +++ b/crates/stackarr-stream/src/session.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; diff --git a/crates/stackarr-stream/src/subtitle.rs b/crates/stackarr-stream/src/subtitle.rs index d475d76c..ce7a843e 100644 --- a/crates/stackarr-stream/src/subtitle.rs +++ b/crates/stackarr-stream/src/subtitle.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::Path; use crate::error::{StreamError, StreamResult}; diff --git a/crates/stackarr-stream/src/types.rs b/crates/stackarr-stream/src/types.rs index afd38969..8c9200ca 100644 --- a/crates/stackarr-stream/src/types.rs +++ b/crates/stackarr-stream/src/types.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use serde::{Deserialize, Serialize}; /// Complete media information extracted by ffprobe. diff --git a/crates/stackarr-web/src/dav_manager.rs b/crates/stackarr-web/src/dav_manager.rs index 1bc03e35..09f44efb 100644 --- a/crates/stackarr-web/src/dav_manager.rs +++ b/crates/stackarr-web/src/dav_manager.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! DAV streaming engine manager. //! //! Wraps the nzbdav components (provider, store, pipeline processor) into a diff --git a/crates/stackarr-web/src/embedded_ui.rs b/crates/stackarr-web/src/embedded_ui.rs index 6be66b40..4a49d54f 100644 --- a/crates/stackarr-web/src/embedded_ui.rs +++ b/crates/stackarr-web/src/embedded_ui.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Embedded UI assets served from the binary via rust-embed. //! //! When the `embed-ui` feature is enabled, the React UI build output is compiled diff --git a/crates/stackarr-web/src/lib.rs b/crates/stackarr-web/src/lib.rs index e28dfc82..a2e4e1b2 100644 --- a/crates/stackarr-web/src/lib.rs +++ b/crates/stackarr-web/src/lib.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod dav_manager; pub mod middleware; pub mod openapi; diff --git a/crates/stackarr-web/src/middleware.rs b/crates/stackarr-web/src/middleware.rs index 7513b9e8..ba6d1046 100644 --- a/crates/stackarr-web/src/middleware.rs +++ b/crates/stackarr-web/src/middleware.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::Json; diff --git a/crates/stackarr-web/src/openapi.rs b/crates/stackarr-web/src/openapi.rs index fbe4e589..9d014a32 100644 --- a/crates/stackarr-web/src/openapi.rs +++ b/crates/stackarr-web/src/openapi.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use utoipa::OpenApi; use utoipa::openapi::security::{ApiKey, ApiKeyValue, Http, HttpAuthScheme, SecurityScheme}; diff --git a/crates/stackarr-web/src/routes/activities.rs b/crates/stackarr-web/src/routes/activities.rs index 5e200a42..d8ae4424 100644 --- a/crates/stackarr-web/src/routes/activities.rs +++ b/crates/stackarr-web/src/routes/activities.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Query, State}; diff --git a/crates/stackarr-web/src/routes/admin.rs b/crates/stackarr-web/src/routes/admin.rs index 31f1f8d3..03853d8c 100644 --- a/crates/stackarr-web/src/routes/admin.rs +++ b/crates/stackarr-web/src/routes/admin.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/auth.rs b/crates/stackarr-web/src/routes/auth.rs index 78675f6f..384391a8 100644 --- a/crates/stackarr-web/src/routes/auth.rs +++ b/crates/stackarr-web/src/routes/auth.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::State; diff --git a/crates/stackarr-web/src/routes/backup.rs b/crates/stackarr-web/src/routes/backup.rs index c042f7a6..4e555090 100644 --- a/crates/stackarr-web/src/routes/backup.rs +++ b/crates/stackarr-web/src/routes/backup.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::State; diff --git a/crates/stackarr-web/src/routes/blocklist.rs b/crates/stackarr-web/src/routes/blocklist.rs index be8fd9a0..97e3534d 100644 --- a/crates/stackarr-web/src/routes/blocklist.rs +++ b/crates/stackarr-web/src/routes/blocklist.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, Query, State}; diff --git a/crates/stackarr-web/src/routes/bootstrap.rs b/crates/stackarr-web/src/routes/bootstrap.rs index a9d53278..48ab97dd 100644 --- a/crates/stackarr-web/src/routes/bootstrap.rs +++ b/crates/stackarr-web/src/routes/bootstrap.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::State; diff --git a/crates/stackarr-web/src/routes/calendar.rs b/crates/stackarr-web/src/routes/calendar.rs index 2b1056f8..87fd089d 100644 --- a/crates/stackarr-web/src/routes/calendar.rs +++ b/crates/stackarr-web/src/routes/calendar.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Query, State}; diff --git a/crates/stackarr-web/src/routes/dav.rs b/crates/stackarr-web/src/routes/dav.rs index 6c0ba69f..ad53f9bf 100644 --- a/crates/stackarr-web/src/routes/dav.rs +++ b/crates/stackarr-web/src/routes/dav.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! DAV streaming routes — WebDAV endpoint + REST API for search/stream. use std::net::IpAddr; diff --git a/crates/stackarr-web/src/routes/discover.rs b/crates/stackarr-web/src/routes/discover.rs index b4f9e782..28956fb0 100644 --- a/crates/stackarr-web/src/routes/discover.rs +++ b/crates/stackarr-web/src/routes/discover.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::{HashMap, HashSet}; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/downloadclients.rs b/crates/stackarr-web/src/routes/downloadclients.rs index 20b2fe56..4c7f6633 100644 --- a/crates/stackarr-web/src/routes/downloadclients.rs +++ b/crates/stackarr-web/src/routes/downloadclients.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/episodes.rs b/crates/stackarr-web/src/routes/episodes.rs index 00efcfee..74f9ef10 100644 --- a/crates/stackarr-web/src/routes/episodes.rs +++ b/crates/stackarr-web/src/routes/episodes.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::HashMap; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/filebrowser.rs b/crates/stackarr-web/src/routes/filebrowser.rs index 040d2ea9..ce18b152 100644 --- a/crates/stackarr-web/src/routes/filebrowser.rs +++ b/crates/stackarr-web/src/routes/filebrowser.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::{Path, PathBuf}; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/general.rs b/crates/stackarr-web/src/routes/general.rs index 06a5977b..c502376d 100644 --- a/crates/stackarr-web/src/routes/general.rs +++ b/crates/stackarr-web/src/routes/general.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::State; diff --git a/crates/stackarr-web/src/routes/health.rs b/crates/stackarr-web/src/routes/health.rs index ae003e24..2200cf1e 100644 --- a/crates/stackarr-web/src/routes/health.rs +++ b/crates/stackarr-web/src/routes/health.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::State; diff --git a/crates/stackarr-web/src/routes/history.rs b/crates/stackarr-web/src/routes/history.rs index eb0b03aa..3e049284 100644 --- a/crates/stackarr-web/src/routes/history.rs +++ b/crates/stackarr-web/src/routes/history.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::HashMap; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/images.rs b/crates/stackarr-web/src/routes/images.rs index 65de48e3..93967ea2 100644 --- a/crates/stackarr-web/src/routes/images.rs +++ b/crates/stackarr-web/src/routes/images.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/import_candidates.rs b/crates/stackarr-web/src/routes/import_candidates.rs index 64df8a4a..359bd8ce 100644 --- a/crates/stackarr-web/src/routes/import_candidates.rs +++ b/crates/stackarr-web/src/routes/import_candidates.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + //! Review + accept/reject API for rows written by the disk scanner when it //! finds media files on disk that don't match an existing series or movie. //! diff --git a/crates/stackarr-web/src/routes/importlists.rs b/crates/stackarr-web/src/routes/importlists.rs index 748cec79..83090251 100644 --- a/crates/stackarr-web/src/routes/importlists.rs +++ b/crates/stackarr-web/src/routes/importlists.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/indexarr.rs b/crates/stackarr-web/src/routes/indexarr.rs index 42b23d76..561e5126 100644 --- a/crates/stackarr-web/src/routes/indexarr.rs +++ b/crates/stackarr-web/src/routes/indexarr.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::HashMap; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/indexers.rs b/crates/stackarr-web/src/routes/indexers.rs index 3c4be114..49725b1d 100644 --- a/crates/stackarr-web/src/routes/indexers.rs +++ b/crates/stackarr-web/src/routes/indexers.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::HashMap; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/logs.rs b/crates/stackarr-web/src/routes/logs.rs index efdf4216..4e090cc3 100644 --- a/crates/stackarr-web/src/routes/logs.rs +++ b/crates/stackarr-web/src/routes/logs.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Query, State}; diff --git a/crates/stackarr-web/src/routes/manual_import.rs b/crates/stackarr-web/src/routes/manual_import.rs index 7861ffec..ef11c6ca 100644 --- a/crates/stackarr-web/src/routes/manual_import.rs +++ b/crates/stackarr-web/src/routes/manual_import.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/medialibraryfolders.rs b/crates/stackarr-web/src/routes/medialibraryfolders.rs index d28e966a..ea5d68ee 100644 --- a/crates/stackarr-web/src/routes/medialibraryfolders.rs +++ b/crates/stackarr-web/src/routes/medialibraryfolders.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/mediamanagement.rs b/crates/stackarr-web/src/routes/mediamanagement.rs index cd96d426..45cb77c2 100644 --- a/crates/stackarr-web/src/routes/mediamanagement.rs +++ b/crates/stackarr-web/src/routes/mediamanagement.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/mod.rs b/crates/stackarr-web/src/routes/mod.rs index 724ec81e..efa22e0d 100644 --- a/crates/stackarr-web/src/routes/mod.rs +++ b/crates/stackarr-web/src/routes/mod.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + pub mod activities; pub mod admin; pub mod auth; diff --git a/crates/stackarr-web/src/routes/movies.rs b/crates/stackarr-web/src/routes/movies.rs index 0ebeb2fa..5ccff9b8 100644 --- a/crates/stackarr-web/src/routes/movies.rs +++ b/crates/stackarr-web/src/routes/movies.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::HashMap; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/naming.rs b/crates/stackarr-web/src/routes/naming.rs index 80528f2e..436d17ef 100644 --- a/crates/stackarr-web/src/routes/naming.rs +++ b/crates/stackarr-web/src/routes/naming.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::State; diff --git a/crates/stackarr-web/src/routes/notification_providers.rs b/crates/stackarr-web/src/routes/notification_providers.rs index 78f27085..f2fdc3b2 100644 --- a/crates/stackarr-web/src/routes/notification_providers.rs +++ b/crates/stackarr-web/src/routes/notification_providers.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/notifications.rs b/crates/stackarr-web/src/routes/notifications.rs index 86ed4bc9..d740aead 100644 --- a/crates/stackarr-web/src/routes/notifications.rs +++ b/crates/stackarr-web/src/routes/notifications.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, Query, State}; diff --git a/crates/stackarr-web/src/routes/plex.rs b/crates/stackarr-web/src/routes/plex.rs index 6dd1d254..e6eab010 100644 --- a/crates/stackarr-web/src/routes/plex.rs +++ b/crates/stackarr-web/src/routes/plex.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Multipart, Path, Query, State}; diff --git a/crates/stackarr-web/src/routes/progress.rs b/crates/stackarr-web/src/routes/progress.rs index ae15ddd9..2e8d1676 100644 --- a/crates/stackarr-web/src/routes/progress.rs +++ b/crates/stackarr-web/src/routes/progress.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, Query, State}; diff --git a/crates/stackarr-web/src/routes/quality.rs b/crates/stackarr-web/src/routes/quality.rs index 142f56ae..fb0417ff 100644 --- a/crates/stackarr-web/src/routes/quality.rs +++ b/crates/stackarr-web/src/routes/quality.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/queue.rs b/crates/stackarr-web/src/routes/queue.rs index 67f96beb..177c8ed1 100644 --- a/crates/stackarr-web/src/routes/queue.rs +++ b/crates/stackarr-web/src/routes/queue.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/releases.rs b/crates/stackarr-web/src/routes/releases.rs index 8fe05cd7..e52a15d4 100644 --- a/crates/stackarr-web/src/routes/releases.rs +++ b/crates/stackarr-web/src/routes/releases.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Query, State}; diff --git a/crates/stackarr-web/src/routes/remote.rs b/crates/stackarr-web/src/routes/remote.rs index c3c765fa..cb445398 100644 --- a/crates/stackarr-web/src/routes/remote.rs +++ b/crates/stackarr-web/src/routes/remote.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/requests.rs b/crates/stackarr-web/src/routes/requests.rs index 7fee25a4..0fbc4592 100644 --- a/crates/stackarr-web/src/routes/requests.rs +++ b/crates/stackarr-web/src/routes/requests.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, Query, State}; diff --git a/crates/stackarr-web/src/routes/rss.rs b/crates/stackarr-web/src/routes/rss.rs index c1c268f8..1097c8fd 100644 --- a/crates/stackarr-web/src/routes/rss.rs +++ b/crates/stackarr-web/src/routes/rss.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, Query, State}; diff --git a/crates/stackarr-web/src/routes/scheduler.rs b/crates/stackarr-web/src/routes/scheduler.rs index 25094335..f420bb6f 100644 --- a/crates/stackarr-web/src/routes/scheduler.rs +++ b/crates/stackarr-web/src/routes/scheduler.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/search.rs b/crates/stackarr-web/src/routes/search.rs index 803b3e29..a4d70e1b 100644 --- a/crates/stackarr-web/src/routes/search.rs +++ b/crates/stackarr-web/src/routes/search.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Query, State}; diff --git a/crates/stackarr-web/src/routes/series.rs b/crates/stackarr-web/src/routes/series.rs index 1cbbfbb8..154d089d 100644 --- a/crates/stackarr-web/src/routes/series.rs +++ b/crates/stackarr-web/src/routes/series.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::collections::HashMap; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/stream.rs b/crates/stackarr-web/src/routes/stream.rs index c60cf8eb..3e2707e7 100644 --- a/crates/stackarr-web/src/routes/stream.rs +++ b/crates/stackarr-web/src/routes/stream.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; diff --git a/crates/stackarr-web/src/routes/stremio.rs b/crates/stackarr-web/src/routes/stremio.rs index a5aeacbc..8a8c5a54 100644 --- a/crates/stackarr-web/src/routes/stremio.rs +++ b/crates/stackarr-web/src/routes/stremio.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/system.rs b/crates/stackarr-web/src/routes/system.rs index 6572da76..a1f23b4a 100644 --- a/crates/stackarr-web/src/routes/system.rs +++ b/crates/stackarr-web/src/routes/system.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/tags.rs b/crates/stackarr-web/src/routes/tags.rs index 462e618a..6ab4ec29 100644 --- a/crates/stackarr-web/src/routes/tags.rs +++ b/crates/stackarr-web/src/routes/tags.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/torrent.rs b/crates/stackarr-web/src/routes/torrent.rs index d7fe3c92..06a1062e 100644 --- a/crates/stackarr-web/src/routes/torrent.rs +++ b/crates/stackarr-web/src/routes/torrent.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::num::NonZeroU32; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/usenet.rs b/crates/stackarr-web/src/routes/usenet.rs index d4978ed2..00826945 100644 --- a/crates/stackarr-web/src/routes/usenet.rs +++ b/crates/stackarr-web/src/routes/usenet.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::io::Read as _; use std::sync::Arc; diff --git a/crates/stackarr-web/src/routes/user.rs b/crates/stackarr-web/src/routes/user.rs index 95e26ca3..2a14043d 100644 --- a/crates/stackarr-web/src/routes/user.rs +++ b/crates/stackarr-web/src/routes/user.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, State}; diff --git a/crates/stackarr-web/src/routes/wanted.rs b/crates/stackarr-web/src/routes/wanted.rs index e2ce09e8..a720e51f 100644 --- a/crates/stackarr-web/src/routes/wanted.rs +++ b/crates/stackarr-web/src/routes/wanted.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Query, State}; diff --git a/crates/stackarr-web/src/routes/watchlist.rs b/crates/stackarr-web/src/routes/watchlist.rs index 705fab78..daefc94b 100644 --- a/crates/stackarr-web/src/routes/watchlist.rs +++ b/crates/stackarr-web/src/routes/watchlist.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::sync::Arc; use axum::extract::{Path, Query, State}; diff --git a/crates/stackarr-web/src/state.rs b/crates/stackarr-web/src/state.rs index a05a778d..da947f37 100644 --- a/crates/stackarr-web/src/state.rs +++ b/crates/stackarr-web/src/state.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use std::sync::Arc; diff --git a/docker/build-test.sh b/docker/build-test.sh index 24b6ce26..9ef75f6f 100755 --- a/docker/build-test.sh +++ b/docker/build-test.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + # build-test.sh — Build the three test Docker images from Dockerfile.test # # Usage: diff --git a/docker/init-indexarr-db.sh b/docker/init-indexarr-db.sh index d15dd9f8..94abcbe9 100755 --- a/docker/init-indexarr-db.sh +++ b/docker/init-indexarr-db.sh @@ -1,4 +1,7 @@ #!/bin/bash +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + # Create the indexarr database if it doesn't exist. # Postgres entrypoint runs this on first init only. set -e diff --git a/docker/run-tests.sh b/docker/run-tests.sh index 5aaa46fb..d0660f99 100755 --- a/docker/run-tests.sh +++ b/docker/run-tests.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + # run-tests.sh — Orchestrate the StackArr Docker test suite # # Expects pre-built images. Run build-test.sh first, or pass --build. diff --git a/scripts/check_dependency_sources.py b/scripts/check_dependency_sources.py index 0263e53b..1fbb9c2b 100755 --- a/scripts/check_dependency_sources.py +++ b/scripts/check_dependency_sources.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + """Enforce NGMS's public dependency boundary and SwarmForge release set.""" from __future__ import annotations diff --git a/scripts/check_license_headers.py b/scripts/check_license_headers.py new file mode 100644 index 00000000..6da6351c --- /dev/null +++ b/scripts/check_license_headers.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + +"""Verify every first-party source file carries the GPL-3.0 header. + +Run with --fix to insert the header into files that are missing it. +""" + +from __future__ import annotations + +import pathlib +import re +import subprocess +import sys + + +ROOT = pathlib.Path(__file__).resolve().parents[1] +SPDX = "SPDX-License-Identifier: GPL-3.0-only" +COPYRIGHT = "Copyright (C) 2026 The StackArr Authors" +COPYRIGHT_PATTERN = re.compile(r"^Copyright \(C\) \d{4}(-\d{4})? The StackArr Authors$") + +# Comment prefix and suffix per source extension. +SLASH = ("// ", "") +HASH = ("# ", "") +BLOCK = ("/* ", " */") +STYLES = { + ".rs": SLASH, + ".ts": SLASH, + ".tsx": SLASH, + ".js": SLASH, + ".jsx": SLASH, + ".mjs": SLASH, + ".cjs": SLASH, + ".css": BLOCK, + ".py": HASH, + ".sh": HASH, +} + + +def tracked_sources() -> list[pathlib.Path]: + listing = subprocess.run( + ["git", "ls-files", "-z"], + cwd=ROOT, + check=True, + capture_output=True, + text=True, + ).stdout + paths = (pathlib.Path(name) for name in listing.split("\0") if name) + return sorted(path for path in paths if path.suffix in STYLES) + + +def header_lines(path: pathlib.Path) -> list[str]: + prefix, suffix = STYLES[path.suffix] + return [f"{prefix}{SPDX}{suffix}", f"{prefix}{COPYRIGHT}{suffix}"] + + +def has_header(path: pathlib.Path, lines: list[str]) -> bool: + prefix, suffix = STYLES[path.suffix] + body = lines[1:] if lines and lines[0].startswith("#!") else lines + if len(body) < 2: + return False + + def uncomment(line: str) -> str | None: + if not line.startswith(prefix) or not line.endswith(suffix): + return None + return line[len(prefix) : len(line) - len(suffix)] if suffix else line[len(prefix) :] + + spdx, copyright_line = uncomment(body[0]), uncomment(body[1]) + return spdx == SPDX and copyright_line is not None and bool(COPYRIGHT_PATTERN.match(copyright_line)) + + +def insert_header(path: pathlib.Path, lines: list[str]) -> list[str]: + shebang = lines[:1] if lines and lines[0].startswith("#!") else [] + rest = lines[len(shebang) :] + while rest and not rest[0].strip(): + rest.pop(0) + return shebang + header_lines(path) + [""] + rest + + +def main() -> int: + fix = "--fix" in sys.argv[1:] + sources = tracked_sources() + missing: list[pathlib.Path] = [] + + for path in sources: + absolute = ROOT / path + text = absolute.read_text() + lines = text.split("\n") + if has_header(path, lines): + continue + if not fix: + missing.append(path) + continue + absolute.write_text("\n".join(insert_header(path, lines))) + + if missing: + print("missing GPL-3.0 header:", file=sys.stderr) + for path in missing: + print(f" {path}", file=sys.stderr) + print( + f"{len(missing)} file(s) without a header; " + "run python3 scripts/check_license_headers.py --fix", + file=sys.stderr, + ) + return 1 + + print(f"license headers verified: {len(sources)} files") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/check_workspace_docs.py b/scripts/check_workspace_docs.py index a5ef503f..6f6db1d5 100644 --- a/scripts/check_workspace_docs.py +++ b/scripts/check_workspace_docs.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + """Keep AGENTS.md's workspace inventory aligned with Cargo.toml.""" from __future__ import annotations diff --git a/scripts/convert_sql_placeholders.py b/scripts/convert_sql_placeholders.py index 9024b281..22dfa691 100644 --- a/scripts/convert_sql_placeholders.py +++ b/scripts/convert_sql_placeholders.py @@ -1,4 +1,7 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + """Audit and optionally convert PostgreSQL `$n` placeholders to MariaDB `?`. The converter changes only Rust string literals that contain SQL-looking text. diff --git a/src/main.rs b/src/main.rs index fd0dea9a..43dd484a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + use std::path::PathBuf; use std::sync::Arc; diff --git a/tests/e2e/common.sh b/tests/e2e/common.sh index 5c3bdc14..44821ebd 100755 --- a/tests/e2e/common.sh +++ b/tests/e2e/common.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + # common.sh — Shared helpers for StackArr e2e test harness set -euo pipefail diff --git a/tests/e2e/setup-existing.sh b/tests/e2e/setup-existing.sh index 0d68bfb4..312c2260 100755 --- a/tests/e2e/setup-existing.sh +++ b/tests/e2e/setup-existing.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + # setup-existing.sh — One-time initialisation for Stack 2 (Existing/Upgrade) # # Run this ONCE to bootstrap the "existing" stack with data. diff --git a/tests/e2e/test-existing.sh b/tests/e2e/test-existing.sh index 0e9c1d29..2d843db0 100755 --- a/tests/e2e/test-existing.sh +++ b/tests/e2e/test-existing.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + # test-existing.sh — Stack 2: Validate existing data survives restart/upgrade # # Prerequisites: run setup-existing.sh at least once. diff --git a/tests/e2e/test-fresh.sh b/tests/e2e/test-fresh.sh index 4ebeb31f..98d48d38 100755 --- a/tests/e2e/test-fresh.sh +++ b/tests/e2e/test-fresh.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + # test-fresh.sh — Stack 1: Fresh install e2e test # # Usage (run on Node B): diff --git a/tests/e2e/test-import.sh b/tests/e2e/test-import.sh index 0c0e4158..9ae45e49 100755 --- a/tests/e2e/test-import.sh +++ b/tests/e2e/test-import.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + # test-import.sh — Stack 3: Import test (Sonarr/Radarr/Prowlarr + SABnzbd) # # Usage (run on Node B): diff --git a/tests/e2e/test-quality-parity.sh b/tests/e2e/test-quality-parity.sh index 6095c132..749a42ea 100755 --- a/tests/e2e/test-quality-parity.sh +++ b/tests/e2e/test-quality-parity.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + # test-quality-parity.sh — Stack 4: Quality Parity Test # # Compares release search scoring between StackArr (after importing diff --git a/ui/e2e/calendar.spec.ts b/ui/e2e/calendar.spec.ts index ac722c88..bacd2e9f 100644 --- a/ui/e2e/calendar.spec.ts +++ b/ui/e2e/calendar.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect, mockApi } from './fixtures' test.describe('Calendar page', () => { diff --git a/ui/e2e/connection-error.spec.ts b/ui/e2e/connection-error.spec.ts index b9852afb..d05af718 100644 --- a/ui/e2e/connection-error.spec.ts +++ b/ui/e2e/connection-error.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect } from '@playwright/test' test.describe('Connection error state', () => { diff --git a/ui/e2e/discover.spec.ts b/ui/e2e/discover.spec.ts index 7fe8cc5f..8999c268 100644 --- a/ui/e2e/discover.spec.ts +++ b/ui/e2e/discover.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect } from './fixtures' test.describe('Discover page', () => { diff --git a/ui/e2e/docker-live.spec.ts b/ui/e2e/docker-live.spec.ts index c196874a..d315ab02 100644 --- a/ui/e2e/docker-live.spec.ts +++ b/ui/e2e/docker-live.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E tests for Docker Compose test environment. * diff --git a/ui/e2e/first-boot.spec.ts b/ui/e2e/first-boot.spec.ts index 3462fc48..97a9cf03 100644 --- a/ui/e2e/first-boot.spec.ts +++ b/ui/e2e/first-boot.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect, mockApi, mockStatus } from './fixtures' test.describe('First boot setup', () => { diff --git a/ui/e2e/fixtures.ts b/ui/e2e/fixtures.ts index 65c063c8..a915fdcc 100644 --- a/ui/e2e/fixtures.ts +++ b/ui/e2e/fixtures.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test as base, type Page, type Route } from '@playwright/test' import type { SystemStatus, diff --git a/ui/e2e/history.spec.ts b/ui/e2e/history.spec.ts index 775b4585..9e6c4c64 100644 --- a/ui/e2e/history.spec.ts +++ b/ui/e2e/history.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect, mockApi } from './fixtures' test.describe('History page', () => { diff --git a/ui/e2e/live-auth.spec.ts b/ui/e2e/live-auth.spec.ts index 842774a2..83122e91 100644 --- a/ui/e2e/live-auth.spec.ts +++ b/ui/e2e/live-auth.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E: Auth and user management (J2-9) * Runs serially against real StackArr instance. diff --git a/ui/e2e/live-discover.spec.ts b/ui/e2e/live-discover.spec.ts index 743b6ba1..3d59601f 100644 --- a/ui/e2e/live-discover.spec.ts +++ b/ui/e2e/live-discover.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E: Discover page + Requests (J54-69) * Discover requires TMDB — tests skip gracefully if unavailable. diff --git a/ui/e2e/live-download-clients.spec.ts b/ui/e2e/live-download-clients.spec.ts index d3a2a460..bbefcb64 100644 --- a/ui/e2e/live-download-clients.spec.ts +++ b/ui/e2e/live-download-clients.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E: Download client CRUD (J75-80) * Runs serially against real StackArr instance. diff --git a/ui/e2e/live-indexers.spec.ts b/ui/e2e/live-indexers.spec.ts index 4669893b..18153897 100644 --- a/ui/e2e/live-indexers.spec.ts +++ b/ui/e2e/live-indexers.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E: Indexer CRUD + Search (J26-35) * Runs serially against real StackArr instance. diff --git a/ui/e2e/live-movies.spec.ts b/ui/e2e/live-movies.spec.ts index f9143272..8568f3dd 100644 --- a/ui/e2e/live-movies.spec.ts +++ b/ui/e2e/live-movies.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E: Movie CRUD (J47-53) * Runs serially against real StackArr instance. diff --git a/ui/e2e/live-quality-tags-folders.spec.ts b/ui/e2e/live-quality-tags-folders.spec.ts index 5ed4900e..672c685d 100644 --- a/ui/e2e/live-quality-tags-folders.spec.ts +++ b/ui/e2e/live-quality-tags-folders.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E: Quality profiles, media folders, tags (J70-74, J147-151) * Runs serially against real StackArr instance. diff --git a/ui/e2e/live-series.spec.ts b/ui/e2e/live-series.spec.ts index c2966bbb..10c38d31 100644 --- a/ui/e2e/live-series.spec.ts +++ b/ui/e2e/live-series.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E: TV Series CRUD (J36-46) * Runs serially against real StackArr instance. diff --git a/ui/e2e/live-settings-misc.spec.ts b/ui/e2e/live-settings-misc.spec.ts index fbe2ac18..12c194bd 100644 --- a/ui/e2e/live-settings-misc.spec.ts +++ b/ui/e2e/live-settings-misc.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E: Settings, naming, blocklist, history (J103-108, J142-146) * Runs serially against real StackArr instance. diff --git a/ui/e2e/live-torrent.spec.ts b/ui/e2e/live-torrent.spec.ts index 687bfb2d..791ce761 100644 --- a/ui/e2e/live-torrent.spec.ts +++ b/ui/e2e/live-torrent.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E: Torrent engine operations (J87-93) * Runs serially against real StackArr instance. diff --git a/ui/e2e/live-usenet.spec.ts b/ui/e2e/live-usenet.spec.ts index 8a11f78b..43794161 100644 --- a/ui/e2e/live-usenet.spec.ts +++ b/ui/e2e/live-usenet.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E: Usenet server CRUD + downloads (J12-25) * Runs serially against real StackArr instance. diff --git a/ui/e2e/live.spec.ts b/ui/e2e/live.spec.ts index a701188d..0550c2cc 100644 --- a/ui/e2e/live.spec.ts +++ b/ui/e2e/live.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** * Live E2E tests — run against real StackArr on Node B. * Only executed when PLAYWRIGHT_LIVE=1 (npm run test:e2e:live). diff --git a/ui/e2e/login.spec.ts b/ui/e2e/login.spec.ts index d04ce580..90b4bb58 100644 --- a/ui/e2e/login.spec.ts +++ b/ui/e2e/login.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test as base, expect } from '@playwright/test' // Login page is shown when authMethod is "forms" and no valid session exists. diff --git a/ui/e2e/logs.spec.ts b/ui/e2e/logs.spec.ts index 0e263e5f..6ee39cf1 100644 --- a/ui/e2e/logs.spec.ts +++ b/ui/e2e/logs.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect, mockApi, mockLogResponse } from './fixtures' test.describe('Logs page', () => { diff --git a/ui/e2e/manage-test-env.sh b/ui/e2e/manage-test-env.sh index dbe41cf2..21ac0447 100755 --- a/ui/e2e/manage-test-env.sh +++ b/ui/e2e/manage-test-env.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only +# Copyright (C) 2026 The StackArr Authors + # manage-test-env.sh — Manage the NGMS GUI test environment on Node B # # Usage: diff --git a/ui/e2e/movies.spec.ts b/ui/e2e/movies.spec.ts index 3d825d1e..d4d764c5 100644 --- a/ui/e2e/movies.spec.ts +++ b/ui/e2e/movies.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect } from './fixtures' test.describe('Movies page', () => { diff --git a/ui/e2e/navigation.spec.ts b/ui/e2e/navigation.spec.ts index 4318d472..904dfde7 100644 --- a/ui/e2e/navigation.spec.ts +++ b/ui/e2e/navigation.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect } from './fixtures' test.describe('App navigation', () => { diff --git a/ui/e2e/queue.spec.ts b/ui/e2e/queue.spec.ts index 60ebaaa2..1693350b 100644 --- a/ui/e2e/queue.spec.ts +++ b/ui/e2e/queue.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect, mockApi } from './fixtures' test.describe('Queue page', () => { diff --git a/ui/e2e/search.spec.ts b/ui/e2e/search.spec.ts index 285e9d70..e470224c 100644 --- a/ui/e2e/search.spec.ts +++ b/ui/e2e/search.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect, mockApi, mockSearchResults, mockIndexerConfigs } from './fixtures' test.describe('Search page', () => { diff --git a/ui/e2e/series.spec.ts b/ui/e2e/series.spec.ts index 53002c23..ff74e86b 100644 --- a/ui/e2e/series.spec.ts +++ b/ui/e2e/series.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect } from './fixtures' test.describe('Series list page', () => { diff --git a/ui/e2e/settings.spec.ts b/ui/e2e/settings.spec.ts index 3b6b693d..29787618 100644 --- a/ui/e2e/settings.spec.ts +++ b/ui/e2e/settings.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect } from './fixtures' test.describe('Settings page', () => { diff --git a/ui/e2e/torrents.spec.ts b/ui/e2e/torrents.spec.ts index 39c3997b..fc0ece71 100644 --- a/ui/e2e/torrents.spec.ts +++ b/ui/e2e/torrents.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect } from './fixtures' test.describe('Torrents page', () => { diff --git a/ui/e2e/usenet.spec.ts b/ui/e2e/usenet.spec.ts index d05f2e31..6be4a713 100644 --- a/ui/e2e/usenet.spec.ts +++ b/ui/e2e/usenet.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect } from './fixtures' test.describe('Usenet page', () => { diff --git a/ui/e2e/users.spec.ts b/ui/e2e/users.spec.ts index 63b0f114..a0b3c8a4 100644 --- a/ui/e2e/users.spec.ts +++ b/ui/e2e/users.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect, mockApi, mockUsers, mockInvites } from './fixtures' test.describe('Users page', () => { diff --git a/ui/e2e/watchlist.spec.ts b/ui/e2e/watchlist.spec.ts index 49564a8e..7078da99 100644 --- a/ui/e2e/watchlist.spec.ts +++ b/ui/e2e/watchlist.spec.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { test, expect, mockApi } from './fixtures' test.describe('Watchlist page', () => { diff --git a/ui/eslint.config.js b/ui/eslint.config.js index 5e6b472f..bdb4a366 100644 --- a/ui/eslint.config.js +++ b/ui/eslint.config.js @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import js from '@eslint/js' import globals from 'globals' import reactHooks from 'eslint-plugin-react-hooks' diff --git a/ui/playwright.config.ts b/ui/playwright.config.ts index a4edb545..021619b9 100644 --- a/ui/playwright.config.ts +++ b/ui/playwright.config.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { defineConfig, devices } from '@playwright/test' /** diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 282e265f..73359ace 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useCallback, lazy, Suspense } from 'react' import { Routes, Route, Navigate } from 'react-router-dom' import { useSystemStatus, useCurrentUser } from './hooks/useApi' diff --git a/ui/src/api/client.ts b/ui/src/api/client.ts index b18aa389..63e5c3ef 100644 --- a/ui/src/api/client.ts +++ b/ui/src/api/client.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + // ── Connection management ─────────────────────────────────────────────────── export interface ServerConnection { diff --git a/ui/src/api/types.ts b/ui/src/api/types.ts index fce94a87..475dc296 100644 --- a/ui/src/api/types.ts +++ b/ui/src/api/types.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + export interface SystemStatus { version: string instanceName: string diff --git a/ui/src/components/ActivityNotificationBell.tsx b/ui/src/components/ActivityNotificationBell.tsx index f5cc30bf..5bbefa6b 100644 --- a/ui/src/components/ActivityNotificationBell.tsx +++ b/ui/src/components/ActivityNotificationBell.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useRef, useEffect } from 'react' import { Bell } from 'lucide-react' import ActivityNotificationPopup from './ActivityNotificationPopup' diff --git a/ui/src/components/ActivityNotificationPopup.tsx b/ui/src/components/ActivityNotificationPopup.tsx index 71c45a3d..368b54a5 100644 --- a/ui/src/components/ActivityNotificationPopup.tsx +++ b/ui/src/components/ActivityNotificationPopup.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import ActivityTab from './ActivityTab' import EventsTab from './EventsTab' diff --git a/ui/src/components/ActivityPanel.tsx b/ui/src/components/ActivityPanel.tsx index 9e460eae..f07b181e 100644 --- a/ui/src/components/ActivityPanel.tsx +++ b/ui/src/components/ActivityPanel.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useCallback } from 'react' import { useQueryClient } from '@tanstack/react-query' import { PanelRightClose, Trash2, Loader2 } from 'lucide-react' diff --git a/ui/src/components/ActivityTab.tsx b/ui/src/components/ActivityTab.tsx index d147e54e..e05610bb 100644 --- a/ui/src/components/ActivityTab.tsx +++ b/ui/src/components/ActivityTab.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { HardDrive, Check, X, XCircle, Loader2, Search, ChevronDown, ChevronUp } from 'lucide-react' import type { SystemActivity } from '../api/types' diff --git a/ui/src/components/AddToLibraryModal.tsx b/ui/src/components/AddToLibraryModal.tsx index c5598446..9107241c 100644 --- a/ui/src/components/AddToLibraryModal.tsx +++ b/ui/src/components/AddToLibraryModal.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { useNavigate } from 'react-router-dom' import { Loader2, Plus, X, Check, FolderOpen } from 'lucide-react' diff --git a/ui/src/components/BulkEditBar.tsx b/ui/src/components/BulkEditBar.tsx index 5c61a33d..ef7956c6 100644 --- a/ui/src/components/BulkEditBar.tsx +++ b/ui/src/components/BulkEditBar.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import type { QualityProfile } from '../api/types' diff --git a/ui/src/components/BulkImportModal.tsx b/ui/src/components/BulkImportModal.tsx index eaad3569..ee3c6bdd 100644 --- a/ui/src/components/BulkImportModal.tsx +++ b/ui/src/components/BulkImportModal.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useMemo } from 'react' import { X, diff --git a/ui/src/components/EventsTab.tsx b/ui/src/components/EventsTab.tsx index a9bc997c..35e12934 100644 --- a/ui/src/components/EventsTab.tsx +++ b/ui/src/components/EventsTab.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { useNavigate } from 'react-router-dom' import { diff --git a/ui/src/components/GenreSlider.tsx b/ui/src/components/GenreSlider.tsx index d11b7473..a1a1c030 100644 --- a/ui/src/components/GenreSlider.tsx +++ b/ui/src/components/GenreSlider.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useRef } from 'react' import MediaSlider from './MediaSlider' import MediaCard from './MediaCard' diff --git a/ui/src/components/HistoryDetailModal.tsx b/ui/src/components/HistoryDetailModal.tsx index 80ac1bc6..920cf676 100644 --- a/ui/src/components/HistoryDetailModal.tsx +++ b/ui/src/components/HistoryDetailModal.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useNavigate } from 'react-router-dom' import { X, diff --git a/ui/src/components/InteractiveSearchModal.tsx b/ui/src/components/InteractiveSearchModal.tsx index 60fabbd0..1bd65ca1 100644 --- a/ui/src/components/InteractiveSearchModal.tsx +++ b/ui/src/components/InteractiveSearchModal.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useMemo } from 'react' import { X, diff --git a/ui/src/components/Layout.tsx b/ui/src/components/Layout.tsx index 64ed61c5..5cbda45c 100644 --- a/ui/src/components/Layout.tsx +++ b/ui/src/components/Layout.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { Outlet } from 'react-router-dom' import { PanelRight, LogOut } from 'lucide-react' diff --git a/ui/src/components/ManualImportModal.tsx b/ui/src/components/ManualImportModal.tsx index 3e92d99e..3753733b 100644 --- a/ui/src/components/ManualImportModal.tsx +++ b/ui/src/components/ManualImportModal.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect } from 'react' import { X, Loader2, Download, AlertCircle, CheckCircle, ChevronDown } from 'lucide-react' import { apiFetch } from '../api/client' diff --git a/ui/src/components/MediaCard.tsx b/ui/src/components/MediaCard.tsx index 6ca53d98..95c68dcc 100644 --- a/ui/src/components/MediaCard.tsx +++ b/ui/src/components/MediaCard.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { memo } from 'react' import { Film, Tv, Star, Plus } from 'lucide-react' import { tmdbPosterUrl, tmdbDisplayTitle, tmdbYear } from '../api/types' diff --git a/ui/src/components/MediaFileDetailModal.tsx b/ui/src/components/MediaFileDetailModal.tsx index 8200e34d..b3e87063 100644 --- a/ui/src/components/MediaFileDetailModal.tsx +++ b/ui/src/components/MediaFileDetailModal.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { X, Film, Volume2, Subtitles, FileText, Info } from 'lucide-react' import type { MediaFile, MediaStreamInfo } from '../api/types' import { qualityName } from '../api/types' diff --git a/ui/src/components/MediaSlider.tsx b/ui/src/components/MediaSlider.tsx index acd65cbb..24dc0e32 100644 --- a/ui/src/components/MediaSlider.tsx +++ b/ui/src/components/MediaSlider.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useRef, useState, useEffect, useCallback, type ReactNode } from 'react' import { ChevronLeft, ChevronRight, Loader2 } from 'lucide-react' diff --git a/ui/src/components/MovieBrowse.tsx b/ui/src/components/MovieBrowse.tsx index 79af2a66..a9fc971c 100644 --- a/ui/src/components/MovieBrowse.tsx +++ b/ui/src/components/MovieBrowse.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import MediaSlider from './MediaSlider' import MediaCard from './MediaCard' diff --git a/ui/src/components/NotificationTab.tsx b/ui/src/components/NotificationTab.tsx index 66db14b9..a6f24625 100644 --- a/ui/src/components/NotificationTab.tsx +++ b/ui/src/components/NotificationTab.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import type { UserNotification } from '../api/types' function relativeTime(dateStr: string): string { diff --git a/ui/src/components/SeriesBrowse.tsx b/ui/src/components/SeriesBrowse.tsx index 5e0820fa..fb24db33 100644 --- a/ui/src/components/SeriesBrowse.tsx +++ b/ui/src/components/SeriesBrowse.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import MediaSlider from './MediaSlider' import MediaCard from './MediaCard' diff --git a/ui/src/components/Sidebar.tsx b/ui/src/components/Sidebar.tsx index 931fd7de..32b0fcc2 100644 --- a/ui/src/components/Sidebar.tsx +++ b/ui/src/components/Sidebar.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { NavLink } from 'react-router-dom' import { Tv, diff --git a/ui/src/components/VideoPlayer.tsx b/ui/src/components/VideoPlayer.tsx index 134ffc8e..c3c04b45 100644 --- a/ui/src/components/VideoPlayer.tsx +++ b/ui/src/components/VideoPlayer.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useEffect, useRef, useState, useCallback } from 'react' import Hls from 'hls.js' import { useStreamInfo, useStartTranscode, useStopStreamSession } from '../hooks/useApi' diff --git a/ui/src/hooks/useApi.ts b/ui/src/hooks/useApi.ts index c4fe98e9..f44cc319 100644 --- a/ui/src/hooks/useApi.ts +++ b/ui/src/hooks/useApi.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { apiFetch } from '../api/client' import type { diff --git a/ui/src/index.css b/ui/src/index.css index 9a25142b..d1e768bd 100644 --- a/ui/src/index.css +++ b/ui/src/index.css @@ -1,3 +1,6 @@ +/* SPDX-License-Identifier: GPL-3.0-only */ +/* Copyright (C) 2026 The StackArr Authors */ + @import "tailwindcss"; /* Hide scrollbar for slider components */ diff --git a/ui/src/main.tsx b/ui/src/main.tsx index 85a6e145..c4208768 100644 --- a/ui/src/main.tsx +++ b/ui/src/main.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import { BrowserRouter } from 'react-router-dom' diff --git a/ui/src/pages/Blocklist.tsx b/ui/src/pages/Blocklist.tsx index 9b46adc1..f3d2c1c9 100644 --- a/ui/src/pages/Blocklist.tsx +++ b/ui/src/pages/Blocklist.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useCallback, useEffect } from 'react' import { Loader2, Ban, Trash2, CheckSquare, Square } from 'lucide-react' import { formatDateTime } from '../utils/date' diff --git a/ui/src/pages/Calendar.tsx b/ui/src/pages/Calendar.tsx index b42c6b27..d43b8bcd 100644 --- a/ui/src/pages/Calendar.tsx +++ b/ui/src/pages/Calendar.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useMemo } from 'react' import { useNavigate } from 'react-router-dom' import { CalendarDays, Loader2, Eye, EyeOff, CheckCircle, Circle, Tv } from 'lucide-react' diff --git a/ui/src/pages/Discover.tsx b/ui/src/pages/Discover.tsx index 74d5aae9..e791d92a 100644 --- a/ui/src/pages/Discover.tsx +++ b/ui/src/pages/Discover.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { Loader2, Compass } from 'lucide-react' import MediaCard from '../components/MediaCard' diff --git a/ui/src/pages/FileBrowser.tsx b/ui/src/pages/FileBrowser.tsx index af47e52d..926f3dd7 100644 --- a/ui/src/pages/FileBrowser.tsx +++ b/ui/src/pages/FileBrowser.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useCallback } from 'react' import { Folder, diff --git a/ui/src/pages/FirstBoot.tsx b/ui/src/pages/FirstBoot.tsx index cafd1c40..76cf4aa0 100644 --- a/ui/src/pages/FirstBoot.tsx +++ b/ui/src/pages/FirstBoot.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useMemo, useRef } from 'react' // react-router-dom not needed — we use window.location for full reload after setup import { diff --git a/ui/src/pages/History.tsx b/ui/src/pages/History.tsx index e09c10b6..b76c7984 100644 --- a/ui/src/pages/History.tsx +++ b/ui/src/pages/History.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { useNavigate } from 'react-router-dom' import { Clock, Loader2, ExternalLink } from 'lucide-react' diff --git a/ui/src/pages/Import.tsx b/ui/src/pages/Import.tsx index 0f404bbf..c30419be 100644 --- a/ui/src/pages/Import.tsx +++ b/ui/src/pages/Import.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useEffect, useMemo, useState, useCallback } from 'react' import { Check, diff --git a/ui/src/pages/LiveStream.tsx b/ui/src/pages/LiveStream.tsx index 71f9fb45..fd6167f7 100644 --- a/ui/src/pages/LiveStream.tsx +++ b/ui/src/pages/LiveStream.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { Search, diff --git a/ui/src/pages/Login.tsx b/ui/src/pages/Login.tsx index 1374ce55..c3a2288b 100644 --- a/ui/src/pages/Login.tsx +++ b/ui/src/pages/Login.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, type FormEvent } from 'react' import { apiLogin } from '../api/client' diff --git a/ui/src/pages/Logs.tsx b/ui/src/pages/Logs.tsx index 69fc00c4..d2f1310a 100644 --- a/ui/src/pages/Logs.tsx +++ b/ui/src/pages/Logs.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useRef, useCallback } from 'react' import { ScrollText, Pause, Play, ArrowDown, Loader2, AlertCircle } from 'lucide-react' import { apiFetch } from '../api/client' diff --git a/ui/src/pages/Migrate.tsx b/ui/src/pages/Migrate.tsx index 97697f37..3ee78867 100644 --- a/ui/src/pages/Migrate.tsx +++ b/ui/src/pages/Migrate.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useRef } from 'react' import { Database, Upload, Loader2, CheckCircle, XCircle, FileUp, Server, Globe, Plus, Trash2, ArrowRight } from 'lucide-react' import { useMigrate } from '../hooks/useApi' diff --git a/ui/src/pages/MovieDetail.tsx b/ui/src/pages/MovieDetail.tsx index 94664314..441cf149 100644 --- a/ui/src/pages/MovieDetail.tsx +++ b/ui/src/pages/MovieDetail.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { useParams, useNavigate } from 'react-router-dom' import { qualityName, tmdbYear } from '../api/types' diff --git a/ui/src/pages/MovieList.tsx b/ui/src/pages/MovieList.tsx index 69658d15..0951f622 100644 --- a/ui/src/pages/MovieList.tsx +++ b/ui/src/pages/MovieList.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { useNavigate } from 'react-router-dom' import { Plus, Search, Film, X, Loader2, CheckCircle, Pencil, Check } from 'lucide-react' diff --git a/ui/src/pages/Notifications.tsx b/ui/src/pages/Notifications.tsx index 7d19466e..07e20ff2 100644 --- a/ui/src/pages/Notifications.tsx +++ b/ui/src/pages/Notifications.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useCallback } from 'react' import { Bell, Plus, Trash2, Loader2, AlertCircle, Check, X, Send, Edit2 } from 'lucide-react' import { apiFetch } from '../api/client' diff --git a/ui/src/pages/Player.tsx b/ui/src/pages/Player.tsx index c68667a6..1f79a19f 100644 --- a/ui/src/pages/Player.tsx +++ b/ui/src/pages/Player.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useParams, useNavigate } from 'react-router-dom' import { ArrowLeft } from 'lucide-react' import VideoPlayer from '../components/VideoPlayer' diff --git a/ui/src/pages/PlexActivity.tsx b/ui/src/pages/PlexActivity.tsx index 066b41d8..2da7300e 100644 --- a/ui/src/pages/PlexActivity.tsx +++ b/ui/src/pages/PlexActivity.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { usePlexEvents, useClearPlexEvents, useCurrentUser } from '../hooks/useApi' import { Play, Pause, Square, BookPlus, Trash2, Loader2, Activity } from 'lucide-react' diff --git a/ui/src/pages/Queue.tsx b/ui/src/pages/Queue.tsx index 3d108918..feae2baf 100644 --- a/ui/src/pages/Queue.tsx +++ b/ui/src/pages/Queue.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { Download, Loader2, RefreshCw } from 'lucide-react' import { Link } from 'react-router-dom' import { useQueue } from '../hooks/useApi' diff --git a/ui/src/pages/Requests.tsx b/ui/src/pages/Requests.tsx index 61990d09..89d7f16f 100644 --- a/ui/src/pages/Requests.tsx +++ b/ui/src/pages/Requests.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { Check, X, Trash2, Clock, Film, Tv, Loader2, MessageSquare } from 'lucide-react' import { diff --git a/ui/src/pages/Rss.tsx b/ui/src/pages/Rss.tsx index 7bb465b2..505fd015 100644 --- a/ui/src/pages/Rss.tsx +++ b/ui/src/pages/Rss.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { Rss as RssIcon, diff --git a/ui/src/pages/Search.tsx b/ui/src/pages/Search.tsx index c02b5321..6a940147 100644 --- a/ui/src/pages/Search.tsx +++ b/ui/src/pages/Search.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useRef, useEffect, useMemo } from 'react' import { useSearchParams } from 'react-router-dom' import { diff --git a/ui/src/pages/SeriesDetail.tsx b/ui/src/pages/SeriesDetail.tsx index 3a0a3393..a72148c9 100644 --- a/ui/src/pages/SeriesDetail.tsx +++ b/ui/src/pages/SeriesDetail.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useParams, useNavigate } from 'react-router-dom' import { ArrowLeft, diff --git a/ui/src/pages/SeriesList.tsx b/ui/src/pages/SeriesList.tsx index e2778b56..486b251d 100644 --- a/ui/src/pages/SeriesList.tsx +++ b/ui/src/pages/SeriesList.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { useNavigate } from 'react-router-dom' import { Plus, Search, Eye, EyeOff, Tv, X, Loader2, Pencil, Check } from 'lucide-react' diff --git a/ui/src/pages/ServerConnect.tsx b/ui/src/pages/ServerConnect.tsx index 2ac178ca..a9de3eb8 100644 --- a/ui/src/pages/ServerConnect.tsx +++ b/ui/src/pages/ServerConnect.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { redeemClaimCode, saveConnection, type ServerConnection } from '../api/client' diff --git a/ui/src/pages/Settings.tsx b/ui/src/pages/Settings.tsx index a9e36366..152dcda8 100644 --- a/ui/src/pages/Settings.tsx +++ b/ui/src/pages/Settings.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import React, { useState, useEffect, useCallback, useRef } from 'react' import type { QualityProfile, diff --git a/ui/src/pages/Streaming.tsx b/ui/src/pages/Streaming.tsx index 9c56eb9d..c974d9b0 100644 --- a/ui/src/pages/Streaming.tsx +++ b/ui/src/pages/Streaming.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { useUnifiedSessions, useStopStreamSession, useSystemStatus } from '../hooks/useApi' import type { UnifiedSession } from '../api/types' diff --git a/ui/src/pages/Torrents.tsx b/ui/src/pages/Torrents.tsx index 9dc68cb4..d8ba31e7 100644 --- a/ui/src/pages/Torrents.tsx +++ b/ui/src/pages/Torrents.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useCallback, useRef, memo } from 'react' import { Link as RouterLink } from 'react-router-dom' import { authHeaders } from '../api/client' diff --git a/ui/src/pages/Usenet.tsx b/ui/src/pages/Usenet.tsx index 811832dc..119df17b 100644 --- a/ui/src/pages/Usenet.tsx +++ b/ui/src/pages/Usenet.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useCallback, useRef, type DragEvent } from 'react' import { HardDrive, diff --git a/ui/src/pages/Users.tsx b/ui/src/pages/Users.tsx index 6b168b94..d1c75587 100644 --- a/ui/src/pages/Users.tsx +++ b/ui/src/pages/Users.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { apiFetch } from '../api/client' diff --git a/ui/src/pages/Wanted.tsx b/ui/src/pages/Wanted.tsx index 817724d5..e2d4b894 100644 --- a/ui/src/pages/Wanted.tsx +++ b/ui/src/pages/Wanted.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { useState, useEffect, useCallback, useRef } from 'react' import { Link } from 'react-router-dom' import { Search, Loader2, AlertCircle, FileQuestion, SearchCheck, Download, XCircle, Filter } from 'lucide-react' diff --git a/ui/src/pages/Watchlist.tsx b/ui/src/pages/Watchlist.tsx index ca72f9be..d925ab00 100644 --- a/ui/src/pages/Watchlist.tsx +++ b/ui/src/pages/Watchlist.tsx @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { Loader2, RefreshCw, Bookmark, Film, Tv } from 'lucide-react' import { useWatchlist, useSyncWatchlist, useSystemStatus } from '../hooks/useApi' import type { WatchlistItem } from '../api/types' diff --git a/ui/src/utils/clipboard.ts b/ui/src/utils/clipboard.ts index bb2afbc2..dbc16173 100644 --- a/ui/src/utils/clipboard.ts +++ b/ui/src/utils/clipboard.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** Copy text to clipboard with fallback for non-HTTPS contexts. */ export async function copyToClipboard(text: string): Promise { // Modern API (requires HTTPS or localhost) diff --git a/ui/src/utils/date.ts b/ui/src/utils/date.ts index 0c714c76..65d46966 100644 --- a/ui/src/utils/date.ts +++ b/ui/src/utils/date.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + /** Format a UTC ISO string or epoch-ms as locale date (e.g. "3/27/2026") */ export function formatDate(value: string | number): string { return new Date(value).toLocaleDateString() diff --git a/ui/vite.config.ts b/ui/vite.config.ts index 73dcc66b..f39b6eb2 100644 --- a/ui/vite.config.ts +++ b/ui/vite.config.ts @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: GPL-3.0-only +// Copyright (C) 2026 The StackArr Authors + import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite'