CRM
LeadStatus
Table lead_statuses. The columns of a studio’s lead pipeline.
Unique on
(studioId, key). Index on (studioId, order).
Lead
Table leads.
Indexes:
(studioId, statusId), (studioId, remindAt), (studioId, createdAt).
Converting a lead creates a Client, so it goes through the plan’s trainee limit guard. See Billing models.
LeadSource
SITE, INSTAGRAM, FACEBOOK, GOOGLE, REFERRAL, WHATSAPP.
LeadNote
Table lead_notes: studioId, leadId (cascade), coachId, coachName (snapshot so the note still shows an author after the coach is gone), body, createdAt. Index on (leadId, createdAt).
LeadActivity
Table lead_activities. The lead’s timeline.
Index on
(leadId, createdAt).
Activity and audit
ClientActivity
Table client_activities. The activity tab on the trainee card.
Indexes:
(studioId, clientId, createdAt), (clientId, actorType, type).
The partner API can add and delete note-type activities on a trainee. See Partner API.
AuditLog
Table audit_logs.
Indexes:
studioId, (studioId, resourceType), (studioId, createdAt).
Rows are written by the audit module’s repository and directly by the partner, automation API, automation hooks, check-ins and foods repositories. Writes made through the automation lane are audited, which is one reason the MCP server and the WhatsApp assistant call that lane over a loopback request and do not touch the database themselves.
Saved trainee filters
SavedTraineeFilter
Table saved_trainee_filters. A named filter preset on the trainee board.
Index on
(studioId, userId).
TraineeFilterState
Table trainee_filter_states. The trainee board’s filter bar as one staff member last left it, so a return visit opens on the same view.
Unique on
(studioId, userId).
Both JSON shapes are in Automation JSON.
WaitlistLead
Table waitlist_leads. Signups from the marketing site. Global, no tenant.
Written by the unauthenticated
POST /v1/public/waitlist-leads in apps/core-api/src/modules/public/public.routes.ts. The same handler forwards the lead to an external webhook whose URL comes from the env var WAITLIST_WEBHOOK_URL.
AutoFit import
These two models exist only inpackages/database/prisma/schema.prisma. There is no migration for them. See The two Prisma schemas.
AutofitImport
Table autofit_imports. One self-serve migration run from AutoFit into a studio.
Index on
(studioId, status).
A partial unique index, applied by hand in production, allows at most one run per studio whose status is not DONE or FAILED. It closes the check-then-create race on the start endpoint.
AutofitExerciseMatch
Table autofit_exercise_matches. One distinct AutoFit exercise found in the pulled programs, with the AI’s proposal and the coach’s verdict.
Unique on
(importId, autofitExerciseId). Index on (importId, status).
Confirmed matches are also remembered globally in ExerciseSourceMap, so the next import of the same exercise needs no review. The flow is in AutoFit import.
AdminDeletion
Table admin_deletions. One studio or user deleted from the admin panel.
Indexes:
(kind, targetId), status.
It has no foreign keys on purpose. The row is the audit record and must outlive everything it describes. The purge logic is in packages/database/prisma/queries/admin-deletion.ts.