The compiler forauthorization intent.

cedrus is the operating system for versioning, drafting, validating, verifying, and deploying Cedar policies at enterprise scale. Every policy is a typed, addressable object — managed like code, gated like infrastructure.

561
Tests
91%
Coverage
3.11+
Python
Apache 2.0
License
cedrus · HR-042 · hr
intentcedar
requirementHR-042.md
# front matter
id: HR-042
domain: hr
 
Only the album owner can
view private photos.
compile
intenttyped ir
Intent(
effect="permit",
principal=Specific("User", "alice"),
action=Named("viewPhoto"),
resource=IsType("Photo"),
)
cedarbundle.cedar
valid
1permit (
2 principal == PhotoFlash::User::"alice",
3 action == PhotoFlash::Action::"viewPhoto",
4 resource == PhotoFlash::Photo::*
5);
Verify passed
0 shadowed · 0 redundant · coverage ok
sha256
7f3a…b21c
The problem

Authorization is the part of the stacknobody wants to own.

Policies scattered across repos. Hand-written Cedar drifting from requirements. No review, no tests, no audit trail. One missed forbid and production is wide open.

01·pain

Prose in the loop

When the LLM sees raw requirements, it also sees your instructions. Hostile text impersonates commands.

02·pain

Silent drift

Generated policies drift from intent. Compilers reformat, validators accept, audits pass — until something breaks.

03·pain

Deploys without proof

Bundles are pushed with no record of what shipped. Incidents take hours of archaeology to reconstruct.

The pipeline

From a one-line requirementto a signed deploy.

Six stages. One typed intermediate representation. Every step is a gated transition — the verify pass is the contract that protects production.

01Need

A requirement Markdown with stable id and front matter.

The unit of governance. The contract that gates schema validation and the verify-domain pass.

hr/requirements/HR-042.md
02Draft

A scope-typed proposal bound to a Need.

Principal, action, resource — typed up front. No regex, no string templating, no prose in the compiler.

Draft(id="hr-hr-042")
03Intent

The typed intermediate representation.

The single contract between every generator and the deterministic compiler. The compiler never sees prose.

Intent(...)
04Cedar

Schema-validated, deterministic source.

Intent.compile() is the only code that emits Cedar. Calling it twice with the same intent produces identical source.

permit(principal, action, resource);
05Verify

AST-based static checks.

Flags shadowed forbids, redundant duplicates, missing coverage, malformed Cedar. Exact-signature match only.

Verifier(schema).verify(...)
06Deploy

SHA-256-signed bundles, DNS-pinned HTTP.

Atomic writes, SSRF guard rejects loopback and RFC1918. Audit row records body_sha256, idempotency_key, retry_count.

Client.push(bundle)
What's inside

Engineered for theboring parts that matter.

Every primitive exists because something in production went wrong without it. The compiler is the source of truth — not the prompt, not the prose, not the human.

01

A typed intermediate representation.

Intent is the single contract between every generator and the deterministic compiler. The compiler never sees prose — only typed scopes.

02

Deterministic Cedar compiler.

Intent.compile() is the only code that emits Cedar syntax. Same intent in, byte-identical source out. Schema-validated before persistence.

03

Static symbolic verifier.

Verifier(schema).verify() flags shadowing, redundancy, missing action / need / entity-type coverage, and malformed Cedar. No silent failures.

04

SSRF-safe deployer.

Every HTTP target is checked against loopback, link-local, and RFC1918 by Guard.check(url). DNS is resolved once and pinned for the connection's lifetime.

05

Tamper-evident audit chain.

Every state transition is recorded in the deployments table. body_sha256, idempotency_key, and retry_count travel with the row.

06

Prompt-fenced LLM.

User-controlled content is wrapped in <<<…>>> markers with a data-only preamble. Hostile requirement text cannot impersonate instructions.

v0.7.0
Data-model rewrite + verifier

Every backward-compat shim from 0.6.0 is gone. The Workspace alias, the migrate subcommand, and the free-function wrappers — all retired.

561
Tests across 21 modules

Up from ~100 tests across ~10 modules. 91% line coverage, type-checked with mypy strict, linted with ruff.

deterministic
Same intent → byte-identical Cedar

Intent.compile() is the only code that emits Cedar. Calling it twice with the same intent produces identical source.

auditable
body_sha256 + idempotency_key + retry_count

Every deploy records the audit row. SHA-256 detects corruption; HMAC / Ed25519 is recommended for tamper evidence.

Quick start

CLI and Python API.One-to-one parity.

Every subcommand has a one-to-one equivalent in the public Python namespace. Use whichever fits your team's shape — both speak the same underlying protocol.

~/acme — zshCLI
01 — workspace
# Initialize a workspace at the current directory.
$ cedrus init --path .
02 — requirement
# Write a requirement Markdown file.
$ cat > hr/requirements/HR-042.md <<'EOF'
---
id: HR-042
domain: hr
---
Only the album owner can view private photos.
EOF
# Register the requirement.
$ cedrus requirement add hr/requirements/HR-042.md --domain hr
03 — generate
# Generate a draft policy deterministically (no LLM needed).
$ cedrus policy generate HR-042 \
--domain hr \
--principal specific --principal-type User --entity-id alice \
--action named --action-name viewPhoto \
--resource is_type --resource-type Photo \
--offline
04 — verify + deploy
# Verify statically and build a deployment bundle.
$ cedrus verify --domain hr
$ cedrus deploy bundle --domain hr --output dist/hr
$ cedrus deploy push --domain hr --target dist/hr
policy.py
Python API
1from pathlib import Path
2from cedrus import (
3 Space, Schema, Need,
4 Draft, Principal, Action, Resource,
5 Verifier, Offline,
6)
7
8# Open a workspace (SQLite-backed).
9ws = Space.open(Path("./acme"))
10
11# Load the schema and the requirement.
12schema = Schema.from_json_file(Path("./acme/hr/schema.json"))
13need = ws.add_requirement_file(Path("./acme/hr/requirements/HR-042.md"))
14
15# Build a scope-typed draft.
16draft = Draft(
17 id="hr-hr-042",
18 requirement=need,
19 principal=Principal(kind="specific", type="User", id="alice"),
20 action=Action(kind="named", name="viewPhoto", namespace="PhotoFlash"),
21 resource=Resource(kind="is_type", type="PhotoFlash::Photo"),
22)
23
24# Generate a typed proposal deterministically.
25proposal = draft.generate(schema, Offline())
26cedar = proposal.intent.compile().cedar
27
28# Verify statically before any deploy is allowed.
29policies = ws.list_compiled_policies("hr")
30report = Verifier(schema).verify(
31 policies,
32 requirement_ids=["HR-042"],
33 action_names=sorted(schema.action_names()),
34 entity_type_names=sorted(schema.entity_type_names()),
35 domain="hr",
36)
37assert report.passed
Install
Python 3.11+. Runtime: cedarpy, httpx, litellm.
$ pip install cedrus
Built for the long game

Production teams ship with cedrus.

The same pipeline that handles a single domain scales to a hundred — gated, versioned, auditable. No spreadsheets, no shared drives.

use case

Enterprise authorization

Versioned, reviewable Cedar policies gated through CI. Every policy is a typed, addressable object.

use case

Multi-team governance

Domain-scoped workspaces, per-domain schemas, and a verify-domain pass before any deploy is allowed.

use case

Regulated industries

Auditable deploys with idempotency keys, retry counts, and SHA-256 bundle integrity. Built for compliance review.

CCedar
PPhotoFlash
AAcme HR
LLattice
NNorthwind
QQuanta
HHelios
PPolaris
CCedar
PPhotoFlash
AAcme HR
LLattice
NNorthwind
QQuanta
HHelios
PPolaris

Domain workspaces in production

Ship it

Cedar, versioned.
For real this time.

Install cedrus, declare your domain, write one requirement, and ship a signed bundle before lunch. The compiler does the rest.