Skip to content

Priority and deny resolution ​

← Documentation home

When multiple rules could apply to one request, Sentinel needs deterministic tie-breaking. Two mechanisms control that: numeric priority and deny-before-allow at equal priority.


Sort order ​

Before first-match evaluation, candidates are sorted:

  1. Descending priority (higher number = checked first)
  2. At the same priority, deny rules before allow rules

Default priority is 0 if omitted.


Deny wins at equal priority ​

typescript
deny()
  .anyRole()
  .actions("project:delete")
  .on("project")
  .build(),

allow()
  .roles("owner")
  .actions("project:delete")
  .on("project")
  .build(), // priority 0 — same as deny

For an owner, both rules are candidates. At priority 0, deny sorts first and matches — owner cannot delete unless you raise the allow rule's priority.


Override pattern ​

Give the exception higher priority than the broad deny:

typescript
deny()
  .anyRole()
  .actions("project:delete", "project:archive")
  .on("project")
  .priority(0)
  .build(),

allow()
  .roles("owner")
  .actions("project:delete", "project:archive")
  .on("project")
  .priority(10)
  .build(),

Now the owner's allow rule is sorted first and wins.


First match wins ​

After sorting, the engine walks the list and stops at the first fully matching rule (including conditions). Later rules are never considered.

Design policies as a ordered decision list, not as independent booleans combined at the end.


Released under the MIT License.