Skip to main content
Access lists are a per-project (or per-user) firewall that runs before the policy engine. They’re the right tool for “I know I never want to hear from this source again” — block in O(1), no ML inference, no upstream cost.

Targets

Each rule blocks or allows a single value of one of these target types: Country rules are cache-only: PromptGuard does not call out to a GeoIP service on the hot path. If the inbound IP isn’t in the cache yet, country rules are skipped for that request and the cache is populated lazily by the dashboard’s geo distribution endpoint. You can pre-warm the cache by visiting the Overview page.

Semantics

The decision logic is intentionally boring and predictable:
  1. Block always wins. If any active block rule matches the request, reject with 403 access_list_block. Done.
  2. Non-empty allow list flips to default-deny. If the project (or user) has any active allow rule, the request must match at least one allow rule to proceed. Otherwise reject.
  3. Otherwise, allow. No rules and no allow list = no opinion = let the policy engine decide.

Scope: project vs. user

Each rule lives at one of two scopes:
  • Project-scoped (project_id set) — the tightest scope. Use when one project needs different access rules from the rest of your account.
  • User-scoped (project_id is NULL) — applies to every project you own. Convenient default for “block this abusive user across all my apps”.
check_access evaluates both scopes in the same query, so a user-wide block plus a project-scoped allow behave exactly the way you’d expect: the block fires.

Recipes

No project_id → user-wide. The next call from this user, on any project, returns 403.
The first allow rule on the project flips it to default-deny. Anything outside 10.0.0.0/8 is rejected.
expires_at lets the rule auto-deactivate without a follow-up DELETE.

What gets denied

A blocked request returns 403 with this body:
The rule_id is the access-list rule that fired, so your client (or your support team) can immediately point at the row in the dashboard.