4.3 KiB
Audit Findings
Date: 2026-04-11
Summary
This audit focused on the highest-risk paths in Alchemist:
- queue claiming and cancellation
- media planning and execution
- conversion validation
- setup/auth exposure
- job detail and failure UX
The current automated checks were green at audit time, but several real correctness and behavior issues remain.
Findings
[P1] Canceling a job during analysis can be overwritten
Relevant code:
src/server/jobs.rs:41src/media/pipeline.rs:927src/media/pipeline.rs:970src/orchestrator.rs:239
request_job_cancel() marks analyzing and resuming jobs as
cancelled immediately. But the analysis/planning path can still run to
completion and later overwrite that state to skipped,
encoding/remuxing, or another follow-on state.
The transcoder-side pending_cancels check only applies around FFmpeg
spawn, so a cancel issued during analysis is not guaranteed to stop the
pipeline before state transitions are persisted.
Impact:
- a user-visible cancel can be lost
- the UI can report a cancelled job that later resumes or becomes skipped
- queue state becomes harder to trust
[P1] VideoToolbox quality controls are effectively a no-op
Relevant code:
src/config.rs:85src/media/planner.rs:633src/media/ffmpeg/videotoolbox.rs:3src/conversion.rs:424
The config still defines a VideoToolbox quality ladder, and the planner
still emits RateControl::Cq for VideoToolbox encoders. But the actual
VideoToolbox FFmpeg builder ignores rate-control input entirely.
The Convert workflow does the same thing by still generating Cq for
non-CPU/QSV encoders even though the VideoToolbox path does not consume
it.
Impact:
- quality profile does not meaningfully affect VideoToolbox jobs
- Convert quality values for VideoToolbox are misleading
- macOS throughput/quality tradeoffs are harder to reason about
[P2] Convert does not reuse subtitle/container compatibility checks
Relevant code:
src/media/planner.rs:863src/media/planner.rs:904src/conversion.rs:272src/conversion.rs:366
The main library planner explicitly rejects unsafe subtitle-copy combinations, especially for MP4/MOV targets. The Convert flow has its own normalization/build path and does not reuse that validation.
Impact:
- the Convert UI can accept settings that are known to fail later in FFmpeg
- conversion behavior diverges from library-job behavior
- users can hit avoidable execution-time errors instead of fast validation
[P2] Completed job details omit metadata at the API layer
Relevant code:
src/server/jobs.rs:344web/src/components/JobManager.tsx:1774
The job detail endpoint explicitly returns metadata = None for
completed jobs, even though the Jobs modal is structured to display
input metadata when available.
Impact:
- completed-job details are structurally incomplete
- the frontend needs special-case empty-state behavior
- operator confidence is lower when comparing completed jobs after the fact
[P2] LAN-only setup is easy to misconfigure behind a local reverse proxy
Relevant code:
src/server/middleware.rs:269src/server/middleware.rs:300
The setup gate uses request_ip() and trusts forwarded headers only when
the direct peer is local/private. If Alchemist sits behind a loopback or
LAN reverse proxy that fails to forward the real client IP, the request
falls back to the proxy peer IP and is treated as LAN-local.
Impact:
- public reverse-proxy deployments can accidentally expose setup
- behavior depends on correct proxy header forwarding
- the security model is sound in principle but fragile in deployment
What To Fix First
- Fix the cancel-during-analysis race.
- Fix or redesign VideoToolbox quality handling so the UI and planner do not promise controls that the backend ignores.
- Reuse planner validation in Convert for subtitle/container safety.
- Decide whether completed jobs should persist and return metadata in the detail API.
What To Investigate Next
- Use runtime diagnostics to confirm whether macOS slowness is true hardware underperformance, silent fallback, or filter overhead.
- Verify whether “only one job at a time” is caused by actual worker serialization or by planner eligibility/skips.
- Review dominant skip reasons before relaxing planner heuristics.