Metadata-Version: 2.4
Name: pyscoped-rules
Version: 0.1.0
Summary: Roles, permissions, entitlements, and limits for scoped SaaS authorization.
Author: Trevor Ewert
License: MIT
Keywords: authorization,entitlements,limits,permissions,rbac,tenancy
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 :: Only
Classifier: Programming Language :: Python :: 3.9
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.9
Provides-Extra: yaml
Requires-Dist: pyyaml>=6.0; extra == 'yaml'
Description-Content-Type: text/markdown

# pyrule

`pyrule` is a framework-agnostic authorization core for SaaS products that need roles, permissions, subscription entitlements, usage limits, and conditional rules in one decision path.

It is designed to answer one question:

```python
decision = engine.check(actor=user, action="project.create", scope=tenant)
```

The result is a structured `Decision`, not only a boolean, so application code can distinguish missing role permissions from upgrade prompts, quota failures, and rule denials.

## Install

From a checkout:

```bash
python3 -m pip install -e .
```

YAML matrix files are optional:

```bash
python3 -m pip install -e ".[yaml]"
```

## Quick Start

```python
from pyrule import AuthorizationEngine, Matrix

matrix = Matrix.from_dict({
    "permissions": {
        "project.create": {"limit": "projects.max"},
        "project.read": {},
        "project.update": {},
        "export.csv": {"feature": "export.csv"},
    },
    "roles": {
        "admin": {"grants": ["project.*", "export.csv"]},
        "viewer": {"grants": ["project.read"]},
    },
    "plans": {
        "free": {
            "features": {"export.csv": False},
            "limits": {"projects.max": 3},
        },
        "pro": {
            "features": {"export.csv": True},
            "limits": {"projects.max": 50},
        },
    },
    "rules": [
        {
            "name": "project_scope_required",
            "action": "project.*",
            "require": "resource_in_scope",
        },
    ],
})

engine = AuthorizationEngine(
    matrix=matrix,
    role_provider=lambda actor, scope: ["admin"],
    plan_provider=lambda scope: "pro",
    usage_provider=lambda key, actor, scope, resource, context: 12,
    predicates={
        "resource_in_scope": lambda actor, scope, resource, context: (
            resource is None or resource.tenant_id == scope.id
        ),
    },
)

decision = engine.check(user, "project.create", scope=tenant)
assert decision.allowed
```

## Documentation

- [Quick Start](docs/quickstart.md)
- [Matrix Schema](docs/schema.md)
- [Decisions](docs/decisions.md)
- [Rules](docs/rules.md)
- [SaaS Examples](docs/saas-examples.md)
- [Using pyrule With pyscoped](docs/pyscoped.md)

## Core Ideas

- Permissions describe actions such as `project.create` or `export.csv`.
- Roles grant permissions to actors inside a scope.
- Plans grant subscription features and numeric limits to a tenant or account.
- Rules apply host-application predicates after the basic role, feature, and limit checks pass.
- Decisions keep structured denial reasons for UI, logs, and audits.

## Runtime Dependencies

The core package uses the Python standard library. YAML support is optional through `pyrule[yaml]`.

## Testing

```bash
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=src python3 -m unittest discover -s tests
```
