ELPOD / DOCS SECURITY

security / reference

Authorization Policies in Elpod

Represent authorization decisions as explicit policies near domain actions in a Bun and Elysia backend.

An Elpod policy makes an authorization decision explicit near a domain action, even when that action is called outside an Elysia route. Use policies when roles alone cannot express resource and tenant permissions in a Bun service.

The idea

Roles are coarse labels. Real authorization asks questions like “can this editor update this post in this tenant?” A policy names that decision and puts the resource in the room with the principal.

How Elpod provides it

Policies are explicit resource-level authorization functions. definePolicy() gives each rule a typed principal and resource and throws FORBIDDEN when a rule returns false.

import { definePolicy, type Principal } from "@elpod/core";

type Post = { ownerId: string; published: boolean };
const postPolicy = definePolicy<Principal, Post>({
  read: ({ user, resource }) => resource.published || resource.ownerId === user.id,
  update: ({ user, resource }) => resource.ownerId === user.id,
});

await postPolicy.enforce("update", { user, resource: post });

Use policies when access depends on both identity and resource state. Keep them close to domain logic and call them from HTTP handlers, jobs, and event consumers.

Common mistakes

  • Checking only a role and forgetting ownership, tenant, or resource state.
  • Authorizing a list endpoint but not each returned resource.
  • Returning false silently and leaking whether a resource exists.
  • Making policy decisions from unverified request headers.

Production notes

Policies are application code. Review them like business-critical code, test allow and deny cases, and decide whether unauthorized and not-found should be indistinguishable for your threat model.

Authentication · Tenancy · Security overview.