Skip to content

Commit 2a41b1b

Browse files
fix: pre-launch security, docs accuracy, and README restructure
Lock /api/search behind _require_auth() (was the only unauthenticated API route), add auth enforcement test, remove false Bazarr auto-rescan claims from docs, update contributor/test docs to lead with make test, fix .eng.srt mismatch in test_single_video.py, reframe README as GUI-first with Known Limitations section, add screenshot placeholders.
1 parent 1b39e4a commit 2a41b1b

9 files changed

Lines changed: 56 additions & 21 deletions

File tree

.env.example

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,8 @@ DISABLE_AUTH=true
9090
# Example: ALLOWED_EMAILS=user1@example.com,user2@example.com
9191
ALLOWED_EMAILS=
9292

93-
# Bazarr Integration (optional)
94-
# Enable automatic subtitle rescan after batch completion
95-
# Leave BAZARR_BASE_URL empty to disable integration
93+
# Bazarr Integration (planned — not yet wired. See roadmap.)
94+
# These env vars are accepted but auto-rescan on batch completion is not yet active.
9695
BAZARR_BASE_URL=
9796
BAZARR_API_KEY=
9897

CONTRIBUTING.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,21 @@ docker compose logs -f web worker
5252
### Testing
5353

5454
```bash
55-
# Validate project structure
55+
# Run the full test suite (preferred — this is what CI runs)
56+
make test
57+
58+
# Validate project structure (no API key needed)
5659
python3 scripts/validate_setup.py
5760

58-
# Test a single video (requires DEEPGRAM_API_KEY)
61+
# Test a single video end-to-end (requires DEEPGRAM_API_KEY)
5962
python3 tests/test_single_video.py /path/to/video.mkv
6063
```
6164

6265
## Pull Requests
6366

6467
1. **Keep PRs focused** — one feature or fix per PR
6568
2. **Write a clear description** — explain what changed and why
66-
3. **Test your changes**verify with `validate_setup.py` at minimum
69+
3. **Test your changes**run `make test` to execute the full test suite
6770
4. **Update docs** if your change affects configuration, CLI flags, or API endpoints
6871

6972
### PR Title Format

README.md

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,25 +83,24 @@ docker compose run --profile cli --rm cli
8383
8484
### Basic Usage
8585

86-
**Process entire media library (CLI):**
86+
**Start the Web UI (recommended):**
8787
```bash
88-
docker compose run --profile cli --rm cli
88+
docker compose up -d
89+
# Open http://localhost:5000
8990
```
9091

91-
**Process specific show/season:**
92+
**Process via CLI (headless/batch):**
9293
```bash
93-
docker compose run --profile cli --rm -e MEDIA_PATH=/media/tv/ShowName/Season\ 01 cli
94-
```
94+
# Process entire media library
95+
docker compose run --profile cli --rm cli
9596

96-
**Start the Web UI:**
97-
```bash
98-
docker compose up -d
99-
# Open http://localhost:5000
97+
# Process specific show/season
98+
docker compose run --profile cli --rm -e MEDIA_PATH=/media/tv/ShowName/Season\ 01 cli
10099
```
101100

102101
---
103102

104-
## Web UI (Optional)
103+
## Web UI
105104

106105
The Web UI provides a browser-based interface for remote management, batch processing, and AI-powered keyterm generation.
107106

@@ -115,13 +114,17 @@ Access at `http://localhost:5000` (or configure reverse proxy for remote access)
115114

116115
> **Security Note:** This app exposes media paths and triggers write operations. `DISABLE_AUTH=true` is the default in the example compose — suitable for local access only. For remote/production deployments, set `DISABLE_AUTH=false` and place a reverse proxy with authentication (OAuth2-Proxy, Authelia, Nginx basic auth) in front of the app.
117116
117+
### Screenshots
118+
119+
<!-- Recommended: main browse page, scan results, transcription progress, settings panel -->
120+
*Screenshots coming soon.*
121+
118122
### Web UI Features
119123

120124
- 🌐 **Remote access** from any device
121125
- 📊 **Real-time progress tracking** with per-file status
122126
- 🤖 **AI Keyterm Generation** with Claude, GPT, or Gemini (optional)
123127
- 📁 **Directory browser** with search and file filtering
124-
- 🔄 **Bazarr integration** for automatic subtitle rescans
125128
-**Batch processing** with parallel workers
126129
- 🔍 **Find Missing Subtitles** — one-click async library scan with CSV export
127130
- ⚙️ **Full Nova-3 feature control** — model selection, redaction, dictation, multichannel, Audio Intelligence, and more via collapsible Transcription Settings panel
@@ -257,7 +260,7 @@ After generation, refresh your media library to detect new subtitles.
257260
1. Download new season via Sonarr/Radarr
258261
2. Run: `docker compose run --profile cli --rm -e MEDIA_PATH=/media/tv/ShowName/Season\ 01 cli`
259262
3. Subtitles generated automatically
260-
4. Bazarr rescan triggers (if Web UI integration enabled)
263+
4. Refresh your media server library to pick up new subtitles
261264

262265
### Complete Library Cleanup
263266

@@ -308,6 +311,13 @@ id -g # Get your GID
308311

309312
---
310313

314+
## Known Limitations
315+
316+
- **Authentication**: `DISABLE_AUTH=true` is the default for local use. For remote access, place a reverse proxy with authentication in front of the app (see Security Note above).
317+
- **CLI vs Web UI**: The CLI processes files synchronously and does not support AI keyterm generation, library scanning, or progress tracking. The Web UI provides all features including async batch processing, real-time progress, and AI keyterm generation.
318+
319+
---
320+
311321
## Contributing
312322

313323
Contributions welcome! Please feel free to submit issues or pull requests.

docs/screenshots/.gitkeep

Whitespace-only changes.

docs/technical.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ The Web UI adds asynchronous processing capabilities:
5353
2. Flask API creates Celery task group
5454
3. Workers process files in parallel (configurable concurrency)
5555
4. Progress updates sent via Server-Sent Events (SSE)
56-
5. Bazarr rescan triggered on completion (if configured)
56+
5. Results returned to the UI
5757

5858
---
5959

tests/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
This directory contains comprehensive tests for the Subgeneratorr CLI tool.
44

5+
## Quick Run (Recommended)
6+
7+
The fastest way to run all unit tests:
8+
9+
```bash
10+
make test
11+
# or: pytest tests/ -v
12+
```
13+
14+
This runs the full pytest suite without needing Docker or API keys. The detailed CLI integration tests described below require Docker and a Deepgram API key.
15+
16+
---
17+
518
## Contents
619

720
- [`CLI_TEST_PLAN.md`](CLI_TEST_PLAN.md) - Detailed test plan with all test cases

tests/test_library_scan_api.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ def test_scan_export_invalid_task_id():
103103
assert response.status_code == 400
104104

105105

106+
def test_search_requires_auth():
107+
"""Verify /api/search rejects unauthenticated requests when auth is enabled."""
108+
with patch.dict(os.environ, {'DISABLE_AUTH': 'false'}, clear=False):
109+
with app.test_client() as client:
110+
response = client.get("/api/search?q=test")
111+
112+
assert response.status_code == 401
113+
114+
106115
def test_scan_status_valid_uuid_pending():
107116
task_result = SimpleNamespace(state="PENDING", info=None)
108117

tests/test_single_video.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def main():
3939
print(f"Please provide a valid video file path.")
4040
sys.exit(1)
4141

42-
srt_path = video_path.with_suffix('.srt')
42+
srt_path = video_path.with_suffix('.eng.srt')
4343
if srt_path.exists():
4444
print(f"⚠️ Warning: SRT file already exists at {srt_path}")
4545
print(f"Delete it first to regenerate, or test with a different video.")
@@ -57,7 +57,7 @@ def main():
5757
print("="*70)
5858
print("✅ TEST SUCCESSFUL")
5959
print("="*70)
60-
print(f"Generated subtitle file: {srt_path}")
60+
print(f"Generated subtitle file: {video_path.with_suffix('.eng.srt')}")
6161
print()
6262
gen.print_summary()
6363
gen.save_stats()

web/app.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ def api_search():
202202
JSON with matching directories and files, each including a context path
203203
showing where the match lives relative to MEDIA_ROOT.
204204
"""
205+
_require_auth()
205206
query = request.args.get("q", "").strip()
206207
root = request.args.get("path", str(MEDIA_ROOT))
207208

0 commit comments

Comments
 (0)