https://github.com/rawkode/prescience
An idiomatic Rust client library for SpiceDB
https://github.com/rawkode/prescience
Last synced: about 2 months ago
JSON representation
An idiomatic Rust client library for SpiceDB
- Host: GitHub
- URL: https://github.com/rawkode/prescience
- Owner: rawkode
- Created: 2026-02-19T16:48:34.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-02-19T20:14:06.000Z (3 months ago)
- Last Synced: 2026-04-04T07:59:13.520Z (about 2 months ago)
- Language: Rust
- Size: 129 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Prescience
An idiomatic Rust client library for [SpiceDB](https://authzed.com/spicedb), the open-source, Google Zanzibar-inspired authorization system.
## Features
- **Type-safe**: Wraps the SpiceDB gRPC API with idiomatic Rust types — no raw protobufs
- **Async-first**: Built on [tonic](https://github.com/hyperium/tonic) and tokio
- **3-state permissions**: `PermissionResult` correctly models `Allowed`, `Denied`, and `Conditional` (caveated) outcomes
- **Streaming**: All streaming RPCs return `impl Stream>`
- **Shareable**: `Client` is `Clone + Send + Sync` — clone it freely across tasks
- **Feature-gated**: `watch`, `experimental`, `serde`, TLS backends
## Quick Start
```rust
use prescience::{Client, ObjectReference, SubjectReference, Consistency, PermissionResult};
#[tokio::main]
async fn main() -> Result<(), prescience::Error> {
let client = Client::new("http://localhost:50051", "my-token").await?;
let result = client
.check_permission(
&ObjectReference::new("document", "doc-123")?,
"view",
&SubjectReference::new(ObjectReference::new("user", "alice")?, None::)?,
)
.consistency(Consistency::FullyConsistent)
.await?;
match result {
PermissionResult::Allowed => println!("access granted"),
PermissionResult::Denied => println!("access denied"),
PermissionResult::Conditional { missing_fields } => {
println!("need caveat context: {:?}", missing_fields);
}
}
Ok(())
}
```
## Writing Relationships
```rust
use prescience::{Client, ObjectReference, SubjectReference, Relationship, RelationshipUpdate};
# async fn example(client: &Client) -> Result<(), prescience::Error> {
let token = client
.write_relationships(vec![
RelationshipUpdate::create(Relationship::new(
ObjectReference::new("document", "doc-123")?,
"viewer",
SubjectReference::new(ObjectReference::new("user", "bob")?, None::)?,
)),
])
.await?;
// Use the token for subsequent reads
let result = client
.check_permission(
&ObjectReference::new("document", "doc-123")?,
"view",
&SubjectReference::new(ObjectReference::new("user", "bob")?, None::)?,
)
.consistency(prescience::Consistency::AtLeastAsFresh(token))
.await?;
# Ok(())
# }
```
## Streaming Lookups
```rust
use tokio_stream::StreamExt;
# async fn example(client: &prescience::Client) -> Result<(), prescience::Error> {
let subject = prescience::SubjectReference::new(
prescience::ObjectReference::new("user", "alice")?,
None::,
)?;
let mut stream = client
.lookup_resources("document", "view", &subject)
.consistency(prescience::Consistency::FullyConsistent)
.send()
.await?;
while let Some(result) = stream.next().await {
let item = result?;
println!("resource: {}, permission: {:?}", item.resource_id, item.permission);
}
# Ok(())
# }
```
## Feature Flags
| Feature | Default | Description |
|---------|---------|-------------|
| `watch` | No | WatchService for streaming relationship changes |
| `experimental` | No | Bulk APIs: BulkCheckPermission, BulkImport/Export |
| `serde` | No | Serialize/Deserialize on ZedToken and domain types |
| `tls-rustls` | No | Use rustls for TLS |
| `tls-native` | No | Use native/system TLS |
## Error Handling
All methods return `Result`. The error type provides:
- **Structured matching**: `Error::Transport`, `Error::Status`, `Error::InvalidArgument`, etc.
- **Retryability**: `error.is_retryable()` returns `true` for `UNAVAILABLE` and `DEADLINE_EXCEEDED`
- **gRPC code access**: `error.code()` returns the gRPC status code
## Development
This project uses [devenv](https://devenv.sh) for a reproducible development environment:
```bash
# Enter the dev shell (provides Rust, protoc, SpiceDB)
devenv shell
# Build
cargo build --all-features
# Test
cargo test --all-features
# Lint
cargo clippy --all-features -- -D warnings
# Start a local SpiceDB for integration testing
spicedb serve --grpc-preshared-key "test-key" --datastore-engine memory
```
## License
Apache-2.0