BLOCK. This is the property that makes enforcement real: an agent (or an
attacker) can never gain capability by making the control plane unavailable.
What counts as a failure
Any of these produce a fail-closedBLOCK:
- The PDP is unreachable, refuses the connection, or times out.
- The PDP returns a non-
2xxstatus. - The response body is missing, malformed, or carries a verdict the client doesn’t recognize.
The synthesized decision
Unknown stages are treated the same way server-side: a stage the engine doesn’t
recognize returns
BLOCK under the fail-closed default rather than silently
allowing.Operational implications
Latency budget
Latency budget
Because the side effect waits on the verdict, set a call timeout you’re
comfortable enforcing. The reference Kotlin client uses an 8-second call
timeout; tune it to your surface. A slow PDP degrades to blocked, never to
unguarded.
High availability
High availability
Fail-closed makes PDP availability a hard dependency for consequential
actions. Run the PDP with the same availability posture as the systems those
actions touch (pharmacy, payments, EHR).
Graceful UX
Graceful UX
A fail-closed block should read as a soft, retryable message to the user
(“I can’t complete that right now”), not a hard error: the step was withheld,
not lost.
Custom clients
Custom clients
If you implement your own PEP, replicate this exactly: default to BLOCK on
any ambiguity, and never map an unrecognized verdict to “continue”.