Skip to content

Decisions, risks and open questions

Part of the temporary reversible deletion plan. The decisions feed the deletion ADR (slice S0).

1. Decisions

Decided by Chris (5 October 2026)

# Decision Effect on the plan
D1 A 30-day restore window, configurable, fixed per item when it is deleted. It is the user-facing window, for searches and projects Restore window §2
D2 No actual permanent deletion. Nothing is ever physically erased: no purge job, no "Delete permanently now", no study, search, project or stored-file deletion. After the 30 days an item leaves the users' Recently deleted view and users can no longer restore it; the data stays in the database, detached and marked, indefinitely. T-POL-01 stays "not approved" for everything Purge and file clean-up dropped (former slices S8a, S8b, S12); restore window; integrated plan rules ACD-R18, ACD-AE17 and AC-R2a-57 kept intact
D3 Permissions. Search delete and restore (within the window): RemoveSearch holders. Project delete: the owner only. Project restore (within the window): the owner and application administrators. After the window: application administrators only. No one can erase Behaviour
D6 A Bulk PDF upload in progress is cancelled, then the deletion proceeds (the 12 August draft's approach) In-flight work §2
D12 Running search imports and bulk study updates are cancelled, then the deletion proceeds (replaces the earlier "wait" recommendation). New cancel paths are needed for both In-flight work §3 and §4; slices S3c and S3d
Q7 Keep the existing import clean-up. A failed or cancelled search import still deletes the Studies it wrote before it was ever shown. Reason: that is clean-up of a failed upload, not user data, so it does not conflict with "no actual permanent deletion" In-flight work §3.1; the no-erasure architecture test allow-lists it
Q8 The proposed performance bound is the initial target: a 100,000-Study search moves in under 10 minutes, with save p95 within 20% of idle during the sweep DL-R1S-13

Decided by Chris (14 October 2026)

# Decision Effect on the plan
Q3 Project restore: the owner within the restore window, plus application administrators, identified by the existing application-administrator capability. The authority programme does not need to name a new one The S2a recovery policy and the S8 administrator routes use the existing check; ADR-024 §8
D13 The explicit FEAT-024 administrator maintenance and backfill routes refuse a deleted project. Its kept statistics stay frozen exactly as they were until it is restored Implemented as slice S2c, reusing the S2a refusal shape; ADR-024 §7
S3d-A A version 1 bulk update stuck in Parsing (option A): the deletion waits at most 30 minutes since the job last changed, then treats it as abandoned and proceeds Implemented in S3d (BulkStudyUpdateDeletionParticipant.Version1StaleAfter): the participant logs a warning and appends one BulkStudyUpdateAbandonedForDeletion ledger record naming the job; nothing is erased; ADR-024 §6

Recommendations that stand (Chris informed; no objection)

# Decision Recommendation
D4 Does a restored search keep its screening and annotation? Yes, exactly. Reservations are not revived; derived screening fields are recalculated against the current settings; answers to questions deleted meanwhile are removed
D5 Members' access while a project is deleted Hidden from all members; memberships kept and returned unchanged on restore; the owner sees it in Recently deleted during the window
D7 The production cut-over Move production from the bulk-update baseline to main only after the MVP is accepted on staging, with deletionLifecycle on in the same promotion (rollout §5)
D8 The data model "Detach and mark" for searches; a project-level state for projects (data model)
D9 The uncommitted August work in .worktrees/bulk-pdf-deletion-lifecycle Preserve it as-is (for example committed to a local archive branch, never pushed unless Chris asks), cite it in ADR-024 as superseded, do not merge its code. This plan does not touch that worktree
D10 Stored files Kept. Under D2 nothing deletes them; the user guide must say so
D11 Is a reason required? Optional in the MVP, shown in Recently deleted; required when the canonical impact preview arrives (R2c)

New recommendations (not yet decided)

# Question Recommendation Alternatives
R-A Work in the project that does not belong to the item being deleted (another search's import, a bulk update that touches none of the deleted search's Studies) Wait for it, without refusing; cancel only the item's own work. Cancelling unrelated work would discard a colleague's upload or edit for no gain (in-flight work §5) Cancel all running imports and bulk updates in the project for any deletion
R-B How do application administrators restore after the window? Two administrator API routes in the MVP, no admin screen. It is meaningfully smaller (no web slice, no M3 design, no user-guide page); after-window restores should be rare; a screen can read the same routes later (restore window §3) A minimal restricted "Deleted items" screen now
R-C Should application administrators also restore projects within the window through the UI? No: the administrator routes cover it; the UI list is for owners An "All projects" filter for administrators on Recently deleted projects
R-D Version 1 bulk updates cannot be rolled back, so a deletion must wait while one applies Enable bulkStudyUpdateAtomicApply (version 2) in production before or with the cut-over, under ADR-020's own approval, so every bulk update can be cancelled (rollout §5) Keep version 1 and accept waits of up to 30 minutes since the job last changed (Version1StaleAfter), after which the job is treated as abandoned and a ledger record is written (decision S3d-A)
R-E Cancelling a version 1 bulk update during a search deletion Wait instead: its scope is unknown until it applies, so a cancel might discard changes to other searches Cancel version 1 updates before they apply for search deletions too

Explicit non-goal

Permanent erasure of any deleted data, by policy, schedule or request, is out of scope. It needs its own decision (T-POL-01), a legal and retention review and its own ADR (restore window §6).

2. Risks

# Risk Likelihood Impact Mitigation
K1 A read that ignores ProjectId still shows a moved Study (an id load without a project check, a global scan) Medium Medium: a deleted Study visible or editable through one path S1's id-load audit and architecture test; the leak catalogue test; the write guard refuses edits regardless
K2 Fold interplay: pending entries stranded under a holding id, or returned into the overlay Medium High: a wrong served count The pending-free move rule; the zero-pending check; FEAT-024 owner review; soak drills
K3 Restore after the project's settings changed leaves stored derived fields drifted, so rebuilds refuse High without the fix Medium: families stay on live fallback Re-persist and deleted-question clean-up inside the restore's fence; drift check in acceptance
K4 Serving a deleted project's kept statistics on restore misses a change made while it was deleted Low High: a wrong served count The write paths keep rows exact or stale them (statistics §6); scheduled maintenance made to skip deleted projects; restore-without-rebuild parity in tests and the projectDeleteRestore drill; fallback option: stale every family on restore
K5 Cancelling an upload races the agent's claim, or clean-up of a cancelled upload depends on the search link Medium Medium: a stuck deletion or orphaned storage The cancel's own race handling (ClaimedForProcessing joins the wait); S3b tests for clean-up after unlink and after project deletion; Bulk PDF owner review
K5a A cancelled import keeps writing after its clean-up (a batch saved after the cancel), leaving unrevealed Studies Medium without the checks Medium: orphaned Studies The parse's start and per-batch status checks; the runner replays the idempotent clean-up after the parse has ended and checks that no unrevealed Study is left before detaching
K5b A cancelled job re-raises its fence after the deletion's release Medium without guards (#4062 makes re-admission real) High: the project stays fenced with no owner; imports and bulk updates refused Fence ordering; #4062's admission guards (a prerequisite of S3c and S3d); the parse's own status check; late-admission tests
K5c A version 2 rollback ends RollbackQuarantined Low Medium: the deletion is blocked until an engineer resolves it ADR-020's existing procedure; the deletion shows BulkStudyUpdateQuarantined and alerts
K5d A version 1 update applying when a deletion arrives cannot be cancelled Medium while version 1 is in use Low: the deletion waits at most 30 minutes since the job last changed, then treats it as abandoned (logged and in the ledger) R-D; decision S3d-A
K5e Cancelling someone else's running work surprises them Medium Low to medium: an import or bulk update has to be redone Only the item's own work is cancelled (R-A); the dialog lists what will be cancelled; the job's owner sees the reason
K6 A waited job never ends (a stuck import, upload processing with no hard time limit) Low Medium: a deletion pending for a long time; the item stays usable meanwhile BlockedReason and the alert after WaitAlertHours; runbook
K7 An image rollback while items are deleted Low Medium: deleted projects reappear, and the baseline's deletion erases again Restore-all before rolling back; ExtraElements keeps the fields; runbook
K8 Large sweeps slow saves or hold the statistics fence too long Medium for very large searches Medium Batching; the 100,000-Study benchmark against the initial target; typed-busy refusals for other operations
K9 Deletion racing an import, bulk update or recalculation Medium High without the waits The wait set; one sweep per project; new-work refusals; the fence admitted only after the waits
K10 Divergence from the integrated plan Low Medium: rework when canonical collections arrive The X-DEL mapping in the README; D2 keeps the plan's no-erasure rules; the deletion state is a top-level field ready for conversion
K11 Storage cost of keeping everything for ever Certain Grows with use: each 1% of the 10.7 GB Study collection that ends up deleted keeps about 107 MB plus index entries; the share is unknown until the Bramble rehearsal (#4068) gives search and project sizes Gauges of detached Studies and deleted projects; monthly review against Atlas storage; a future erasure policy remains possible because deleted data is scoped by holding id and operation
K12 Users assume deleted data is erased Medium Medium (privacy expectation) Dialog copy and user guide say plainly that SyRF keeps deleted data
K13 On staging, turning the deletion flag off forces Bulk PDF upload off (startup rule) Certain when used Low (staging) Documented in rollback; prefer a fix-forward
K14 A production release from main before the MVP removes deletion Depends on D7 High (user-visible regression) D7
K15 The uncommitted August work is lost, or merged by mistake Low Medium D9
K16 Shared searches (linked to several projects) behave unexpectedly Low Medium Explicit tests; only this project's link and Studies move

3. Open questions

# Question Who answers Needed by
Q1 How large are the largest searches and projects in production? Answered later from the production-copy rehearsal on Bramble (#4068), not by querying production. It also sizes the storage risk (K11) The #4068 rehearsal S4a benchmark; K11 estimate
Q2 Are any production searches linked to more than one project? Also from the #4068 rehearsal The #4068 rehearsal S4a tests
Q3 Who names the application-administrator capability for the restore routes? Decided 14 October: the existing application-administrator capability (see above) —
Q4 Should running data exports be waited for (planned, with a 1-hour staleness bound) or allowed to finish with mixed content? Chris S3b. S3b-2 (#4212) implements the planned wait with the 1-hour bound; Chris to confirm
Q5 Who owns and reviews the statistics-owned IsProjectDeleted writer and the maintenance skip? FEAT-024 owner S2, S6
Q6 Is a 2-day staging restore window during acceptance acceptable, returning to 30 days afterwards? Chris S9
Q7 Keep the clean-up of a failed import's unrevealed Studies? Decided: keep it (see D-table) —
Q8 Acceptable sweep time and save-latency bound Decided: the proposed bound is the initial target —