Repository navigation
showtime 0.3.3
Behaviour changes to know about (all deliberate, all security or correctness):
-
A symlink inside a project that points outside it is no longer served by the preview or capture servers
(403, with a message saying to copy the file into the project). showtime never creates such links itself. -
Page capture refuses a host whose name does not resolve, unless an HTTP(S) proxy is configured for it.
-
job note --output: a hand-setfinal=/preview=that is not a video, or an unknownKIND=, is now an
error (usereport=for HTML and PDF deliverables). -
An audio mirror for sandboxes. 0.3.2's model mirror covered models; the hosts real music and sound
effects come from (opengameart.org, scottbuckley.com.au, incompetech.com, archive.org,
upload.wikimedia.org, bigsoundbank.com, kenney.nl) are blocked by the same sandbox proxies, so a video's
soundtrack and sound effects silently went missing instead. The music catalog'sfetch, the audio
library'sdownload(also used by sound-effect packs) now try the primary host, then a
SHOWTIME_AUDIO_MIRROR folder or URL, then the mirror bases inlib/st/mirror.json's newaudioblock
(release assets under theaudio-v1tag of this repository) when the primary refuses; after one refusal
a host's later files go straight to the mirror. Every copy is sha256-verified against the same pin as
the primary, and a mismatch is never kept. The primary hosts' politeness rules (OpenGameArt's 10 s,
Scott Buckley's no-bulk) still apply; a GitHub mirror needs no delay.SHOWTIME_AUDIO_MIRRORhas the
same semantics asSHOWTIME_MODEL_MIRROR(a base URL, a local folder checked before any network,
comma-separated, oroff), and when every source fails the error names the blocked hosts and the mirror
file to provide.scripts/stage_audio_mirror.pydownloads every pinned music track, sound-effect pack
and library file from its primary (Scott Buckley's tracks included, with his permission, staged in bulk
only by this script), verifies size and sha256, writes LICENSES.txt and SHA256SUMS, and prints the
gh release create/gh release uploadcommands; it uploads nothing.showtime doctorreports a
blocked network with a reachable audio mirror as a warning, not a failure. docs/agents.md's Claude app
section and the music guide cover it.
--pinfirst pins the 218 extended-tier library sources that had no size or sha256 yet (the
library's own maintainer pin), so they can be mirrored and verified too. -
A symlink inside a served project could point anywhere on disk.
server.mjs'ssafeJoin/
sendFileandcapture.mjs'sstaticJoin/serveStaticchecked requested paths only as text, so a
symlink inside the served folder (evil -> /etc/passwd) was servable, and a name either server picks
for itself afterwards (a directory'sindex.html, a pretty-URL.html, the SPA fallback,404.html)
was never re-checked at all. Both now resolve the real path and refuse (403) anything outside the
served root, via a sharedrealpathUnderRoothelper in the newscripts/lib/pathguard.mjs. -
The SSRF guard treated "DNS did not resolve" as "safe to fetch."
capture.mjs'shostIsPrivate
returnedfalse(not private) when a lookup failed for any reason, so an unresolvable host passed
the guard instead of being refused.hostPrivacynow distinguishes'private' | 'public' | 'unknown',
andhostIsPrivate/safeDownloadfail closed on'unknown'(reasonunresolved-host) unless a
proxy is configured for that URL (proxyConfiguredFor, honouringHTTP(S)_PROXY/NO_PROXY) --
behind an explicit proxy with no local resolver, a failed lookup says nothing about reachability. -
footage stabilize's deshake fallback used a radius ffmpeg often rejects. ffmpeg'sdeshake
filter requires its search radius to be a multiple of 16; the strength-to-radius formula rounded to
arbitrary integers (17, 33, 49, ...) that fail the whole encode, andrender_edl.py's own fallback
hard-codedrx=24:ry=24, which is not a multiple of 16 either. Both now go through a shared
stabilize.deshake_filter()that snaps the radius to 16, 32 or 48. -
job/ledger.pyhad no "report" output kind. An HTML or PDF deliverable saved with
job note --outputhad nowhere to go: it was either ignored or, worse, could be set as the job's
final/previewby name, whichqa/review-pack/deliverthen fail on as an unreadable video.
Output kinds gain"report"(.html/.htm/.pdf), inferred from the file name or set with
report=path; a hand-setfinal=/preview=that is not a video is now refused with a hint to use
report=instead (a tool's own output,--auto, is logged as a variant rather than refused). An
unknownKIND=(e.g. a typo) is now a clear error instead of being recorded as a literal file name.
Audio mirror release: https://github.com/FavioVazquez/showtime/releases/tag/audio-v1
Install or update: /plugin marketplace update showtime in Claude Code, npx -y @faviovazquez/showtime-mcp@0.3.3 for the MCP server, or the attached showtime-0.3.3.mcpb for Claude Desktop.