Phase 5e — Refused, Not Failed: the Flutter 409 cascade
25 JUL AT 10:44 AM

Phase 5e — Refused, Not Failed: the Flutter 409 cascade

0 LOVES 1 VIEWS
The server refuses to delete a block that grounds facts, answering 409 with the blast radius; Studio wrapped that in a confirm. Flutter had been swallowing the refusal, so a grounded block simply failed to delete with a useless toast. 5e makes the refusal a modeled outcome: show the blast radius, get a second confirm, re-issue to the cascade route. 7 tests, live-smoked. Shipped 2026-07-19.

A refusal is not a failure — but only if the client says so. Phase 5c made the server refuse to delete a block that grounds recorded facts, answering 409 with the blast radius. Studio wrapped that in a confirm modal (5d). Flutter did not: it fired the plain delete and swallowed the refusal, so a grounded block simply failed to delete — an error toast carrying the server's message and nothing else, no enumeration of what depended on the block and no way to proceed. The blast radius the server had carefully computed was thrown on the floor.

5e is the client half of refuse-by-default. It models the refusal as an outcome, not an exception: the 409 payload is the actionable part, so it is decoded into a sealed BlockDeleteOutcome type — refused-with-blast-radius, or done. The user sees what would break, and can proceed on a second, explicit confirm.

The confirmation is the route — and one honest gap

The design detail that keeps it safe: the confirmation is the ROUTE, not a flag. A plain DELETE /blocks/{id} can only ever refuse-or-succeed-if-safe; proceeding-anyway is a different endpoint, DELETE /blocks/{id}/cascade. There is no ?force=true that a careless caller could set once and forget — to take the facts down with the block, you must call the route that says so out loud. Seven tests, mutation-verified; live-smoked by the Flutter team on a real post.

And the honest gap, recorded rather than hidden: today the dialog reports counts, not names — "this affects 3 facts," not which three. The 409 route doesn't eager-load the target edges, so the client has nothing to name them with. Closing it is a Go-side change, parked on the running list — a real edge, disclosed, not quietly shipped as done.

Total Recall — the AI Memory Layer (master)
Total Recall — the AI Memory Layer (master)
Jul 25, 2026 Total Recall
← Back to Total Recall