Commit graph

27 commits

Author SHA1 Message Date
Claude
e55555d2b7 Fix AMPP picker: text input, path-based queuing, worker path resolution 2026-04-30 21:49:16 -04:00
34695f3caf feat: AMPP placement worker — background job poller, folder list API, pending placements 2026-04-30 17:45:21 -04:00
6667f320c5 feat: wire AMPP folder placer into server — add /api/ampp/place endpoint 2026-04-30 17:17:39 -04:00
Zac
340837fa72 fix: close desktop/multipart/abort route missing res.json and closing brace 2026-04-08 22:16:48 -04:00
Zac
c4158f0cfd merge: keep desktop multipart API routes alongside parallel chunk upload routes 2026-04-08 22:09:25 -04:00
Zac
675ff9985f feat: add desktop multipart API endpoints for Dragon Wind Desktop app 2026-04-08 22:05:53 -04:00
84cf9cccbe Fix folder sorting, default selection, subfolder S3 keys, and HTTP mode description
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>
2026-04-08 21:40:44 -04:00
Zac
5b0a3ef2cc Add server-side AMPP job debug logging to identify field names
Logs the first job's keys and data (truncated to 1000 chars) on each
/api/ampp/jobs request to help identify which field contains the asset name.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 09:16:24 -04:00
Zac
ecdfe0f7cd Presigned direct-to-S3 uploads — bypass Node server entirely
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>
2026-04-07 01:08:55 -04:00
Zac
44c22bd95e Replace Upload class with PutObjectCommand for RustFS compatibility
The @aws-sdk/lib-storage Upload class internally uses
CreateMultipartUploadCommand for files over the part size threshold,
which returns non-standard XML from RustFS causing UnknownError.
PutObjectCommand does a simple single PUT request that RustFS handles
correctly. Fixed in both /api/upload and /api/link/:id/upload endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 00:52:54 -04:00
Zac
43aa18f963 Use ListObjectsV2Command for S3 test instead of raw HTTP signing 2026-04-07 00:42:52 -04:00
Zac
1bc30010a4 Replace AWS SDK test with raw S3v4 signed HTTP request for RustFS/MinIO compat 2026-04-07 00:38:44 -04:00
Zac
4b0f56ac2a Add full S3 error dump for debugging 2026-04-07 00:34:46 -04:00
Zac
89291a4baf Fix S3 test: always merge with saved config, add debug logging 2026-04-07 00:32:59 -04:00
Zac
ae4360e85a Fix S3 test (use HeadBucket like VPM-Uploader), replace UDP button with grayed Electron App 2026-04-07 00:30:28 -04:00
Zac
db25255472 Fix S3 save, remove UDP relay entirely, remove Extension tab 2026-04-07 00:26:43 -04:00
Zac
f3aa44104c Remove Extension tab, fix S3 save, update footer, add Electron uploader coming soon to UDP Relay 2026-04-07 00:21:31 -04:00
2b713fd169 fix: remove duplicate require causing SyntaxError on startup
CreateMultipartUploadCommand etc. were already declared at top of file.
Appended block re-declared them causing 'Identifier already declared' crash.
2026-04-06 23:32:08 -04:00
8ec43c299e Add parallel chunked HTTP upload (Option 4 — Aspera-class speed)
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
2026-04-06 23:22:51 -04:00
efdaa48cb6 fix: UDP upload was completely broken — relay never received sessions or chunks
Root cause: three critical bugs in the UDP upload flow:

1. Main server never registered sessions on the relay — it stored them
   in its own memory but never called POST /session on the relay, so
   the relay had no idea about any upload sessions.

2. Relay had no HTTP chunk endpoint — the Chrome extension sends chunks
   via HTTP POST to /session/:id/chunk/:index, but the relay only had
   a binary UDP listener. Added the HTTP fallback endpoint.

3. Relay had no CORS headers — browser requests from chrome-extension://
   origins were blocked. Added CORS middleware.

The flow now works:
  Browser → POST /api/udp/session (main server)
  Main server → POST /session (relay, with s3Config)
  Browser → POST /session/:id/chunk/:n (relay, via public URL)
  Relay → S3 multipart upload
  Browser → POST /api/udp/session/:id/complete (main server)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:12:22 -04:00
42fead82aa fix: split relay URL into internal + public for browser clients
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>
2026-04-06 22:02:14 -04:00
978d447b3d fix: add CORS headers for Chrome extension + fix Save & Connect button
- Add CORS middleware to server.js allowing chrome-extension:// origins
  so the popup can make authenticated API requests without browser blocking
- Fix popup.js saveSettings(): require password on save, call login() directly
  instead of tryConnect() to avoid password-not-found loop
- Fix init(): open settings panel automatically if no saved token, so users
  know they need to enter credentials after first install or session expiry
- Don't persist password to chrome.storage (security), use remove('token')
  instead of set({token:null}) to properly clear the old session

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 21:30:17 -04:00
c03b7ef491 Add per-user upload quotas/permissions and share link system
- Per-user quota tracking (MB limit + uploadedBytes counter)
- Per-user allowed folders restriction (empty = all folders allowed)
- Admin permissions modal: quota config, folder checkboxes, usage reset
- Share links: create tokenized upload URLs with expiry, max-uses, folder
- Public share.html upload page (no auth required) with drag-drop + progress
- Backend routes: GET/PUT /api/users/:u/permissions, POST .../quota/reset
- Backend routes: GET/POST /api/sharelinks, DELETE .../token, GET /share/:token
- migrateData() ensures existing user records gain new fields on startup
- Frontend JS: loadUsers quota column, openPermissions modal, loadShareLinks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:58:29 -04:00
e2c6db7113 fix: S3 generic compat, nav tab reliability, single logo
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>
2026-04-05 20:42:21 -04:00
895145e1ed feat: Chrome extension download + install guide in admin panel
- GET /api/extension/download — streams chrome-extension/ as a .zip using archiver
- Admin → 🧩 Extension tab with:
  - One-click download button (fetches zip via auth'd API, triggers browser save)
  - 5-step install guide: unzip, chrome://extensions, developer mode, load unpacked, configure
  - UDP port-forwarding reminder note
- Added archiver dependency to package.json

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 20:33:56 -04:00
155c821ef8 feat: AMPP configuration in admin settings
- 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>
2026-04-05 20:22:51 -04:00
641701edf8 feat: Dragon Wind v1.0 — dual-mode broadcast uploader
- Full VPM Uploader feature set (auth, users, folders, AMPP monitor)
- HTTP upload via presigned S3 URLs with XHR progress tracking
- UDP upload mode with relay server (WebRTC DataChannel + HTTP fallback)
- S3 Admin settings with live Test Connection (upload+delete verify)
- UDP Relay Admin settings with health check
- Standalone UDP relay server (Node.js + Docker) with multipart S3 assembly
- Chrome Extension (Manifest v3): popup, background, content script
- Dynamic S3 client — reconfigures on save without restart
- Dark/light theme, full AMPP job monitor
- docker-compose.yml with dragon-wind + udp-relay services

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 20:05:34 -04:00