feat(cf): blocked delete state with reason classification + latch - #5407
Merged
norman-abramovitz merged 3 commits intoJun 2, 2026
Merged
Conversation
Pure classifier mapping a delete failure (HttpErrorResponse or polled StratosJobError) to a BlockReason: 403 -> forbidden, async/last_operation in progress -> operation-in-progress, CF-AssociationNotEmpty -> has-dependents. Transient/5xx/generic-validation stay failure (undefined). Mechanism-owned defaults so every caller gets the universal CF cases.
Classified delete failures (classifyBlock) now terminate as `blocked` with a reason instead of `failure`, and latch the entity by cnsi:kind:guid. While latched, delete() short-circuits to blocked (re-emitting the stored reason+error, no server call) until clear(). isBlocked()/clear() expose the latch; a successful delete clears it defensively. Blocked runs no invalidation/cleanup and fires a blocked diagnostics counter.
runCfDelete now throws on a blocked terminal as well as failure, so the stored CF error (e.g. association_not_empty) reaches the component catch and snackbar instead of resolving silently.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds the
blockedlifecycle state to the signal-nativeEntityDeleteController(Increment 3 of the common delete-mechanism work), so a delete that fails for a known precondition is surfaced distinctly from a transient failure and stops auto-retry loops.classifyBlock(error)— pure classifier mapping a delete failure (either anHttpErrorResponseor a polledStratosJobError) to aBlockReason:403→forbidden, async/last_operationin-progress →operation-in-progress,CF-AssociationNotEmpty→has-dependents. Transient/5xx/generic-validation stayfailure.blockedterminal (withreason+ error) instead offailurefor classified cases, and latches the entity bycnsi:kind:guid. While latched,delete()short-circuits toblocked(re-emitting the stored reason/error, no server call) until an explicitclear().isBlocked()/clear()expose the latch; a successful delete clears it defensively. Blocked runs no invalidation/cleanup and fires adelete-eventstate:'blocked'diagnostics counter.runCfDeletethrows onblockedtoo, so the stored CF error (e.g. association_not_empty) reaches the component snackbar instead of resolving silently.Presentation of the
blockedstate (rendering the latch, wiring a UIclear()) is intentionally out of scope — it lands when a view adopts the lifecycle stream.Testing
Full
make check gategreen (2389 frontend tests, 0 TS/build errors). TDD throughout — 22 controller tests, classifier and runCfDelete specs.