Zeroth is a minimal first-party identity provider and social login broker.
It is intended to cover the Auth0-shaped role for owned products:
- hosted login
- upstream provider brokering
- OIDC authorization-code flow with PKCE
- Wavey-owned tokens and JWKS
- browser sessions
- native app login for Swift/iOS clients
wavey-id should become a deployment of Zeroth. Zeroth should stay generic:
no Wavey domains, provider credentials, branding, or deployment-specific
policy should live in these crates.
zeroth
crates/zeroth-core
crates/zeroth-oidc
crates/zeroth-providers
crates/zeroth-storage
crates/zeroth-server
crates/zeroth-cli
crates/zeroth-ui
crates/zeroth-worker
The crates are intentionally thin for now. They define the ownership boundaries
for extracting generic auth code from wavey-id and reworking hyper-idp
concepts into a persistent, deployable server.
The facade crate keeps the Leptos UI behind the optional ui feature so API and
Worker consumers do not pull UI dependencies by default.
zeroth-worker follows the existing Rust Cloudflare Worker shape in this repo:
worker-build produces build/worker/shim.mjs, and D1 is exposed through a
ZEROTH_DB binding.
Implemented so far:
- provider presets for Apple, Google, and Spotify
- OIDC authorization request parsing and registered-client validation
- native loopback redirect validation for Swift clients that use an ephemeral localhost callback port
- D1 schema for users, identities, clients, provider auth transactions, auth codes, refresh tokens, sessions, signing keys, and audit events
- Worker
/authorizeflow that stores provider transaction state in D1 before redirecting upstream, plusprompt=nonesilent SSO from an active Zeroth browser session - Worker hosted Leptos
/loginand/accountpages;/loginsupports browser-session login with client-boundedreturn_to, and/authorizerenders the provider picker when the OIDC request omitsprovider - Worker hosted Leptos
/adminand/admin/clientspage for provider readiness, D1 schema status, user list/disable/enable, audit events, and registered-client list/create/update operations through the generic management APIs, including a first-party Zeroth sign-in action for allowlisted admin sessions - Worker Apple App Site Association endpoint backed by deployment-provided JSON
- Worker
/readypublic launch preflight for HTTPS issuer, parseable signing material, and Apple/Google/Spotify provider configuration without D1 reads or secret disclosure - Worker JWKS publishing and token verification for the active ES256 signing key plus optional previous public ES256 keys during signing-key rotation
- CLI
signing-keygenerator for fresh Zeroth issuer keys and public JWKS rotation records - CLI
schemaexporter for generic D1 migrations and compatibility repair SQL, so deployments do not copyzeroth-storageschema details by hand - CLI
validate-secretchecks for Zeroth ES256 private keys, Apple PKCS #8 private keys, and previous public JWKS rotation JSON without printing secret material - Worker
/clientsmanagement API as the minimal Auth0-management replacement for registered-client create/update/list/disable, protected by either a deployment admin bearer token or an allowlisted Zeroth browser session, and backed by D1 - Worker
POST /__zeroth/db/ensureschema bootstrap endpoint protected by the same admin gate, applying unrecorded generic migrations, persisting migration history in D1, and repairing D1 compatibility columns exported byzeroth-storage - Worker
GET /__zeroth/db/statusread-only persistence preflight protected by the same admin gate, reporting required D1 tables, migrations, compatibility columns, and registered-client count without slowing public/ready - Worker
/usersand/providers/statusmanagement APIs for bounded user inspection, reversible user disable/enable with session/refresh-token revocation, and provider configuration readiness without exposing secrets - Worker
/eventsmanagement API, D1 audit persistence, and hosted admin filters for bounded Auth0-style event inspection without storing token values or provider secrets - Worker
/oauth2/callbackparsing for query callbacks and Appleform_post, with D1 transaction lookup, browser transaction-cookie binding, conditional one-time transaction consumption before provider token exchange, and replay rejection - Provider-side callback errors such as user cancellation redirect back to the stored OIDC, browser-login, or identity-link return URL with error details and original app state
- Spotify profile fetch and D1 user/identity upsert
- Google/Apple RS256 ID-token verification against provider JWKS and D1 user/identity upsert from verified OIDC claims
- provider callback completion that either creates a D1-backed browser session
and returns to the hosted-login
return_toURL, or issues a hashed Zeroth authorization code and redirects back to the registered OIDC client with the original app state plus Zeroth'sissauthorization response parameter - client-bound authorization error redirects after registered redirect URI
validation, so relying apps receive
error, original app state, andissinstead of JSON for OIDC request failures that are safe to redirect - Worker
/oauth/tokenauthorization-code validation for public PKCE clients and confidential clients, including registered-client lookup, client-secret verification, code lookup, expiry/reuse checks, redirect URI matching, S256code_verifiervalidation when the authorization code used PKCE, and conditional one-time D1 code consumption before credentials are minted - registered-client CORS/preflight support for browser calls to token, revocation, introspection, userinfo, session, sessions, profile, identities, validate, and logout endpoints
- ES256 Zeroth-owned access/ID token issuance, standard scoped OIDC ID-token
claims for
email/profile, session-boundsidclaims, refresh-token persistence foroffline_access, and Worker/.well-known/jwks.json - OIDC discovery metadata for query-mode code responses, rejection of
unsupported downstream
response_modevalues, theauthorization_response_iss_parameter_supportedflag, Zeroth-owned issuer/JWKS endpoints for native and browser clients, OAuth Authorization Server metadata at/.well-known/oauth-authorization-server, andauth_timeclaims for clients that usemax_age - refresh-token grant exchange with rotation and fresh Zeroth token issuance;
auth-code-issued refresh tokens are bound to the browser session that created
the code, preserve original
auth_time, require conditional D1 rotation to win before a replacement token is issued, and supportprompt=nonesilent SSO withmax_agefreshness checks - refresh-token replay detection that revokes the active session-scoped token family when a rotated token is presented again by the same client
- Worker
/oauth/revokerefresh-token revocation for registered clients - Worker
/oauth/introspectfor RFC7662-style access-token and same-client refresh-token introspection by confidential clients, returning inactive responses without exposing token values; session-bound access tokens introspect as inactive when their D1 session is missing, revoked, expired, or mismatched - Worker
/userinfowith ES256 bearer access-token verification and D1-backed scoped profile response; disabled users or disabled/missing token clients are rejected from D1 before profile data is returned, and session-bound access tokens require the referenced browser session to still be active - Worker browser sessions with D1 persistence, secure session cookies,
/session,/sessions,/profile,/identities, and/logout; session revocation also revokes that session's refresh-token family - Worker OIDC
end_session_endpointmetadata and bounded post-logout redirects through/logout - Worker
PATCH /profilefor bounded local display-name and picture updates - Worker
/identities/linkfor session-bound provider linking through Apple, Google, or Spotify, with client-bounded return URLs and callback completion - Worker
DELETE /identitiesfor guarded linked-identity unlinking without allowing removal of the last login method - Worker
/validatefor bearer access-token and browser-session validation against active D1 users, registered clients, and active D1 sessions when the access token carries asid - Leptos account/login UI for hosted provider choice, profile management, linked identities, sessions, and compact OIDC application inventory
- Worker CPU-budget guardrails for the 10 ms Free-plan target: cached ES256 signing material/JWKS, cached Apple/Google provider JWKS, bounded session and identity lists, indexed list queries, bounded request-path cleanup, and bounded CORS origin scans
- CLI minting of Sign in with Apple client-secret JWTs from Apple team/key/client configuration without mutating Apple Developer records
- Worker runtime minting and isolate caching of Sign in with Apple client-secret JWTs from deployment-provided Apple team/key/private-key secrets
Still required before Auth0 can be removed:
- deployment-specific Wavey/Bitneedle Apple Developer identifier setup
- real Apple, Google, and Spotify OAuth client IDs/secrets in the
wavey-iddeployment - a real Cloudflare D1 database ID, schema application, and Wavey client
seed or
/clientsmanagement upsert - relying app cutover to Zeroth issuer, client IDs, redirect URIs, and JWKS
- crates.io ownership for the root
zerothcrate name. As of 2026-06-04, crates.io already haszeroth = 0.0.0owned byjason-yau; the split crate names such aszeroth-core,zeroth-oidc, andzeroth-workerare not claimed by search, but the root name needs transfer or an owner invite before publish.
The root crate should remain named zeroth, but the name is currently occupied
on crates.io by an unrelated placeholder. Until ownership is transferred, publish
only the split crates.
Publish order matters because crates.io verifies versioned dependencies against already-published packages:
cargo publish -p zeroth-core
cargo publish -p zeroth-providers
cargo publish -p zeroth-oidc
cargo publish -p zeroth-storage
cargo publish -p zeroth-server
cargo publish -p zeroth-ui
cargo publish -p zeroth-cli
cargo publish -p zeroth-workerAfter the root name is transferred:
cargo publish -p zeroth