🐛 Symptom
On demo (v5.5.0) "Purge unavailable…" always refuses: 1532 of 2556 media rows are purge candidates, so MediaRepository.PurgeUnavailableAsync's counted * 2 <= total gate withholds the DELETE and the endpoint 409s ("possible mount outage").
🔎 Why the refusal is wrong this time
The 1532 are the old flat-layout demo library, replaced wholesale in July — all unavailable since the db/28 backfill stamp (2026-07-29), 0 booth-log plays, files long gone. The live library is the 1024 genre-foldered rows. The tripwire can't distinguish "mount outage, rows will come back" from "library replaced, corpses now exceed half and will never come back."
The dev box hits the same wall after its 5.5.0 upgrade: 9145 unavailable of 18270 total (the gh-#610 wire-topology ghosts, quarantined 08-28) also trips the gate.
🔧 Fix direction
Keep the fail-closed default (the tripwire is right for the outage case). Add an explicit operator override for the refused path — e.g. a typed confirmation naming the count ("delete 1532 tracks") that resends with an acknowledge flag the endpoint honors. Exact shape at /design.
Escape hatch today = one manual DELETE on the box.
🐛 Symptom
On demo (v5.5.0) "Purge unavailable…" always refuses: 1532 of 2556 media rows are purge candidates, so
MediaRepository.PurgeUnavailableAsync'scounted * 2 <= totalgate withholds the DELETE and the endpoint 409s ("possible mount outage").🔎 Why the refusal is wrong this time
The 1532 are the old flat-layout demo library, replaced wholesale in July — all
unavailablesince the db/28 backfill stamp (2026-07-29), 0 booth-log plays, files long gone. The live library is the 1024 genre-foldered rows. The tripwire can't distinguish "mount outage, rows will come back" from "library replaced, corpses now exceed half and will never come back."The dev box hits the same wall after its 5.5.0 upgrade: 9145 unavailable of 18270 total (the gh-#610 wire-topology ghosts, quarantined 08-28) also trips the gate.
🔧 Fix direction
Keep the fail-closed default (the tripwire is right for the outage case). Add an explicit operator override for the refused path — e.g. a typed confirmation naming the count ("delete 1532 tracks") that resends with an acknowledge flag the endpoint honors. Exact shape at /design.
Escape hatch today = one manual
DELETEon the box.