hodei-authz-postgres 0.1.0

PostgreSQL policy store adapter for Hodei authorization framework
Documentation
# hodei-authz-sdk-authz-postgres

PostgreSQL adapter for the Hodei authorization framework.

## Overview

`hodei-authz-sdk-authz-postgres` provides a production-ready PostgreSQL implementation of the `PolicyStore` trait from `hodei-authz-sdk-authz`. It handles policy persistence, CRUD operations, and includes database migrations.

## Features

- **PolicyStore Implementation**: Full CRUD for Cedar policies
- **Database Migrations**: Automatic schema management with sqlx
- **UUID Generation**: Unique policy identifiers
- **Error Handling**: Typed errors with detailed messages
- **Async/Await**: Built on tokio and sqlx

## Installation

```toml
[dependencies]
hodei-authz-sdk-authz-postgres = "0.1"
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres"] }
```

## Usage

### Basic Setup

```rust
use hodei_postgres::PostgresPolicyStore;
use hodei_authz::PolicyStore;
use sqlx::PgPool;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create database connection pool
    let pool = PgPool::connect("postgres://user:pass@localhost/db").await?;
    
    // Create policy store
    let store = PostgresPolicyStore::new(pool);
    
    // Run migrations
    store.migrate().await?;
    
    Ok(())
}
```

### Creating Policies

```rust
use hodei_authz::PolicyStore;

let policy_content = r#"
permit(
    principal == User::"alice",
    action == Action::"read",
    resource
);
"#;

let policy_id = store.create_policy(policy_content.to_string()).await?;
println!("Created policy: {}", policy_id);
```

### Loading Policies

```rust
use hodei_authz::PolicyStore;

// Load all policies as a Cedar PolicySet
let policy_set = store.load_all_policies().await?;

// Use with Cedar Authorizer
use cedar_policy::{Authorizer, Request, Entities};

let authorizer = Authorizer::new();
let decision = authorizer.is_authorized(&request, &policy_set, &entities);
```

### CRUD Operations

```rust
use hodei_authz::PolicyStore;

// Get a policy
let policy = store.get_policy(&policy_id).await?;

// List all policies
let policies = store.list_policies().await?;
for (id, content) in policies {
    println!("{}: {}", id, content);
}

// Update a policy
store.update_policy(&policy_id, new_content).await?;

// Delete a policy
store.delete_policy(&policy_id).await?;
```

## Database Schema

The migration creates the following table:

```sql
CREATE TABLE policies (
    id TEXT PRIMARY KEY,
    content TEXT NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP
);
```

## Migrations

Migrations are embedded in the binary and run automatically:

```rust
let store = PostgresPolicyStore::new(pool);
store.migrate().await?;
```

## Error Handling

```rust
use hodei_authz::PolicyStoreError;

match store.get_policy("invalid-id").await {
    Ok(Some(policy)) => println!("Found: {}", policy),
    Ok(None) => println!("Not found"),
    Err(PolicyStoreError::Database(e)) => eprintln!("DB error: {}", e),
    Err(PolicyStoreError::NotFound(id)) => eprintln!("Policy {} not found", id),
    Err(e) => eprintln!("Error: {}", e),
}
```

## Testing

Integration tests require a running PostgreSQL instance:

```bash
# Start PostgreSQL
docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:15

# Run tests
DATABASE_URL="postgres://postgres:postgres@localhost/test" cargo test -- --ignored
```

## License

MIT OR Apache-2.0