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
| Actor | Description | Entry point |
|---|---|---|
| System Admin | Anthropic- or Vetty-internal operator who provisions clinics and manages the platform. Uses the Filament UI. | /systemadmin |
| Clinic Admin | Owner/manager of a single veterinary clinic. Registers the clinic, invites staff, configures settings. | React SPA (role: clinic_admin) |
| Veterinarian | Clinical staff who treats pets, takes appointments, writes prescriptions. | React SPA (role: veterinarian) |
| Clinic Staff / Receptionist | Handles front-desk activities — check-in, billing, scheduling. | React SPA (role: staff) |
| Pet Owner | External 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:
| Seam | Today | Future hook |
|---|---|---|
MAIL_MAILER=log in dev | SMTP/Resend/SES for reminders and invoices | |
| SMS | Stub channel on reminders.channel | Twilio / MSG91 |
| Push | Stub channel on reminders.channel | FCM/APNs for pet-owner app |
| Payments | payments.payment_method supports cash, card, upi, bank_transfer, online | Razorpay/Stripe/Paytm |
| Analytics / BI | Reports module only | Warehouse export |
Context diagram
Tenant boundary
A tenant in Vetty equals one veterinary clinic. The boundary is enforced by:
tenantstable — one row per clinic.tenant_userpivot — many-to-many between users and tenants withrole,status,is_defaultcolumns. A user can belong to multiple clinics.users.current_tenant_id— the default tenant resolved at login.ResolveTenantMembershipmiddleware — 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 atenant_idforeign key.
Usage scenarios
- Vetty signs up a new clinic — System Admin POSTs to
/api/v1/tenants; aTenantrow is created, an adminUseris created with roleclinic_adminin the pivot. - 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. - A pet owner registers — POST
/api/v1/auth/owner/registerwith atenant_ididentifying the clinic they belong to; creates aUser(account_type=owner) and a pairedClientrow. - A receptionist checks in a pet — The SPA calls
PATCH /api/v1/tenant/{tenant}/appointments/{appointment}with a new status. - An invoice is paid —
POST /api/v1/tenant/{tenant}/invoices/{invoice}/paymentsrecords aPayment; backend recalculatesbalance_dueand flipsinvoices.statustopartialorpaid.