Skip to content

Releases: EmagjbyLabs/nythos

nythos-core v0.2.1

07 Jun 20:43
1f2b745

Choose a tag to compare

Summary

nythos-core v0.2.1 introduces the domain-level OAuth foundation for Nythos.

This release adds the core OAuth provider model, tenant-scoped external identities, tenant OAuth provider configuration, verified external profile boundaries, OAuth-specific ports, and decision-first OAuth login/linking orchestration.

The release keeps nythos-core infrastructure-free. Provider redirects, PKCE, authorization code exchange, token validation, JWKS fetching, userinfo calls, secrets, cookies, HTTP routes, and runtime/framework integration remain outside core.

Highlights

  • Added OAuth provider modeling:

    • OAuthProviderKind
    • Supported providers: Google, GitHub, Microsoft
    • Stable lowercase persistence strings
    • Parsing and display support
  • Added external identity domain modeling:

    • ExternalIdentity
    • Tenant-scoped provider identity links
    • Natural key: (tenant_id, provider_kind, provider_subject)
    • Provider email and display name metadata
    • linked_at and last_seen_at timestamps
    • Explicit touch(now) support for successful provider login tracking
  • Added tenant OAuth provider configuration:

    • TenantOAuthProviderConfig
    • Provider enabled/disabled flag
    • Registration allowed/disallowed flag
    • No secrets, client IDs, URLs, JWKS endpoints, redirect URIs, or provider HTTP configuration in core
  • Added verified external profile boundary:

    • VerifiedExternalProfile
    • Represents gateway-verified provider profile data
    • verified_email() exposes email only when the provider has verified it
    • Unverified email remains metadata only and is not safe for account-linking decisions
  • Added new OAuth ports:

    • ExternalIdentityRepository
    • TenantOAuthProviderConfigPort
  • Added OAuth login/linking orchestration:

    • OAuthLoginService::resolve_login
    • OAuthLoginService::link_identity
    • OAuthLoginOutcome
  • Added explicit OAuth login outcomes:

    • ProviderDisabled
    • ExistingIdentityLogin
    • LinkRequired
    • RegistrationRequired
  • Added OAuth-specific error variants:

    • OAuthIdentityAlreadyLinked
    • OAuthIdentityAlreadyLinkedToSelf
    • UserNotFoundOrInactive
  • Added tests for:

    • OAuth domain models
    • External identity repository contract
    • Tenant OAuth provider config port contract
    • OAuth login resolution
    • Explicit external identity linking
    • Public exports
    • Error variants
  • Added documentation for the OAuth core/gateway boundary.

Why this changed

Nythos needs OAuth support without pulling provider mechanics into nythos-core.

OAuth itself requires infrastructure concerns: redirects, HTTP calls, token exchange, JWKS validation, PKCE, secrets, cookies, callback routes, and provider-specific behavior. Those belong in nythos-gateway or adapter layers.

This release gives core the domain model and decision boundary instead:

  1. Gateway verifies provider data.
  2. Gateway constructs VerifiedExternalProfile.
  3. Core resolves the tenant-scoped auth decision.
  4. Gateway decides how to complete UX, linking, registration, or session issuance.

This keeps the core crate clean, portable, testable, and runtime-agnostic.

Important behavior

OAuthLoginService::resolve_login is decision-first.

It does not:

  • create users
  • link identities
  • issue sessions
  • perform provider verification
  • inspect unverified email
  • cross tenant boundaries

It only returns the next domain outcome.

OAuthLoginService::link_identity is explicit.

It should be called only after gateway obtains user consent. It validates that the target user exists and can authenticate, checks for duplicate provider identity links, persists the external identity, and returns the linked identity.

Core/gateway boundary

nythos-core owns:

  • OAuth provider domain types
  • tenant OAuth provider configuration shape
  • verified profile boundary type
  • external identity domain model
  • repository port contracts
  • login/linking decisions
  • account status checks
  • tenant-scoped auth rules

nythos-gateway owns:

  • OAuth redirects
  • OAuth state / CSRF
  • PKCE
  • authorization code exchange
  • provider token exchange
  • provider ID token validation
  • JWKS fetching
  • provider userinfo fetching
  • client secrets
  • cookies
  • HTTP routes
  • framework/runtime integration
  • database schema and migrations
  • session issuance after core returns an outcome
  • OAuth registration UX and completion

Compatibility

This is an additive patch release from 0.2.0 to 0.2.1.

  • No existing public APIs were removed.
  • No existing service constructors were changed.
  • No existing port methods were changed.
  • No runtime, framework, database, or OAuth provider dependencies were added.
  • Existing email/password registration, login, refresh, revoke, session, and RBAC flows remain unchanged.

New public API surface

New domain types:

  • OAuthProviderKind
  • ExternalIdentity
  • TenantOAuthProviderConfig
  • VerifiedExternalProfile

New auth types:

  • OAuthLoginOutcome
  • OAuthLoginService

New ports:

  • ExternalIdentityRepository
  • TenantOAuthProviderConfigPort

New errors:

  • OAuthIdentityAlreadyLinked
  • OAuthIdentityAlreadyLinkedToSelf
  • UserNotFoundOrInactive

nythos-core v0.2.0

07 Jun 12:57
e6d5226

Choose a tag to compare

Summary

nythos-core v0.2.0 adds the identity profile and login identifier foundation.

This release introduces optional username and display-name support, tenant-policy-gated profile fields, and identifier-based login while keeping email/password accounts intact and preserving the core crate’s infrastructure-free boundary.

OAuth is not part of this release.

Highlights

Added new domain value objects:
    Username
    DisplayName
    LoginIdentifier

Added typed tenant auth policy:
    TenantAuthPolicy
    username_registration_enabled
    display_name_registration_enabled
    username_login_enabled

Added TenantPolicyPort for loading tenant auth policy inside core services.

Extended User with optional profile fields:
    username: Option<Username>
    display_name: Option<DisplayName>

Extended NewUser with optional profile fields while preserving NewUser::new(email).

Extended RegisterInput with optional raw profile input:
    username: Option<String>
    display_name: Option<String>

Updated RegisterService to enforce tenant profile policy:
    username registration is accepted only when enabled
    display-name registration is accepted only when enabled
    duplicate username checks are tenant-scoped
    email/password registration still works with default policy when no profile fields are supplied

Moved LoginInput toward identifier-based login:
    preserved LoginInput::new(..., email: String, ...)
    added LoginInput::new_with_identifier(...)
    added identifier()
    preserved email() as a compatibility alias

Updated LoginService to support LoginIdentifier:
    email login uses find_credentials_by_email
    username login uses find_credentials_by_username only when enabled
    disabled username login returns InvalidCredentials
    username credential lookup is not called when username login is disabled

Evolved UserRepository with username lookup methods:
    find_by_username
    find_credentials_by_username

Added ADR 0006 documenting login identifiers and optional profile fields.

Updated README and core docs for v0.2.0 behavior.

Why this changed

Nythos needs a foundation for richer identity profiles and future product-facing login options without weakening the core auth boundary.

Email remains the required credential identity for email/password accounts. Username and display name are optional profile fields. Username-based login is available only when a tenant explicitly enables it through TenantAuthPolicy.

This release keeps policy decisions visible in the service layer. Services parse LoginIdentifier, load tenant auth policy through TenantPolicyPort, and then call explicit repository methods. Repositories resolve concrete lookup keys only.

This avoids a vague find_credentials_by_identifier-style repository method where parsing, policy checks, and lookup behavior would be hidden behind one swampy abstraction.

Security behavior

Username login is disabled by default.

When username login is disabled, LoginService returns AuthError::InvalidCredentials and does not call username credential lookup.

The following cases intentionally collapse to the same public error:

username login disabled
username not found
wrong password

This prevents callers from using login responses to discover whether username login is enabled or whether a tenant-scoped username exists.

Breaking API shape changes

This release includes public API shape changes for port implementors and service constructors.

UserRepository implementors must now implement:

async fn find_by_username(
&self,
tenant_id: TenantId,
username: &Username,
) -> NythosResult<Option>;

async fn find_credentials_by_username(
&self,
tenant_id: TenantId,
username: &Username,
) -> NythosResult<Option>;

RegisterService::new now requires a TenantPolicyPort dependency.

LoginService::new now requires a TenantPolicyPort dependency.

Example:

let register_service = RegisterService::new(
&user_repository,
&tenant_policy_port,
&session_store,
&password_hasher,
&token_signer,
);

let login_service = LoginService::new(
&user_repository,
&role_repository,
&tenant_policy_port,
&session_store,
&password_hasher,
&token_signer,
);

Compatibility notes

Email/password registration still works with the default tenant auth policy when no optional profile fields are supplied.
LoginInput::new(..., email: String, ...) is preserved.
LoginInput::email() is preserved as a compatibility alias returning the raw identifier string.
LoginInput::new_with_identifier(...) is available for email-or-username login input.
User::new(...) and User::with_status(...) are preserved and set optional profile fields to None.
NewUser::new(email) is preserved and sets optional profile fields to None.
TenantSettings remains available, but it is not used for auth policy decisions.
TenantAuthPolicy defaults all optional profile and username-login features to false.
No HTTP, database, gateway, worker, OAuth, Cloudflare, or concrete crypto dependency was added to nythos-core.
Service structs remain borrow-oriented and continue taking dependencies by reference.

nythos-core v0.1.2

01 May 19:51

Choose a tag to compare

Summary

nythos-core v0.1.2 updates the core auth boundary from synchronous ports to native async ports.

This release unblocks async infrastructure adapters, especially Cloudflare Workers D1, without introducing runtime, database, HTTP, or Cloudflare-specific dependencies into the core crate.

Highlights

  • Converted core port traits to async:

    • UserRepository
    • RoleRepository
    • SessionStore
    • PasswordHasher
    • TokenSigner
    • RevocationChecker
  • Converted auth orchestration services to async:

    • RegisterService::register
    • LoginService::login
    • RefreshService::refresh
    • RevokeSessionService::revoke
    • RevokeAllSessionsService::revoke_all
  • Updated internal auth helpers to await async port calls.

  • Added ADR 0005 documenting the async core port decision.

  • Updated test fakes and orchestration tests for async execution.

Why this changed

The previous synchronous port shape blocked natural implementations for async infrastructure. Cloudflare Workers D1 APIs are async, so gateway adapters could not implement core repository/session traits cleanly without fake blocking behavior.

This release makes the core async-native while keeping it infrastructure-free and runtime-agnostic.

Breaking API shape change

This is a public API shape change for consumers implementing or calling core ports/services.

Trait implementations now use async fn, and service flow calls must be awaited.

Example:

let result = login_service.login(input).await?;

Compatibility notes

  • No HTTP, database, Cloudflare, or async runtime dependency was added to nythos-core.
  • Domain models and value objects remain unchanged.
  • Service structs remain borrow-oriented and continue taking dependencies by reference.

nythos-core v0.1.1

30 Apr 20:10

Choose a tag to compare

Fixed

  • Added a wasm feature that enables uuid/js so UUID v4 generation works on wasm32-unknown-unknown targets such as Cloudflare Workers.

nythos-core v0.1.0

28 Apr 18:36
02ae2d9

Choose a tag to compare

Summary

nythos-core v0.1.0 is the first public release of the Nythos core authentication and authorization library.

This release establishes the infrastructure-free Rust core for Nythos, including domain primitives, identity models, auth/session/RBAC concepts, core orchestration services, and pure trait contracts for outer infrastructure layers.

Highlights

  • Published nythos-core as a public Rust crate.
  • Added a strict core-only architecture with no HTTP, database, cache, queue, provider, or deployment-specific code.
  • Introduced typed ID newtypes over Uuid:
    • UserId
    • TenantId
    • SessionId
    • RoleId
  • Added validated domain value objects:
    • Email
    • Password
  • Added identity models:
    • User
    • UserStatus
    • Tenant
    • TenantSettings
  • Added auth/token models:
    • PasswordHash
    • AccessToken
    • Claims
    • TokenPurpose
  • Added session and refresh-token models:
    • Session
    • RefreshToken
  • Added tenant-scoped RBAC models:
    • Permission
    • Role
    • RoleAssignment
    • RoleRegistry
  • Added core auth orchestration services:
    • RegisterService
    • LoginService
    • RefreshService
    • RevokeSessionService
    • RevokeAllSessionsService
  • Added pure infrastructure boundary ports:
    • UserRepository
    • RoleRepository
    • SessionStore
    • PasswordHasher
    • TokenSigner
    • RevocationChecker
  • Added mandatory refresh-token rotation semantics.
  • Added tenant-scoped RBAC rules with no global admin concept in core.
  • Added a crate-wide AuthError and NythosResult.
  • Added reference documentation under docs/.
  • Added ADRs for core boundaries, single-crate start, tenant-scoped RBAC, and refresh-token rotation.
  • Added integration-style tests using in-memory fakes for repository, session, token, password, and revocation ports.

Architecture

nythos-core is intentionally infrastructure-free.

The crate owns:

  • domain types and invariants
  • auth, session, and RBAC business rules
  • orchestration logic for register, login, refresh, and revocation flows
  • trait contracts for storage, signing, hashing, role lookup, and revocation checking

The crate does not own:

  • HTTP handlers or status-code mapping
  • database drivers, ORM models, SQL, or migrations
  • Redis/cache adapters
  • queues or event buses
  • email/SMS/OAuth provider integrations
  • concrete password hashing or token signing implementations
  • product-specific gateway behavior

Outer layers are expected to implement the provided ports.

Core Flows

Register

Registration validates email/password input, checks tenant-scoped duplicate users, hashes the password through PasswordHasher, creates the user through UserRepository, and can optionally issue session auth material.

Login

Login validates credentials, loads user credentials within a tenant, checks account status, verifies the password, loads tenant-scoped roles, creates a session, signs access claims, and returns auth material.

Refresh

Refresh resolves an opaque refresh token through SessionStore, rejects missing/revoked/expired sessions, reloads tenant-scoped roles, signs fresh access claims, and rotates the refresh token.

Revoke Session

Single-session revocation checks current revocation state and revokes the session through SessionStore.

Revoke All Sessions

Revoke-all invalidates all sessions for a user within a tenant boundary.

Known Design Notes

  • Claims currently include subject, tenant, token purpose, issued-at, and expiry timestamps.
  • Claims do not currently include SessionId.
  • Because RevocationChecker operates on SessionId, request-time revocation cannot be driven from verified Claims alone yet.
  • This gap is documented and intentionally deferred past v0.1.0.

Install

[dependencies]
nythos-core = "0.1.0"