decide-core 0.1.1

A fast, lightweight permission engine for Rust and TypeScript with condition support.
Documentation
# Decide
---
**A tiny and fast permission engine for Rust.**

Define roles and permissions with simple logic like `user_id == resource_owner`. Done.

## Features

- 🦀 Written in pure Rust (zero dependencies for the core logic)
- 💡 Declarative permission checks using embedded expressions (via [Rhai]https://rhai.rs)
- 🧱 Define your roles + permissions in JSON
- 📦 Also powers a JS/TS SDK via NAPI — cross-platform ready

## Table of Contents
- [Installation]#installation
- [Quickstart]#quickstart
- [File-Based Config (Optional, but Recommended)]#file-based-config-(optional,-but-recommended)
- [Expressions]#expressions
- [Error Handling]#error-handling
- [Structs]#structs

## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
decide-core = "0.1.1"
```

## Quickstart
```rust
use decide_core::types::{User, Resource, RoleMap};
use decide_core::evaluator::Decide;

fn main() {
    let roles_json = r#"
    {
        "editor": {
            "name": "editor",
            "permissions": [
                { "action": "edit_post", "condition": "user_id == resource_owner" },
                { "action": "like_post", "condition": null }
            ]
        }
    }
    "#;

    let user_json = r#"
    {
        "id": "123",
        "roles": ["editor"]
    }
    "#;

    let resource_json = r#"
    {
        "owner_id": "123",
        "resource_name": "hello-world",
        "resource_type": "post"
    }
    "#;

    let role_map: RoleMap = serde_json::from_str(roles_json).unwrap();
    let user: User = serde_json::from_str(user_json).unwrap();
    let resource: Resource = serde_json::from_str(resource_json).unwrap();

    let decide = Decide::new(role_map);
    let allowed = decide.can(&user, "edit_post", &resource).unwrap();

    println!("Can edit? {}", allowed); // true
}
```

## File-Based Config (Optional, but Recommended)
```rust
let decide = Decide::from_file("config_file.json").unwrap();
// or use default "decide.config.json" from root:
let decide = Decide::default().unwrap();
```

## Expressions
Conditions are written in a simple expression format using [Rhai](https://rhai.rs), a safe and embeddable scripting language.

Available fields:
- `user_id` => `user.id`
- `user_roles` => `user.roles`
- `resource_owner` => `resource.owner_id`
- `resource_name` => `resource.resource_name`
- `resource_type` => `resource.resource_type`

You can write things like:
```
condition: 'user_id == resource_owner'
condition: 'user_roles.contains("admin")'
condition: 'user_roles.contains("moderator") || user_id == resource_owner'
```

## Error Handling
`Decide::can()` returns a `Result<bool, DecideError>`. So you can check and handle errors as follows:
```rust
match decide.can(&user, "edit_post", &resource) {
    Ok(true) => println!("Access granted"),
    Ok(false) => println!("Access denied"),
    Err(e) => eprintln!("Error: {}", e),
}
```

## Structs
```rust
pub struct User {
    pub id: String,
    pub roles: Vec<String>,
}

pub struct Resource {
    pub owner_id: String,
    pub resource_name: String,
    pub resource_type: String,
}

pub struct Permission {
    pub action: String,
    pub condition: Option<String>,
}

pub struct Role {
    pub name: String,
    pub permissions: Vec<Permission>,
}

pub type RoleMap = HashMap<String, Role>;
```

## License
MIT