schlussel 0.5.0

Cross-platform OAuth 2.0 with PKCE for CLI applications
Documentation
# πŸ” Schlussel

> **Secure OAuth 2.0 for CLI applications** - Written in Rust, works everywhere πŸ¦€

OAuth authentication made simple for command-line tools. No more copying tokens or managing credentials manually!

---

## ✨ Features

πŸ”‘ **Multiple OAuth Flows**
- Device Code Flow (perfect for CLI!)
- Authorization Code Flow with PKCE
- Automatic browser handling

πŸ”’ **Secure by Default**
- OS credential manager integration (Keychain/Credential Manager)
- Cross-process token refresh locking
- Automatic token refresh

⚑ **Developer Friendly**
- Provider presets (GitHub, Google, Microsoft, GitLab, Tuist)
- One-line configuration
- Automatic expiration handling

🌍 **Cross-Platform**
- Linux, macOS, Windows
- x86_64 and ARM64

---

## πŸš€ Quick Start

### Installation

**Rust:**
```toml
[dependencies]
schlussel = "0.1"
```

**Swift Package Manager:**
```swift
.binaryTarget(
    name: "Schlussel",
    url: "https://github.com/tuist/schlussel/releases/download/0.5.0/Schlussel.xcframework.zip",
    checksum: "36c002746caa5c1af8c6edea751ad971c5b67940775dba398308207dc981e253"
)
```

### Authenticate with GitHub (3 lines!)

```rust
use schlussel::prelude::*;
use std::sync::Arc;

let storage = Arc::new(SecureStorage::new("my-app").unwrap());
let config = OAuthConfig::github("your-client-id", Some("repo user"));
let client = OAuthClient::new(config, storage);

// That's it! Opens browser, handles OAuth, returns token
let token = client.authorize_device().unwrap();
```

---

## πŸ“– Documentation

πŸ‘‰ **[Full Documentation](docs/README.md)**

Quick links:
- πŸƒ [Quick Start Guide]docs/quick-start.md
- πŸ”Œ [Provider Presets]docs/provider-presets.md - GitHub, Google, Microsoft, etc.
- πŸ’Ύ [Storage Options]docs/storage-backends.md - Secure, File, or Memory
- πŸ”„ [Token Refresh]docs/token-refresh.md - Automatic refresh strategies
- πŸ“± [Swift/iOS Integration]docs/swift-integration.md - XCFramework usage

---

## πŸ’‘ Why Schlussel?

### Before Schlussel 😫
```rust
// 50+ lines of boilerplate
// Manual token expiration checking
// Race conditions with multiple processes
// Plaintext tokens in files
// Complex OAuth flow management
```

### With Schlussel πŸŽ‰
```rust
// 3 lines total
let storage = Arc::new(SecureStorage::new("app").unwrap());
let config = OAuthConfig::github("client-id", Some("repo"));
let token = OAuthClient::new(config, storage).authorize_device().unwrap();
```

---

## 🎯 Use Cases

βœ… CLI tools that need GitHub/GitLab API access  
βœ… Build tools that integrate with cloud services  
βœ… Developer tools with OAuth authentication  
βœ… Cross-platform desktop applications  
βœ… CI/CD tools with secure credential management  

---

## πŸ—οΈ Architecture

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Your CLI App  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
    β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”
    β”‚ Schlusselβ”‚
    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
         β”‚
    β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  Storage Backend            β”‚
    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚ SecureStorage (OS Keyring)  β”‚ ← Recommended
    β”‚ FileStorage   (JSON files)  β”‚
    β”‚ MemoryStorage (In-memory)   β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

---

## 🌟 Highlights

### πŸ” Secure by Default
Tokens stored in **OS credential manager** (Keychain on macOS, Credential Manager on Windows, libsecret on Linux)

### 🎨 Provider Presets
```rust
OAuthConfig::github("id", Some("repo"))      // GitHub
OAuthConfig::google("id", Some("email"))     // Google
OAuthConfig::microsoft("id", "common", None) // Microsoft
OAuthConfig::gitlab("id", None, None)        // GitLab
OAuthConfig::tuist("id", None, None)         // Tuist
```

### ⚑ Automatic Token Refresh
```rust
let refresher = TokenRefresher::new(client);
let token = refresher.get_valid_token("key").unwrap();
// Auto-refreshes if expired!
```

### πŸ”„ Cross-Process Safe
Multiple processes can safely refresh the same token without race conditions

---

## πŸ“¦ Examples

Check out [examples/](examples/) for working code:

- πŸ™ [GitHub Device Flow]examples/github_device_flow.rs
- 🌐 [GitHub with Callback]examples/github_callback.rs
- πŸ”„ [Token Refresh]examples/token_refresh.rs
- ⚑ [Automatic Refresh]examples/automatic_refresh.rs
- πŸ” [Secure Storage]examples/secure_storage.rs
- πŸ”€ [Cross-Process Refresh]examples/cross_process_refresh.rs

---

## 🀝 Contributing

Contributions welcome! Please ensure:
- βœ… Tests pass: `cargo test`
- βœ… Code formatted: `cargo fmt`
- βœ… Clippy clean: `cargo clippy`

---

## πŸ“„ License

See [LICENSE](LICENSE) for details.

---

## πŸ”— Links

- πŸ“š [Documentation]docs/README.md
- πŸ› [Issues]https://github.com/tuist/schlussel/issues
- πŸ”„ [Changelog]CHANGELOG.md
- πŸ“– [API Docs]https://docs.rs/schlussel

---

**Made with πŸ’™ by the Tuist team**