feat(projects): worktree remove + prune from any device (W4)
Closes the create-only loop — delete losing worktrees and prune stale ones without a terminal. Destructive, so guarded hard: - src/http/worktrees.ts: removeWorktree + pruneWorktrees (execFile, no shell, never rm -rf; git worktree remove [--force] / git worktree prune). Safeguards: (1) target realpath must match an entry git itself reports in `git worktree list` for THIS repo → 404 otherwise (arbitrary FS paths never match, so git is never invoked against them); (2) reject the MAIN worktree → 400; (3) realpath containment on request + each list entry, operating on git's canonical path (+ --); (4) dirty tree without force → 409 "force required"; (5) locked → 409; (6) errors classified to fixed safe strings (raw stderr/paths never leaked). - DELETE /projects/worktree + POST /projects/worktree/prune — both behind requireAllowedOrigin + worktreeEnabled + audit-logged, mirroring the create route. - public/projects.ts: ✕ remove button per linked-worktree row (hidden for main/locked) + a prune button; force needs an explicit second confirm (no single-click data loss). Verified: typecheck + build:web clean, worktree tests 108 pass (unit covers reject-non-registered / reject-main / reject-escape / refuse-dirty-without-force / clean-remove / force-remove / prune), full suite green at --test-timeout=30000.
This commit is contained in:
20
src/types.ts
20
src/types.ts
@@ -594,6 +594,26 @@ export interface CreateWorktreeResult {
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/** Result of DELETE /projects/worktree (W4 remove). `error` is a SAFE message
|
||||
* only (never raw git stderr, SEC-M10); `status` is the HTTP status to return.
|
||||
* `path` echoes git's own canonical worktree path that was removed. */
|
||||
export interface RemoveWorktreeResult {
|
||||
ok: boolean;
|
||||
path?: string;
|
||||
status?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/** Result of POST /projects/worktree/prune (W4). `pruned` lists best-effort
|
||||
* human labels of the stale worktrees git reclaimed (empty = nothing to prune,
|
||||
* idempotent). `error` is a SAFE message only (SEC-M10). */
|
||||
export interface PruneWorktreesResult {
|
||||
ok: boolean;
|
||||
pruned?: string[];
|
||||
status?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/* ── v0.6 Projects UI preferences (server-persisted, cross-device) ── */
|
||||
|
||||
/** Cross-device UI preferences for the Projects launcher (impl: src/http/prefs-store.ts).
|
||||
|
||||
Reference in New Issue
Block a user