mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-29 21:07:40 +01:00
Close the second destructive lifecycle race. The archive route calls archiveWorkspaceUnderLifecycleLock. That method rejected only missing or already-closed rows, then cleared the reopen flag and archived. A reopen sets the reopen-pending flag when it publishes a rebuilt worktree as active while the source issue is still terminal. In that window an authorized actor could invoke the archive control; the method archived the row and the destruction fence then removed the rebuilt worktree. Make archiveWorkspaceUnderLifecycleLock return a distinct "reopen_pending" outcome for a flagged row. It does not clear the flag and does not archive. Add the flag predicate to the update WHERE as defense in depth. Map the outcome to HTTP 409 in the route, before any lease teardown, runtime-service stop, or artifact cleanup. Add a service regression: a terminal-source, active, flagged row rejects the archive and keeps its status, generation, flag, and worktree. Add a route regression: the archive returns 409 and never runs the destruction fence. Co-authored-by: Paperclip <noreply@paperclip.ing>