Skip to content

Registration

leadr.registration

Modules:

leadr.registration.adapters

Modules:

  • orm – Registration ORM models.
leadr.registration.adapters.orm

Registration ORM models.

Classes:

leadr.registration.adapters.orm.JamCodeORM

Bases: Base

Jam Code ORM model.

Represents a promotional code in the database. Maps to the jam_codes table. Used for tracking game jam codes, marketing campaigns, and referrals.

Functions:

  • from_domain – Convert domain entity to ORM model.
  • to_domain – Convert ORM model to domain entity.

Attributes:

# leadr.registration.adapters.orm.JamCodeORM.active
active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True, server_default='true')
# leadr.registration.adapters.orm.JamCodeORM.code
code: Mapped[str] = mapped_column(String(50), nullable=False, unique=True, index=True)
# leadr.registration.adapters.orm.JamCodeORM.created_at
created_at: Mapped[timestamp]
# leadr.registration.adapters.orm.JamCodeORM.current_uses
current_uses: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default='0')
# leadr.registration.adapters.orm.JamCodeORM.deleted_at
deleted_at: Mapped[nullable_timestamp]
# leadr.registration.adapters.orm.JamCodeORM.description
description: Mapped[str] = mapped_column(String, nullable=False)
# leadr.registration.adapters.orm.JamCodeORM.expires_at
expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
# leadr.registration.adapters.orm.JamCodeORM.features
features: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False, default={}, server_default='{}')
# leadr.registration.adapters.orm.JamCodeORM.from_domain
from_domain(domain)

Convert domain entity to ORM model.

Parameters:

  • domain (JamCode) – The domain entity to convert.

Returns:

# leadr.registration.adapters.orm.JamCodeORM.id
id: Mapped[uuid_pk]
# leadr.registration.adapters.orm.JamCodeORM.max_uses
max_uses: Mapped[int | None] = mapped_column(Integer, nullable=True)
# leadr.registration.adapters.orm.JamCodeORM.to_domain
to_domain()

Convert ORM model to domain entity.

Returns:

  • JamCode – The domain entity instance.
# leadr.registration.adapters.orm.JamCodeORM.updated_at
updated_at: Mapped[timestamp] = mapped_column(onupdate=(func.now()))
leadr.registration.adapters.orm.JamCodeRedemptionORM

Bases: Base

Jam Code Redemption ORM model.

Represents a single use of a jam code during registration. Maps to the jam_code_redemptions table with foreign keys to jam_codes and accounts. Tracks which account redeemed which code and when.

Functions:

  • from_domain – Convert domain entity to ORM model.
  • to_domain – Convert ORM model to domain entity.

Attributes:

# leadr.registration.adapters.orm.JamCodeRedemptionORM.account_id
account_id: Mapped[UUID] = mapped_column(ForeignKey('accounts.id', ondelete='CASCADE'), nullable=False, index=True)
# leadr.registration.adapters.orm.JamCodeRedemptionORM.created_at
created_at: Mapped[timestamp]
# leadr.registration.adapters.orm.JamCodeRedemptionORM.deleted_at
deleted_at: Mapped[nullable_timestamp]
# leadr.registration.adapters.orm.JamCodeRedemptionORM.from_domain
from_domain(domain)

Convert domain entity to ORM model.

Parameters:

Returns:

# leadr.registration.adapters.orm.JamCodeRedemptionORM.id
id: Mapped[uuid_pk]
# leadr.registration.adapters.orm.JamCodeRedemptionORM.jam_code_id
jam_code_id: Mapped[UUID] = mapped_column(ForeignKey('jam_codes.id', ondelete='CASCADE'), nullable=False, index=True)
# leadr.registration.adapters.orm.JamCodeRedemptionORM.meta
meta: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False, default={}, server_default='{}')
# leadr.registration.adapters.orm.JamCodeRedemptionORM.redeemed_at
redeemed_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
# leadr.registration.adapters.orm.JamCodeRedemptionORM.to_domain
to_domain()

Convert ORM model to domain entity.

Returns:

# leadr.registration.adapters.orm.JamCodeRedemptionORM.updated_at
updated_at: Mapped[timestamp] = mapped_column(onupdate=(func.now()))
leadr.registration.adapters.orm.VerificationCodeORM

Bases: Base

Verification Code ORM model.

Represents an email verification code in the database. Maps to the verification_codes table. Used during account registration to verify email ownership.

Functions:

  • from_domain – Convert domain entity to ORM model.
  • to_domain – Convert ORM model to domain entity.

Attributes:

# leadr.registration.adapters.orm.VerificationCodeORM.code
code: Mapped[str] = mapped_column(String(6), nullable=False)
# leadr.registration.adapters.orm.VerificationCodeORM.created_at
created_at: Mapped[timestamp]
# leadr.registration.adapters.orm.VerificationCodeORM.deleted_at
deleted_at: Mapped[nullable_timestamp]
# leadr.registration.adapters.orm.VerificationCodeORM.email
email: Mapped[str] = mapped_column(String, nullable=False, index=True)
# leadr.registration.adapters.orm.VerificationCodeORM.expires_at
expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, index=True)
# leadr.registration.adapters.orm.VerificationCodeORM.from_domain
from_domain(domain)

Convert domain entity to ORM model.

Parameters:

Returns:

# leadr.registration.adapters.orm.VerificationCodeORM.id
id: Mapped[uuid_pk]
# leadr.registration.adapters.orm.VerificationCodeORM.status
status: Mapped[VerificationCodeStatusEnum] = mapped_column(Enum(VerificationCodeStatusEnum, name='verification_code_status', native_enum=True, values_callable=(lambda x: [(e.value) for e in x])), nullable=False, default=(VerificationCodeStatusEnum.PENDING), server_default='pending')
# leadr.registration.adapters.orm.VerificationCodeORM.to_domain
to_domain()

Convert ORM model to domain entity.

Returns:

# leadr.registration.adapters.orm.VerificationCodeORM.updated_at
updated_at: Mapped[timestamp] = mapped_column(onupdate=(func.now()))
# leadr.registration.adapters.orm.VerificationCodeORM.used_at
used_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
leadr.registration.adapters.orm.VerificationCodeStatusEnum

Bases: str, Enum

Verification code status enum for database.

Attributes:

# leadr.registration.adapters.orm.VerificationCodeStatusEnum.EXPIRED
EXPIRED = 'expired'
# leadr.registration.adapters.orm.VerificationCodeStatusEnum.PENDING
PENDING = 'pending'
# leadr.registration.adapters.orm.VerificationCodeStatusEnum.USED
USED = 'used'

leadr.registration.api

Modules:

  • routes – Public registration API routes.
  • schemas – API schemas for registration endpoints.
leadr.registration.api.routes

Public registration API routes.

Functions:

Attributes:

leadr.registration.api.routes.complete_registration
complete_registration(request, registration_service)

Complete registration by creating the account, user, and API key.

This endpoint creates the full account structure:

  • Account with the specified name and slug
  • User associated with the verified email
  • API key for CLI authentication
  • Optional jam code redemption

The API key is returned in plaintext and should be stored securely by the client.

leadr.registration.api.routes.create_jam_code
create_jam_code(request, jam_code_service, auth)

Create a new jam code (superadmin only).

Jam codes can be used for promotional campaigns, game jams, or referral tracking. They can optionally have usage limits, expiration dates, and custom features.

leadr.registration.api.routes.get_jam_code
get_jam_code(jam_code_id, jam_code_service, auth)

Get a specific jam code by ID (superadmin only).

leadr.registration.api.routes.initiate_registration
initiate_registration(request, verification_service)

Initiate registration by sending a verification code to the provided email.

This endpoint is publicly accessible and requires no authentication. A 6-character verification code will be sent to the email address.

leadr.registration.api.routes.list_jam_codes
list_jam_codes(jam_code_service, auth)

List all jam codes (superadmin only).

Returns a list of all jam codes, including their usage statistics.

leadr.registration.api.routes.public_router
public_router = APIRouter(prefix='/register')
leadr.registration.api.routes.resend_verification_code
resend_verification_code(request, verification_service)

Resend a verification code to the provided email.

This endpoint invalidates any existing codes for the email and sends a new one.

leadr.registration.api.routes.router
router = APIRouter()
leadr.registration.api.routes.update_jam_code
update_jam_code(jam_code_id, request, jam_code_service, auth)

Update a jam code (superadmin only).

Can update description, features, max uses, active status, and expiration.

leadr.registration.api.routes.verify_code
verify_code(request, verification_service)

Verify an email verification code and return a temporary token.

This endpoint validates the verification code and returns a short-lived token that can be used to complete the registration process.

leadr.registration.api.schemas

API schemas for registration endpoints.

Classes:

leadr.registration.api.schemas.CompleteRegistrationRequest

Bases: BaseModel

Request to complete registration and create account.

Functions:

Attributes:

# leadr.registration.api.schemas.CompleteRegistrationRequest.account_name
account_name: str = Field(description='Name for the new account', min_length=1, max_length=100)
# leadr.registration.api.schemas.CompleteRegistrationRequest.account_slug
account_slug: str | None = Field(default=None, description='Optional URL slug (auto-generated if not provided)')
# leadr.registration.api.schemas.CompleteRegistrationRequest.display_name
display_name: str | None = Field(default=None, description='Optional display name for user (auto-generated from email if not provided)')
# leadr.registration.api.schemas.CompleteRegistrationRequest.jam_code
jam_code: str | None = Field(default=None, description='Optional jam/promo code')
# leadr.registration.api.schemas.CompleteRegistrationRequest.normalize_display_name
normalize_display_name(value)

Convert empty/whitespace strings to None.

# leadr.registration.api.schemas.CompleteRegistrationRequest.verification_token
verification_token: str = Field(description='Token from code verification step')
leadr.registration.api.schemas.CompleteRegistrationResponse

Bases: BaseModel

Response after completing registration.

Functions:

  • from_domain – Create response from domain entities.

Attributes:

# leadr.registration.api.schemas.CompleteRegistrationResponse.account_id
account_id: AccountID = Field(description='ID of the created account')
# leadr.registration.api.schemas.CompleteRegistrationResponse.account_slug
account_slug: str = Field(description='URL slug of the account')
# leadr.registration.api.schemas.CompleteRegistrationResponse.api_key
api_key: str = Field(description='API key for authentication')
# leadr.registration.api.schemas.CompleteRegistrationResponse.display_name
display_name: str = Field(description='Display name of the created user')
# leadr.registration.api.schemas.CompleteRegistrationResponse.from_domain
from_domain(account, user, api_key)

Create response from domain entities.

Parameters:

  • account – Account domain entity.
  • user – User domain entity.
  • api_key (str) – API key string.

Returns:

leadr.registration.api.schemas.CreateJamCodeRequest

Bases: BaseModel

Request to create a new jam code.

Attributes:

# leadr.registration.api.schemas.CreateJamCodeRequest.code
code: str = Field(description='Alphanumeric code (3-50 characters)', min_length=3, max_length=50)
# leadr.registration.api.schemas.CreateJamCodeRequest.description
description: str = Field(description='Human-readable description')
# leadr.registration.api.schemas.CreateJamCodeRequest.expires_at
expires_at: datetime | None = Field(default=None, description='Expiration date (null = never)')
# leadr.registration.api.schemas.CreateJamCodeRequest.features
features: dict = Field(default_factory=dict, description='Features/config for this code')
# leadr.registration.api.schemas.CreateJamCodeRequest.max_uses
max_uses: int | None = Field(default=None, description='Maximum redemptions (null = unlimited)')
leadr.registration.api.schemas.InitiateRegistrationRequest

Bases: BaseModel

Request to initiate registration by sending verification code.

Attributes:

# leadr.registration.api.schemas.InitiateRegistrationRequest.email
email: EmailStr = Field(description='Email address to send verification code to')
leadr.registration.api.schemas.InitiateRegistrationResponse

Bases: BaseModel

Response after initiating registration.

Attributes:

# leadr.registration.api.schemas.InitiateRegistrationResponse.code_expires_in
code_expires_in: int = Field(description='Seconds until the code expires')
# leadr.registration.api.schemas.InitiateRegistrationResponse.message
message: str = Field(description='Success message')
leadr.registration.api.schemas.JamCodeRedemptionResponse

Bases: BaseModel

Response representing a jam code redemption.

Functions:

Attributes:

# leadr.registration.api.schemas.JamCodeRedemptionResponse.account_id
account_id: AccountID
# leadr.registration.api.schemas.JamCodeRedemptionResponse.from_domain
from_domain(redemption)

Create response from domain entity.

Parameters:

  • redemption – JamCodeRedemption domain entity.

Returns:

# leadr.registration.api.schemas.JamCodeRedemptionResponse.id
id: JamCodeRedemptionID
# leadr.registration.api.schemas.JamCodeRedemptionResponse.jam_code_id
jam_code_id: JamCodeID
# leadr.registration.api.schemas.JamCodeRedemptionResponse.meta
meta: dict
# leadr.registration.api.schemas.JamCodeRedemptionResponse.redeemed_at
redeemed_at: datetime
leadr.registration.api.schemas.JamCodeResponse

Bases: BaseModel

Response representing a jam code.

Functions:

Attributes:

# leadr.registration.api.schemas.JamCodeResponse.active
active: bool
# leadr.registration.api.schemas.JamCodeResponse.code
code: str
# leadr.registration.api.schemas.JamCodeResponse.created_at
created_at: datetime
# leadr.registration.api.schemas.JamCodeResponse.current_uses
current_uses: int
# leadr.registration.api.schemas.JamCodeResponse.description
description: str
# leadr.registration.api.schemas.JamCodeResponse.expires_at
expires_at: datetime | None
# leadr.registration.api.schemas.JamCodeResponse.features
features: dict
# leadr.registration.api.schemas.JamCodeResponse.from_domain
from_domain(jam_code)

Create response from domain entity.

Parameters:

  • jam_code – JamCode domain entity.

Returns:

# leadr.registration.api.schemas.JamCodeResponse.id
id: JamCodeID
# leadr.registration.api.schemas.JamCodeResponse.max_uses
max_uses: int | None
# leadr.registration.api.schemas.JamCodeResponse.updated_at
updated_at: datetime
leadr.registration.api.schemas.UpdateJamCodeRequest

Bases: BaseModel

Request to update a jam code.

Attributes:

# leadr.registration.api.schemas.UpdateJamCodeRequest.active
active: bool | None = Field(default=None, description='New active status')
# leadr.registration.api.schemas.UpdateJamCodeRequest.description
description: str | None = Field(default=None, description='New description')
# leadr.registration.api.schemas.UpdateJamCodeRequest.expires_at
expires_at: datetime | None = Field(default=None, description='New expiration date')
# leadr.registration.api.schemas.UpdateJamCodeRequest.features
features: dict | None = Field(default=None, description='New features/config')
# leadr.registration.api.schemas.UpdateJamCodeRequest.max_uses
max_uses: int | None = Field(default=None, description='New max uses')
leadr.registration.api.schemas.VerifyCodeRequest

Bases: BaseModel

Request to verify an email verification code.

Attributes:

# leadr.registration.api.schemas.VerifyCodeRequest.code
code: str = Field(description='6-character verification code', min_length=6, max_length=6)
# leadr.registration.api.schemas.VerifyCodeRequest.email
email: EmailStr = Field(description='Email address')
leadr.registration.api.schemas.VerifyCodeResponse

Bases: BaseModel

Response after verifying a code.

Attributes:

# leadr.registration.api.schemas.VerifyCodeResponse.expires_in
expires_in: int = Field(description='Seconds until the token expires')
# leadr.registration.api.schemas.VerifyCodeResponse.verification_token
verification_token: str = Field(description='Temporary token for completing registration')

leadr.registration.domain

Modules:

  • jam_code – Jam code domain models for promotional codes and special features.
  • jam_code_redemption – Jam code redemption domain models for tracking code usage.
  • verification_code – Verification code domain models for email verification during registration.
leadr.registration.domain.jam_code

Jam code domain models for promotional codes and special features.

Classes:

  • JamCode – Jam code domain entity.
leadr.registration.domain.jam_code.JamCode

Bases: Entity

Jam code domain entity.

Represents a promotional code that grants special features or access during registration. Codes can be used for game jams, marketing campaigns, or referral tracking. Supports optional usage limits, expiration dates, and custom feature flags stored as JSON.

Functions:

  • activate – Activate the jam code, allowing redemptions.
  • deactivate – Deactivate the jam code, preventing further redemptions.
  • get_feature – Get a feature value from the features dictionary.
  • has_uses_remaining – Check if the jam code has remaining uses.
  • increment_uses – Increment the usage count by one.
  • is_expired – Check if the jam code has expired.
  • is_valid – Check if the jam code is valid and can be redeemed.
  • restore – Restore a soft-deleted entity.
  • soft_delete – Mark entity as soft-deleted.
  • validate_code – Validate and normalize the jam code.

Attributes:

# leadr.registration.domain.jam_code.JamCode.activate
activate()

Activate the jam code, allowing redemptions.

Used to re-enable a previously deactivated code.

# leadr.registration.domain.jam_code.JamCode.active
active: bool = Field(default=True, description='Whether this code can currently be redeemed')
# leadr.registration.domain.jam_code.JamCode.code
code: str = Field(description='Alphanumeric code (3-50 characters, case-insensitive)', min_length=3, max_length=50)
# leadr.registration.domain.jam_code.JamCode.created_at
created_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp when entity was created (UTC)')
# leadr.registration.domain.jam_code.JamCode.current_uses
current_uses: int = Field(default=0, description='Current number of times this code has been redeemed')
# leadr.registration.domain.jam_code.JamCode.deactivate
deactivate()

Deactivate the jam code, preventing further redemptions.

Used to manually disable a code (e.g., if it's compromised or no longer needed).

# leadr.registration.domain.jam_code.JamCode.deleted_at
deleted_at: datetime | None = Field(default=None, description='Timestamp when entity was soft-deleted (UTC), or null if active')
# leadr.registration.domain.jam_code.JamCode.description
description: str = Field(description="Human-readable description of this code's purpose")
# leadr.registration.domain.jam_code.JamCode.expires_at
expires_at: datetime | None = Field(default=None, description='When this code expires (None = never expires)')
# leadr.registration.domain.jam_code.JamCode.features
features: dict[str, Any] = Field(default_factory=dict, description='Custom features/config for this code (e.g., CLI templates, score limits)')
# leadr.registration.domain.jam_code.JamCode.get_feature
get_feature(key, default=None)

Get a feature value from the features dictionary.

Parameters:

  • key (str) – The feature key to retrieve.
  • default (Any) – Default value if the key doesn't exist.

Returns:

  • Any – The feature value or the default.
# leadr.registration.domain.jam_code.JamCode.has_uses_remaining
has_uses_remaining()

Check if the jam code has remaining uses.

Returns:

  • bool – True if the code has no usage limit or has not reached its limit.
# leadr.registration.domain.jam_code.JamCode.id
id: Any = Field(frozen=True, default_factory=uuid4, description='Unique identifier (auto-generated UUID or typed ID)')
# leadr.registration.domain.jam_code.JamCode.increment_uses
increment_uses()

Increment the usage count by one.

Called when a jam code is successfully redeemed during registration.

# leadr.registration.domain.jam_code.JamCode.is_deleted
is_deleted: bool

Check if entity is soft-deleted.

Returns:

  • bool – True if the entity has a deleted_at timestamp, False otherwise.
# leadr.registration.domain.jam_code.JamCode.is_expired
is_expired()

Check if the jam code has expired.

Returns:

  • bool – True if the code has an expiration date and it has passed.
# leadr.registration.domain.jam_code.JamCode.is_valid
is_valid()

Check if the jam code is valid and can be redeemed.

A code is valid if it's active, not expired, and has uses remaining.

Returns:

  • bool – True if the code can be used for registration.
# leadr.registration.domain.jam_code.JamCode.max_uses
max_uses: int | None = Field(default=None, description='Maximum number of redemptions allowed (None = unlimited)')
# leadr.registration.domain.jam_code.JamCode.model_config
model_config = ConfigDict(validate_assignment=True)
# leadr.registration.domain.jam_code.JamCode.restore
restore()

Restore a soft-deleted entity.

Clears the deleted_at timestamp, making the entity active again.

Example > > > account.soft_delete() > > > account.restore() > > > assert account.is_deleted is False
# leadr.registration.domain.jam_code.JamCode.soft_delete
soft_delete()

Mark entity as soft-deleted.

Sets the deleted_at timestamp to the current UTC time. Entities that are already deleted are not affected (deleted_at remains at original deletion time).

Example > > > account = Account(name="Test", slug="test") > > > account.soft_delete() > > > assert account.is_deleted is True
# leadr.registration.domain.jam_code.JamCode.updated_at
updated_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp of last update (UTC)')
# leadr.registration.domain.jam_code.JamCode.validate_code
validate_code(v)

Validate and normalize the jam code.

Parameters:

  • v (str) – The code value to validate.

Returns:

  • str – The normalized (uppercase) code.

Raises:

  • ValueError – If the code contains non-alphanumeric characters.
leadr.registration.domain.jam_code_redemption

Jam code redemption domain models for tracking code usage.

Classes:

leadr.registration.domain.jam_code_redemption.JamCodeRedemption

Bases: Entity

Jam code redemption domain entity.

Represents a single use of a jam code during account registration. Tracks which account redeemed which code, when it was redeemed, and any associated metadata (e.g., CLI configuration, user agent).

Functions:

  • get_meta – Get a metadata value from the meta dictionary.
  • restore – Restore a soft-deleted entity.
  • soft_delete – Mark entity as soft-deleted.

Attributes:

# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.account_id
account_id: AccountID = Field(description='ID of the account that redeemed the code')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.created_at
created_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp when entity was created (UTC)')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.deleted_at
deleted_at: datetime | None = Field(default=None, description='Timestamp when entity was soft-deleted (UTC), or null if active')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.get_meta
get_meta(key, default=None)

Get a metadata value from the meta dictionary.

Parameters:

  • key (str) – The metadata key to retrieve.
  • default (Any) – Default value if the key doesn't exist.

Returns:

  • Any – The metadata value or the default.
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.id
id: Any = Field(frozen=True, default_factory=uuid4, description='Unique identifier (auto-generated UUID or typed ID)')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.is_deleted
is_deleted: bool

Check if entity is soft-deleted.

Returns:

  • bool – True if the entity has a deleted_at timestamp, False otherwise.
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.jam_code_id
jam_code_id: UUID = Field(description='ID of the jam code that was redeemed')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.meta
meta: dict[str, Any] = Field(default_factory=dict, description='Additional metadata about the redemption (e.g., CLI config, user agent)')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.model_config
model_config = ConfigDict(validate_assignment=True)
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.redeemed_at
redeemed_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='When the code was redeemed (UTC)')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.restore
restore()

Restore a soft-deleted entity.

Clears the deleted_at timestamp, making the entity active again.

Example > > > account.soft_delete() > > > account.restore() > > > assert account.is_deleted is False
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.soft_delete
soft_delete()

Mark entity as soft-deleted.

Sets the deleted_at timestamp to the current UTC time. Entities that are already deleted are not affected (deleted_at remains at original deletion time).

Example > > > account = Account(name="Test", slug="test") > > > account.soft_delete() > > > assert account.is_deleted is True
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.updated_at
updated_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp of last update (UTC)')
leadr.registration.domain.verification_code

Verification code domain models for email verification during registration.

Classes:

leadr.registration.domain.verification_code.VerificationCode

Bases: Entity

Verification code domain entity.

Represents a one-time email verification code used during account registration. Codes are 6-character alphanumeric strings with a 10-minute expiration window. Once used or expired, codes become invalid and cannot be reused.

Functions:

  • is_expired – Check if the verification code has expired.
  • is_used – Check if the verification code has been used.
  • is_valid – Check if the verification code is valid and can be used.
  • mark_as_expired – Mark the verification code as expired.
  • mark_as_used – Mark the verification code as used.
  • restore – Restore a soft-deleted entity.
  • soft_delete – Mark entity as soft-deleted.
  • validate_code – Validate and normalize the verification code.

Attributes:

# leadr.registration.domain.verification_code.VerificationCode.code
code: str = Field(description='6-character alphanumeric verification code (case-insensitive)', min_length=6, max_length=6)
# leadr.registration.domain.verification_code.VerificationCode.created_at
created_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp when entity was created (UTC)')
# leadr.registration.domain.verification_code.VerificationCode.deleted_at
deleted_at: datetime | None = Field(default=None, description='Timestamp when entity was soft-deleted (UTC), or null if active')
# leadr.registration.domain.verification_code.VerificationCode.email
email: EmailStr = Field(description='Email address this code was sent to')
# leadr.registration.domain.verification_code.VerificationCode.expires_at
expires_at: datetime = Field(description='When this code expires (UTC)')
# leadr.registration.domain.verification_code.VerificationCode.id
id: Any = Field(frozen=True, default_factory=uuid4, description='Unique identifier (auto-generated UUID or typed ID)')
# leadr.registration.domain.verification_code.VerificationCode.is_deleted
is_deleted: bool

Check if entity is soft-deleted.

Returns:

  • bool – True if the entity has a deleted_at timestamp, False otherwise.
# leadr.registration.domain.verification_code.VerificationCode.is_expired
is_expired()

Check if the verification code has expired.

Returns:

  • bool – True if the code's expiration time has passed.
# leadr.registration.domain.verification_code.VerificationCode.is_used
is_used()

Check if the verification code has been used.

Returns:

  • bool – True if the code status is USED.
# leadr.registration.domain.verification_code.VerificationCode.is_valid
is_valid()

Check if the verification code is valid and can be used.

A code is valid if it hasn't been used and hasn't expired.

Returns:

  • bool – True if the code is valid and can be used for verification.
# leadr.registration.domain.verification_code.VerificationCode.mark_as_expired
mark_as_expired()

Mark the verification code as expired.

Sets the status to EXPIRED. This is typically done when cleaning up old codes or when explicitly invalidating codes.

# leadr.registration.domain.verification_code.VerificationCode.mark_as_used
mark_as_used()

Mark the verification code as used.

Sets the status to USED and records the current timestamp in used_at. Once marked as used, the code cannot be reused.

# leadr.registration.domain.verification_code.VerificationCode.model_config
model_config = ConfigDict(validate_assignment=True)
# leadr.registration.domain.verification_code.VerificationCode.restore
restore()

Restore a soft-deleted entity.

Clears the deleted_at timestamp, making the entity active again.

Example > > > account.soft_delete() > > > account.restore() > > > assert account.is_deleted is False
# leadr.registration.domain.verification_code.VerificationCode.soft_delete
soft_delete()

Mark entity as soft-deleted.

Sets the deleted_at timestamp to the current UTC time. Entities that are already deleted are not affected (deleted_at remains at original deletion time).

Example > > > account = Account(name="Test", slug="test") > > > account.soft_delete() > > > assert account.is_deleted is True
# leadr.registration.domain.verification_code.VerificationCode.status
status: VerificationCodeStatus = VerificationCodeStatus.PENDING
# leadr.registration.domain.verification_code.VerificationCode.updated_at
updated_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp of last update (UTC)')
# leadr.registration.domain.verification_code.VerificationCode.used_at
used_at: datetime | None = None
# leadr.registration.domain.verification_code.VerificationCode.validate_code
validate_code(v)

Validate and normalize the verification code.

Parameters:

  • v (str) – The code value to validate.

Returns:

  • str – The normalized (uppercase) code.

Raises:

  • ValueError – If the code contains non-alphanumeric characters.
leadr.registration.domain.verification_code.VerificationCodeStatus

Bases: Enum

Verification code status enumeration.

Attributes:

# leadr.registration.domain.verification_code.VerificationCodeStatus.EXPIRED
EXPIRED = 'expired'
# leadr.registration.domain.verification_code.VerificationCodeStatus.PENDING
PENDING = 'pending'
# leadr.registration.domain.verification_code.VerificationCodeStatus.USED
USED = 'used'

leadr.registration.services

Modules:

  • dependencies – Dependency injection for registration services.
  • jam_code_service – Jam code service for managing promotional codes.
  • registration_service – Registration service for orchestrating account creation flow.
  • repositories – Registration repository services for verification codes and jam codes.
  • verification_service – Verification service for generating and validating email verification codes.
leadr.registration.services.dependencies

Dependency injection for registration services.

Functions:

Attributes:

leadr.registration.services.dependencies.EmailServiceDep
EmailServiceDep = Annotated[EmailService, Depends(get_email_service)]
leadr.registration.services.dependencies.JamCodeServiceDep
JamCodeServiceDep = Annotated[JamCodeService, Depends(get_jam_code_service)]
leadr.registration.services.dependencies.RegistrationServiceDep
RegistrationServiceDep = Annotated[RegistrationService, Depends(get_registration_service)]
leadr.registration.services.dependencies.VerificationServiceDep
VerificationServiceDep = Annotated[VerificationService, Depends(get_verification_service)]
leadr.registration.services.dependencies.get_email_service
get_email_service(db)

Get EmailService dependency.

Parameters:

Returns:

leadr.registration.services.dependencies.get_jam_code_service
get_jam_code_service(db)

Get JamCodeService dependency.

Parameters:

Returns:

leadr.registration.services.dependencies.get_registration_service
get_registration_service(db, account_service, user_service, api_key_service, verification_service, jam_code_service, email_service)

Get RegistrationService dependency.

Parameters:

Returns:

leadr.registration.services.dependencies.get_verification_service
get_verification_service(db, email_service)

Get VerificationService dependency.

Parameters:

Returns:

leadr.registration.services.jam_code_service

Jam code service for managing promotional codes.

Classes:

leadr.registration.services.jam_code_service.JamCodeService
JamCodeService(db)

Service for managing jam codes and redemptions.

Functions:

Attributes:

Parameters:

# leadr.registration.services.jam_code_service.JamCodeService.create_jam_code
create_jam_code(code, description, features=None, max_uses=None, expires_at=None)

Create a new jam code.

Parameters:

  • code (str) – The code value (will be normalized to uppercase).
  • description (str) – Human-readable description.
  • features (dict | None) – Optional features dictionary.
  • max_uses (int | None) – Optional maximum number of redemptions.
  • expires_at (datetime | None) – Optional expiration date.

Returns:

  • JamCode – The created jam code.

Raises:

  • ValueError – If a jam code with this code already exists.
# leadr.registration.services.jam_code_service.JamCodeService.db
db = db
# leadr.registration.services.jam_code_service.JamCodeService.get_jam_code_by_id
get_jam_code_by_id(jam_code_id)

Get a jam code by its ID.

Parameters:

  • jam_code_id (UUID) – The jam code ID.

Returns:

  • JamCode | None – The jam code if found, None otherwise.
# leadr.registration.services.jam_code_service.JamCodeService.jam_code_repository
jam_code_repository = JamCodeRepository(db)
# leadr.registration.services.jam_code_service.JamCodeService.list_jam_codes
list_jam_codes()

List all jam codes.

Returns:

# leadr.registration.services.jam_code_service.JamCodeService.redeem_jam_code
redeem_jam_code(jam_code, account_id, meta=None)

Redeem a jam code for an account.

Parameters:

  • jam_code (JamCode) – The jam code to redeem.
  • account_id (AccountID) – The account redeeming the code.
  • meta (dict | None) – Optional metadata to store with the redemption.

Returns:

Raises:

  • ValueError – If the jam code has already been redeemed by this account.
# leadr.registration.services.jam_code_service.JamCodeService.redemption_repository
redemption_repository = JamCodeRedemptionRepository(db)
# leadr.registration.services.jam_code_service.JamCodeService.update_jam_code
update_jam_code(jam_code_id, description=None, features=None, max_uses=None, active=None, expires_at=None)

Update a jam code.

Parameters:

  • jam_code_id (UUID) – The jam code ID.
  • description (str | None) – Optional new description.
  • features (dict | None) – Optional new features dictionary.
  • max_uses (int | None) – Optional new max uses.
  • active (bool | None) – Optional new active status.
  • expires_at (datetime | None) – Optional new expiration date.

Returns:

  • JamCode – The updated jam code.

Raises:

# leadr.registration.services.jam_code_service.JamCodeService.validate_and_get_jam_code
validate_and_get_jam_code(code)

Validate a jam code and return it if valid.

Parameters:

  • code (str) – The jam code to validate.

Returns:

  • JamCode | None – The jam code if valid, None if invalid or not found.
leadr.registration.services.registration_service

Registration service for orchestrating account creation flow.

Classes:

leadr.registration.services.registration_service.RegistrationService
RegistrationService(db, account_service, user_service, api_key_service, verification_service, jam_code_service, email_service)

Service for orchestrating the complete account registration flow.

Functions:

Attributes:

Parameters:

# leadr.registration.services.registration_service.RegistrationService.account_service
account_service = account_service
# leadr.registration.services.registration_service.RegistrationService.api_key_service
api_key_service = api_key_service
# leadr.registration.services.registration_service.RegistrationService.complete_registration
complete_registration(verification_token, account_name, account_slug=None, jam_code=None, display_name=None)

Complete the registration process and create account, user, and API key.

Parameters:

  • verification_token (str) – JWT token from email verification.
  • account_name (str) – Name for the new account.
  • account_slug (str | None) – Optional slug (will be auto-generated if not provided).
  • jam_code (str | None) – Optional jam code for promotional features.
  • display_name (str | None) – Optional display name (will use email prefix if not provided).

Returns:

Raises:

  • ValueError – If verification token is invalid or jam code is invalid.
# leadr.registration.services.registration_service.RegistrationService.db
db = db
# leadr.registration.services.registration_service.RegistrationService.email_service
email_service = email_service
# leadr.registration.services.registration_service.RegistrationService.jam_code_service
jam_code_service = jam_code_service
# leadr.registration.services.registration_service.RegistrationService.user_service
user_service = user_service
# leadr.registration.services.registration_service.RegistrationService.verification_service
verification_service = verification_service
leadr.registration.services.repositories

Registration repository services for verification codes and jam codes.

Classes:

leadr.registration.services.repositories.JamCodeRedemptionRepository

Bases: BaseRepository[JamCodeRedemption, JamCodeRedemptionORM]

Jam code redemption repository for tracking code usage.

Functions:

  • create – Create a new entity in the database.
  • delete – Soft delete an entity by setting its deleted_at timestamp.
  • filter – Filter jam code redemptions by criteria.
  • find_by_account – Find all jam code redemptions for an account.
  • get_by_id – Get an entity by its ID.
  • has_redeemed – Check if an account has already redeemed a specific jam code.
  • update – Update an existing entity in the database.

Attributes:

# leadr.registration.services.repositories.JamCodeRedemptionRepository.create
create(entity)

Create a new entity in the database.

Parameters:

Returns:

# leadr.registration.services.repositories.JamCodeRedemptionRepository.delete
delete(entity_id)

Soft delete an entity by setting its deleted_at timestamp.

Parameters:

Raises:

# leadr.registration.services.repositories.JamCodeRedemptionRepository.filter
filter(account_id=None, **kwargs)

Filter jam code redemptions by criteria.

Parameters:

  • account_id (Any | None) – Optional account ID to filter by.
  • **kwargs (Any) – Additional filter parameters.

Returns:

# leadr.registration.services.repositories.JamCodeRedemptionRepository.find_by_account
find_by_account(account_id)

Find all jam code redemptions for an account.

Parameters:

Returns:

# leadr.registration.services.repositories.JamCodeRedemptionRepository.get_by_id
get_by_id(entity_id, include_deleted=False)

Get an entity by its ID.

Parameters:

  • entity_id (UUID4 | PrefixedID) – Entity ID to retrieve
  • include_deleted (bool) – If True, include soft-deleted entities. Defaults to False.

Returns:

  • DomainEntityT | None – Domain entity if found, None otherwise
# leadr.registration.services.repositories.JamCodeRedemptionRepository.has_redeemed
has_redeemed(account_id, jam_code_id)

Check if an account has already redeemed a specific jam code.

Parameters:

  • account_id (AccountID) – The account ID.
  • jam_code_id (UUID) – The jam code ID.

Returns:

  • bool – True if the account has redeemed this code, False otherwise.
# leadr.registration.services.repositories.JamCodeRedemptionRepository.session
session = session
# leadr.registration.services.repositories.JamCodeRedemptionRepository.update
update(entity)

Update an existing entity in the database.

Parameters:

Returns:

Raises:

leadr.registration.services.repositories.JamCodeRepository

Bases: BaseRepository[JamCode, JamCodeORM]

Jam code repository for managing promotional codes.

Functions:

  • create – Create a new entity in the database.
  • delete – Soft delete an entity by setting its deleted_at timestamp.
  • filter – Filter jam codes by criteria.
  • find_by_code – Find a jam code by its code value.
  • get_by_id – Get an entity by its ID.
  • update – Update an existing entity in the database.

Attributes:

# leadr.registration.services.repositories.JamCodeRepository.create
create(entity)

Create a new entity in the database.

Parameters:

Returns:

# leadr.registration.services.repositories.JamCodeRepository.delete
delete(entity_id)

Soft delete an entity by setting its deleted_at timestamp.

Parameters:

Raises:

# leadr.registration.services.repositories.JamCodeRepository.filter
filter(account_id=None, **kwargs)

Filter jam codes by criteria.

Parameters:

  • account_id (Any | None) – Not used for jam codes (top-level entity).
  • **kwargs (Any) – Filter parameters (code, etc.)

Returns:

# leadr.registration.services.repositories.JamCodeRepository.find_by_code
find_by_code(code)

Find a jam code by its code value.

Parameters:

  • code (str) – The jam code to look up (case-insensitive).

Returns:

  • JamCode | None – The jam code if found, None otherwise.
# leadr.registration.services.repositories.JamCodeRepository.get_by_id
get_by_id(entity_id, include_deleted=False)

Get an entity by its ID.

Parameters:

  • entity_id (UUID4 | PrefixedID) – Entity ID to retrieve
  • include_deleted (bool) – If True, include soft-deleted entities. Defaults to False.

Returns:

  • DomainEntityT | None – Domain entity if found, None otherwise
# leadr.registration.services.repositories.JamCodeRepository.session
session = session
# leadr.registration.services.repositories.JamCodeRepository.update
update(entity)

Update an existing entity in the database.

Parameters:

Returns:

Raises:

leadr.registration.services.repositories.VerificationCodeRepository

Bases: BaseRepository[VerificationCode, VerificationCodeORM]

Verification code repository for managing email verification codes.

Functions:

  • create – Create a new entity in the database.
  • delete – Soft delete an entity by setting its deleted_at timestamp.
  • filter – Filter verification codes by criteria.
  • find_valid_code_by_email – Find a valid (pending) verification code by email and code value.
  • get_by_id – Get an entity by its ID.
  • invalidate_codes_for_email – Mark all pending verification codes for an email as expired.
  • update – Update an existing entity in the database.

Attributes:

# leadr.registration.services.repositories.VerificationCodeRepository.create
create(entity)

Create a new entity in the database.

Parameters:

Returns:

# leadr.registration.services.repositories.VerificationCodeRepository.delete
delete(entity_id)

Soft delete an entity by setting its deleted_at timestamp.

Parameters:

Raises:

# leadr.registration.services.repositories.VerificationCodeRepository.filter
filter(account_id=None, **kwargs)

Filter verification codes by criteria.

Parameters:

  • account_id (Any | None) – Not used for verification codes (top-level entity).
  • **kwargs (Any) – Filter parameters (email, status, etc.)

Returns:

# leadr.registration.services.repositories.VerificationCodeRepository.find_valid_code_by_email
find_valid_code_by_email(email, code)

Find a valid (pending) verification code by email and code value.

Parameters:

  • email (str) – The email address.
  • code (str) – The verification code.

Returns:

  • VerificationCode | None – The verification code if found and valid, None otherwise.
# leadr.registration.services.repositories.VerificationCodeRepository.get_by_id
get_by_id(entity_id, include_deleted=False)

Get an entity by its ID.

Parameters:

  • entity_id (UUID4 | PrefixedID) – Entity ID to retrieve
  • include_deleted (bool) – If True, include soft-deleted entities. Defaults to False.

Returns:

  • DomainEntityT | None – Domain entity if found, None otherwise
# leadr.registration.services.repositories.VerificationCodeRepository.invalidate_codes_for_email
invalidate_codes_for_email(email)

Mark all pending verification codes for an email as expired.

Used when generating a new code to invalidate previous ones.

Parameters:

  • email (str) – The email address.
# leadr.registration.services.repositories.VerificationCodeRepository.session
session = session
# leadr.registration.services.repositories.VerificationCodeRepository.update
update(entity)

Update an existing entity in the database.

Parameters:

Returns:

Raises:

leadr.registration.services.verification_service

Verification service for generating and validating email verification codes.

Classes:

leadr.registration.services.verification_service.VerificationService
VerificationService(db, email_service)

Service for managing email verification codes.

Functions:

Attributes:

Parameters:

  • db (AsyncSession) – Database session.
  • email_service (EmailService) – Email service for sending verification codes.
# leadr.registration.services.verification_service.VerificationService.db
db = db
# leadr.registration.services.verification_service.VerificationService.email_service
email_service = email_service
# leadr.registration.services.verification_service.VerificationService.initiate_verification
initiate_verification(email)

Generate and send a verification code to an email address.

Invalidates any existing pending codes for the email before creating a new one.

Parameters:

  • email (str) – Email address to send the verification code to.
# leadr.registration.services.verification_service.VerificationService.repository
repository = VerificationCodeRepository(db)
# leadr.registration.services.verification_service.VerificationService.validate_verification_token
validate_verification_token(token)

Validate a verification token and return the email.

Parameters:

  • token (str) – JWT verification token.

Returns:

  • str – The email address from the token.

Raises:

  • ValueError – If the token is invalid or expired.
# leadr.registration.services.verification_service.VerificationService.verify_code
verify_code(email, code)

Verify a code and return a short-lived verification token.

Parameters:

  • email (str) – Email address to verify.
  • code (str) – Verification code to check.

Returns:

  • str – A JWT verification token valid for 10 minutes.

Raises:

  • ValueError – If the code is invalid, expired, or already used.