Skip to content

feat(cli): 安全删除单个远端路径 / safely remove one remote path - #488

Open
Jinghao-coding wants to merge 5 commits into
raids-lab:mainfrom
Jinghao-coding:codex/issue-482-file-remove
Open

feat(cli): 安全删除单个远端路径 / safely remove one remote path#488
Jinghao-coding wants to merge 5 commits into
raids-lab:mainfrom
Jinghao-coding:codex/issue-482-file-remove

Conversation

@Jinghao-coding

Copy link
Copy Markdown
Member

中文

功能

  • 新增 crater file rm <remote-path>,支持 --recursive--yes/-y
  • 交互确认默认选择 No;--json--no-interactive 必须显式传入 --yes,取消时不会创建 API client 或发送请求。
  • CLI 在发请求前拒绝逻辑根、原始 . / .. 路径段、反斜杠、控制字符和管理员保留根。
  • 新增专用 DELETE /api/ss/files/*path?recursive=<bool>,不回退到旧的无条件递归删除接口。
  • 文件和最终 symlink 只删除条目本身;目录必须显式指定 recursive=true
  • Unix 递归删除使用目录 FD、O_NOFOLLOWfstatatunlinkat,检测类型替换和跨文件系统边界;不支持安全实现的平台直接失败。
  • 补齐中英文帮助/错误、补全、CLI 文档、Skill、API/命令/后端单测和双语快照。

安全边界

  • 一次只删除一个精确目标,不支持 glob、批量删除、Trash、恢复或管理员跨用户删除。
  • 删除目录需要两层显式授权:--recursive 和交互确认(或 --yes)。
  • 递归过程中若目录被替换、出现嵌套挂载点或文件系统不支持所需原语,会安全失败;递归删除发生错误时可能已删除部分子项,调用方应先重新检查再决定是否重试。

验证

  • go test -race ./internal/storage -count=1
  • go vet ./internal/storage ./cmd/storage-server
  • make lint(full + changed,均为 0 issues)
  • Linux amd64/arm64、FreeBSD、DragonFly、NetBSD、OpenBSD、Windows 交叉编译
  • go test -race ./cmd ./internal/api ./test/snapshots/file -count=1
  • go vet ./cmd ./internal/api
  • go build
  • 真实 CLI ↔ storage-server 联调:文件删除、目录递归门禁、递归删除、缺少 --yes、根目录拒绝、404、symlink 外部目标保护

CLI 全量 make pre-commit-check 的单元测试与 file 快照均通过;它随后只在尚未合入的 #477 job 分页 golden 上失败。该差异由 #477 修复,与本 PR 的 file 功能无关。

联调截图

Issue 482 live integration


English

What changed

  • Added crater file rm <remote-path> with --recursive and --yes/-y.
  • Interactive confirmation defaults to No. --json or --no-interactive requires an explicit --yes; cancellation creates no API client and sends no request.
  • The CLI rejects logical roots, raw . / .. segments, backslashes, control characters, and reserved admin roots before making a request.
  • Added the dedicated DELETE /api/ss/files/*path?recursive=<bool> endpoint, with no fallback to the legacy unconditional recursive-delete route.
  • Regular files and final symlinks are unlinked as entries; directories require explicit recursive=true.
  • Unix recursive removal uses directory FDs, O_NOFOLLOW, fstatat, and unlinkat, detecting type replacement and filesystem boundaries. Platforms without a safe implementation fail closed.
  • Added bilingual help/errors, completion, CLI docs, Skill guidance, API/command/backend tests, and bilingual snapshots.

Safety boundary

  • Exactly one target is accepted; globs, bulk removal, Trash/recovery, and admin cross-user removal remain out of scope.
  • Directory removal requires two explicit safeguards: --recursive and interactive confirmation (or --yes).
  • Directory substitution, nested mounts, and unsupported filesystem primitives fail closed. A recursive failure may be partial, so callers should inspect the remaining path before retrying.

Validation

  • go test -race ./internal/storage -count=1
  • go vet ./internal/storage ./cmd/storage-server
  • make lint (full + changed, both 0 issues)
  • Cross-compilation for Linux amd64/arm64, FreeBSD, DragonFly, NetBSD, OpenBSD, and Windows
  • go test -race ./cmd ./internal/api ./test/snapshots/file -count=1
  • go vet ./cmd ./internal/api
  • go build
  • Live CLI ↔ storage-server integration for file removal, recursive-directory gating/removal, missing --yes, root rejection, 404 handling, and external-target protection through symlinks

The unit-test and file-snapshot phases of the full CLI make pre-commit-check pass. The command then fails only on the job pagination golden owned by the not-yet-merged #477; that baseline difference is unrelated to this file feature.

Live validation screenshot

Issue 482 live integration

Depends on #487.

Closes #482.

Copilot AI review requested due to automatic review settings July 25, 2026 20:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Jinghao-coding
Jinghao-coding force-pushed the codex/issue-482-file-remove branch from 8be88d6 to 7e3c999 Compare July 28, 2026 14:48
@Jinghao-coding
Jinghao-coding force-pushed the codex/issue-482-file-remove branch from 7e3c999 to 20b3f8a Compare July 30, 2026 07:29
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.

feat(cli): 安全删除单个远端路径 / safely remove one remote path

2 participants