This release is a pre-release and may not be stable for production use.
Dogwood Policy Python SDK
Python SDK and PyO3 binding for the Dogwood policy language. Dogwood is a policy language for fine-grained authorization decisions that depend on history or patterns of events over time - not just a single request. It adds temporal conditions (since, formerly, once, aggregations) and information providers (computed guardrail facts) on top of Cedar policy syntax, then lowers everything back to Cedar for evaluation. Existing Cedar policies stay valid as-is. For information, read the Dogwood documentation.
⚠️⚠️⚠️ Current Dogwood reference interpreter is not intended for production use; therefore, this Python SDK and PyO3 binding is experimental in nature.
The public API is modeled after the Rust dogwood-language lifecycle:
- Build a
ServiceSchemaandPolicySchema. - Parse and lower policy source into a
LoweredPolicySet. - Validate it.
- Feed
Eventvalues to a statefulAuthorizer.
This package uses PyO3/maturin to bind the Rust dogwood-language reference
for schema-backed lowering, validation, and trace replay. The Python SDK also
keeps a temporary pure-Python fallback only for source-tree examples that omit
a full Cedar action schema. Schema-backed workflows require the native
extension.
Install
Install the latest released package from PyPI:
pip install dogwood-py
Pre-release builds are published for pull requests. To try the latest pre-release:
pip install --pre dogwood-py
To install the optional example dependencies:
pip install "dogwood-py[examples]"
The package installs as dogwood:
from dogwood import native
assert native.available()
Native vs. Non-Native Execution
This package has two execution paths.
Native path
The native extension imports as dogwood._dogwood_native; convenience wrappers
live in dogwood.native. The native path is the PyO3 extension built by maturin. It calls the Rust
dogwood-language reference implementation.
Used for:
- schema-backed policy lowering
- schema-backed validation
- schema-backed trace replay
- augmented Cedar schema export
This is the path to use for compatibility with the Rust reference. It requires a real Cedar action schema.
You can check whether it is available:
from dogwood import native
assert native.available()
For repeated decisions, use a persistent native authorizer so policy lowering happens once:
from dogwood import native
authorizer = native.NativeAuthorizer(policy_source, cedar_schema_source)
decision = authorizer.authorize_request(
"Drupe::Action::SellShares",
'Drupe::OAuthUser::"alice"',
'Drupe::Gateway::"trading"',
{"shares": 25, "stock": "AMZN"},
)
assert decision == "Allow"
Non-native fallback
The fallback path is pure Python. It exists only so SDK examples can run without a full Cedar schema while the native API surface is still being built out.
It supports only a small subset:
- basic
permit/forbid when/unlesschecks overcontext.*- simple trace parsing
- simple
formerly withintemporal checks
It is not a replacement for the Rust reference implementation.
The SDK requires native behavior when a non-empty PolicySchema is supplied.
It will raise a clear error if the native extension is missing. If the schema is
empty, examples may still use the Python fallback.
Event Schema
Dogwood has two schema layers:
- The policy/action schema is the Cedar
.cedarschemafile. It defines entities, actions, and request context types such ascontext.input.amount. - The event schema tells Dogwood how actions become historical events:
which event kinds exist (
request,response,error), which fields are recorded in the temporal history, and which event kinds produce authorization decisions.
The examples use Dogwood's default event schema. Under that default,
request events are decision points, and the event history records request
input fields plus reserved fields like callerPrincipal,
callerResource, and requestId. That is why a temporal policy can ask about
past events such as:
Drupe::Action::"Transfer"::request{ input.user: context.input.user }
In other words, the Cedar schema says what a Transfer request looks like;
the event schema says that Transfer::request is both authorizable and stored
in history for later temporal checks.
Python API
from dogwood import Authorizer, Event, LoweredPolicySet, PolicySchema, ServiceSchema
policy = '''
@id("sell_small_only")
permit (
principal,
action == Drupe::Action::"SellShares",
resource
)
when { context.input.shares <= 50 };
'''
policies = LoweredPolicySet.from_str(policy, ServiceSchema.defaults(), PolicySchema(""))
authorizer = Authorizer(policies)
event = (
Event.builder('Drupe::Action::"SellShares"', "request")
.principal('Drupe::OAuthUser::"alice"')
.resource('Drupe::Gateway::"gw1"')
.field("input", "shares", 50)
.request_context("input", "shares", 50)
.build()
)
assert authorizer.is_authorized(event).allowed()
There is also a runnable example:
make example
FastAPI Native Example
The FastAPI example uses the native binding and a real Cedar schema. It loads
its own examples/fastapi_simple/policy.dw and
examples/fastapi_simple/schema.cedarschema, creates a persistent
native.NativeAuthorizer, and exposes an authorization endpoint.
The policy enforces a $50 daily transfer limit per user. Three $20
transfers by the same user produce:
Allow, Allow, Deny
Run it:
make develop
make examples-deps
make fastapi-example
First transfer:
curl -s http://127.0.0.1:8000/authorize \
-H 'content-type: application/json' \
-d '{"user":"alice","amount":20}'
Expected response:
{"decision":"Allow","allowed":true,"daily_limit":50}
Second transfer:
curl -s http://127.0.0.1:8000/authorize \
-H 'content-type: application/json' \
-d '{"user":"alice","amount":20}'
Expected response:
{"decision":"Allow","allowed":true,"daily_limit":50}
Third transfer:
curl -s http://127.0.0.1:8000/authorize \
-H 'content-type: application/json' \
-d '{"user":"alice","amount":20}'
Expected response:
{"decision":"Deny","allowed":false,"daily_limit":50}
Dogwood authorizers are stateful. The example keeps one shared native authorizer and protects it with a lock. For high-throughput services, use a pool or request-partitioned authorizers based on your temporal semantics.
The same FastAPI app also includes a quota-based rate limit endpoint:
curl -s http://127.0.0.1:8000/authorize/quota \
-H 'content-type: application/json' \
-d '{"user":"carol","amount":1}'
That endpoint uses examples/fastapi_simple/quota_policy.dw, which permits fewer
than three transfers by the same user within one hour. For one user, the first
two requests are allowed and the third is denied.
CLI
dogwood-py validate policy.dw --policy-schema schema.cedarschema
dogwood-py replay policy.dw --policy-schema schema.cedarschema --trace trace.log
dogwood-py lower policy.dw --policy-schema schema.cedarschema
When using the local virtualenv directly:
.venv/bin/dogwood-py validate policy.dw --policy-schema schema.cedarschema
Run the checked-in CLI example:
make cli-example
Equivalent command:
.venv/bin/dogwood-py replay examples/cli/policy.dw \
--policy-schema examples/cli/schema.cedarschema \
--trace examples/cli/trace.log
Expected output:
@0 (time point 0): true
@1 (time point 1): false
Make Targets
make setupcreates.venvand installs development tools.make developbuilds and installs the PyO3 extension in editable mode.make examples-depsinstalls optional dependencies used by examples.make testruns the Python test suite.make perf-testruns the opt-in native-vs-Python replay performance check.make examplerunsexamples/api_usage.py.make cli-exampleruns thedogwood-py replayexample.make fastapi-examplestarts the native-backed FastAPI server.make buildbuilds a wheel with maturin.make cleanremoves generated caches and Rust build output.
The performance test is a coarse regression guard, not a precise benchmark. It
uses DOGWOOD_PERF_TESTS=1, prints native and pure-Python replay timings, and
asserts the Rust-backed end-to-end path is not catastrophically slower than the
fallback on the same generated trace. Tune the ceiling with
DOGWOOD_NATIVE_MAX_RATIO when needed.
Latest local performance check:
native replay: 0.4793s
python fallback replay: 0.0708s
ratio native/python: 6.77
persistent native authorizer: 0.4424s
python fallback authorizer: 0.0147s
ratio native/python: 30.14
This result does not mean the reference Rust implementation is slower in general. The test compares the full native Dogwood path, including real schema-backed Rust lowering/replay semantics, against the intentionally minimal Python fallback. The value of the test is detecting large accidental regressions in the binding path, not benchmarking the Rust engine in isolation.
The persistent native authorizer avoids repeated policy lowering, but each request still crosses the Python/Rust boundary, converts Python input into Dogwood values, and runs the full Cedar-backed decision path. The fallback remains much faster for this tiny policy because it evaluates only a narrow regex-parsed subset with no real Cedar schema semantics.
Current Scope
Rust-backed operations cover schema-backed lowering, validation, and trace replay. The Python fallback is temporary and schema-less only. The intended end state is to remove it once the Rust-backed SDK objects cover the same ergonomic surface.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dogwood_py-0.0.1.dev10.tar.gz.
File metadata
- Download URL: dogwood_py-0.0.1.dev10.tar.gz
- Upload date:
- Size: 33.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4aa82fb36322c70576202aa452b08278f1cf2a6d4e2335cc6b1efe266f939f3
|
|
| MD5 |
54b45789109aa406eaba2c6331f239b7
|
|
| BLAKE2b-256 |
169052a1ef7b2ed9282878e827c26f23df007fd9d6ddf9e01bf4340b07e3b386
|
Provenance
The following attestation bundles were made for dogwood_py-0.0.1.dev10.tar.gz:
Publisher:
release.yml on abhishektiwari/dogwood-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dogwood_py-0.0.1.dev10.tar.gz -
Subject digest:
c4aa82fb36322c70576202aa452b08278f1cf2a6d4e2335cc6b1efe266f939f3 - Sigstore transparency entry: 2387661459
- Sigstore integration time:
-
Permalink:
abhishektiwari/dogwood-py@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Branch / Tag:
refs/pull/4/merge - Owner: https://github.com/abhishektiwari
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file dogwood_py-0.0.1.dev10-cp310-abi3-win_amd64.whl.
File metadata
- Download URL: dogwood_py-0.0.1.dev10-cp310-abi3-win_amd64.whl
- Upload date:
- Size: 5.4 MB
- Tags: CPython 3.10+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54e00d5bdbc447edd1ca50a7704757e7bd557275d8e11703b796949e97363f89
|
|
| MD5 |
9faf24653b04be718e2a5c210f728895
|
|
| BLAKE2b-256 |
9e89ca3d64eaaf22df4e65b2fe969c01c97a0f49ac955a3e57443c1200ab459d
|
Provenance
The following attestation bundles were made for dogwood_py-0.0.1.dev10-cp310-abi3-win_amd64.whl:
Publisher:
release.yml on abhishektiwari/dogwood-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dogwood_py-0.0.1.dev10-cp310-abi3-win_amd64.whl -
Subject digest:
54e00d5bdbc447edd1ca50a7704757e7bd557275d8e11703b796949e97363f89 - Sigstore transparency entry: 2387661476
- Sigstore integration time:
-
Permalink:
abhishektiwari/dogwood-py@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Branch / Tag:
refs/pull/4/merge - Owner: https://github.com/abhishektiwari
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file dogwood_py-0.0.1.dev10-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: dogwood_py-0.0.1.dev10-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 6.1 MB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e585caf987e720a53dc27a230e450de14c73b1b95ecf658958db0ec7b26eb116
|
|
| MD5 |
2245db311f884eb57cd08b03a80e9a2c
|
|
| BLAKE2b-256 |
72f0bc420b113ba59a7d0bc19d54985c0700bde4fded2100d8a494eed7525261
|
Provenance
The following attestation bundles were made for dogwood_py-0.0.1.dev10-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on abhishektiwari/dogwood-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dogwood_py-0.0.1.dev10-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
e585caf987e720a53dc27a230e450de14c73b1b95ecf658958db0ec7b26eb116 - Sigstore transparency entry: 2387661484
- Sigstore integration time:
-
Permalink:
abhishektiwari/dogwood-py@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Branch / Tag:
refs/pull/4/merge - Owner: https://github.com/abhishektiwari
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file dogwood_py-0.0.1.dev10-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: dogwood_py-0.0.1.dev10-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 5.9 MB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ace184aabfaf06c8c03d944990583db088355133f96479b38d4335c07f0b4249
|
|
| MD5 |
4e7bcc515f60a7a6e24ed6bb9f3a598e
|
|
| BLAKE2b-256 |
1583456f98a98070d4dfaafe948459c46bd76c972192892e9671fe3ccee82ce7
|
Provenance
The following attestation bundles were made for dogwood_py-0.0.1.dev10-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on abhishektiwari/dogwood-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dogwood_py-0.0.1.dev10-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
ace184aabfaf06c8c03d944990583db088355133f96479b38d4335c07f0b4249 - Sigstore transparency entry: 2387661468
- Sigstore integration time:
-
Permalink:
abhishektiwari/dogwood-py@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Branch / Tag:
refs/pull/4/merge - Owner: https://github.com/abhishektiwari
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file dogwood_py-0.0.1.dev10-cp310-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: dogwood_py-0.0.1.dev10-cp310-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 5.3 MB
- Tags: CPython 3.10+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79bfa3f3671e58901527477d4403e44652f89d21d8730c92ea138901957c7b75
|
|
| MD5 |
bb38538c72ae9f4fb36ff5ca3c0f778e
|
|
| BLAKE2b-256 |
17c1e4dbaf416e9645262960965c00e9635c0f30a2aaa5449bf960f452293d22
|
Provenance
The following attestation bundles were made for dogwood_py-0.0.1.dev10-cp310-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on abhishektiwari/dogwood-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dogwood_py-0.0.1.dev10-cp310-abi3-macosx_11_0_arm64.whl -
Subject digest:
79bfa3f3671e58901527477d4403e44652f89d21d8730c92ea138901957c7b75 - Sigstore transparency entry: 2387661493
- Sigstore integration time:
-
Permalink:
abhishektiwari/dogwood-py@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Branch / Tag:
refs/pull/4/merge - Owner: https://github.com/abhishektiwari
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Trigger Event:
pull_request
-
Statement type:
File details
Details for the file dogwood_py-0.0.1.dev10-cp310-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: dogwood_py-0.0.1.dev10-cp310-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 5.6 MB
- Tags: CPython 3.10+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
675f434962fab6b7526751eb4a3a471373c49cbd8d8bd7c92c8db5d63edd8f35
|
|
| MD5 |
1eef0c83ec815cc3093b40b2d67a671f
|
|
| BLAKE2b-256 |
f350089f746b699d9cda831367a58ceb4ef5f94a8a72f46b5d77f3c803deeae8
|
Provenance
The following attestation bundles were made for dogwood_py-0.0.1.dev10-cp310-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on abhishektiwari/dogwood-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dogwood_py-0.0.1.dev10-cp310-abi3-macosx_10_12_x86_64.whl -
Subject digest:
675f434962fab6b7526751eb4a3a471373c49cbd8d8bd7c92c8db5d63edd8f35 - Sigstore transparency entry: 2387661488
- Sigstore integration time:
-
Permalink:
abhishektiwari/dogwood-py@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Branch / Tag:
refs/pull/4/merge - Owner: https://github.com/abhishektiwari
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d6380b36117e3cd1fbb26b4a64ca68621cb38ce8 -
Trigger Event:
pull_request
-
Statement type: