Metadata-Version: 2.4
Name: decionis
Version: 0.2.0
Summary: Enterprise Decision Protocol for policy-enforced automation and verifiable audit trails.
Project-URL: Homepage, https://decionis.com
Project-URL: Documentation, https://docs.decionis.com
Project-URL: Repository, https://github.com/orepos/Decionis
Author-email: Decionis <sdk@decionis.ai>
License: MIT
Keywords: audit,decionis,execution-gate,governance,interceptor,policy,sdk
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: cryptography>=42
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.7
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.111; extra == 'fastapi'
Provides-Extra: flask
Requires-Dist: flask>=3; extra == 'flask'
Provides-Extra: lint
Requires-Dist: mypy>=1.10; extra == 'lint'
Requires-Dist: ruff>=0.5; extra == 'lint'
Provides-Extra: test
Requires-Dist: pytest>=8; extra == 'test'
Requires-Dist: respx>=0.21; extra == 'test'
Description-Content-Type: text/markdown

# Decionis Python SDK

[![PyPI version](https://img.shields.io/pypi/v/decionis.svg)](https://pypi.org/project/decionis/)
[![Python versions](https://img.shields.io/pypi/pyversions/decionis.svg)](https://pypi.org/project/decionis/)
[![License](https://img.shields.io/pypi/l/decionis.svg)](https://pypi.org/project/decionis/)

**Decionis: The Governance Protocol for Automated Enterprise Decisions.**

Decionis is the Decision Protocol infrastructure for encoding, evaluating, and
auditing organizational policy at scale. The Python SDK acts as an execution
interceptor: it captures execution intent, sends it to Decionis, and locally
continues, stops, or hands off based on the signed decision.

## Core Concept

- **Trust:** Every governed action receives a deterministic Decionis decision:
  `ALLOW`, `BLOCK`, `ESCALATE`, `REVIEW_REQUIRED`, or `ERROR`.
- **Automation:** Applications, bots, API routes, and workflows keep moving only
  after Decionis returns a signed policy evaluation.
- **Auditability:** Decision Dossiers preserve the execution intent, reason
  codes, cryptographic signature, and verification trail for enterprise review.

## Installation

```bash
pip install decionis
```

## Quickstart

Set `DECIONIS_API_KEY` in your server-side runtime. Get a key by subscribing at
<https://decionis.com> or by requesting an API key from Decionis. API-key
registration can include an industry such as `financial_services`, `healthcare`,
`retail`, or `technology`; Decionis can provision a default encoded policy
binding for that industry in shadow mode.

```python
import os

from decionis import DecionisClient

client = DecionisClient(
    api_key=os.environ["DECIONIS_API_KEY"],
    base_url="https://api.decionis.com",
    tenant_id="bank_001",
)

def execute_transfer():
    return {"submitted": True}

execution = client.enforce(
    {
        "actor": {"id": "agent_42", "type": "AI_AGENT"},
        "action": {"type": "TRANSFER_FUNDS", "resource": "liquidity_pool"},
        "context": {"workflow": "treasury_ops", "environment": "production"},
        "policy_refs": ["treasury-transfer-policy-v3"],
        "idempotency_key": "txn_<unique_execution_id>",
    },
    execute=lambda decision: execute_transfer(),
)

decision = execution.decision
dossier = client.create_dossier(decision.decision_id)
health = client.ping()

print(decision.status.value)
print(decision.dossier_url)
print(dossier["decision_id"])
print(health["status"])
```

Use one idempotency key per execution intent. Reusing the same key returns the
same Decionis decision replay instead of creating a new governed decision record.

Use `evaluate` for decision-only diagnostics, simulations, or pre-flight
observability. Production gates should bind the Decionis decision to the code
that performs the action by passing `execute=...` into `enforce`.

```python
decision = client.evaluate(
    {
        "actor": {"id": "checkout-worker", "type": "SERVICE"},
        "action": {"type": "CAPTURE_PAYMENT", "resource": "order_9812"},
        "context": {"surface": "shopify", "channel": "checkout"},
        "policy_refs": ["commerce-integrity-policy-v1"],
    }
)
```

`enforce` fails closed for non-allowed decisions before the callback runs:

```python
from decionis import DecionisBlockedException

try:
    execution = client.enforce(
        {
            "actor": {"id": "checkout-worker", "type": "SERVICE"},
            "action": {"type": "CAPTURE_PAYMENT", "resource": "order_9812"},
            "context": {"surface": "shopify", "channel": "checkout"},
            "policy_refs": ["commerce-integrity-policy-v1"],
        },
        execute=lambda decision: payment_gateway.capture("order_9812"),
    )
except DecionisBlockedException as exc:
    print(exc.decision_id)
    print(exc.status.value)
    print(exc.dossier_url)
```

Decision-only `enforce(request)` remains available during the `0.x` transition,
but it is deprecated. Use `evaluate(request)` for diagnostics and bound
`enforce(request, execute=...)` for production gates.

```python
execution = client.enforce(request, execute=lambda decision: run_job(), shadow=True)
assert execution.shadow_mode is True
```

## Interceptors

Decorators keep execution policy outside the application while giving Decionis a
clear interception point.

```python
import os

from decionis import DecionisClient, decionis_gate

client = DecionisClient(
    api_key=os.environ["DECIONIS_API_KEY"],
    tenant_id="trading_client_001",
)


@decionis_gate(
    client=client,
    action="OPEN_POSITION",
    policy="cfd-risk-policy",
    actor={"id": "cfd_bot_7", "type": "TRADING_BOT"},
)
def open_position(order):
    return broker.open_position(order)
```

## Policy Encoding

Most applications should not call policy encoding. Use it only from an internal
policy authoring or deployment pipeline that already has a reviewed Decionis
policy bundle artifact. The SDK forwards that artifact to Decionis and returns
the accepted artifact metadata; it does not evaluate policy rules locally.

```python
encoding = client.encode_policy(
    {
        "protocol_version": "1.0",
        "bundle_id": "018f4e6a-64d1-7b31-91ac-42d6db8a0001",
        "org_id": "trading_client_001",
        "version": "cfd-risk-policy@2026-05-03",
        "effective_from": "2026-05-03T00:00:00Z",
        "rules": [{"artifact_ref": "decionis-admin-export:policy-rule-001"}],
        "metadata": {"source": "decionis-admin-export"},
    },
    idempotency_key="policy-bundle-001",
)

print(encoding.artifact_id)
```

## FastAPI

```python
import os

from fastapi import FastAPI

from decionis import DecionisClient
from decionis.middleware.fastapi import FastAPIDecionisMiddleware

app = FastAPI()
client = DecionisClient(api_key=os.environ["DECIONIS_API_KEY"], tenant_id="bank_001")

app.add_middleware(
    FastAPIDecionisMiddleware,
    client=client,
    build_request=lambda scope: {
        "actor": {"id": "api", "type": "SERVICE"},
        "action": {"type": "HTTP_REQUEST"},
        "context": {"path": scope["path"]},
        "policy_refs": ["api-execution-policy-v1"],
    },
)
```

## Configuration

```python
client = DecionisClient(
    api_key=os.environ["DECIONIS_API_KEY"],
    base_url="https://api.decionis.com",
    timeout=10.0,
    max_retries=2,
    retry_backoff=0.25,
    tenant_id="bank_001",
)
```

## Changelog

### v0.2.0

- Introduced bound enforcement with `enforce(request, execute=..., shadow=...)`
  so execution happens inside the SDK-controlled gate.
- Deprecated decision-only `enforce(request)` in favor of `evaluate(request)`
  for diagnostics and bound `enforce` for production execution.
- Updated decorators and middleware to execute handlers only from the
  SDK-controlled enforcement callback.

### v0.1.3

- Routed SDK evaluation through the canonical
  `/v1/protocol/evaluate-decision` endpoint.
- Normalized protocol outcomes into SDK decision statuses while preserving the
  protocol response for audit/debug context.
- Kept policy validation and bundle encoding aligned with the API gateway
  routes used for SDK provisioning.

### v0.1.2

- Focused the package description on SDK installation, client usage,
  interception, enforcement, FastAPI middleware, and policy encoding.

### v0.1.1

- Published the professional PyPI project description and package metadata for
  the Decision Protocol positioning.
- Added `ping()` as a connectivity alias for `health()`.
- Updated default SDK API routing to `https://api.decionis.com`.

### v0.1.0

- Introduced Decionis execution interceptors for Python applications and FastAPI
  services.
- Introduced Cryptographic Decision Dossiers for verifiable audit trails,
  signed decisions, dossier URLs, and local signature verification.
- Released the initial Protocol Logic Engine integration surface for policy
  bundle encoding, validation, evaluation, and enforcement.

## Release

The package is ready for PyPI Trusted Publishing from GitHub Actions. Releases
are triggered from GitHub Releases and start at `0.1.0`.
