Skip to main content

System Context

This page describes the actors that interact with Vetty, the systems it depends on, and the boundaries it lives within — essentially the C4 Level 1 view.

Actors

ActorDescriptionEntry point
System AdminAnthropic- or Vetty-internal operator who provisions clinics and manages the platform. Uses the Filament UI./systemadmin
Clinic AdminOwner/manager of a single veterinary clinic. Registers the clinic, invites staff, configures settings.React SPA (role: clinic_admin)
VeterinarianClinical staff who treats pets, takes appointments, writes prescriptions.React SPA (role: veterinarian)
Clinic Staff / ReceptionistHandles front-desk activities — check-in, billing, scheduling.React SPA (role: staff)
Pet OwnerExternal user. Sees their pets, appointments, and invoices only.React SPA (account_type: owner)

External systems

Vetty is currently an almost-standalone product. The seams where external systems could plug in are already present:

SeamTodayFuture hook
EmailMAIL_MAILER=log in devSMTP/Resend/SES for reminders and invoices
SMSStub channel on reminders.channelTwilio / MSG91
PushStub channel on reminders.channelFCM/APNs for pet-owner app
Paymentspayments.payment_method supports cash, card, upi, bank_transfer, onlineRazorpay/Stripe/Paytm
Analytics / BIReports module onlyWarehouse export

Context diagram

Tenant boundary

A tenant in Vetty equals one veterinary clinic. The boundary is enforced by:

  • tenants table — one row per clinic.
  • tenant_user pivot — many-to-many between users and tenants with role, status, is_default columns. A user can belong to multiple clinics.
  • users.current_tenant_id — the default tenant resolved at login.
  • ResolveTenantMembership middleware — validates the {tenant} route parameter on every /api/v1/tenant/{tenant}/… request before the controller is invoked.
  • Every business-data migration (clients, pets, appointments, invoices, payments, reminders) carries a tenant_id foreign key.

Usage scenarios

  1. Vetty signs up a new clinic — System Admin POSTs to /api/v1/tenants; a Tenant row is created, an admin User is created with role clinic_admin in the pivot.
  2. A clinic staffer logs in — POST /api/v1/auth/login, receives a user payload containing the clinic (current_tenant) and all tenants they belong to.
  3. A pet owner registers — POST /api/v1/auth/owner/register with a tenant_id identifying the clinic they belong to; creates a User (account_type=owner) and a paired Client row.
  4. A receptionist checks in a pet — The SPA calls PATCH /api/v1/tenant/{tenant}/appointments/{appointment} with a new status.
  5. An invoice is paidPOST /api/v1/tenant/{tenant}/invoices/{invoice}/payments records a Payment; backend recalculates balance_due and flips invoices.status to partial or paid.