Skip to main content

Module authz_policy

Module authz_policy 

Source
Expand description

AuthzPolicy capability trait. See plan/ecosystem/02-capabilities.md §AuthzPolicy.

An AuthzPolicyPlugin answers “given this request context, is the action allowed?” using an externalised policy language — Cedar, CEL, OPA/Rego, or a custom engine. It sits one layer above crate::auth::AuthPlugin: auth establishes who the caller is, authz-policy decides what they may do with that identity.

§Why the return shape is an enum, not Result<_, String>

This is the one capability in bext-plugin-api where a flat enum is load-bearing. Callers branch on three genuinely distinct outcomes:

  1. Allow. Let the request proceed untouched.
  2. Deny. Short-circuit with a 403, forwarding the reason to the logs and (optionally) to the client. The reason string is policy author–controlled (“principal lacks posts:write on posts/123”) and the host must not discard it.
  3. Mutate. Let the request proceed, but rewrite the response on the way out — inject headers (CSP, X-Tenant, audit trailers) or substitute the body (redact fields, stamp a watermark). Cedar’s response-side obligations and a handful of custom engines need this; without it the trait cannot represent what they do.

Folding these into Result<_, String> would collapse Mutate into Allow, which silently drops the rewrite. Folding Deny into Err would conflate “the policy said no” with “the policy engine crashed” — the host treats those completely differently (Deny is a normal 403, engine failure is a 500 and a wakeup).

Backend-failure errors still exist, but they live on the outer AuthzPolicyPlugin::evaluate signature’s companion methods (AuthzPolicyPlugin::reload_policies) and in the contract documented on evaluate itself (engines fail-closed: on internal error, return PolicyDecision::Deny with the error as the reason). This keeps the evaluate hot path allocation-free in the success cases — no Result::unwrap_or_else chains at every call site.

§Backends

Two reference backends ship alongside this trait in crates/bext-impls/:

  • bext-policy-cedar — AWS Cedar. Rich entity/resource model, designed around exactly the Allow / Deny / obligations shape.
  • bext-policy-cel — Google’s Common Expression Language. Simpler boolean expressions over a flat attribute map; maps to Allow/Deny with Mutate unused.

An OPA/Rego backend is planned but not shipped as a reference — deploying a Rego runtime is heavier than the ref-plugin bar.

§AuthzPolicy vs Auth, in one paragraph

crate::auth::AuthPlugin turns a bearer token or session cookie into an crate::auth::AuthUser (id, scopes, attributes). It knows nothing about what the user is trying to do — it cannot, because it runs before routing. AuthzPolicyPlugin runs after routing has identified the action and resource, and evaluates the per-request policy against the already-authenticated principal. A site can run with only Auth (scope strings are enough), only AuthzPolicy (every request is anonymous but policy-gated), or both stacked (auth fills principal, policy evaluates action).

Modules§

fuel
Fuel budgets for WASM authz-policy plugin calls. Matches the convention in crate::locking::fuel and crate::scheduled::fuel.

Structs§

PolicyContext
Evaluation context for a single authorization decision.

Enums§

PolicyDecision
Outcome of a single policy evaluation.

Traits§

AuthzPolicyPlugin
A policy engine plugin.