Deterministic policy evaluation layer for dbl-core
Project description
DBL Policy
Deterministic, tenant-scoped policy evaluation for DBL. This package produces DECISION events only. It does not execute tasks.
What it is
dbl-policy is the normative gate in the DBL stack:
- It evaluates a policy from authoritative inputs only
- It returns ALLOW or DENY with stable reason codes
- It can be bridged into a
dbl-coreDECISION event with a strict, contract-shapeddatamapping - It is pure: no IO, no time, no randomness, no env, no network, no trace-dependence
Non-goals
- No execution
- No orchestration
- No reading or depending on observational fields (trace, runtime, exceptions, etc.)
- No mutation of event streams
Contract
The authoritative specification is in:
docs/dbl_policy_contract.md
Key invariants enforced by this package:
- Inputs must be JSON-safe and deterministic
- No floats (including nested)
- Mapping keys must be exact
str(no subclasses)
- Policy input is whitelisted
- Unknown keys are rejected
PolicyContextis snapshotted- Caller mutation after construction cannot affect evaluation or digest
- Output can be converted into a
dbl-coreDECISION eventDECISION.datais a Mapping with a strict shape- Includes policy lineage:
policy_id,policy_version,tenant_id
Install
pip install dbl-policy
Requires Python 3.11+ and dbl-core>=0.3,<0.4.
Quickstart
- Use a built-in policy
from dbl_policy import PolicyContext, TenantId
from dbl_policy.allow_all import POLICY as ALLOW_ALL
ctx = PolicyContext(
tenant_id=TenantId("tenant-1"),
inputs={"use_case": "llm-generate"},
)
decision = ALLOW_ALL.evaluate(ctx)
- Convert a decision to a DBL DECISION event
from dbl_policy import decision_to_dbl_event
event = decision_to_dbl_event(decision, correlation_id="c1")
event.data will be shaped like:
{
"policy_id": "...",
"policy_version": "...",
"tenant_id": "...",
"gate": {
"decision": "ALLOW" | "DENY",
"reason_code": "...",
# "reason_message": "..." (optional)
}
}
Writing your own policy
Policies only implement evaluate(context) and must be deterministic.
from dataclasses import dataclass
from dbl_policy import (
PolicyContext,
PolicyDecision,
PolicyId,
PolicyVersion,
DecisionOutcome,
)
from dbl_policy import reason_codes
@dataclass(frozen=True)
class ExamplePolicy:
policy_id: PolicyId = PolicyId("example")
policy_version: PolicyVersion = PolicyVersion("1.0.0")
def evaluate(self, context: PolicyContext) -> PolicyDecision:
use_case = context.inputs.get("use_case")
if use_case == "blocked":
return PolicyDecision(
outcome=DecisionOutcome.DENY,
reason_code=reason_codes.TENANT_BLOCKED,
reason_message="blocked use_case",
policy_id=self.policy_id,
policy_version=self.policy_version,
tenant_id=context.tenant_id,
)
return PolicyDecision(
outcome=DecisionOutcome.ALLOW,
reason_code=reason_codes.OK,
policy_id=self.policy_id,
policy_version=self.policy_version,
tenant_id=context.tenant_id,
)
Safe evaluation (recommended)
decide_safe wraps context validation and converts failures into a stable DENY.
- Valid inputs: evaluates policy, ensures
authoritative_digestis populated - Invalid inputs: DENY with stable reason_code
- Exceptions during evaluation: DENY with
evaluation_error
from dbl_policy import decide_safe
from dbl_policy.allow_all import POLICY
d1 = decide_safe(POLICY, "tenant-1", {"use_case": "x"})
d2 = decide_safe(POLICY, "tenant-1", {"unknown_key": "x"}) # -> DENY
Reason codes
Reason codes are stable semantic identifiers:
- ok
- allow_all
- deny_all
- invalid_input
- unknown_context_key
- tenant_blocked
- missing_required_input
- evaluation_error
See src/dbl_policy/reason_codes.py.
Development
python -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install -e ".[dev]"
pytest
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
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 dbl_policy-0.2.1.tar.gz.
File metadata
- Download URL: dbl_policy-0.2.1.tar.gz
- Upload date:
- Size: 11.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ed5f53dc65ff30d911691884bbf3f5af0e2c4395351f8466b2254f1fccf5eae
|
|
| MD5 |
8d27f83f717b9e8281506050c5a17a3b
|
|
| BLAKE2b-256 |
13aca077a020cb7a088aa88eb2ce91b5637cc1e3a20c660ff6c5fc1bb305d37b
|
File details
Details for the file dbl_policy-0.2.1-py3-none-any.whl.
File metadata
- Download URL: dbl_policy-0.2.1-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13fc69c4b1fb7a7ef8c67cbd21c8baea16036611c95143a2b78d1fa5443026c2
|
|
| MD5 |
fec99d26c8c1da816130d39e18c295f6
|
|
| BLAKE2b-256 |
a2974844c2614e5ed330b23ca9fc882c2d5ebf75eb576b2a217b13122fda5498
|