@fnnas-labs/fnos-cli 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +169 -2
  3. package/THIRD_PARTY_NOTICES.txt +38904 -0
  4. package/cordis.patch.yml +3 -0
  5. package/npm/README.dsh.md +49 -0
  6. package/npm/acceptance-report.cjs +53 -0
  7. package/npm/dsh-integration.mjs +159 -0
  8. package/npm/dsh-test-support.mjs +55 -0
  9. package/npm/dsh.mjs +31 -0
  10. package/npm/install.cjs +130 -0
  11. package/npm/package-lib.cjs +274 -0
  12. package/npm/run.cjs +39 -0
  13. package/package.json +46 -4
  14. package/skill/LICENSE +21 -0
  15. package/skill/SKILL.md +143 -0
  16. package/skill/THIRD_PARTY_NOTICES.txt +38904 -0
  17. package/skill/bin/trim-cli-darwin-arm64 +0 -0
  18. package/skill/bin/trim-cli-darwin-x64 +0 -0
  19. package/skill/bin/trim-cli-linux-arm64 +0 -0
  20. package/skill/bin/trim-cli-linux-x64 +0 -0
  21. package/skill/bin/trim-cli-windows-arm64.exe +0 -0
  22. package/skill/bin/trim-cli-windows-x64.exe +0 -0
  23. package/skill/build-provenance.json +44 -0
  24. package/skill/entries/trim-app.md +63 -0
  25. package/skill/entries/trim-baidu-netdisk.md +42 -0
  26. package/skill/entries/trim-docker.md +35 -0
  27. package/skill/entries/trim-download.md +38 -0
  28. package/skill/entries/trim-file.md +30 -0
  29. package/skill/entries/trim-log.md +32 -0
  30. package/skill/entries/trim-monitor.md +41 -0
  31. package/skill/entries/trim-network.md +22 -0
  32. package/skill/entries/trim-photos.md +32 -0
  33. package/skill/entries/trim-shared.md +54 -0
  34. package/skill/entries/trim-storage.md +34 -0
  35. package/skill/entries/trim-system.md +59 -0
  36. package/skill/entries/trim-user.md +28 -0
  37. package/skill/manifest.json +43 -0
  38. package/skill/reference/_conventions.md +76 -0
  39. package/skill/reference/_index.md +78 -0
  40. package/skill/reference/app-center.md +234 -0
  41. package/skill/reference/baidu-netdisk.md +221 -0
  42. package/skill/reference/dockermgr.md +244 -0
  43. package/skill/reference/download.md +357 -0
  44. package/skill/reference/file.md +752 -0
  45. package/skill/reference/log.md +224 -0
  46. package/skill/reference/network.md +41 -0
  47. package/skill/reference/oauth.md +51 -0
  48. package/skill/reference/photos.md +158 -0
  49. package/skill/reference/power.md +34 -0
  50. package/skill/reference/resmon.md +160 -0
  51. package/skill/reference/stor.md +525 -0
  52. package/skill/reference/sysinfo.md +133 -0
  53. package/skill/reference/user.md +139 -0
  54. package/skill/reference/workflows/device-validation.md +66 -0
  55. package/skill/reference/workflows/file-routing.md +44 -0
  56. package/skill/reference/workflows/file-upload-validation.md +63 -0
  57. package/skill/reference/workflows/photos-routing.md +83 -0
  58. package/skill/reference/workflows/storage-dangerous-ops.md +53 -0
  59. package/skill/scripts/fnos-cli +63 -0
  60. package/skill/scripts/fnos-cli.cmd +36 -0
  61. package/skill/scripts/fnos-cli.ps1 +31 -0
  62. package/skill/scripts/trim-cli +63 -0
  63. package/skill/scripts/trim-cli.cmd +36 -0
  64. package/skill/scripts/trim-cli.ps1 +31 -0
@@ -0,0 +1,752 @@
1
+ # file 模块
2
+
3
+ ## 模块概述
4
+ 文件系统操作模块,涵盖文件列表、目录创建、删除、复制、移动、finder 搜索、共享目录/ACL 流程、传输任务、回收站、收藏夹、最近文件和团队文件操作。
5
+
6
+ ## 模块约定
7
+ - 路径约束:必须使用 canonical fnOS 路径格式 `/vol{v}/...`,聚合根行为需在端点说明中明确标注。
8
+ - 列表/搜索类端点可能使用流式响应(多包),需明确标注终态判定规则。
9
+ - `file.share.*` 共享目录端点属于本模块;`appcgi.sharesvr.share.link.*` 共享链接管理属于单独的 share 模块。
10
+
11
+ ## 任务路由
12
+
13
+ 先按用户意图选命令,再看后面的端点详情:
14
+
15
+ | 用户意图 | 优先命令 | 说明 |
16
+ | --- | --- | --- |
17
+ | 看当前可见目录 | `fnos-cli file ls` | 无参数和 `/` 都是省略 `path` 的模式 |
18
+ | 看某个具体目录 | `fnos-cli file ls /vol{v}/...` | 只接受 canonical 路径 |
19
+ | 搜当前用户目录下的文件 | `fnos-cli file search <key>` | CLI 会先探测再推导当前用户目录 |
20
+ | 在显式路径下搜索 | `fnos-cli file search <key> /vol{v}/...` | 每个路径都必须是 canonical 路径 |
21
+ | 搜别人共享给当前用户的文件 | `fnos-cli file search-others <key>` | 这是 finder 搜索,不是共享目录列表 |
22
+ | 列目录、统计路径、查看访问权限 | `file ls-dir/calc/access <path>` | `calc`、`access` 只接受具体 `/vol{v}/...` 路径,`ls-dir` 也可不传路径 |
23
+ | 统计卷空间分类 | `fnos-cli file usage <vol>` | `vol` 是存储空间 ID;CLI 汇总全部分段响应 |
24
+ | 检查目录内的额外挂载点 | `fnos-cli file is-mount-point <path>` | `hasMount=false` 表示该目录及子目录没有额外挂载点,不表示所在存储卷未挂载 |
25
+ | 看文件属性、大小或下载 URL | `file prop/size/download-url <path>` | 只接受具体 `/vol{v}/...` 路径 |
26
+ | 看共享目录元数据或列表 | `file share info/list/list-others/admin-list/admin-list-others` | 共享目录与 share link 不是同一语义 |
27
+ | 看 ACL | `fnos-cli file acl get <path>` | ACL 查询与共享目录状态不是同一概念 |
28
+ | 设置 ACL 或所有者 | `file acl set` / `file chown` | 权限写操作,需要 `--yes` |
29
+ | 转换或导出 TrimACL 报告 | `file trimacl conv/report` | 权限转换类写操作,需要 `--yes` |
30
+ | 做创建、重命名、删除、复制、移动 | `file mkdir/rename/rm/cp/mv` | 写操作默认要求具体 `/vol{v}/...` 路径,并需要 `--yes` |
31
+ | 压缩或解压文件 | `file compress/extract` | 写操作,需要 `--yes` |
32
+ | 管理当前用户回收站 | `file trash list/search/restore/clear` | 恢复和清空需要 `--yes` |
33
+ | 管理收藏夹 | `file fav list/add/del` | `add`、`del` 是写操作,必须显式传 `--yes` |
34
+ | 管理团队文件和团队回收站 | `file team list/trash-list-trashbin/trash-list/trash-restore/trash-clear` | `trash-list` 需要团队回收站具体 `path`;无路径时先用 `trash-list-trashbin`;恢复和清空需要 `--yes`,清空需要团队卷号和团队目录名 |
35
+ | 上传前检查目标路径 | `fnos-cli file check-upload /vol{v}/... <size> --yes` | 不上传内容,但设备可能创建临时占位 |
36
+ | 上传单个本地文件 | `fnos-cli file upload /vol{v}/... <localFile> --yes` | 远端参数是目录,CLI 会拼接本地文件名 |
37
+ | 下载一个或多个文件 | `/multiple-download` HTTP flow | 当前没有命名 CLI 命令;属于平台文件下载服务,不是 Download Center CGI |
38
+
39
+ 如果还没判断清楚该走 `ls`、`search`、`search-others` 还是 `share`,先看 `workflows/file-routing.md`。
40
+
41
+ ## 常见误判
42
+
43
+ - `file ls /` 不是把 `/` 直接传给后端,而是和无参数一样省略 `path`
44
+ - “当前用户目录”不是固定写死值,而是由设备返回和 session 信息共同决定
45
+ - `file share.*` 说的是共享目录,不是 share link
46
+ - `file search-others` 找的是“别人共享给我”的文件搜索结果,不是共享目录列表
47
+ - `file cp` / `file mv` 的目标参数是目标目录,不是最终文件路径
48
+
49
+ ## 高风险提醒
50
+
51
+ - 写操作不要使用聚合根、相对路径或模糊路径
52
+ - 用户只给了“共享链接”这类表述时,不要直接落到 `file share.*`
53
+ - 涉及多路径搜索时,每个路径都要先确认是 `/vol{v}/...`
54
+ - 如果需求依赖“当前用户目录”,优先让 CLI 自己探测,不要手工猜 payload
55
+
56
+ ## 端点索引
57
+ - 核心列表和元数据:
58
+ - `file.ls`
59
+ - `file.lsDir`
60
+ - `file.calc`
61
+ - `file.prop`
62
+ - `file.access`
63
+ - `file.usage`
64
+ - 变更和传输:
65
+ - `file.mkdir`
66
+ - `file.rename`
67
+ - `file.rm`
68
+ - `file.cp`
69
+ - `file.mv`
70
+ - `file.cancel`
71
+ - 所有权和 ACL:
72
+ - `file.chown`
73
+ - `file.getAcl`
74
+ - `file.setAcl2`
75
+ - `file.trimacl.conv`
76
+ - `file.trimacl.conv.report`
77
+ - `file.setAcl`(旧 ACL 接口未实现)
78
+ - 上传/下载/压缩:
79
+ - `file.checkUpload`
80
+ - `file upload` CLI `/upload` flow;上传传输跟随当前连接安全策略
81
+ - `/multiple-download` HTTP flow(当前未实现命名 CLI 命令)
82
+ - `file.download`
83
+ - `file.compress`
84
+ - `file.extract`
85
+ - `file.size`
86
+ - 搜索:
87
+ - `appcgi.finder.fileSearch`
88
+ - `appcgi.finder.searchOtherSharing`
89
+ - `appcgi.finder.trashSearch`
90
+ - `appcgi.finder.cancelSearch`
91
+ - 共享目录:
92
+ - `file.share.info`
93
+ - `file.share.list`
94
+ - `file.share.listOthers`
95
+ - `file.share.admin.list`
96
+ - `file.share.admin.listOthers`
97
+ - `file.share.add2`
98
+ - `file.share.del2`
99
+ - 收藏夹/最近文件:
100
+ - `file.fav.list`、`file.fav.add`、`file.fav.del`
101
+ - `file.recent.list`、`file.recent.add`、`file.recent.del`、`file.recent.clear`
102
+ - 应用文件和系统分区:
103
+ - `appcgi.filestor.getAppDirList`
104
+ - `appcgi.filestor.getSysPartInfo`
105
+ - `appcgi.filestor.isMountPoint`
106
+ - 回收站:
107
+ - `file.trash.list`、`file.trash.clear`、`file.trash.restore`
108
+ - 团队文件:
109
+ - `file.team.lsDir`
110
+ - `file.team.trash.listTrashbin`
111
+ - `file.team.trash.list`
112
+ - `file.team.trash.clear`
113
+ - `file.team.trash.restore`
114
+
115
+ ## 端点详情
116
+
117
+ ### file.ls
118
+
119
+ #### Endpoint
120
+ `file.ls`
121
+
122
+ #### Purpose
123
+ 列出后端默认视图或指定 canonical fnOS 路径下的文件。
124
+
125
+ #### Trim CLI Mapping
126
+ ```
127
+ fnos-cli file ls
128
+ fnos-cli file ls /
129
+ fnos-cli file ls /vol{v}/...
130
+ ```
131
+
132
+ 路径处理:
133
+ - 无参数或 `/` 都归一化为省略 `path` 的模式。
134
+ - 非根路径必须为 `/vol{v}/...` 格式,否则 CLI 在发送请求前拒绝。
135
+
136
+ #### Request
137
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
138
+ | --- | --- | --- | --- | --- | --- | --- |
139
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.ls` | `file.ls` |
140
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
141
+ | `path` | body | no | string | 具体目录路径 | 省略时走后端默认视图;指定时必须为 `/vol{v}/...` | `/vol3/1106/test3` |
142
+
143
+ #### Response
144
+ | Field | Always Present | Type | Meaning | Conditions / Notes | Example |
145
+ | --- | --- | --- | --- | --- | --- |
146
+ | `files` | no | array | 文件条目块 | 可出现在多个中间包中 | `[{"name":"Photos","dir":1}]` |
147
+ | `result` | no | string | Terminal marker | `succ`/`fail`;中间包可省略 | `succ` |
148
+ | `errno` | no | number | 错误码 | `errno: 0` 视为成功 | `65534` |
149
+ | `errmsg` | no | string | 错误描述 | 失败时出现 | `path not found` |
150
+
151
+ #### Protocol Notes
152
+ - `file.ls` 可能是多包响应:非终态包携带 `files`,终态包包含 `result`、`errno` 或 `errmsg`。
153
+ - 成功判定:`result: succ` 或 `errno: 0`;`result: fail` 或非零 `errno` 为失败。
154
+ - 使用签名请求(当 session secret 可用时),格式遵循 `_conventions.md`。
155
+
156
+ #### Field Semantics
157
+ - 无参数和 `/` 都会完全省略 `path`,不是设置为 `/`。
158
+ - 目标固件如何解释省略 `path` 由设备决定;当前已验证设备会返回当前用户目录,而不是单独的 volume 列表。
159
+ - `files[].dir` 是目录标记。
160
+ - CLI 目前不暴露分页控制,流式消费直到终态包。
161
+
162
+ #### Errors
163
+ - 非法路径格式在发送请求前被拒绝,提示使用 `/vol{v}/...`。
164
+ - 后端错误通过 `errmsg`/`errno` 传播。
165
+
166
+ ### file.lsDir
167
+
168
+ #### Purpose
169
+ 列出文件管理器目录入口或指定目录。该端点可能分多包返回 `files`。
170
+
171
+ #### Trim CLI Mapping
172
+ ```
173
+ fnos-cli file ls-dir
174
+ fnos-cli file ls-dir /vol{v}/...
175
+ ```
176
+
177
+ #### Protocol Notes
178
+ - CLI 持续接收响应直至终态包,并把所有中间包的 `files` 合并为一个 JSON 数组。
179
+ - 终态包通常只包含 `result`、`uver` 等元数据,不会作为目录条目输出。
180
+
181
+ ### file.usage
182
+
183
+ #### Purpose
184
+ 按分类查询指定存储空间的容量使用情况。
185
+
186
+ #### Trim CLI Mapping
187
+ ```
188
+ fnos-cli file usage <vol>
189
+ ```
190
+
191
+ #### Protocol Notes
192
+ - 接口会分多包推送;每个数据包用 `category` 区分 `user`、`team`、`app`、`docker` 等容量分类。
193
+ - CLI 输出一个 JSON 数组,不包含没有 `category` 的终态包。
194
+ - 同一分类可能重复推送,必须以最后一次为准,不能累加。用户和团队相关分类按 `category + id` 区分,其余分类按 `category` 区分。
195
+
196
+ ### file.fav.add / file.fav.del
197
+
198
+ ```bash
199
+ fnos-cli file fav add /vol{v}/... --yes
200
+ fnos-cli file fav del /vol{v}/... --yes
201
+ ```
202
+
203
+ 两者都会修改当前用户收藏夹,必须显式传 `--yes`。缺失时 CLI 会在读取 session 或访问网络前拒绝。
204
+
205
+ ### file.mkdir
206
+
207
+ #### Endpoint
208
+ `file.mkdir`
209
+
210
+ #### Purpose
211
+ 在指定 canonical fnOS 路径创建目录。
212
+
213
+ #### Trim CLI Mapping
214
+ ```
215
+ fnos-cli file mkdir /vol{v}/... --yes
216
+ ```
217
+
218
+ #### Request
219
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
220
+ | --- | --- | --- | --- | --- | --- | --- |
221
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.mkdir` | `file.mkdir` |
222
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
223
+ | `path` | body | yes | string | 目标目录路径 | 必须为 `/vol{v}/...` | `/vol2/1106/new-dir` |
224
+
225
+ #### Response
226
+ | Field | Always Present | Type | Meaning | Conditions / Notes | Example |
227
+ | --- | --- | --- | --- | --- | --- |
228
+ | `result` | no | string | Terminal marker | `succ`/`fail` | `succ` |
229
+ | `errno` | no | number | 错误码 | 失败时出现 | `17` |
230
+ | `errmsg` | no | string | 错误描述 | | `file exists` |
231
+
232
+ #### Field Semantics
233
+ - `path` 是完整目标路径,不是父目录加名称。
234
+ - 目前不支持可选的权限参数。
235
+
236
+ ### file.prop
237
+
238
+ #### Endpoint
239
+ `file.prop`
240
+
241
+ #### Purpose
242
+ 查看指定文件或目录的属性。
243
+
244
+ #### Trim CLI Mapping
245
+ ```
246
+ fnos-cli file prop /vol{v}/...
247
+ ```
248
+
249
+ #### Request
250
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
251
+ | --- | --- | --- | --- | --- | --- | --- |
252
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.prop` | `file.prop` |
253
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
254
+ | `files` | body | yes | string[] | 要查询的路径列表 | CLI 当前发送单个路径 | `["/vol2/1106/a.txt"]` |
255
+
256
+ ### file.size
257
+
258
+ #### Endpoint
259
+ `file.size`
260
+
261
+ #### Purpose
262
+ 查看单个文件或目录的大小。
263
+
264
+ #### Trim CLI Mapping
265
+ ```
266
+ fnos-cli file size /vol{v}/...
267
+ ```
268
+
269
+ #### Request
270
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
271
+ | --- | --- | --- | --- | --- | --- | --- |
272
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.size` | `file.size` |
273
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
274
+ | `file` | body | yes | string | 要计算的路径 | 单个 canonical 路径 | `/vol2/1106/a.txt` |
275
+
276
+ ### file.download
277
+
278
+ #### Endpoint
279
+ `file.download`
280
+
281
+ #### Purpose
282
+ 请求一个或多个文件的下载 URL。
283
+
284
+ #### Trim CLI Mapping
285
+ ```
286
+ fnos-cli file download-url /vol{v}/...
287
+ ```
288
+
289
+ #### Request
290
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
291
+ | --- | --- | --- | --- | --- | --- | --- |
292
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.download` | `file.download` |
293
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
294
+ | `files` | body | yes | string[] | 要下载的路径列表 | CLI 当前发送单个路径 | `["/vol2/1106/a.txt"]` |
295
+
296
+ ### file.rename
297
+
298
+ #### Endpoint
299
+ `file.rename`
300
+
301
+ #### Purpose
302
+ 重命名指定文件或目录。
303
+
304
+ #### Trim CLI Mapping
305
+ ```
306
+ fnos-cli file rename /vol{v}/... <newName> --yes
307
+ ```
308
+
309
+ #### Request
310
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
311
+ | --- | --- | --- | --- | --- | --- | --- |
312
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.rename` | `file.rename` |
313
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
314
+ | `path` | body | yes | string | 要重命名的路径 | 必须为 `/vol{v}/...` | `/vol2/1106/a.txt` |
315
+ | `newName` | body | yes | string | 新名称 | 只能是名称片段,不能包含 `/` | `b.txt` |
316
+
317
+ ### file.checkUpload
318
+
319
+ #### Endpoint
320
+ `file.checkUpload`
321
+
322
+ #### Purpose
323
+ 上传文件前检查完整目标文件路径是否可用,并返回同名冲突、断点续传或最终文件名等提示。
324
+
325
+ #### Trim CLI Mapping
326
+ ```
327
+ fnos-cli file check-upload /vol{v}/... <size> [--overwrite skip|replace|rename] --yes
328
+ ```
329
+
330
+ #### Request
331
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
332
+ | --- | --- | --- | --- | --- | --- | --- |
333
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.checkUpload` | `file.checkUpload` |
334
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
335
+ | `path` | body | yes | string | 完整目标文件路径 | 必须包含文件名,且为 `/vol{v}/...` | `/vol2/1106/new.jpg` |
336
+ | `size` | body | yes | number | 文件大小 | 字节数 | `12345` |
337
+ | `overwrite` | body | no | number | 同名冲突处理 | `0` skip, `1` replace, `2` rename | `2` |
338
+
339
+ #### Response
340
+ | Field | Always Present | Type | Meaning | Conditions / Notes | Example |
341
+ | --- | --- | --- | --- | --- | --- |
342
+ | `result` | no | string | Terminal marker | `succ`/`fail` | `succ` |
343
+ | `skip` | no | number | 跳过提示 | 部分版本返回 | `1` |
344
+ | `uploadName` | no | string | HTTP 上传/断点路径文件名 | POST `/upload` 的 `Trim-Path` 使用该名称;它不一定等于用户最终看到的文件名 | `new.iso.~#2` |
345
+ | `from` | no | number | 续传起点 | 部分版本返回 | `1048576` |
346
+ | `completed` | no | number | 已完成字节数 | 部分版本返回 | `1048576` |
347
+ | `errno` | no | number | 错误码 | 失败时出现 | `4386` |
348
+ | `errmsg` | no | string | 错误描述 | | `no space left` |
349
+
350
+ #### Field Semantics
351
+ - `path` 是完整目标文件路径,不是目标目录。
352
+ - `file check-upload` 不传输文件内容,但后端可能分配 `.~#n` 临时上传占位,因此仍属于写操作。
353
+ - `--overwrite` 支持 `skip`、`replace`、`rename`,也可传对应数值 `0`、`1`、`2`。
354
+
355
+ ### file upload CLI flow
356
+
357
+ #### Purpose
358
+ 上传单个本地文件到远端目录。
359
+
360
+ #### Trim CLI Mapping
361
+ ```
362
+ fnos-cli file upload /vol{v}/... <localFile> [--overwrite skip|replace|rename] --yes
363
+ ```
364
+
365
+ #### Flow
366
+ 1. 远端目录规范化为 `/vol{v}/...`。
367
+ 2. 使用本地文件名拼出完整远端目标路径。
368
+ 3. 调用 `file.checkUpload`。
369
+ 4. 如果返回 `skip` 或 `completed`,直接视为成功。
370
+ 5. 如果返回 `uploadName`,HTTP `Trim-Path` 使用父目录加该名称;用户可见结果仍是请求的目标路径。
371
+ 6. 使用 `POST /upload` 上传 multipart 字段 `trim-upload-file`;本机或显式允许的远端 WS 使用 HTTP,远端默认 HTTPS 使用 HTTPS。
372
+ 7. 20 MiB 及以上文件会缓存 `uploadName` 路径用于后续断点续传;缓存按 NAS endpoint、profile、登录用户、远端目标、文件大小、覆盖策略和本地文件 SHA-256 隔离,只有完整匹配时才会续传。同一 NAS endpoint 和远端目标的上传会跨进程串行执行。缓存续传遇到 `328496` 会重试,遇到 `4100` 会回退普通检查。
373
+
374
+ #### HTTP Headers
375
+ | Header | Required | Meaning |
376
+ | --- | --- | --- |
377
+ | `Trim-Path` | yes | URI-encoded HTTP upload path; may use backend `uploadName` |
378
+ | `Trim-From` | yes | 续传起点;无续传时为 `0` |
379
+ | `Trim-Overwrite` | yes | `0` skip, `1` replace, `2` rename |
380
+ | `Trim-Mtim` | yes | 本地文件 mtime,Unix 秒 |
381
+ | `Trim-Token` | yes | 当前 session token |
382
+
383
+ ### multiple-download HTTP flow
384
+
385
+ #### Endpoint
386
+
387
+ ```plaintext
388
+ POST /multiple-download
389
+ GET /multiple-download?token=<download-token>
390
+ ```
391
+
392
+ #### Purpose
393
+
394
+ 为一个或多个 fnOS 文件/目录创建临时下载链接;单文件可直接下载,多目标通常由平台打包后下载。
395
+
396
+ #### Request
397
+
398
+ | Field | Location | Required | Type | Meaning | Example |
399
+ | --- | --- | --- | --- | --- | --- |
400
+ | `accessToken` | POST body | yes | string | Current OAuth access token | `<access-token>` |
401
+ | `paths` | POST body | yes | string[] | 下载目标路径 | `["/vol1/1000/a.txt"]` |
402
+ | `downloadLimit` | POST body | no | number | 当前前端使用的下载/打包限制 | `2` |
403
+ | `noZipWhenSingleFile` | POST body | no | boolean | 单文件不打 zip | `true` |
404
+ | `zipFileName` | POST body | no | string | 下载或压缩包名称 | `a.txt等2个文件` |
405
+ | `token` | GET query | yes | string | POST 返回的临时下载 token | `<download-token>` |
406
+
407
+ #### Flow
408
+
409
+ 1. 携带 Bearer,并向 `/ogh/ac/h/multiple-download` POST `accessToken` 和 `paths`;成功响应读取临时 `token`。
410
+ 2. 携带 Bearer 打开 `GET /ogh/ac/h/multiple-download?token=<download-token>` 获取文件或压缩包字节流。
411
+ 3. 可使用 `Range` 请求分段下载,成功时返回 HTTP 206;只有临时 token 而没有 Bearer 时会返回 401。
412
+ 4. HTTP 403 时,响应 body 表示首个无权限路径。
413
+
414
+ #### CLI support
415
+
416
+ - 当前 Rust CLI 未实现对应命名命令,也不能通过 `download request` 调用,因为它不是 `appcgi.downloadcenter.*` CGI。
417
+ - GET 临时链接仍要求 Bearer,不可当作匿名、免鉴权分享链接。
418
+ - access token 和临时下载 token 都属于敏感凭据,不应记录或转发。
419
+
420
+ ### file.rm
421
+
422
+ #### Endpoint
423
+ `file.rm`
424
+
425
+ #### Purpose
426
+ 删除指定 canonical fnOS 路径的文件或目录。
427
+
428
+ #### Trim CLI Mapping
429
+ ```
430
+ fnos-cli file rm /vol{v}/... --yes
431
+ ```
432
+
433
+ #### Request
434
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
435
+ | --- | --- | --- | --- | --- | --- | --- |
436
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.rm` | `file.rm` |
437
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
438
+ | `files` | body | yes | string[] | 要删除的路径列表 | CLI 当前发送单个路径 | `["/vol2/1106/old-dir"]` |
439
+
440
+ #### Field Semantics
441
+ - 后端使用 `files: string[]`,不是单个 `path` 字段。
442
+ - CLI 当前只暴露单目标删除,但后端支持数组。
443
+
444
+ ### file.trash.list
445
+
446
+ #### Endpoint
447
+ `file.trash.list`
448
+
449
+ #### Purpose
450
+ 列出当前用户回收站文件。
451
+
452
+ #### Trim CLI Mapping
453
+ ```
454
+ fnos-cli file trash list
455
+ ```
456
+
457
+ #### Request
458
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
459
+ | --- | --- | --- | --- | --- | --- | --- |
460
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.trash.list` | `file.trash.list` |
461
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
462
+
463
+ ### file.trash.restore
464
+
465
+ #### Endpoint
466
+ `file.trash.restore`
467
+
468
+ #### Purpose
469
+ 从回收站恢复指定文件。
470
+
471
+ #### Trim CLI Mapping
472
+ ```
473
+ fnos-cli file trash restore /vol{v}/... --yes
474
+ ```
475
+
476
+ #### Request
477
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
478
+ | --- | --- | --- | --- | --- | --- | --- |
479
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.trash.restore` | `file.trash.restore` |
480
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
481
+ | `files` | body | yes | string[] | 要恢复的回收站路径 | CLI 当前发送单个路径 | `["/vol2/1106/a.txt"]` |
482
+ | `overwrite` | body | yes | number | 冲突处理策略 | `2` 表示自动改名保留两者 | `2` |
483
+
484
+ ### file.trash.clear
485
+
486
+ #### Endpoint
487
+ `file.trash.clear`
488
+
489
+ #### Purpose
490
+ 清空当前用户回收站。
491
+
492
+ #### Trim CLI Mapping
493
+ ```
494
+ fnos-cli file trash clear --yes
495
+ ```
496
+
497
+ #### Request
498
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
499
+ | --- | --- | --- | --- | --- | --- | --- |
500
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.trash.clear` | `file.trash.clear` |
501
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
502
+
503
+ ### file.cp
504
+
505
+ #### Endpoint
506
+ `file.cp`
507
+
508
+ #### Purpose
509
+ 将文件或目录复制到指定 canonical fnOS 目标目录。
510
+
511
+ #### Trim CLI Mapping
512
+ ```
513
+ fnos-cli file cp <src> <destDir> --yes
514
+ ```
515
+
516
+ `src` 和 `destDir` 必须都是 `/vol{v}/...` 格式。
517
+
518
+ #### Request
519
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
520
+ | --- | --- | --- | --- | --- | --- | --- |
521
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.cp` | `file.cp` |
522
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
523
+ | `files` | body | yes | string[] | 源路径列表 | CLI 当前发送单个源路径 | `["/vol3/1106/source"]` |
524
+ | `pathTo` | body | yes | string | 目标目录路径 | 必须为 `/vol{v}/...` | `/vol4/1106/backup` |
525
+ | `overwrite` | body | yes | number | 冲突策略 | CLI 默认 `2`(保留两者/重命名) | `2` |
526
+
527
+ #### Field Semantics
528
+ - 后端使用 `files + pathTo`,不是 `src + dest`。
529
+ - `overwrite: 2` 当前作为保留两者/重命名策略。
530
+ - CLI 当前只暴露单源复制,但后端支持数组。
531
+
532
+ ### file.mv
533
+
534
+ #### Endpoint
535
+ `file.mv`
536
+
537
+ #### Purpose
538
+ 将文件或目录移动到指定 canonical fnOS 目标目录。
539
+
540
+ #### Trim CLI Mapping
541
+ ```
542
+ fnos-cli file mv <src> <destDir> --yes
543
+ ```
544
+
545
+ `src` 和 `destDir` 必须都是 `/vol{v}/...` 格式。
546
+
547
+ #### Request
548
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
549
+ | --- | --- | --- | --- | --- | --- | --- |
550
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.mv` | `file.mv` |
551
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69ba...` |
552
+ | `files` | body | yes | string[] | 源路径列表 | CLI 当前发送单个源路径 | `["/vol4/1106/source"]` |
553
+ | `pathTo` | body | yes | string | 目标目录路径 | 必须为 `/vol{v}/...` | `/vol2/1106/archive` |
554
+ | `overwrite` | body | yes | number | 冲突策略 | CLI 默认 `2`(保留两者/重命名) | `2` |
555
+
556
+ #### Field Semantics
557
+ - 与 `file.cp` 相同的请求结构和冲突策略。
558
+
559
+ ### appcgi.finder.fileSearch
560
+
561
+ #### Endpoint
562
+ `appcgi.finder.fileSearch`
563
+
564
+ #### Purpose
565
+ 使用 finder 服务在一个或多个 canonical fnOS 路径下按关键字搜索文件。
566
+
567
+ #### Trim CLI Mapping
568
+ ```
569
+ fnos-cli file search <key> [paths...]
570
+ ```
571
+
572
+ 路径处理:
573
+ - 每个显式路径必须为 `/vol{v}/...` 格式,传给 finder 时去除前导斜杠。
574
+ - 未提供路径时,CLI 先做一次省略 `path` 的 `file.ls` 探测,再从返回条目的 `v` 字段推导当前用户的 `vol{v}/{uid}` 搜索根。
575
+ - 当 session 中包含 `uid` 时会在请求中包含。
576
+
577
+ #### Request
578
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
579
+ | --- | --- | --- | --- | --- | --- | --- |
580
+ | `req` | body | yes | string | Endpoint selector | Fixed value | `appcgi.finder.fileSearch` |
581
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69be...` |
582
+ | `key` | body | yes | string | 搜索关键字 | 不能为空 | `.txt` |
583
+ | `path` | body | yes | string[] | finder 搜索根 | 使用 `vol{v}/...` 格式(无前导斜杠) | `["vol2/1000"]` |
584
+ | `uid` | body | no | number | 当前用户 ID | 从 session 获取时包含 | `1000` |
585
+
586
+ #### Response
587
+ | Field | Always Present | Type | Meaning | Conditions / Notes | Example |
588
+ | --- | --- | --- | --- | --- | --- |
589
+ | `data` | no | array | 搜索结果块 | 流式包将结果放在顶层 `data` 中 | `[{"path":"/vol2/1000/a.txt"}]` |
590
+ | `result` | no | string | finder 状态 | `doing` 处理中;`succ` 完成;`fail` 失败 | `doing` |
591
+ | `errno` | no | number | 错误码 | 可终止请求 | `100000002` |
592
+ | `errmsg` | no | string | 错误描述 | | `param invalid` |
593
+
594
+ #### Protocol Notes
595
+ - Finder 搜索是多包响应。中间包可同时携带 `data` 和 `result: doing`。
596
+ - `result: doing` 不是终态。CLI 等待后续包中的非 `doing` 状态。
597
+
598
+ ### appcgi.finder.searchOtherSharing
599
+
600
+ #### Endpoint
601
+ `appcgi.finder.searchOtherSharing`
602
+
603
+ #### Purpose
604
+ 搜索其他用户共享给当前用户的文件。
605
+
606
+ #### Trim CLI Mapping
607
+ ```
608
+ fnos-cli file search-others <key>
609
+ ```
610
+
611
+ #### Request
612
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
613
+ | --- | --- | --- | --- | --- | --- | --- |
614
+ | `req` | body | yes | string | Endpoint selector | Fixed value | `appcgi.finder.searchOtherSharing` |
615
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69be...` |
616
+ | `key` | body | yes | string | 搜索关键字 | | `.txt` |
617
+
618
+ #### Protocol Notes
619
+ - 与 `fileSearch` 相同的 finder 终态语义。
620
+ - 中间包 `result: doing` 为非终态。
621
+ - 流式结果字段为 `files`。
622
+
623
+ ### file.getAcl
624
+
625
+ #### Endpoint
626
+ `file.getAcl`
627
+
628
+ #### Purpose
629
+ 返回指定 canonical fnOS 路径的 ACL 信息,可选包含文件属性数据。
630
+
631
+ #### Trim CLI Mapping
632
+ ```
633
+ fnos-cli file acl get <path>
634
+ fnos-cli file acl get <path> --prop
635
+ ```
636
+
637
+ #### Request
638
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
639
+ | --- | --- | --- | --- | --- | --- | --- |
640
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.getAcl` | `file.getAcl` |
641
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69be...` |
642
+ | `path` | body | yes | string | 目标路径 | 必须为 `/vol{v}/...` | `/vol1/1000/docs` |
643
+ | `getProp` | body | no | boolean | 是否包含属性数据 | `--prop` 时发送 `true` | `true` |
644
+
645
+ #### Field Semantics
646
+ - `permset` 是最有用的原始 ACL/共享权限数据,CLI 原样保留。
647
+ - `getProp` 为透传标志。
648
+
649
+ ### file.share.info
650
+
651
+ #### Endpoint
652
+ `file.share.info`
653
+
654
+ #### Purpose
655
+ 返回指定 canonical fnOS 路径的共享目录元数据。
656
+
657
+ #### Trim CLI Mapping
658
+ ```
659
+ fnos-cli file share info <path>
660
+ ```
661
+
662
+ ### file.share.list / file.share.admin.list
663
+
664
+ #### Endpoint
665
+ `file.share.list` 和 `file.share.admin.list`
666
+
667
+ #### Purpose
668
+ 列出共享目录。`list` 使用当前用户视角;`admin-list` 使用管理员视角。
669
+
670
+ #### Trim CLI Mapping
671
+ ```
672
+ fnos-cli file share list [uid]
673
+ fnos-cli file share admin-list [uid]
674
+ ```
675
+
676
+ #### Request
677
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
678
+ | --- | --- | --- | --- | --- | --- | --- |
679
+ | `req` | body | yes | string | Endpoint selector | `file.share.list` 或 `file.share.admin.list` | `file.share.list` |
680
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69be...` |
681
+ | `uid` | body | no | number | 源用户/owner ID 过滤 | 必须为正整数 | `1001` |
682
+
683
+ #### Protocol Notes
684
+ - 两个端点都是多包列表流。中间包贡献 `share[]`。
685
+
686
+ ### file.share.listOthers / file.share.admin.listOthers
687
+
688
+ #### Endpoint
689
+ `file.share.listOthers` 和 `file.share.admin.listOthers`
690
+
691
+ #### Purpose
692
+ 列出哪些用户拥有可见的共享目录。
693
+
694
+ #### Trim CLI Mapping
695
+ ```
696
+ fnos-cli file share list-others
697
+ fnos-cli file share admin-list-others
698
+ ```
699
+
700
+ ### file.share.add2
701
+
702
+ #### Endpoint
703
+ `file.share.add2`
704
+
705
+ #### Purpose
706
+ 将指定路径创建为共享目录,使用显式的 `permset` 权限。
707
+
708
+ #### Trim CLI Mapping
709
+ ```
710
+ fnos-cli file share add <path> <shareName> --permset <json> [--sub] [--acl-mode <mode>] --yes
711
+ ```
712
+
713
+ #### Request
714
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
715
+ | --- | --- | --- | --- | --- | --- | --- |
716
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.share.add2` | `file.share.add2` |
717
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69be...` |
718
+ | `path` | body | yes | string | 目标路径 | 必须为 `/vol{v}/...` | `/vol1/1000/docs` |
719
+ | `shareName` | body | yes | string | 共享目录显示名 | | `docs` |
720
+ | `permset` | body | yes | array | ACL/共享权限 | 必须为 JSON 对象数组 | `[{"owner":32719,"inherit":7}]` |
721
+ | `sub` | body | no | boolean | 是否应用到子项 | `--sub` 时发送 | `true` |
722
+ | `aclMode` | body | no | number | 显式 ACL 模式 | `--acl-mode` 时发送 | `1` |
723
+
724
+ #### Field Semantics
725
+ - `permset` 原样转发,可直接复用 `file acl get` 返回的原始数据。
726
+
727
+ ### file.share.del2
728
+
729
+ #### Endpoint
730
+ `file.share.del2`
731
+
732
+ #### Purpose
733
+ 移除指定路径的共享目录状态。
734
+
735
+ #### Trim CLI Mapping
736
+ ```
737
+ fnos-cli file share del <path> [--sub] [--acl-mode <mode>] --yes
738
+ ```
739
+
740
+ #### Request
741
+ | Field | Location | Required | Type | Meaning | Constraints / Notes | Example |
742
+ | --- | --- | --- | --- | --- | --- | --- |
743
+ | `req` | body | yes | string | Endpoint selector | Fixed value `file.share.del2` | `file.share.del2` |
744
+ | `reqid` | body | yes | string | Request correlation ID | Generated per request | `69be...` |
745
+ | `path` | body | yes | string | 目标路径 | 必须为 `/vol{v}/...` | `/vol1/1000/docs` |
746
+ | `sub` | body | no | boolean | 是否应用到子项 | `--sub` 时发送 | `true` |
747
+ | `aclMode` | body | no | number | 显式 ACL 模式 | `--acl-mode` 时发送 | `1` |
748
+
749
+ ## 注意事项
750
+ - 长时间运行的文件操作(如大文件复制/移动)的包终态行为可能因固件版本而异。
751
+ - ACL 和跨卷传输的完整错误码分类尚未完全确认。
752
+ - `overwrite: 2` 的具体冲突处理行为(保留两者/重命名)取决于后端实现。