Files
caravel/backend/spec/models.md
2026-04-20 18:14:14 +00:00

5.0 KiB

This file describes the domain model. This description should be translated into standard structs and sqlite schemas in a way that makes sense.

  • Fields marked as private should use #[serde(skip_serializing)] in their definition.
  • Fields marked as readonly should use #[serde(skip_deserializing)] in their definition.

Identity

Identity is a description of a user.

  • pubkey - the user's nostr pubkey
  • is_admin - whether the user is an admin

Activity

Activity is an audit log of all actions performed by a user or a worker process. This allows us to trace history to create invoices, synchronize actions to external services, and debug system behavior.

  • id - a random activity ID
  • tenant - a tenant ID
  • created_at - unix timestamp when the activity was created
  • activity_type is one of:
    • create_tenant
    • update_tenant
    • create_relay
    • update_relay
    • activate_relay
    • deactivate_relay
    • fail_relay_sync
    • complete_relay_sync
  • resource_type is a string identifying the resource type being modified.
  • resource_id is a string identifying the resource id being modified.

Plan

A plan represents a rate charged for relays at a given feature/usage limit. Plans aren't saved to the database, but are simply hardcoded. However, they are exposed through the API so they can be used as a single source of truth.

  • id - the plan slug
  • name - the plan name
  • amount - the plan monthly cost in USD
  • members - the max number of members a relay can have before needing to upgrade. If empty, membership is not limited.
  • blossom - whether blossom media hosting is available on this plan
  • livekit - whether livekit audio/video calls are available on this plan
  • stripe_price_id (nullable) - the identifier of the price in Stripe. Null for the free plan.

There are three plans available:

  • free - $0/mo, up to 10 members, no blossom/livekit
  • basic - $5/mo, up to 100 members, includes blossom/livekit
  • growth - $25/mo, unlimited members, includes blossom/livekit

Tenant

Tenants are customers of the service, identified by a nostr pubkey. Public metadata like name etc are pulled from the nostr network. They also have associated billing information.

  • pubkey is the nostr public key identifying the tenant
  • nwc_url (private) a nostr wallet connect URL used for paying invoices generated by the system on the tenant's behalf
  • nwc_error (private) a string indicating the most recent NWC payment error, if any. Cleared on successful NWC payment.
  • created_at unix timestamp identifying tenant creation time
  • stripe_customer_id a string identifying the associated stripe customer
  • stripe_subscription_id (nullable) a string identifying the associated stripe subscription. Created when the first paid (non-free) relay is activated, deleted when the last paid relay is removed or deactivated. Free-only tenants have no subscription.
  • past_due_at (nullable) unix timestamp when the tenant's subscription became past due. Set on payment failure, cleared on payment success.

Relay

A relay is a nostr relay owned by a tenant and hosted by the attached zooid instance. Relay subdomains MUST be unique.

  • id - a random ID identifying the relay
  • tenant - the tenant's pubkey
  • schema - the relay's db schema (read_only, calculated based on subdomain + id)
  • subdomain - the relay's subdomain
  • plan - the relay's plan
  • stripe_subscription_item_id (nullable) - the Stripe subscription item id. Only set for relays on paid plans.
  • status - one of active|inactive|delinquent. Only active relays count toward billing. delinquent is set by the billing system when a relay's subscription becomes past due; inactive is set when a user or admin manually deactivates a relay.
  • synced - whether the relay has been successfully synced to zooid at least once.
  • sync_error - a string indicating any errors encountered when synchronizing.
  • info_name - the relay's name
  • info_icon - the relay's icon image URL
  • info_description - the relay's description
  • policy_public_join - whether to allow non-members to join the relay without an invite code
  • policy_strip_signatures - whether to remove signatures when serving events to non-admins
  • groups_enabled - whether NIP 29 groups are enabled
  • management_enabled - whether NIP 86 management API is enabled
  • blossom_enabled - whether blossom file storage is enabled
  • livekit_enabled - whether livekit calls are enabled
  • push_enabled - whether relay push is enabled

Some attributes persisted to zooid via API have special handling:

  • The relay's secret is generated once on relay creation, persisted to the zooid configuration, and isn't stored in the database. Relay updates do not resend secret.
  • The relay's host is calculated based on subdomain + RELAY_DOMAIN
  • The value of inactive is calculated based on status
  • The relay's livekit_* configuration is inferred based on environment variables and livekit_enabled.
  • The relay's roles are hard-coded for now.