A 46MB file now splits into 6 chunks (all 6 streams active) instead
of 2 chunks (4 streams idle). Better saturation of available bandwidth
on high-latency or constrained links.
Large files (>32MB) now use presigned S3 multipart URLs via
/api/desktop/multipart/init, letting the browser PUT 32MB chunks
directly to S3 in 6 parallel streams. No data passes through Node.
Small files still use single presigned PUT. Updated HTTP mode
description to "HTTP multi-part upload".
Reverts accidental landing page overwrite. Files >32MB now use S3
multipart upload with 32MB chunks and 6 parallel streams per file.
Files <=32MB still use fast direct presigned PUT.
Files >32MB now use S3 multipart upload with 32MB chunks and 6 parallel
streams per file. Files <=32MB still use fast direct presigned PUT.
Fixes slow upload speeds for large files.
Files >32MB now use S3 multipart upload with 32MB chunks and 6 parallel
streams per file. Files <=32MB still use fast direct presigned PUT.
Fixes slow upload speeds for large files.
Addresses feedback from Gavin (VPM):
- Sort folders alphabetically in both upload tree and admin tree views
- Auto-select VPM as default folder on login instead of Root
- Fix S3 key construction for nested folders: convert "/" to "--" so FLX
correctly maps subfolders (e.g. Content/TEST - AMPP Demo now produces
Content--TEST - AMPP Demo--file.ext instead of Content/TEST - AMPP Demo--file.ext)
- Clarify HTTP mode note: "Files are processed 6 at a time" instead of
"up to 6 concurrent files" which implied a total file limit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Browser now uploads files directly to RustFS/S3 via presigned PUT URLs.
The Node server only generates signed URLs and tracks quota — file data
never touches the server. 6 concurrent file uploads.
Falls back to server-proxied PutObjectCommand upload if presigned fails.
Server changes:
- /api/presigned now checks folder permissions, quota, and blocked files
- /api/presigned/complete endpoint for post-upload quota tracking
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add search/filter input to destination folder browser with 320px
scrollable container
- Add User Audit button showing each user's visible pages, role,
quota, and folder access permissions
- Fix admin Folders tab delete buttons (were broken due to
JSON.stringify quote conflicts in innerHTML onclick handlers)
- Add more AMPP job name field fallbacks and debug logging to
diagnose asset name display issue
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The manual CreateMultipartUploadCommand/UploadPartCommand/CompleteMultipartUploadCommand
flow fails with RustFS due to non-standard XML responses (same issue as HeadBucketCommand).
Switch front-end to use /api/upload endpoint which uses @aws-sdk/lib-storage Upload class —
the same method that worked reliably in VPM-Uploader with RustFS.
Uses XMLHttpRequest for upload progress tracking.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AMPP API returns keys like 'state:jobState', 'name:text', 'type:jobType',
'creator:id', 'created:dateTime', 'job:id' — not plain 'status', 'name',
etc. Frontend was falling back to 'Job' / 'Unknown' for every entry.
Updated field lookups to read colon-namespaced keys first, with fallbacks
for compatibility. Also added 'aborted' to the failed status detection.
Split files into 32 MB chunks, POST 6 concurrently to /api/upload/chunk,
server proxies each chunk as an S3 multipart part. Up to 4 files upload
in parallel simultaneously. Achieves Aspera-class throughput over plain
HTTP with no UDP port forwarding or custom protocols required.
Same approach used by MASV under the hood.
- server.js: Add /api/upload/initiate, /chunk, /complete, /abort endpoints
- public/index.html: Replace single-PUT uploadHTTP() with parallel chunked version
The relay container is reached internally via docker service name
(http://dragon-wind-relay:3001) but browsers need the public address.
Previously the internal URL was sent to clients causing UDP uploads to fail.
- Add publicRelayUrl field to relay config (server + admin UI)
- /api/udp/session now returns publicRelayUrl to browser clients
- Internal relayUrl still used for server-side health checks
- Falls back to internal URL if public not set
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Same fix as the Chrome extension — the web GUI's uploadHTTP() was using
item.file.type (browser-determined MIME) instead of presigned.contentType
(server-signed MIME). For broadcast formats like MXF, R3D, BRAW where
the browser returns empty or generic types, this causes an S3 signature
mismatch and the PUT fails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix duplicate id="ampp-status" collision between the monitor page and
admin AMPP panel — admin panel now uses id="ampp-cfg-status" so the
monitor status messages are no longer silently hijacked
- AMPP monitor now shows a clear "not configured" card with a direct
button to Admin → AMPP instead of a cryptic error when the API key
hasn't been entered yet
- Improve job field mapping to handle AMPP response variations
(jobStatus, displayName, jobType, results array vs items array)
- Add 30-second auto-refresh while on the Monitor tab; timer is cleared
when navigating away to avoid ghost requests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add readonly+onfocus trick to prevent browser autofilling secret key with garbage
- Set region value="us-east-1" so it always has a real default, not just placeholder
- loadS3Config always clears secret field and sets contextual placeholder
- Secret hint now clearly shows saved vs not-saved state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add chrome-extension/ to Dockerfile COPY (was missing, caused 404 on download)
- Remove UDP Relay tab from admin panel (relay is server-side, no user config needed)
- Remove upload mode toggle buttons, replace with clean inline status bar
- Extension panel: drop relay port-forwarding note, simplify to 'extension required' message
- UDP hint shown inline only when extension is detected in browser
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace chip-pill folder selector with clean vertical tree list
- VPM text wordmark replaces vpm-logo.png in login + header (no PNG/invert hack)
- Wild Dragon logo/icon retained only on favicon and splash animation
- Auto-detect prefers-color-scheme on first load (no longer defaults to dark)
- System theme changes update UI if user hasn't manually toggled
- Remove dragon icon from login card and app header
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Added VPM logo (vpm-logo.png) to login card and header left side
(subtle, opacity 50%, auto-inverted in light mode)
- Footer at bottom of app: "Built by Zac Gaetano & Wild Dragon LLC
· In partnership with Broadcast Management Group"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
S3:
- Endpoint is now optional (leave blank = AWS S3, custom = MinIO/R2/Backblaze/etc.)
- forcePathStyle only applied when a custom endpoint is set (harmless on AWS)
- initS3() no longer requires endpoint to be present
- Updated form hint to explain AWS vs generic S3 usage
Nav tabs:
- Switched admin tab active-state matching from fragile array-index to data-tab attribute
- Added user-select:none to prevent text selection on click for both nav and admin tabs
- Admin tabs now flex-wrap for narrow viewports
Logo:
- Removed wilddragon-logo.png wordmark from splash, login, and header
- Single dragon-icon.png used throughout — no CSS invert hack needed
- Cleaner header: icon + "Dragon Wind" badge only
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- GET/PUT /api/ampp/config — store base URL + API key in db.json (no restart needed)
- POST /api/ampp/test — authenticate against AMPP token endpoint and report result
- Refactored AMPP_BASE/AMPP_API_KEY constants to dynamic getAmppBase()/getAmppApiKey()
functions so live config changes take effect immediately
- Admin → AMPP tab: base URL field, masked API key field, Test Connection + Save buttons
- Cached token invalidated automatically on config save
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>