No project description provided
Project description
🛡️ GuardNet
GuardNet is a graph-based, type-safe ReBAC (Relationship-Based Access Control) engine for Python 3.11+.
Inspired by distributed state machine patterns, GuardNet allows you to model complex authorization logic as a directed graph of Python classes. It solves the "spaghetti if-statement" problem in authorization by using recursive delegation, short-circuiting logical gates, and request-scoped memoization.
✨ Key Features
- Code as Truth: Policies are standard Python classes. No custom DSLs, JSON, or YAML logic.
- Context Awareness: Use Pydantic models to define exactly what data is needed for a specific check.
- Relationship-Based (ReBAC): Easily model inheritance (e.g., Document -> Folder -> Organization) using the
Delegatepattern. - Memoization: Identical checks within the same request context are executed only once, saving database overhead.
- Short-Circuiting:
AnyOf(OR) andAllOf(AND) gates stop execution as soon as a result is determined. - Static Validation: Detect circular dependencies and connectivity issues in your authorization graph before you deploy.
🚀 Quick Start
1. Define your Context and Nodes
Nodes are the building blocks of your policy. They receive a typed context and return a Decision.
from pydantic import BaseModel
from guardnet import GuardNode, Effect, AnyOf, PolicyEngine
class AuthCtx(BaseModel):
user_id: str
resource_id: str
class IsAdmin(GuardNode[AuthCtx]):
async def evaluate(self, ctx: AuthCtx):
# Direct boolean logic
return Effect.ALLOW if ctx.user_id == "admin-1" else Effect.DENY
class IsOwner(GuardNode[AuthCtx]):
async def evaluate(self, ctx: AuthCtx):
# You can perform async DB calls here
return Effect.ALLOW if ctx.resource_id == "owner-res" else Effect.DENY
class RootPolicy(GuardNode[AuthCtx]):
async def evaluate(self, ctx: AuthCtx):
# Logical composition with short-circuiting
return AnyOf(branches=[IsAdmin, IsOwner])
2. Execute the Check
The PolicyEngine manages the evaluation and handles request-scoped caching.
engine = PolicyEngine(nodes=[RootPolicy, IsAdmin, IsOwner])
allowed = await engine.check(
start_node=RootPolicy,
context=AuthCtx(user_id="user-1", resource_id="owner-res")
)
if allowed:
print("Access Granted!")
🛠️ Advanced: ReBAC and Inheritance
GuardNet shines when resources inherit permissions from parents. Use Delegate to switch contexts mid-evaluation.
class CheckDocument(GuardNode[DocCtx]):
async def evaluate(self, ctx: DocCtx):
# Look up the parent folder ID
parent_id = await db.get_parent_folder(ctx.doc_id)
# Delegate checking to the Folder policy with a new context
return Delegate(
node_cls=CheckFolder,
sub_context=FolderCtx(user_id=ctx.user_id, folder_id=parent_id)
)
🔍 Static Analysis
Prevent infinite loops or broken logic in your security graph by validating it at startup or in CI/CD.
from guardnet import GraphAnalyzer
# This will raise a RecursionError if a cycle is found
GraphAnalyzer.validate(RootPolicy, engine._registry)
⚖️ License
MIT
Project details
Release history Release notifications | RSS feed
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 guardnet-0.1.3.tar.gz.
File metadata
- Download URL: guardnet-0.1.3.tar.gz
- Upload date:
- Size: 4.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36a6e7432771daad5ae5bdfbafe9d26d9696ba6c82a56fd72f56cae737b0670a
|
|
| MD5 |
1519d2bd06d490cf577b2543ec88d857
|
|
| BLAKE2b-256 |
95af30ec8bd7c8c8a50e675f9e5498cc1a56cab7ff89073caa01c9d8de172245
|
File details
Details for the file guardnet-0.1.3-py3-none-any.whl.
File metadata
- Download URL: guardnet-0.1.3-py3-none-any.whl
- Upload date:
- Size: 5.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
41a0a8b67868b11166cebdad05488dc9ef1bd55027be02171423ae45ea9c9d70
|
|
| MD5 |
6ccf51df1305b5681b35c88a3f31a026
|
|
| BLAKE2b-256 |
d6b4874ac99658386dab9e262d9146afbfca11ad5436e5a9d3211e8e553d27d0
|