Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/KevxxAlva/femesalud-zen-flow/llms.txt

Use this file to discover all available pages before exploring further.

FemeSalud’s persistence layer is a PostgreSQL database hosted on Supabase. The public schema contains 10 tables that cover the full clinical workflow — from patient registration and appointment scheduling through consultation records, laboratory results, and clinic configuration. All tables have Row Level Security (RLS) enabled, and two database functions (has_role and is_admin) are used across RLS policies to enforce access control without duplicating logic.
The schema is managed directly in the Supabase dashboard. There are no SQL migration files tracked in the application repository — all DDL changes must be applied through the Supabase Studio or the Supabase CLI project linked to the production instance.

Tables

patients

Core patient registry. Stores demographics, gynecological history, obstetric history, family antecedents, and personal history as structured JSONB fields.

appointments

Scheduled visits linking a patient to a doctor. Tracks datetime, duration, status, and payment information including method and reference.

consultations

Detailed clinical encounter records attached to an appointment. Contains vitals, physical exam findings, colposcopy data, obstetric control, and treatment plan.

consultation_consumables

Line-item materials consumed during a consultation. Always written atomically with their parent consultation via Supabase RPC.

clinical_notes

Free-form clinical notes scoped to a patient. Supports file attachments stored in the clinical-attachments Supabase Storage bucket.

profiles

Doctor and admin user profiles. Extends auth.users with display name, specialty, and avatar URL.

user_roles

Maps authenticated users to application roles. A user may hold multiple roles. Used as the authoritative source for all RLS policy checks.

prescription_templates

Reusable prescription and indication templates created by doctors. Speeds up consultation data entry by pre-filling common indications.

clinic_info

Single-row configuration table for the practice. Stores the clinic name, address lines, phone number, and tax ID (RIF).

lab_results

Laboratory test results linked to both an appointment and a patient. Tracks test type, status, result text, result date, and an optional file URL.

Enums

Two PostgreSQL enums are defined in the public schema.

app_role

Controls which role a user entry in user_roles represents.
type app_role = "admin" | "doctor";
ValueDescription
adminFull access to all records, clinic settings, and user management.
doctorScoped access — sees only their own patients and appointments.

visit_type_enum

Classifies the clinical purpose of a consultation.
type visit_type_enum =
  | "CONTROL"
  | "EMERGENCIA"
  | "CONSULTA_NUEVA"
  | "POST_TRATAMIENTO"
  | "OTRO";
ValueDescription
CONTROLRoutine follow-up or monitoring visit.
EMERGENCIAUnscheduled or urgent emergency visit.
CONSULTA_NUEVAFirst consultation for a new clinical concern.
POST_TRATAMIENTOPost-treatment review.
OTROAny other visit type not covered above.

Database Functions

Two helper functions are exposed in the public schema and called from RLS policies across tables.

has_role(_role app_role, _user_id uuid) → boolean

Returns true when the given user holds the specified role in user_roles.
SELECT has_role('admin', auth.uid());

is_admin(_user_id uuid) → boolean

Convenience wrapper around has_role that specifically checks for the admin role.
SELECT is_admin(auth.uid());

Key Relationships

The diagram below describes the foreign-key graph between the core tables.
patients
  ├── appointments          (appointments.patient_id → patients.id)
  │     ├── consultations   (consultations.appointment_id → appointments.id)
  │     │     └── consultation_consumables
  │     │           (consultation_consumables.consultation_id → consultations.id)
  │     └── lab_results     (lab_results.appointment_id → appointments.id)
  └── clinical_notes        (clinical_notes.patient_id → patients.id)
All consultations also carry a direct patient_id foreign key to patients for queries that do not need to traverse through appointments. Similarly, lab_results carries both appointment_id and patient_id to support direct patient-scoped queries without joining through appointments.

Row Level Security

RLS is enabled on every table in the public schema. The enforcement model follows two tiers:
  • Admins — rows returned by the is_admin() function see all records across all tables.
  • Doctors — rows visible to a given doctor are limited to patients assigned to them (assigned_doctor_id = auth.uid()) and appointments where doctor_id = auth.uid(). Cascading joins restrict consultation and lab result visibility accordingly.
Role membership is always resolved through the user_roles table using the has_role() function, keeping RLS policies consistent and avoiding hard-coded role strings scattered across policies.
When testing locally with the Supabase CLI, use a service-role key to bypass RLS and inspect raw table contents during development. Never expose the service-role key to the client.

Build docs developers (and LLMs) love