I’ve been wrestling with this exact "revocation during operation" problem for a DSL I'm building, specifically regarding the inconsistent states you mentioned.
I use a mostly standard caretaker pattern (with an optional built in invocation quota), which is easy for people to grasp.
But for mid-operation revocation, I’ve been experimenting with a function modifier for the v0.5 version of my language spec that I call 'diffusible'.
The goal is to allow the target object to finish executing so it doesn't leave the application in a bad state, but to safely and voluntarily "diffuse" any downstream actions it tries to take after revocation.
Under the hood, it works like this:
The diffusible modifier wraps all of the function's outgoing invocations in a special apply-like wrapper (an extra argument called diffuse).
When a caretaker invokes the function, it injects a clone of itself into the diffuse argument.
If the caretaker is still unrevoked, diffuse acts as a normal 'apply'.
If the caretaker is revoked mid-flight, diffuse instantly becomes a null function (a no-op).
The parent function finishes its local logic safely, but its ability to affect the outside world is cleanly severed.
I struggle to explain this intuitively, and I also have no idea how this would map to a non-language, cert-caps context like W3C.
I have a type system on my side that ensures only built-in caretakers can overload diffuse. I fear it would be hard to find an equivalent mechanism in a distributed, certificate-based system to silently swallow outgoing requests mid-flight.
Maybe this is something worth brainstorming over though?
Regards,