Contributing1.x
Shared environment
Section titled “Shared environment”Frontend and backend must share:
export CONFIG_PATH=/where/to/create/database/export FRONTEND_BACKEND_API_KEY=$(head -c 32 /dev/urandom | hexdump -ve '1/1 "%.2x"')export BACKEND_URL=http://localhost:5000Optional: THREADPOOL_MIN_THREADS, THREADPOOL_MAX_THREADS.
Preferred workflow
Section titled “Preferred workflow”# Terminal 1./scripts/run-backend.sh
# Terminal 2cd frontend && npm install && npm run devUI: http://localhost:5173 → proxies to backend :5000.
run-backend.sh defaults LOG_LEVEL=Debug and LOG_BUFFER_SIZE=2000 for local debugging. The Docker image sets LOG_LEVEL=warning; LOG_BUFFER_SIZE is unset and the backend defaults to 2000. The script also enables the contributor-only admin API reference locally: sign in and use http://localhost:5173/scalar/ through the frontend. The backend’s /openapi/admin.json endpoint requires x-api-key when accessed directly. Set ENABLE_API_DOCS=false to disable it; Docker keeps the reference disabled unless explicitly enabled.
After changing a frontend-used admin endpoint, refresh the committed contract with ./scripts/export-admin-openapi.sh and regenerate types with cd frontend && npm run generate:api.
Stream tracing is off by default — toggle it from Settings → Support, or export STREAM_TRACE_EVENTS=20000 for an always-on capture.
Real-provider playback
Section titled “Real-provider playback”- Add Usenet + WebDAV credentials in Settings.
- Queue an
.nzb, play via Explore or rclone against the frontend port. - Dump stream traces with
./scripts/dump-stream-trace.sh.
PR checks
Section titled “PR checks”cd frontendnpm run lintnpm run format:checknpm run typechecknpm run buildnpm testnpm run test:coveragecd ..dotnet test tests/NzbWebDAV.Tests/NzbWebDAV.Tests.csproj -c Releasedotnet test \ tests/NzbWebDAV.ArchitectureTests/NzbWebDAV.ArchitectureTests.csproj \ -c DebugThe backend checks also run the quality-ratchet scripts and
dotnet format whitespace --verify-no-changes; see
CONTRIBUTING.md
for the exact commands.
Branch protection on main should require CI / Required quality gate
(plus Documentation build and the three CodeQL language jobs). That aggregate
check covers frontend lint/typecheck/build/tests, backend format/build/tests,
PostgreSQL migrations, native yEnc jobs, quality ratchets, HTTP contracts, and the Docker
runtime smoke when image inputs change.
Full details, local commands, and ratchet/allowlist rules: repository CONTRIBUTING.md and AGENTS.md.
Performance regression gates
Section titled “Performance regression gates”Pull request CI compares deterministic fields from the streaming, SAB API
and NNTP whole-path reports (transportRequests, transportBytes, SAB
rowsReturned / totalCount / dbCommands) against
backend.Benchmarks/Baselines/.
Timing never blocks a PR.
If that gate fails because you intentionally changed transport or query
shape, update the matching baseline JSON in the same PR (and any adjacent
count constants in
tests/NzbWebDAV.Tests/Streams/RepeatableStreamingBenchmarkCoverageTests.cs):
BENCH=backend.Benchmarks/NzbWebDAV.Benchmarks.csprojBASE=backend.Benchmarks/Baselinesdotnet run --project $BENCH -c Release -- \ --streaming-report --json /tmp/streaming.jsondotnet run --project $BENCH -c Release -- \ --sab-api-report --json /tmp/sab-api.jsondotnet run --project $BENCH -c Release -- \ --nntp-whole-path-report --set quick --json /tmp/nntp-whole-path.jsonpython3 scripts/check-performance-baseline.py \ --candidates /tmp/streaming.json \ --write-baseline $BASE/streaming-baseline.jsonpython3 scripts/check-performance-baseline.py \ --candidates /tmp/sab-api.json \ --write-baseline $BASE/sab-api-baseline.jsonpython3 scripts/check-performance-baseline.py \ --candidates /tmp/nntp-whole-path.json \ --write-baseline $BASE/nntp-whole-path-baseline.jsonNightly Performance
runs check latency / throughput / CPU against floored 3× envelopes. To refresh
those envelopes: Actions → Performance → Run workflow → rebaseline. The
workflow opens a PR and does not merge it. PRs created with GITHUB_TOKEN do
not trigger CI — close/reopen (or push) to run checks.