All checks were successful
Build and Push Docker Image / build (push) Successful in 1m30s
worked through AUDIT.md. triage: - finding 2 (subtitle rescan wipes decisions): confirmed. /:id/rescan now snapshots custom_titles and calls reanalyze() after the stream delete/ insert, mirroring the review rescan flow. exported reanalyze + titleKey from review.ts so both routes share the logic. - finding 3 (scan limit accepts NaN/negatives): confirmed. extracted parseScanLimit into a pure helper, added unit tests covering NaN, negatives, floats, infinity, numeric strings. invalid input 400s and releases the scan_running lock. - finding 4 (parseId lenient): confirmed. tightened the regex to /^\d+$/ so "42abc", "abc42", "+42", "42.0" all return null. rewrote the test that codified the old lossy behaviour. - finding 5 (setup_complete set before jellyfin test passes): confirmed. the /jellyfin endpoint still persists url+key unconditionally, but now only flips setup_complete=1 on a successful connection test. - finding 6 (swallowed errors): partial. the mqtt restart and version- fetch swallows are intentional best-effort with downstream surfaces (getMqttStatus, UI fallback). only the scan.ts db-update swallow was a real visibility gap — logs via logError now. - finding 1 (auth): left as-is. redacting secrets on GET without auth on POST is security theater; real fix is an auth layer, which is a design decision not a bugfix. audit removed from the tree. - lint fail on ffmpeg.test.ts: formatted. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
32 lines
1.5 KiB
TypeScript
32 lines
1.5 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { parseScanLimit } from "../scan";
|
|
|
|
describe("parseScanLimit", () => {
|
|
test("accepts positive integers and nullish/empty as no-limit", () => {
|
|
expect(parseScanLimit(5)).toEqual({ ok: true, value: 5 });
|
|
expect(parseScanLimit(1)).toEqual({ ok: true, value: 1 });
|
|
expect(parseScanLimit(10_000)).toEqual({ ok: true, value: 10_000 });
|
|
expect(parseScanLimit(null)).toEqual({ ok: true, value: null });
|
|
expect(parseScanLimit(undefined)).toEqual({ ok: true, value: null });
|
|
expect(parseScanLimit("")).toEqual({ ok: true, value: null });
|
|
});
|
|
|
|
test("coerces numeric strings (env var path) but rejects garbage", () => {
|
|
expect(parseScanLimit("7")).toEqual({ ok: true, value: 7 });
|
|
expect(parseScanLimit("abc")).toEqual({ ok: false });
|
|
expect(parseScanLimit("12abc")).toEqual({ ok: false });
|
|
});
|
|
|
|
test("rejects the footguns that would silently disable the cap", () => {
|
|
// NaN: processed >= NaN never trips → cap never fires.
|
|
expect(parseScanLimit(Number.NaN)).toEqual({ ok: false });
|
|
// Negative: off-by-one bugs in Math.min(limit, total).
|
|
expect(parseScanLimit(-1)).toEqual({ ok: false });
|
|
expect(parseScanLimit(0)).toEqual({ ok: false });
|
|
// Float: Math.min is fine but percentage math breaks on non-integers.
|
|
expect(parseScanLimit(1.5)).toEqual({ ok: false });
|
|
// Infinity is technically a number but has no business as a cap.
|
|
expect(parseScanLimit(Number.POSITIVE_INFINITY)).toEqual({ ok: false });
|
|
});
|
|
});
|