Skip to content

security: fail cache-trash permanent deletion closed - #263

Draft
seonghobae wants to merge 125 commits into
mainfrom
feat/physical-cache-reclaim-v1
Draft

security: fail cache-trash permanent deletion closed#263
seonghobae wants to merge 125 commits into
mainfrom
feat/physical-cache-reclaim-v1

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Scope

This PR is the converged canonical repair for the cache-Trash permanent-delete defect tracked by #170.

Protected main at this verification point: 79067c1160ddedf7fc962cbf8067ce7e83c4564a.
Exact head: 6deb5ea0a207be9d44490c775104b228d84bd383.

The branch is deliberately reduced to exactly four cache-safety files on current main:

  • src-tauri/src/bin/disksage-cache-cleanup.rs
  • src-tauri/src/cache_cleanup.rs
  • src-tauri/tests/cache_cleanup_cli_purge_fail_closed.rs
  • src-tauri/tests/cache_cleanup_coverage_runtime_contract.rs

Release-verifier files that had been concurrently reabsorbed into this branch were removed/restored to protected-main state; the release artifact verifier remains owned solely by #264.

Security behavior

  • --purge-proven-cache-trash remains available only as read-only review evidence.
  • --execute --purge-proven-cache-trash fails closed with cache-trash-identity-bound-permanent-delete-unavailable before journal or filesystem mutation.
  • The library-side purge boundary also refuses irreversible removal rather than calling pathname-recursive remove_dir_all.
  • list_cache_targets and clean_cache_contents remain present in instrumented builds instead of disappearing behind cfg(coverage).
  • Browser profile roots are not accepted as proven cache-Trash candidates.

Ownership / stale convergence

The previous branch had accumulated unrelated cloud, Git-worktree, iCloud, duplicate-management, customer-copy, Podman, release-verifier, and canonical-documentation changes. Those deltas are not overlaid here because they are owned by their dedicated current branches or protected main.

The broader physical-reclaim UI remains deferred while irreversible deletion is unavailable. This PR preserves the highest-value safety invariant instead of exposing an affordance that cannot safely mutate.

Current verification state

The exact-head workflows regenerated after the ownership-boundary repair and are non-passing until terminal:

  • Test 32956404087 — queued;
  • Release 32956403743 — queued;
  • Security Scan 32956403711 — queued;
  • SAST Semgrep 32956403704 — pending.

The PR therefore remains Draft. Predecessor checks/reviews do not transfer to this head.

Required before review/merge progression

  • exact-head Test, Release, Security Scan, SAST, and every applicable central required workflow must be terminal-success;
  • focused shipped-CLI regressions must prove the reviewed cache object and journal remain unchanged on refusal;
  • repository-wide exact non-vacuous coverage remains a separate ci: require exact-head production coverage evidence #156 requirement;
  • live inherited ruleset review/conversation requirements remain authoritative;
  • no release-verifier or canonical-documentation delta may re-enter this owner branch.

Do not merge using predecessor, queued, pending, stale, synthetic, no-source, model-only, or status-only evidence.

@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cecc394b-3c69-40d6-b141-cb0250991f98

📥 Commits

Reviewing files that changed from the base of the PR and between c036d7c and 09e1fd7.

📒 Files selected for processing (16)
  • CHANGELOG.md
  • docs/architecture/adr/0002-cache-cleanup-is-per-item-evidence-bound.md
  • docs/product-technical-gap-baseline.md
  • src-tauri/src/bin/disksage-cache-cleanup.rs
  • src-tauri/src/cache_cleanup.rs
  • src/lib/Cleanup.svelte
  • src/lib/CloudArchive.svelte
  • src/lib/GitWorktreeCleanup.svelte
  • src/lib/IcloudLocalEviction.svelte
  • src/lib/OrphanCleanup.svelte
  • src/lib/cacheCleanupFlowContract.test.ts
  • src/lib/cacheTrashPurgeSummary.test.ts
  • src/lib/cacheTrashPurgeSummary.ts
  • src/lib/cleanupCustomerCopyContract.test.ts
  • src/lib/cloudArchiveErrorFeedback.ts
  • src/lib/cloudArchiveErrorPrivacy.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/lib/OrphanCleanup.svelte
  • docs/product-technical-gap-baseline.md
  • src/lib/CloudArchive.svelte
  • src/lib/GitWorktreeCleanup.svelte

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

macOS Trash의 재생성 가능한 캐시만 검토 후보로 노출합니다. 검토 스냅샷을 파일시스템 객체 identity에 결합합니다. 객체 바인딩 영구 삭제 primitive가 없으면 purge를 fail closed하고 후보를 보존합니다. 관련 Tauri API, CLI, UI, 테스트 및 문서를 갱신합니다.

Changes

캐시 Trash 검토 및 reclaim

Layer / File(s) Summary
객체 identity 기반 검토와 fail-closed purge
src-tauri/src/cache_trash_reclaim.rs, src-tauri/tests/*cache_trash*
native macOS Trash의 전용 캐시 후보를 탐색합니다. root identity와 승인 문구를 검증합니다. 영구 삭제 primitive가 없으면 오류를 반환하고 후보를 보존합니다.
기존 정리 경로와 CLI 전환
src-tauri/src/cache_cleanup.rs, src-tauri/src/lib.rs, src-tauri/src/bin/disksage-cache-cleanup.rs, src-tauri/tests/cache_cleanup_*
기존 영구 삭제 경로를 제거합니다. Tauri 명령과 CLI는 검토 결과를 출력하고 직접 purge 요청은 fail closed합니다.
검토 API와 캐시 정리 UI 연결
src/lib/cacheTrash*, src/lib/cacheTrashPurge*, src/lib/Cleanup.svelte
검토 API, 삭제 가능성 판정, 결과 요약 및 캐시 정리 상태를 연결합니다. 영구 삭제가 불가능하면 수동 Trash 처리를 안내합니다.
고객용 정리 화면과 정책 문서
src/lib/*.svelte, src/lib/*.test.ts, README.md, CHANGELOG.md, docs/architecture/..., docs/product-technical-gap-baseline.md
내부 진단 정보와 원문 오류 표시를 제거합니다. 클라우드, Homebrew, Git, iCloud, 파일 정리 및 미사용 캐시 문구를 갱신합니다. 읽기 전용 검토와 fail-closed 정책을 문서화합니다.

Estimated code review effort: 4 (Complex) | ~60 minutes

Merge Risk: 🟠 High · up to 09e1f

The cleanup flow can permanently remove items from Trash, but the current implementation may classify an entire browser Default profile—including possible user data—as disposable cache. That creates a concrete risk of irreversible data loss and should be fixed or explicitly accepted before merge; the purge loop may also cause noticeable IPC delays.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 60 functions across 33 files. (8 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 캐시 휴지통의 영구 삭제를 fail closed로 변경한 PR의 핵심 내용을 정확히 설명합니다.
Full details: Docstring Coverage

Explanation

Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 60 functions across 33 files. (8 skipped: 8 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/physical-cache-reclaim-v1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae
seonghobae enabled auto-merge (squash) August 26, 2026 02:45
@seonghobae
seonghobae force-pushed the feat/physical-cache-reclaim-v1 branch from 7bd7540 to 50a897e Compare August 26, 2026 02:45
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@opencode-agent
opencode-agent Bot disabled auto-merge August 26, 2026 03:08
@seonghobae
seonghobae marked this pull request as draft August 26, 2026 03:11
@seonghobae
seonghobae marked this pull request as ready for review August 26, 2026 03:16
@seonghobae
seonghobae enabled auto-merge (squash) August 26, 2026 03:16
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae
seonghobae marked this pull request as draft August 26, 2026 04:07
auto-merge was automatically disabled August 26, 2026 04:07

Pull request was converted to draft

@seonghobae
seonghobae marked this pull request as draft August 26, 2026 08:03
auto-merge was automatically disabled August 26, 2026 08:03

Pull request was converted to draft

devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae seonghobae changed the title feat: expose physical cache reclaim security: fail cache-trash permanent deletion closed Aug 26, 2026
@seonghobae
seonghobae marked this pull request as ready for review August 26, 2026 09:18
@seonghobae
seonghobae enabled auto-merge (squash) August 26, 2026 09:18
devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae
seonghobae marked this pull request as draft August 26, 2026 09:25
auto-merge was automatically disabled August 26, 2026 09:25

Pull request was converted to draft

@seonghobae
seonghobae marked this pull request as ready for review August 26, 2026 09:37
@seonghobae
seonghobae enabled auto-merge (squash) August 26, 2026 09:37
devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae
seonghobae marked this pull request as draft August 26, 2026 10:06
auto-merge was automatically disabled August 26, 2026 10:06

Pull request was converted to draft

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

Open in Devin Review

Comment on lines 386 to 391
}

/// Move only the reviewed cache children to the OS Trash, retaining the cache root itself.
#[cfg(not(coverage))]
#[tauri::command]
pub fn clean_cache_contents(
dir: String,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Cache handlers compiled but unregistered under coverage

list_cache_targets and clean_cache_contents lost their #[cfg(not(coverage))] guards, but the generate_handler! block that registers them (run) stays gated on #[cfg(not(coverage))]. Under a coverage build the two #[tauri::command] functions now compile without being registered. Confirm the macro-generated wrappers still compile cleanly in that configuration.

(Refers to this code)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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