Commit graph

112 commits

Author SHA1 Message Date
08e8377309 fix: bump api.js cache-buster to v=6 in upload.html 2026-05-19 00:33:11 -04:00
280fc9dff2 fix: XSS in renderTags and stale api.js version in player.html
Tag values were inserted into innerHTML unsanitized — a tag containing
HTML would execute as markup. Switch to DOM-only construction for the
tag badges. Also bump api.js cache-buster to v=6.
2026-05-19 00:30:54 -04:00
f1e0453b0a fix: bump api.js cache-buster to v=6 in capture.html 2026-05-19 00:28:50 -04:00
9f7cb91cc2 fix: prevent JS injection via token name in confirmRevoke onclick
Token names containing single quotes (e.g. "O'Brien's key") broke the
onclick attribute string by closing the JS string literal early.
Apply JSON.stringify+esc pattern so name is safely embedded as a
JSON string literal instead of a raw single-quoted string.
2026-05-19 00:27:31 -04:00
d18fa2f761 feat(library): add Retry button for error-status assets in library grid
Error assets now show an amber circular-arrow action button on hover.
Clicking it calls POST /api/v1/assets/:id/retry, resets status to
'processing', and refreshes the grid — no manual DB intervention needed
when a proxy job fails.
2026-05-19 00:20:19 -04:00
130906ef42 feat(api.js): add retryAsset() helper for POST /assets/:id/retry 2026-05-19 00:17:39 -04:00
2bb731c7fc fix(users): prevent JS injection in delete onclick handlers for users/groups
confirmDeleteUser and confirmDeleteGroup were building onclick handlers
like onclick="confirmDeleteUser('id','NAME')" using esc() which doesn't
escape single quotes.  Usernames or group names containing ' would break
the JS string; a crafted value like `'; alert(1)//` is stored XSS.

Fix: use JSON.stringify(value) to produce a properly-escaped double-quoted
JS string literal, then esc() to HTML-encode the surrounding quotes for
safe embedding in the HTML attribute.  Same technique now used in both
renderUsers() and renderGroups().
2026-05-19 00:11:06 -04:00
1e8cde81be fix(projects): prevent JS injection via bin names in onclick handlers
binCard() was building onclick="renameBinPrompt('id', 'NAME')" by
calling esc() then .replace(/'/g, "\\'").  The problem: esc() converts
' to ', so the replace never fires on raw single quotes.  When the
HTML parser evaluates the attribute it decodes ' back to ', breaking
the JS string — and for injected payloads like `'; alert(1)//` this is
stored XSS.

Fix: use JSON.stringify(b.name) to produce a properly-escaped double-
quoted JS string literal, then esc() to HTML-encode the surrounding
double-quotes for safe embedding in the HTML attribute.
2026-05-19 00:09:49 -04:00
0ea8d7ce33 fix(timeline): cap right-trim at source asset boundary
When duration_ms is known, dragging the right-trim handle past the end
of the source clip could push timeline_out_frames beyond what the source
material covers.  Cap the delta so neither timeline_out_frames nor
source_out_frames can extend past the available source frames.

Also changed assetFrames fallback from origSrcOut (prevents any extension
when duration is unknown) to null, so the guard is simply skipped when
we don't have duration metadata.
2026-05-19 00:02:34 -04:00
3c689ccddf fix(timecode): correct framesToTC for all frames beyond position 3
The previous algorithm used `if (rem >= DROP)` (i.e. rem >= 4) to decide
whether to advance to the next minute group.  This fired immediately at
frame 4, still inside minute 0 of the 10-minute non-drop group, producing
00:01:00;00 for what should be 00:00:00;04.  Every timecode display in
the editor was wrong for any position past the first four frames.

Each 10-minute block has one 3600-frame non-drop minute followed by nine
3596-frame drop minutes.  The fix checks `rem < FRAMES_FIRST_MIN` (3600)
to identify the non-drop minute, then subtracts it before dividing into
drop-minute slots.  Frame labels within drop minutes are shifted by DROP
(+4) so the first usable label is :00;04 as per SMPTE 12M.
2026-05-19 00:01:18 -04:00
0f37d01b2d fix(editor): keyboard tool shortcuts now actually switch the active tool
V/C/H key shortcuts called updateToolbarActive() which only updated button
visual state — Timeline.setTool() was never called so the cursor stayed on
the previous tool. Fix by calling Timeline.setTool() inside updateToolbarActive.

Also bump api.js reference to ?v=6 to match other pages.
2026-05-18 23:53:38 -04:00
ff892a1ad5 fix(capture): use duration_ms field for recent captures duration display
The asset schema stores duration as duration_ms (milliseconds).
renderRecent() was checking c.duration (always undefined) so duration
always showed as '—'. Fix to use c.duration_ms / 1000.
2026-05-18 23:50:05 -04:00
08e5ba6298 fix(jobs): fetchJobs → loadJobs, add credentials to inline api helper
killJob() referenced fetchJobs() which is undefined — the correct name is
loadJobs(). Also the inline api() wrapper was missing credentials:'include'
so any API call on the jobs page would fail with a 401 in prod.
2026-05-18 23:48:56 -04:00
e472075087 fix(library): evict stale thumb URL on image load error, re-observe for retry
When a signed S3 URL expires the img fires onerror. Previously the stale URL
stayed in thumbCache so the broken image would persist. Now we delete the cache
entry, clear the loaded class, and re-add the element to the IntersectionObserver
so the next time it scrolls into view a fresh signed URL is fetched.
2026-05-18 23:46:12 -04:00
660afb94bb feat(editor): show fps/codec/resolution/duration in media panel asset list
- Add two-line layout to media panel items: name on top, metadata below
- fmtMs() converts duration_ms to MM:SS or HH:MM:SS for display
- Meta line shows resolution · codec · fps · duration, skipping null fields
- Assets with no extracted metadata (no proxy yet) show name only
- Active item meta line inherits accent color at reduced opacity
2026-05-18 23:37:56 -04:00
508cf8d41b feat(recorders): add Edit Recorder panel with PATCH support
- Edit (pencil) button appears on idle recorder cards; hidden while recording
- openEditPanel() pre-populates all form fields from existing recorder state
- openPanel() resets editingId and restores "New recorder" defaults
- closePanel() clears editingId and removes any stale probe result
- handleSaveRecorder() dispatches PATCH /recorders/:id in edit mode, POST otherwise
- Fix field name bugs in create path: codec→recording_codec, resolution→recording_resolution,
  proxy_config object→proxy_enabled/proxy_codec/proxy_resolution flat fields
- Badge in card now reads rec.recording_codec (correct DB field) instead of rec.codec
- Bump api.js cache-buster to v=6
2026-05-18 23:35:16 -04:00
79d44826fe feat(api.js): add patchRecorder() helper for PATCH /recorders/:id 2026-05-18 23:32:33 -04:00
e895a2f2df fix: show duration overlay on asset cards using duration_ms
asset.duration is not a DB field — it's duration_ms (milliseconds).
Divide by 1000 before passing to formatDuration() which expects seconds.
2026-05-18 23:27:03 -04:00
596f755a6c fix: remove stray Wild Dragon brand remnant from editor.html 2026-05-18 23:14:14 -04:00
656c820638 feat: wire editor.html as primary editor, fix its sidebar/branding
- All pages: Editor nav link now points to editor.html (in-house NLE)
- Removes the :47435 OpenReel resolver script from all pages
- editor.html: canonical Z-AMPP sidebar (all 10 nav items, correct icons)
- editor.html: Z-AMPP brand logo, removes Wild Dragon SVG mark
- editor.html: removes Google Fonts import
- editor.html: adds auth-guard.js
2026-05-18 23:11:53 -04:00
910bbf8d3f merge: bring NLE editor pages (editor.html, timeline.js, timecode.js) from main 2026-05-18 23:02:51 -04:00
e8e26dd4d8 fix: remove Google Fonts, fix editor link to :47435, fix page titles
- Remove @import Google Fonts from common.css (was blocking CSS on LAN)
- Update Editor nav link on all pages to dynamically resolve to :47435
  (OpenReel SPA) using inline script so it works on any hostname
- Fix page titles from Wild Dragon -> Z-AMPP across all pages
- Resolver: <a href="#" id="editor-nav-link"> + IIFE sets href at load
2026-05-18 22:56:51 -04:00
1f31d1037d merge: bring sequences/auth/admin backend + auth-guard frontend into fix/library-and-signal-indicator 2026-05-18 21:25:36 -04:00
8ab71239e3 feat(ui): add Open in Editor action to library cards 2026-05-18 20:14:29 -04:00
78a887a3e0 feat(ui): add NLE editor page (editor.html) 2026-05-18 20:10:25 -04:00
2fabc73299 fix(ui): prevent keydown listener accumulation on re-init 2026-05-18 20:05:34 -04:00
10152b5ad7 feat(ui): add DOM-based timeline engine (select, razor, playhead) 2026-05-18 20:02:41 -04:00
ad6e836345 feat(ui): add sequence API helpers to api.js 2026-05-18 19:58:35 -04:00
7d8ccc95e9 feat(ui): add 59.94 DF timecode utility module 2026-05-18 19:58:34 -04:00
0b94153518 Replace inline auth script with shared auth-guard.js in tokens.html 2026-05-18 13:46:10 -04:00
3203832aa9 Replace inline auth script with shared auth-guard.js in users.html 2026-05-18 13:44:35 -04:00
88c0781767 Replace inline auth script with shared auth-guard.js in jobs.html 2026-05-18 13:43:22 -04:00
81b832dc70 Replace inline auth script with shared auth-guard.js in recorders.html 2026-05-18 13:41:52 -04:00
936867c0c3 Replace inline auth script with shared auth-guard.js on recorders, jobs, users, tokens pages: tokens.html 2026-05-18 13:38:27 -04:00
de3920dd4a Replace inline auth script with shared auth-guard.js on recorders, jobs, users, tokens pages: users.html 2026-05-18 13:38:26 -04:00
9dfefc5731 Replace inline auth script with shared auth-guard.js on recorders, jobs, users, tokens pages: jobs.html 2026-05-18 13:38:25 -04:00
f3fbb027f6 Replace inline auth script with shared auth-guard.js on recorders, jobs, users, tokens pages: recorders.html 2026-05-18 13:38:24 -04:00
e3128acb15 fix: use shared auth-guard.js on capture.html 2026-05-18 13:27:24 -04:00
d8766f18cc fix: use shared auth-guard.js on upload.html 2026-05-18 13:26:19 -04:00
a40232e2b5 fix: use shared auth-guard.js on settings.html 2026-05-18 13:25:03 -04:00
ebe8b3be59 fix: use shared auth-guard.js on index.html 2026-05-18 13:24:25 -04:00
4f649b41a9 feat: add shared auth-guard.js with 401 → login redirect 2026-05-18 13:21:22 -04:00
725c3ed292 feat: rebuild settings.html with new shell layout 2026-05-18 13:08:19 -04:00
9ceb5db1e3 feat: add admin sidebar section and user footer widget 2026-05-18 13:08:04 -04:00
533250b1c3 feat: add admin sidebar section and user footer widget 2026-05-18 13:07:47 -04:00
ffffe8039e feat: add admin sidebar section and user footer widget 2026-05-18 13:07:40 -04:00
027e73467f feat: add admin sidebar section and user footer widget 2026-05-18 13:06:57 -04:00
95fa1b83b6 feat: add admin sidebar section and user footer widget 2026-05-18 13:06:40 -04:00
4213c8a7b3 feat: auth system — CSS page transitions, API helpers, users/tokens pages 2026-05-18 13:00:31 -04:00
c7d8be9f28 feat: auth system — CSS page transitions, API helpers, users/tokens pages 2026-05-18 12:59:36 -04:00