easy-auth-sdk 0.2.0

A simple JWT-based authentication SDK with RBAC support
Documentation
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Build and Test Commands

```bash
cargo build          # Build the library
cargo test           # Run all tests
cargo test <name>    # Run a specific test (e.g., cargo test test_rbac)
cargo clippy         # Lint
cargo fmt            # Format code
```

Note: Tests generate RSA keys at runtime, so they take a few seconds.

## Architecture

This is a Rust JWT authentication library (`easy-auth-sdk`) that validates RS256-signed tokens and provides RBAC checks.

### Core Design

```
EasyAuth (main struct)
    ├── from_jwks_json() / from_pem()  → Initialize with public keys
    └── validate(&token)               → Decode token → Returns Claims

Claims (JWT payload struct)
    ├── is_subject(sub)                → Check subject → Returns bool
    └── allowed_domain_roles(&[roles]) → Check roles → Returns bool
```

**Key principle**: `validate()` decodes the token once and returns `Claims`. Then `is_subject()` and `allowed_domain_roles()` operate on `Claims` directly, returning booleans for easy OR/AND logic:

```rust
// Allow if subject matches OR user has admin role
if claims.is_subject("user-123") || claims.allowed_domain_roles(&["admin"]) {
    // Access granted
}
```

### Module Structure

- `lib.rs` - `EasyAuth` struct and public API
- `claims.rs` - `Claims` struct (JWT payload: `sub`, `domain_roles`, `exp`, `iat`)
- `error.rs` - `AuthError` enum using `thiserror`
- `jwks.rs` - JWKS JSON parsing, converts JWK to `DecodingKey`

### JWT Claims Format

```json
{
  "sub": "user-uuid",
  "domain_roles": ["domain:role", "product.feature:permission"],
  "exp": 1699999999
}
```

- `domain_roles` uses exact string matching
- Hierarchical permissions encoded in strings (e.g., `product_a.feature_x:admin`)

### Error Categories

- Token errors (401): `TokenExpired`, `InvalidSignature`, `InvalidToken`, `MissingClaim`
- Config errors (500): `InvalidKey`, `JsonError`

## Coding Standards

- All code must pass `cargo fmt` and `cargo clippy -- -D warnings` (enforced by CI).
- Use conventional commit messages: `feat:`, `fix:`, `refactor:`, `chore:`, `docs:`. See @README.md Contributing section.

## CI/CD

- CI runs on push/PR to `main`: check, clippy, fmt, test. See @.github/workflows/ci.yml.
- Releases via release-please: conventional commits → auto PR → merge triggers publish to crates.io. See @.github/workflows/release.yml.