Developers & Integrations
Database Schema
The core Prisma models and how they relate.
The full schema lives in packages/shared/prisma/schema.prisma — that
file is the actual source of truth; this page is a map to help you find
your way around it, not a substitute for reading it.
People and organizations
Customer— one row per real person, matched by email. Has astatus(LEAD,ACTIVE, orFORMER— a former customer who can be reactivated back toACTIVElater without losing history), an optionalcompanyId, and optional Clerk/Stripe identifiers.Company— groups customers for shared billing/access.CompanyContact— the join betweenCustomerandCompany, carryingisAdmin/isBillingContact/isEmployeeindependently.StaffMember— internal accounts, with arole(OWNER/ADMIN/FRONT_DESK) and its own Clerk identifier, entirely separate fromCustomer.
Catalog and bookings
Resource— a physical bookable thing (MEETING_ROOMorPRIVATE_OFFICE), with its own rate and capacity.Product— a sellable non-resource item (day passes, registered-office plans, store items).Booking— one reservation. Can belong to aBookingSeries(recurring) or aBookingGroup(checked out together), and can self-reference viarescheduledFromBookingIdto form a reschedule chain.DayPassPack/DayPassReservation— a purchased multi-use pack and each day it's actually redeemed against.OfficeLease— a private-office lease: billing type, payment schedule, status, and its own credit-pool fields.OfficeLeaseInquiry— the guided-inquiry funnel's own record, separate fromOfficeLeaseuntil staff approve it into one.RegisteredOfficeAccount— a mail/virtual-office subscription, with its compliance fields (1583 data, PMB number, ID expiry) alongside it.
Money
Invoice/InvoiceLineItem— every real charge, itemized, with a loosely-typedsourceType/sourceIdpointer back to whatever it's for (a booking, a day pass, a lease, etc.).Payment— one attempt to collect an invoice.Refund— always tied to a specificPayment.
Oversight
PendingApproval— a generic "propose now, decide later" record; its payload shape varies bytype(REFUND,INVOICE_VOID,WEEKEND_BOOKING,STAFF_INVITE,STAFF_ROLE_CHANGE,PROPOSAL_DISCOUNT).AuditLog— append-only.actorType/actorId(who),action(what, as a dotted string likestaff.role_changed),entityType/entityId(on what), and a free-formmetadataJSON blob for the specifics.CommunicationLog— one row per email actually attempted, including deliberately suppressed ones, with the template name, rendered subject, and success/failure.
CRM
Proposal— a full CPQ document with its own status lifecycle (DRAFT→SENT→ACCEPTED/DECLINED), separate from the simpler self-serve signup flows.
Conventions worth knowing before you write a migration
- Money is always stored in cents, as an integer — never a float.
- A "why" is usually written directly above the field or model as a comment in the schema — read it before assuming a field's purpose from its name alone.
- See Quick Start: Developer for how migrations actually get applied to the real database (there's no separate staging database for this project).