Metadata-Version: 2.4
Name: tagth
Version: 1.1.1
Summary: Pure Python Stateless Tag-Based Authorization Library
Project-URL: Homepage, https://github.com/scartill/tagth
Author-email: Boris Resnick <boris.resnick@gmail.com>
License: MIT License
        
        Copyright (c) 2025 Boris Resnick
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Requires-Python: >=3.8
Description-Content-Type: text/markdown

# Stateless Tag-Based Authorization Library

## Background

Traditional role-based authorization models are not flexible enough to cover all required use cases. On the other side, full-managed ACLs are too complex for account managers to handle. `tagth` is a simple and flexible authorization model that can be easily implemented and maintained.

## Tag-Based Authorization

A lightweight model that is based on three concepts:
* a principal and its associated tags,
* a resource and its associated tags,
* an action.

The model adheres to the following principles:
* the model is stateless and purely functional, and it has no internal persistence,
* the model does not interpret the tags or actions, besides the special values,
* the model produces a binary result: either the action is allowed or not.

### Principal and Principal Tags

A Principal is an acting entity. A Principal can be a user, a role, a group, or any other entity that can perform actions.

Principal’s auth tag string looks like a comma-separated list of tags: `tag_one, tag_two, tag_three`. Each tag should be a string that is a valid Python identifier.

A supertag is a tag that is a prefix of another tag. For example, `admin` is a supertag of `admin_user`.

A principal is said to possess a tag if the tag or its supertag exists in the principal’s auth tag string.

Special values:
* `void` (can only access resources with `anyone` access, see below),
* `root` (unlimited access).

### Resource and Resource Tags

A Resource is an object that can be accessed by a Principal. A Resource can be a user, a channel, a source asset, an extension, a tenant, a campaign, etc.

A resource tag is a string that is a valid Python identifier. *NB: there is no such thing as a supertag for a resource tag.*

An action is a string that is a valid Python identifier. A superaction is an action that is a prefix of another action. For example, `create` is a superaction of `create_asset`.

Resource auth tag string looks like a comma-separated of colon-separarted pairs of tags and actions: `tag_one:read, tag_two:write` (tags with associated actions).

An action is allowed for a principal if it possesses:
* a tag that is associated with the action
* a tag that is associated with the superaction of the action
* the `root` tag

Special values:
* `anyone` resource tag (any principal is allowed to perform action).
* `all` action (all action are allowed).

### Access Resolution

The model makes a decision based on the following three values **only**:
* the principal’s auth tag string
* the resource’s auth tag string
* the action to be performed

The resolution is binary: either the action is allowed or not.

## Examples

### Basic Usage

```python
from tagth import allowed

# A regular user with basic permissions
principal_tags = 'user, content'
resource_tags = 'content:read, metadata:write'

# Check if user can read content
allowed(principal_tags, resource_tags, 'read')  # Returns True
# Check if user can delete content
allowed(principal_tags, resource_tags, 'delete')  # Returns False

# Root user has unlimited access
principal_tags = 'root'
allowed(principal_tags, resource_tags, 'anything')  # Returns True

# Void user can only access 'anyone' resources
void_tags = 'void'
allowed(void_tags, 'anyone:read', 'read')  # Returns True
allowed(void_tags, 'content:read', 'read')  # Returns False
```

### Supertags and Superactions

```python
# Principal tags can be supertags
principal_tags = 'admin'
resource_tags = 'admin_user:write, admin_content:delete'

# 'admin' is a supertag of 'admin_user' and 'admin_content'
allowed(principal_tags, resource_tags, 'write')  # Returns True
allowed(principal_tags, resource_tags, 'delete')  # Returns True

# Actions can have superactions
principal_tags = 'content'
resource_tags = 'content:create'

# 'create' is a superaction of 'create_asset'
allowed(principal_tags, resource_tags, 'create_asset')  # Returns True
```

### Special Values

```python
# 'anyone' resource tag allows access to all principals
principal_tags = 'basic_user'
resource_tags = 'anyone:read'
allowed(principal_tags, resource_tags, 'read')  # Returns True

# 'all' action allows all actions
principal_tags = 'content'
resource_tags = 'content:all'
allowed(principal_tags, resource_tags, 'read')  # Returns True
allowed(principal_tags, resource_tags, 'write')  # Returns True
```
