feat(files): W5-A2 move/copy via planImport, organize overrides, delete records, download
- /files/move|copy go through planImport's new `transfer` variant (keep names, directory expanded to per-file plan) → organization_record + verifyAndImport/executeRecord: per-file ledger resumable, fsproxy, cross-volume directory move = per-file copy→verify→delete then remove empty source dirs; shared plan store + plan_stale; asset_location follows per file, path_binding revised when a whole directory moved (finalizeTransfer); request waits up to FILES_TRANSFER_WAIT_SEC, else executed.pending - /files/organize per-item overrides take effect: season/episodes (domain planOrganize overrides), contentUnitId coverage, targetDir (no binding), operation, slotId (satisfied after verify); warnings only for inapplicable overrides - delete/trash/restore write organization_record (action trash|delete|restore, file-level results; migration 0026) - GET /files/download (admin session, nfo/subtitle/image, size cap, streamed, audited) - GET /files/records?ids|planIds for the organize page - fs race errors map to 503/404/403/400 instead of 500 - runbook updated Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
3641ab9573
commit
36aa99b8aa
25 files changed
+1766
-271
No files matched your search
@@ -210,6 +210,8 @@ describe.skipIf(skip)("files 写操作", () => {
|
||||
size: 8,
|
||||
conflict: false,
|
||||
registered: false,
|
||||
files: 1,
|
||||
crossDevice: false,
|
||||
},
|
||||
]);
|
||||
const planId = dry.body.data.planId;
|
||||
@@ -271,7 +273,8 @@ describe.skipIf(skip)("files 写操作", () => {
|
||||
.select(["action", "status"])
|
||||
.where("id", "=", exec.body.data.executed.recordId)
|
||||
.executeTakeFirstOrThrow();
|
||||
expect(rec).toEqual({ action: "relocate", status: "succeeded" });
|
||||
// W5-A2:搬运走 planImport → verifyAndImport,记录 action 与整理一致(move/copy)
|
||||
expect(rec).toEqual({ action: "move", status: "succeeded" });
|
||||
});
|
||||
|
||||
it("TOCTOU:预览后把源换成指向根外的符号链接,执行被拒绝且根外文件不动", async () => {
|
||||
|
||||
Reference in new issue
Block a user