The shared Rust crates every FerrLabs API is built on.
Auth, permissions, database, errors, telemetry, billing, queues.
Written once here, consumed everywhere, never copy-pasted between products.
23 crates, all real code in production use. Versions are independent, each published to crates.io.
| Crate | Role |
|---|---|
auth |
JWT, sessions, password hashing (argon2id), TOTP |
oauth |
Authorization-code clients, PKCE S256 with CSRF state: fixed providers (Google, GitHub, Discord) and per-tenant OIDC issuers discovered at runtime, with id_token validation and cached JWKS |
github |
GitHub App auth: scoped installation access tokens, and verifying a user actually owns the installation they are claiming |
permissions |
Typed scope and capability checks. A closed enum of every scope on the platform, so adding one is a crate change rather than a typo in a string literal |
id |
Typed id newtypes over UUID, turning cross-tenant and IDOR mistakes into compile errors |
types |
Shared domain types: User, Organization, Membership, Plan, and contact::ContactRequest, the contact-form contract between FerrLabs-Cloud and FerrTrack |
license |
Offline ed25519-signed license keys for self-host editions: mint, verify, gate |
| Crate | Role |
|---|---|
db |
Postgres pool, transaction helpers, migration runner |
cache |
Shared Valkey pool and config |
queue |
Postgres-backed durable job queue: SKIP LOCKED, LISTEN/NOTIFY, retries, idempotency |
audit |
Append-only audit log with typed actions and actors |
| Crate | Role |
|---|---|
errors |
Error types, domain error codes, axum IntoResponse |
middleware |
Rate limit, CORS, request ID, security headers |
ratelimit |
Token-bucket limiting and trusted-proxy client-IP extraction |
http |
Outbound client with SSRF defenses: IP allowlist, DNS pinning, redirect re-checks, bounded body and deadline |
api-version |
Date-based contract versioning, rendering older shapes to older clients |
webhooks |
Inbound HMAC-SHA256 verification and idempotent delivery dedup |
| Crate | Role |
|---|---|
crypto |
Envelope encryption and GCP Cloud KMS integration |
vault |
HashiCorp Vault KV v2 client |
billing |
Stripe customers, subscriptions, webhooks |
telemetry |
Tracing and OTLP setup, Prometheus metrics, product analytics event registry |
testkit |
Ephemeral Postgres for integration tests, via testcontainers |
Every crate is published to crates.io under MIT OR Apache-2.0:
[dependencies]
ferrlabs-auth = "2"
ferrlabs-db = "2"
ferrlabs-errors = "2"Consumed by the FerrVault, FerrTrack, FerrGrowth, FerrFleet, FerrLens and FerrLabs-Cloud APIs.
FerrGames takes leaf crates only (api-version, mail) and none of the shared identity, data
or error model, because its gameplay is stateful and real-time over WebSocket.
Renovate updates them through the ferrlabs-* rule in the shared preset. The version in a
product's Cargo.toml is only a floor, so compare against its Cargo.lock.
If a product needs something a crate almost does, add it here in its own PR, then consume it. Copying a struct or a function into a product API is not an option, including as a temporary measure, because the migration back never happens.
users, organizations, memberships and subscriptions live in crates/db/migrations/ and
are applied by ferrlabs-db::migrate_shared. Product tables (releases, secrets, issues, runs)
live in each product API's own migrations and version independently.
cargo check
cargo test
cargo clippy -- -D warnings
cargo fmt --checkLicensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.