Delete Only Before History
Deletion still has one legitimate place: correcting a row that has never participated in work. An operator may create a misspelled or mistaken pipeline and want it gone. If no delegation references the row, deleting it removes unused configuration rather than history.
The safety condition must be checked by the canonical writer in the same transaction as deletion. A UI that first counts references and then sends delete opens a race: another session can queue work between the count and the mutation. The database-side decision must see one consistent state.
The protected oneoff row is stricter. Even with zero references it cannot be deleted because its existence is a product invariant, not a consequence of history. This shows why foreign keys alone are insufficient: referential integrity cannot express every domain rule.
A good refusal tells the operator what to do. If referenced, archive the row. If protected, edit its allowed fields or leave it alone. If unused, delete succeeds and the record should still emit a mutation event so operational history can explain the disappearance.
Resolve the Exact Target First
Show the row name, version, archival state, and reference count before offering deletion. Confirmation should repeat the stable key, not only a mutable title. Destructive operations become safer when the target is boringly explicit.
After deletion, verify that compose and get no longer return the row while existing event history still shows who deleted unused configuration. Recoverability is limited, so precision and a retained mutation receipt matter.