Policies
Author enforcement policies in Cedar — from plain language to deployed
Overview
A Checkpoint policy is a Cedar policy that decides what happens when the Gateway or Middleware classifies a request. You author policies in Compose: describe the rule in plain language, Checkpoint compiles it to Cedar, you dry-run it against real traffic, then Authorize & deploy.
Migrating from the legacy policy config? Earlier versions of Checkpoint used a structured JSON
config (default_action, block_threshold, allow_list / deny_list, path_rules). That model
is superseded by Cedar — everything it expressed is now a Cedar rule (see Common
patterns). A project with no deployed Cedar policy falls back to a permissive
baseline until you deploy one.
How policies evaluate
Checkpoint uses an allow-by-default, carve-out posture. Every deployed policy starts from a baseline that permits all traffic:
@id("baseline-allow")
@verdict("ALLOW")
permit ( principal, action, resource );Each rule you add is a forbid that carves out a stricter verdict — BLOCK, CHALLENGE, REDIRECT, or INSTRUCT — for the requests it matches. Cedar is forbid-overrides: when more than one rule applies to a request, the restriction wins. So a policy reads as "allow everything, except…" — you never enumerate the traffic you want to let through.
A rule matches on facts the detection engine supplies about each request:
| Fact | Example | Meaning |
|---|---|---|
resource.path | resource.path like "/checkout*" | The request path (== exact, like glob) |
principal.name | principal.name == "GPTBot" | The detected agent's name |
principal.category | principal.category == "scraper" | Class: ai_agent, scraper, etc. |
principal.reputation | principal.reputation.lessThan(decimal("0.7")) | Agent reputation, 0.0–1.0 |
principal.delegation | principal.delegation == "verified" | Whether a valid KYA-OS delegation was presented |
context.granted_scopes | context.granted_scopes.contains("settings:read") | Consent scopes the agent has been granted |
Use when { … } for the facts that make a rule apply and unless { … } for carve-outs (for example, exempting an agent that presents a verified delegation).
Authoring in Compose
Compose (Policy → Compose, /policy/compose) turns a plain-language description into a reviewable Cedar policy.
- Describe the rule. For example: "Block unverified agents from checkout, but let Claude and ChatGPT browse the catalog." Compose parses the intent and emits Cedar (
⌘⏎to compile). - Review the Cedar. Compose shows the generated rules as editable sentence chips alongside the raw Cedar — what you see is what runs. Hand-edit the Cedar directly if you need to.
- Run dry test. The dry-run replays the policy against representative agents (or your last 7 days of traffic) through the real engine — dry run · no traffic affected — and shows the verdict and the reason for each request.
- Authorize & deploy. Once you've reviewed the dry-run and confirmed Compose's assumptions, Authorize & deploy promotes the policy to production. It's enforcing on the gateway within about a minute.
Draft vs. deployed
Save as draft (and edits made on a policy's detail page) update the draft only — the gateway keeps enforcing the last deployed version until you redeploy. A live policy shows an ● Enforcing on the gateway badge; a policy with saved-but-not-redeployed changes shows ● Enforcing a previous version — redeploy to apply. Deploying is what flips a project into engine enforcement.
Managing a policy
The policy list lives at Policy (/policy). Open a policy for its detail page, which has four tabs:
| Tab | What it does |
|---|---|
| Overview | The authentication & consent experience this policy produces |
| Edit | Hand-edit this policy's raw Cedar block |
| Builder | Edit the policy visually as a graph |
| Decisions | The allow / block / challenge log for this policy |
Verdicts
A rule's @verdict(...) sets what happens to a matching request:
| Verdict | Description | HTTP response |
|---|---|---|
ALLOW | Let the request through (the baseline; also re-permits a subset) | Proxied to origin |
BLOCK | Reject the request | 403 Forbidden |
REDIRECT | Send to another URL (absolute or same-origin path) | 302 Redirect |
CHALLENGE | Require consent or step-up approval before proceeding | 401 (consent / approval flow) |
INSTRUCT | Require a cryptographic KYA-OS identity | 401 with WWW-Authenticate: KYA |
CHALLENGE and INSTRUCT are the consent / cryptographic paths and are enforced at the edge by
the Gateway. In-app middleware enforces ALLOW / BLOCK / REDIRECT
directly; challenge support varies by SDK — see Middleware and the
.NET Cedar cookbook.
Choosing a verdict
Match the verdict to the threat model of the endpoint. Because policies are allow-by-default, you write rules for the traffic you want to restrict.
BLOCK
Return a 403 and refuse to serve the request. Use it when the endpoint is strictly not for agents — competitor scraping of proprietary content, admin surfaces, endpoints that cost money per request — or as a short-term block during an incident (e.g. an AI crawler hammering your origin).
Not a good fit for a general content site: a blanket block will catch legitimate AI agents your users are delegating to. Prefer REDIRECT or INSTRUCT for soft-to-cryptographic enforcement.
REDIRECT
Return a 302 to a URL you choose — a consent page, a sign-in flow, a pricing page, or your hosted Bouncer consent. It's soft enforcement: "you can get what you need, just through this other flow." The target accepts absolute URLs (https://acme.com/for-ai) and same-origin paths (/ai-welcome), so one policy can cover staging and production.
Not a good fit for sensitive endpoints — a 302 is trivial for a sophisticated agent to ignore. Use INSTRUCT there.
CHALLENGE
Require the agent to satisfy a consent or approval step before proceeding. Two shapes:
- Consent — the agent must carry the scopes the rule demands (
@scopes(...)+ acontext.granted_scopescarve-out). Use it to gate specific tools or data behind explicit user consent. - Step-up approval — the request must collect a quorum of approvals from named approvers (
@approvers(...)+@quorum("N")). Use it for high-stakes actions like fund transfers.
INSTRUCT
Return a 401 KYA-OS challenge that requires a cryptographic identity on retry. Use it for sensitive work — payments, data exports, authenticated APIs, admin actions — where you want cryptographic assurance rather than best-effort detection. It is bypass-proof for agents that cannot forge a valid signature, and it defeats tool-delegation evasion (a request proxied through a third-party tool cannot carry the proof).
INSTRUCT requires the Gateway in front of your origin. Pair it with REDIRECT per path — INSTRUCT on /api/payments/*, REDIRECT on / — rather than as a site-wide default, so non-cooperating agents on public surfaces aren't stranded on a 401. See KYA-OS Enforcement for the full flow.
Common patterns
Real Cedar for the rules teams write most often. In Compose you'd describe these in plain language; the Cedar below is what it emits.
Block a specific agent everywhere:
@id("block-gptbot")
@verdict("BLOCK")
forbid ( principal, action, resource )
when { principal.name == "GPTBot" };Block an agent on one path (allow it elsewhere):
@id("block-scraper-on-pricing")
@verdict("BLOCK")
forbid ( principal, action, resource )
when { resource.path like "/pricing*" && principal.name == "GPTBot" };Redirect scrapers to an AI portal:
@id("redirect-scrapers")
@verdict("REDIRECT")
@redirect("/for-ai")
forbid ( principal, action, resource )
when { principal.category == "scraper" };Gate low-reputation agents behind a challenge:
@verdict("CHALLENGE")
forbid ( principal, action, resource )
when { principal.reputation.lessThan(decimal("0.7")) };Require consent (scopes) for an agent on a path — unless it already has them:
@id("challenge-chatgpt-on-account")
@verdict("CHALLENGE")
@scopes("settings:read settings:write")
forbid ( principal, action, resource )
when { (resource.path == "/account" || resource.path like "/account/*") && principal.name == "ChatGPT" }
unless { context.granted_scopes.contains("settings:read") && context.granted_scopes.contains("settings:write") };Require a 2-of-N approval quorum on a sensitive action:
@verdict("CHALLENGE")
@quorum("2")
@approvers("did:web:acme:approvers:alice did:web:acme:approvers:bob")
forbid ( principal, action, resource )
when { resource.path == "/transfer" };Exempt verified agents from a restriction — add an unless carve-out so agents that present a valid delegation pass through:
unless { principal.delegation == "verified" }Match a single agent with principal.name == "X"; match a set with an OR-disjunction
(principal.name == "X" || principal.name == "Y"). Cedar's in operator is for entity
hierarchies, not string sets, so principal.name in [...] will not match.
Enforce vs. observe
Enforcement has an orthogonal mode that controls whether a matched verdict actually acts:
- Observe — evaluate the policy and record what would have happened (the dashboard shows "Would have been: Block(…)"), but let every request through. Nothing is blocked.
- Enforce — apply the verdict for real (403 for
BLOCK, the consent/challenge flow forCHALLENGE/INSTRUCT, the 302 forREDIRECT).
The recommended rollout is to deploy in observe, watch the dashboard for a week or two, then flip to enforce once the verdicts look right. The enforcement toggle is a per-project switch, separate from deploying a policy.
Identity & consent
Some Cedar facts — principal.delegation == "verified", context.granted_scopes.contains(...) — come from the identity layer, not detection. That layer (auth methods, providers, per-tool consent) is configured under Govern as Protections; it produces the facts your Cedar policy evaluates. A common pattern is "known, verified agents welcome; unknown agents challenged or blocked", expressed with an unless { principal.delegation == "verified" } carve-out on an otherwise-restrictive rule.
Testing a policy
- Compose the rule and Run dry test — replays it against the real engine with no traffic affected.
- Authorize & deploy in observe mode and review the "would have been" decisions in the dashboard.
- Tune the rules against real traffic, then flip to enforce when you're confident.
Next Steps
- Detection in Enforce Mode — the signals behind
principal.*facts - Gateway Enforcement — the edge Gateway that enforces your policy
- Middleware Enforcement — code-based enforcement
- Monitoring — track policy decisions