pub trait AuthzPolicyPlugin: Send + Sync {
// Required methods
fn name(&self) -> &str;
fn evaluate(&self, ctx: &PolicyContext) -> PolicyDecision;
fn reload_policies(&self) -> Result<(), String>;
// Provided method
fn cleanup(&self) -> Result<(), String> { ... }
}Expand description
A policy engine plugin.
The runtime holds one instance per configured backend and invokes
evaluate on every gated route. Unlike crate::auth::AuthPlugin,
which runs once per request in the auth middleware, AuthzPolicyPlugin
runs per decision point — a single request may evaluate multiple
policies if it touches multiple resources.
§Fail-closed contract
If the engine cannot evaluate (malformed policy file, internal panic
unwind, missing attribute that the policy declared required),
implementations MUST return PolicyDecision::Deny with the error
string as the reason rather than allowing. Allow-on-failure is a
well-known authorization anti-pattern and the trait contract forbids it.
Concurrency: implementations MUST be safe to call from multiple threads simultaneously. The host evaluates policies from every request-handling thread without serialization.
Required Methods§
Sourcefn name(&self) -> &str
fn name(&self) -> &str
Unique plugin name (e.g. "cedar", "cel", "opa"). Used in
the dev dashboard, metrics labels, and cap_conformance.
Sourcefn evaluate(&self, ctx: &PolicyContext) -> PolicyDecision
fn evaluate(&self, ctx: &PolicyContext) -> PolicyDecision
Evaluate the configured policy set against ctx and return the
decision.
This is the hot path. Implementations SHOULD:
- Be allocation-free in the
Allowcase when possible. - Fail closed (see the type-level fail-closed contract above).
- NOT block on I/O — all policy state is loaded in
reload_policiesor at construction time. The trait is sync, and the host calls it per request.
Sourcefn reload_policies(&self) -> Result<(), String>
fn reload_policies(&self) -> Result<(), String>
Reload the policy set from the backing store.
Called by the host when the policy source changes — file-watcher
notifications for disk-backed engines, push events for remote
stores, or on demand from the dev dashboard. Backends SHOULD
perform the reload atomically: either the new policy set is
live, or the old one remains, never a partial state visible to
concurrent evaluate calls.
Returns Err(message) on backend failure (file unreadable,
parse error, remote fetch timeout). The old policy set remains
active on failure — the host does NOT switch to an empty/fail-open
set.