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_billing_anchor` - `update_tenant_nwc_url` - `create_relay` - `update_relay` - `activate_relay` - `deactivate_relay` - `fail_relay_sync` - `create_invoice` - `mark_invoice_paid` - `mark_invoice_attempted` - `mark_invoice_sent` - `mark_invoice_closed` - `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 - `sats` - the plan't cost per month - `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 There are three plans available: - `free` - 0 sats/mo, up to 10 members, no blossom/livekit - `basic` - 10k sats/mo, up to 100 members, includes blossom/livekit - `growth` - 50k sats/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 - `created_at` unix timestamp identifying tenant creation time - `billing_anchor` unix timestamp identifying billing cycle anchor. This gets reset when the tenant has no paid relays and adds (or reactivates) one. # 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 - `status` - `new|active|inactive`. Only `active` relays count toward billing. - `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 - `synced` (private) - whether the relay has been successfully synced to zooid at least once. Used by infra to decide POST vs PUT. Some attributes persisted to zooid via API have special handling: - The relay's `secret` is generated once and persisted to the zooid configuration but isn't stored in the database. - 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. # Invoice Invoices are generated at the end of a tenant's monthly billing period. The billing module is responsible for creating them, collecting them, and dunning them. - `id` - random invoice ID - `tenant` - tenant pubkey - `status` - `pending|paid|closed` - `amount` is derived as the sum of associated invoice item `sats` values (not stored as a separate source of truth) - `created_at` - unix timestamp for when the invoice was created - `attempted_at` - nullable unix timestamp for when collection was last attempted - `error` - optional human-readable error from the last failed collection attempt - `closed_at` - nullable unix timestamp for when the invoice was closed - `sent_at` - nullable unix timestamp for when the invoice was sent via DM - `paid_at` - nullable unix timestamp for when the invoice was paid - `bolt11` - a BOLT 11 lightning invoice that can be used to pay the invoice - `period_start` - unix timestamp for period start - `period_end` - unix timestamp for period end # Invoice Item Invoice items are attached to an invoice and represent charges for a given relay. - `id` - random invoice item ID - `invoice` - invoice ID - `relay` - relay ID - `sats` - amount in satoshis