Skip to content

feat(seed): add advanced transfer seed UI (generate/preview/manage) - #3058

Open
PIKACHUIM wants to merge 18 commits into
mainfrom
feat/advanced-transfer-seeds
Open

feat(seed): add advanced transfer seed UI (generate/preview/manage)#3058
PIKACHUIM wants to merge 18 commits into
mainfrom
feat/advanced-transfer-seeds

Conversation

@PIKACHUIM

Copy link
Copy Markdown
Member

title: Advanced Transfer Seeds — Implementation PR
categories: [guide, advanced]
top: 22

Advanced Transfer Seeds — Implementation PR

This document is the implementation pull-request description for the Advanced Transfer Seeds feature. It complements the design and compatibility specification in transfer-seeds.md and records what was actually implemented, how it was validated, and what remains out of scope.

1. Summary

Advanced Transfer Seeds add a portable, cross-driver, cross-user metadata system built on three sidecar formats:

  • .ossopenlist-sharing-seed v1 JSON. The most complete and lossless envelope; every field is optional except format, version, name, created_at, created_by, piece_size, and files.
  • .torrent — standard BitTorrent v1 plus a root-level x-openlist extension and a legacy-compatible x-cas extension. Always carries the SHA-1 piece hashes required by BT; additional MD5/SHA-256 and comments/sources live in the extension.
  • .cas — byte-for-byte compatible with the reference OpenList-CAS payload: padded Base64 of JSON containing exactly name, size, md5, sliceMd5, and create_time. No extension keys are added, preserving third-party client compatibility.

Users can generate seeds during upload or from the right-click context menu, preview and consume them, convert between formats, rapid-save into another driver, relay a save through an intermediate driver, and edit/recalculate metadata.

2. What is included

Repository Branch Scope
OpenList-Backends feat/advanced-transfer-seeds Go format library, /fs/seed/* API, upload sidecars, file-op sidecars, settings
OpenList-Frontend feat/advanced-transfer-seeds HopeUI generation wizard, seed preview, upload/file-op sidecar toggles, settings
OpenList-TSWorker feat/advanced-transfer-seeds TS codec and /fs/seed/* routes, streaming hashing, settings
OpenList-Docs docs/advanced-transfer-seeds Design spec, compatibility reference, and this PR document

Implemented capabilities:

  1. Generate — single or multiple files, three formats at once (oss, torrent, cas), a content hash matrix (md5/sha1/sha256 × whole/pieces), per-file and overall comments, trackers, channels, piece size, and optional share/direct-source embedding.
  2. Preflight — driver-provided hashes are reported so the UI can show whether files must be fetched before generation, and the estimated traffic.
  3. Preview/parse — unified parsing of .oss, .torrent, and .cas with files, hashes, comments, timestamps, trackers, channels, sources, conversion feasibility, and operation capabilities.
  4. Convert — between all three formats with explicit missing-information diagnostics; semantic projection is used instead of incorrect strict-subset claims.
  5. Rapid upload — native driver reuse (189pc CAS) when hashes are available; otherwise an explicit unavailable reason (never a silent generic upload).
  6. Offline download — authorized source URL into the destination driver via PutURL, an offline-download tool, or a server-side streamed transfer.
  7. Relayed transferoptions.mode: "transfer" with transit_path materializes synchronously into an intermediate storage (native rapid upload or PutURL), then copies server-side to the final destination. Asynchronous offline downloads are rejected for relay.
  8. Edit — update the overall comment, trackers, channels, per-file comments, and per-file share/direct sources; sources are validated against the configured site URL.
  9. Recalculate — re-read server-side files (bounded to 1 GiB) and recompute whole and piece hashes using a supplied matrix; the piece size is validated and written back to the seed.
  10. Sidecar lifecycle — upload, copy, move, rename, and delete can optionally manage .oss/.torrent/.cas sidecars alongside the source file.

3. Format specification

.oss (openlist-sharing-seed v1)

{
  "format": "openlist-sharing-seed",
  "version": 1,
  "name": "example",
  "comment": "",
  "created_at": "2026-09-08T00:00:00Z",
  "created_by": "OpenList",
  "piece_size": 10485760,
  "trackers": [],
  "channels": [{"driver": "189pc", "mount_path": "/189pc"}],
  "files": [
    {
      "path": "a.txt",
      "size": 12,
      "modified": "2026-09-08T00:00:00Z",
      "comment": "",
      "hashes": {
        "md5": "...",
        "sha1": "...",
        "sha256": "...",
        "pieces": {"md5": ["..."], "sha1": ["..."], "sha256": ["..."]}
      },
      "sources": [{"type": "openlist-direct", "url": "https://site/d/path"}]
    }
  ]
}
  • channels contain only public driver and optional mount_path; credentials are never serialized.
  • sources are public direct (/d/) or share (/sd/) URLs validated against the configured site URL.

.torrent

Standard BT v1 info/pieces plus a root x-openlist dictionary holding the same optional metadata and a root x-cas dictionary for 189pc rapid-upload info. x-openlist is cross-validated against info (name, piece length, file list, and SHA-1 pieces) before use.

.cas

Strict reference payload. No extension keys. Large files require either a preserved legacy aggregate sliceMd5 or complete 10 MiB MD5 pieces so conversion is lossless.

4. API reference

All endpoints are under POST /api/fs/seed/* (mounted as /fs/seed/*), with legacy /fs/torrent/* routes retained.

Endpoint Purpose
/capabilities Source preflight and destination import planning
/generate Generate one or more seed artifacts
/parse Parse and preview a seed document
/convert Convert between formats with diagnostics
/rapid_upload Native driver reuse only
/offline_download Source → destination transfer (including relayed transfer)
/update Edit metadata and/or recalculate hashes

Common operation envelope: { "seed_data": "<base64>", "file_name": "...", "path": "...", "selected_files": [0], "options": {...} }.

parse returns capabilities: rapid_upload, offline_download, transfer, convert, edit, and recalculate, so the UI only enables actions the backend actually supports.

5. Settings

  • seed_site_url — public site URL used to build share/direct sources (required before embedding sources).
  • seed_default_matrix — default right-click hash matrix.
  • seed_format_policies — global per-format auto-generation switches (all default off).
  • seed_auto_generate_policy — global off/on automatic sidecar policy.
  • seed_single_direct_preview — open single-file seeds directly in preview (default off).
  • Per-storage seed_policyinherit/on/off override that resolves against the global default.

6. Acceptance criteria

  1. Generating a seed for N files reads each file once and computes whole and piece MD5/SHA-1/SHA-256 without loading a whole file into memory.
  2. Selecting torrent forces SHA-1 whole + pieces; selecting cas forces MD5 whole + pieces and a fixed 10 MiB slice size.
  3. .cas output is byte-identical to the reference five-field payload and round-trips without extra keys.
  4. A seed with only MD5 cannot be converted to torrent (missing SHA-1 pieces) and reports that reason.
  5. rapid_upload never silently falls back to a generic upload; it reports unavailable.
  6. A relayed transfer refuses asynchronous offline downloads and requires a synchronous intermediate save.
  7. update validates source URLs against the configured site and rejects cross-host URLs.
  8. recalculate writes the effective piece size back to the seed so piece hashes and piece_size stay consistent.
  9. File operations with follow_seed only touch sidecars of real files, not directories.
  10. All seed parsing enforces byte, file-count, depth, and path-traversal limits.

7. Validation

  • Go: go build ./... passes; go test ./pkg/torrent/... ./server/handles/... ./internal/op/... passes (format compatibility, path safety, parse limits).
  • TypeScript: tsc --noEmit reports zero errors in internal/seed and server/seed.
  • HopeUI: pnpm lint reports zero errors in the seed preview, types, and API files; production build transforms 1209 modules successfully.

8. Security, stability, performance, compliance

  • Security: path-traversal checks, content-write and copy/offline-download permission bits, source URLs restricted to the configured site, SSRF-safe fetch with redirect re-validation, and parse resource limits.
  • Stability: streaming single-pass hashing, bounded memory, synchronous-vs-async relay separation, and rollback of created shares on generation failure.
  • Performance: single-pass multi-hash computation, driver-capability preflight to avoid unnecessary fetches, and 1 GiB synchronous hashing bound.
  • Compliance: no credentials or usernames are serialized into shareable seeds; channels carry only public discovery metadata.

9. Risks and limitations

  • .cas intentionally preserves only the five reference fields; it is lossy by design and cannot carry comments, channels, trackers, or sources.
  • Relayed transfer requires an intermediate storage with synchronous native reuse or PutURL; a fully asynchronous cross-driver relay is out of scope.
  • Recalculate requires the source file to already exist on the server; it does not download from an external source.
  • BT distribution produces a valid .torrent but does not make OpenList a BitTorrent peer; tracker/webseed availability depends on deployment.

PIKACHUIM and others added 18 commits September 5, 2026 21:52
commit 2d51c9a
Author: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Date:   Mon Sep 7 14:14:22 2026 +0800

    feat!(init): add initialization wizard (#3041)

    feat: add system initialization (setup wizard) support

    Co-authored-by: PIKACHUIM <PIKACHUIM@users.noreply.github.com>

commit d9d8aa2
Author: ShenLin <773933146@qq.com>
Date:   Mon Sep 7 12:01:15 2026 +0800

    fix(s3): default upload content types and return partial content (#3053)

    - Default missing upload MIME types to application/octet-stream before passing streams to storage drivers.
    - Return HTTP 206 for successful ranged GET responses while preserving error statuses.
    - Add isolated response-status regression tests without database initialization.

    Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
    Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

commit 55530ff
Author: ShenLin <773933146@qq.com>
Date:   Mon Sep 7 12:00:50 2026 +0800

    fix(release): fetch frontend assets from edge (#3052)

    - Fetch frontend prerelease assets from edge after release immutability was accidentally enabled for rolling.

    Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
    Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

commit 6247cf7
Author: MadDogOwner <xiaoran@xrgzs.top>
Date:   Sat Sep 5 15:56:40 2026 +0800

    feat(server/s3): support multipart upload (#2813)

commit eee910b
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Sep 5 12:22:53 2026 +0800

    fix(deps): update module github.com/rclone/rclone to v1.75.1 (#3035)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 6b55a82
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Sep 5 12:14:09 2026 +0800

    chore(deps): update docker/setup-qemu-action digest to 1f40c72 (#3021)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 93dac16
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Sep 5 12:12:51 2026 +0800

    chore(deps): update go toolchain directive to v1.27.1 (#3024)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit 6ad4460
Author: Pikachu Ren <40362270+PIKACHUIM@users.noreply.github.com>
Date:   Sat Sep 5 12:11:51 2026 +0800

    feat(drivers/guangyapan): add md5-based instant upload support (#3034)

    feat(guangyapan): add md5-based instant upload support

    Co-authored-by: PIKACHUIM <PIKACHUIM@users.noreply.github.com>

commit d90d849
Author: UcnacDx2 <127503808+UcnacDx2@users.noreply.github.com>
Date:   Sat Sep 5 11:55:41 2026 +0800

    fix(drivers/139): improve mail login credential renewal (#3029)

    * fix(drivers/139): improve mail login credential renewal

    * fix(drivers/139): guard mail login client initialization

    Fall back to base.NewRestyClient() when base.RestyClient has not been initialized, while preserving cloned global-client behavior and the login/SMS retry and redirect policies.

commit c3d3da9
Author: ShenLin <773933146@qq.com>
Date:   Sat Sep 5 00:12:20 2026 +0800

    fix(drivers/189): decode JSON strings before parsing timestamps (#3033)

    - Decode JSON time strings before normalizing Unicode spaces in both 189 drivers
    - Exercise escaped spaces and existing date formats through JSON unmarshalling
    - Cover invalid JSON input and XML time parsing

    Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
    Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Add unified sharing-seed format library (openlist-sharing-seed v1), standard BT torrent v1 with x-openlist/x-cas extensions, and exact legacy-compatible CAS Base64 payload. Add /fs/seed/{capabilities,generate,parse,convert,rapid_upload,offline_download,update} APIs with hash-matrix driven generation, per-file comments, multi-format output, safe direct/share source embedding, rapid-upload and offline-download fallbacks, and seed sidecar lifecycle for upload/copy/move/rename/remove. Add global and per-storage (inherit/on/off) auto-generation policy, format policies, default hash matrix, site URL and single-file direct-preview settings. Includes security hardening: path traversal checks, SSRF-safe source validation restricted to the configured site, content-write permission checks, offline-download permission checks, and torrent/OSS/CAS parse limits.
Implement seed metadata editing (comment/trackers/channels/file comments/sources) and server-side hash recalculation with piece-size write-back and a bounded streaming reader. Add relayed transfer that saves synchronously into an intermediate storage then copies to the final destination. Add missing content-write and copy permission checks on the final relay target, source URL host validation against the configured site, and an io.LimitReader hard cap. Expose transfer/edit/recalculate in parse capabilities.
Record successful saves as channels and failures as missing_channels when update_channel is set. Return share_status during edit by validating openlist-share sources. Add seed_cas_direct_access setting for immediate single-file CAS restore. Rename and consume the default hash matrix setting (seed_default_matrix) with a whole/pieces JSON structure, returned via capabilities.
…m/OpenList into feat/advanced-transfer-seeds
SeedCapabilityReq embeds SeedDataReq whose SeedData field was bound with required. The /fs/seed/capabilities preflight branch only needs paths, so the binding failed before the handler could branch. Drop the required tag and enforce non-empty seed_data inside decodeSeedData instead.
Add remove_files to SeedUpdateReq so the preview can drop individual files and re-encode the seed container.
Capabilities now report streamable/direct_source_available/share_available and the configured tracker list. Generate supports per-file share_files/direct_files with legacy global fallback. Add seed_default_trackers setting.
…pability

ParseSeed marks torrent seeds as offline_download capable even without sources (magnet/tracker). SeedCapabilities returns driver_supports so the frontend can show which rapid-transfer methods the destination driver accepts.
Extract seed generation into fs.GenerateSeedArtifacts and add a SeedGenerateTask manager. Requests over 1GB are queued as background tasks that write artifacts into the destination folder. Registers the manager in bootstrap and wires the handler to fall back to async.
Export NormalizeSeedFormats and EncodeGeneratedSeed so fsup.go can reuse them after the generation logic moved into internal/fs. Drop the now-unused slices import.
CAS is a single-file container, so multi-file generation now emits one .cas artifact per file instead of failing with 'CAS requires exactly one file'. Capabilities no longer gate cas on single-file selection.
CAS now supports multiple files via a files array while keeping the legacy five-field single-file payload byte-compatible. Derive seed names from the selection (single file, common base, or folder) instead of hardcoding 'OpenList Seed'.
Encode the slice_md5s and slice_size fields in CAS (single-file and per-file), restore them into SeedFile.Hashes.Pieces.MD5 on decode, and hide the legacy warning when piece hashes are present. Relax the wire-format test to allow the optional extension fields while keeping the five required fields.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant