Bug fixes:
- #91: dockerApi() 10s socket timeout (Docker daemon hang)
- #77: await syncToAmpp() with .catch() — no longer fire-and-forget
- #75: migration 016 — add 'proxy','import' to job_type enum; add 'completed' to job_status
- #73: BullMQ orphan job cleanup on hard asset delete
- #70: batch-trim jobs table gets expires_at; trim-status auto-expires stale rows
- #66: scheduler tick marks stale live assets (>2h) as error
- #63: migration 017 — partial unique index prevents concurrent live asset overwrite
- #61: recorders.js uses getS3Bucket() not stale process.env.S3_BUCKET
- #60: already fixed (copy nulls proxy/thumbnail keys, requeues proxy)
- #40: already fixed (All projects clears openProject)
- #64: already fixed (sourceType/needsProxy handled)
- #90: GET /jobs now includes DB jobs table (trim jobs visible in UI)
- #74: nginx Content-Type header preserved; multer 500MB file size limit
- #68: GET /upload returns in-progress ingesting assets
- #58: /stream and /video endpoints fall back to original file for all video types
- #55: recorder poll .catch() logs auth errors cleanly; redirect stops interval
- #52: thumb-status and thumb-duration moved inside position:relative wrapper
- #50: ProjectCard gets onContextMenu handler with rename/delete menu
- #49: project context menu dismisses on contextmenu + scroll events
Features:
- #93: POST /assets/:id/reprocess?type=proxy|thumbnail — force re-queue any asset
Asset ⋯ menu now shows 'Re-generate proxy' and 'Re-generate thumbnail' buttons
UI:
- Logo: brightness(0) invert(1) filter applied consistently in sidebar, launcher,
and login — white logo pops on dark UI; inline style removed from login.html
Dispatch df:bins-changed custom event from onBinDrop and
AssetContextMenu.moveToBin so the bin rail counts update
immediately after moving an asset into a bin.
RenameProjectModal is exported to window from screens-projects.jsx,
so Library screen must reference it via window object and use
React.createElement instead of JSX syntax.
- Fix 500 error when creating bins: missing updated_at column on bins table
(migration 013 adds the column, schema.sql updated)
- Add drag-and-drop support for moving asset cards/list rows onto bin rail items
with visual droppable highlight
- Add right-click context menu on project rail items (Rename/Delete)
- Expose RenameProjectModal via window so Library screen can reuse it
- Bins context menu already existed — was hidden by the 500 error
- recorders: dispatch df:recorders-changed on create/start/stop/delete so the
list updates immediately instead of waiting for the 10s poll tick
- library: poll every 4s while any asset is live/processing (15s otherwise) and
listen for df:assets-changed so a stopped recorder's LIVE badge drops and
the thumbnail appears without a manual refresh
- auth: synthetic /auth/me (AUTH_ENABLED=false) now uses LOCAL_OPERATOR / USER /
USERNAME instead of hardcoding "Admin", and flags synthetic:true
- shell: Sidebar takes `me` as a prop, drops the misleading "Admin" fallback,
and surfaces an "auth off" hint when the response is synthetic
- jobs: replace the always-empty ETA column with a Time column that shows
queued/started/done/failed N ago (full timestamp on hover); widen column
- schedule: new month-calendar view (default) with events plotted on day cells
by status; clicking a day pre-fills the new-schedule modal with a 30-min
window on that day; List view kept behind a toggle
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Library's Bins section now always renders (not just when bins exist)
with a + button that prompts for a name and POSTs /api/v1/bins with
the open project's id. Bins re-fetch on project change so the rail
shows project-scoped bins when a project is open, or global view
otherwise.
Bins list now hydrates from local state instead of stale ZAMPP_DATA
so newly-created bins appear without a full reload. Without an open
project the + button is dimmed with a helpful tooltip — "Open a
project to create a bin".
Projects:
- Per-row 3-dot menu in list view: Open / Rename / Delete (PATCH + DELETE)
- ProjectCard's bottom bar now shows real ready/in-flight/error counts
for the project's assets instead of fake 70/20 segments
- After mutations, project list refreshes from /projects + recomputes
asset counts client-side
Bins:
- GET /api/v1/bins now returns every bin across every project when
no project_id is supplied; result rows include project_name + asset_count
- Asset right-click 'Move to bin' filters to bins in the same project as
the asset and surfaces project_name as a tooltip
Jobs:
- 'Retry all failed' button in the header appears when there are
failed jobs and POSTs /retry for each one in parallel
- Failed-row error message now clips with title= tooltip so 3KB
ffmpeg stderr doesn't blow out the row layout
window.PROJECT_COLORS exposed for cross-screen access.
Asset detail:
- Download now fetches /assets/:id/hires presigned URL and triggers a
named browser download instead of doing nothing
- More icon now opens a kebab menu (Copy ID, Delete permanently)
- Approve button removed (no backend); audio + fullscreen icons
in the player controls now actually toggle mute / requestFullscreen
Shell:
- Sidebar Sign-out now POSTs /auth/logout + reloads (no-op when auth disabled, by design)
- Topbar Notifications bell removed (dead, no backend)
- Topbar search wired: typing + Enter routes to Library with the term
pre-loaded into Library's own search box
- Cluster-healthy pip now polls /metrics/home every 30s so it reflects
real online-vs-total instead of always showing green
Editor:
- Dead Export / Publish / Mark in / Mark out / Add to timeline / Step
buttons are now visibly disabled with explanatory titles; a PREVIEW
badge sits next to the sequence name so the WIP state is obvious
Containers / Cluster admin:
- Logs button opens a modal with the docker tail command + Copy button
instead of a JS alert
- Restart now shows an inline toast (pending/ok/fail) instead of alerts
- Cluster Add Node / Drain / Logs replace alert() with a styled advice
modal that supports multi-line commands + Copy
- Dead Cluster topology Graph/List tab toggle removed (only Graph is
implemented anyway)
Proxy failures ("moov atom not found"):
- root cause: failed/aborted SRT/RTMP recordings still uploaded 0-byte
(or ftyp-only ~1KB) objects to S3, which ffmpeg can't probe
- worker proxy.js now bails on inputs < 4 KiB with a clear message
before handing the file to ffmpeg
- capture-manager.stop() returns framesReceived + empty flag
- capture shutdown handler skips POST /assets entirely on empty
sessions, instead calls new POST /assets/:id/mark-empty to flip
the pre-created live asset to 'error' with a note
Library asset right-click menu:
- new AssetContextMenu component on screens-library.jsx; right-click
any asset in grid or list view to open
- actions: Open, Rename, Move to bin (lists up to 10 bins), Remove
from bin, Copy asset ID, Delete permanently (hard=true)
- viewport-aware positioning (won't clip past window edges)
- dismisses on outside click / contextmenu / scroll
- Library now refreshes via /assets after mutations; normalizeAsset
exposed on window so the re-fetch shape matches boot
- ctx-menu styles in styles-rest.css
Fetches stream URL on hover after 350ms delay; renders muted autoplay
video overlay over the thumbnail. Supports both mp4 and HLS streams.
Only triggers for ready/live assets to avoid pointless API calls.