RealMeet es un MVP SaaS para agendamiento de profesionales orientado inicialmente a salud y servicios legales. El proyecto sigue un enfoque de monolito modular: backend FastAPI, frontend React/Vite, PostgreSQL, Docker Compose, migraciones Alembic y seed local.
- Autenticacion JWT con roles
admin,professional,client - Autorizacion backend por rol y restauracion de sesion frontend contra
/auth/me - Registro base y acceso por roles
- Catalogo de categorias y especialidades
- Perfil profesional y especialidades asociadas
- Reglas de disponibilidad semanal, bloqueos manuales y calculo publico de slots
- Reserva de horas con validacion de disponibilidad, solapamientos, estados e historial
- Meeting provider mock preparado para futuras integraciones
- Servicio de correo por SMTP o salida a log en desarrollo
- Notificaciones basicas para reserva creada, confirmada y cancelada
- Dashboards por rol y backoffice administrativo minimo
- Metricas basicas para profesional y administrador
- Backoffice minimo para usuarios, profesionales y reservas
app/api: routers FastAPIapp/core: configuracion, seguridad, scheduler y dependenciasapp/db: sesion SQLAlchemy y metadataapp/models: entidades ORMapp/schemas: contratos Pydanticapp/services: logica de negocioapp/repositories: acceso a datos puntualapp/meetings: providers desacopladosapp/emails: servicio de envio de correosapp/seed: seed inicial local
src/pages: pantallas principalessrc/layouts: layouts publico y dashboardsrc/components: UI reutilizablesrc/api: cliente HTTP y consultassrc/store: estado global con Zustandsrc/routes: enrutado y proteccion basicasrc/types: tipos compartidos de UI
Entidades incluidas:
UserProfessionalProfileClientProfileCategorySpecialtyProfessionalSpecialtyAvailabilityRuleAvailabilityBlockAppointmentAppointmentHistoryAuditLogSystemSetting
Base API: http://localhost:18000/api/v1
POST /auth/registerPOST /auth/loginGET /auth/meGET /users/mePATCH /users/meGET /users/me/profilePATCH /users/me/profileGET /categoriesPOST /categoriesPATCH /categories/{id}GET /specialtiesPOST /specialtiesPATCH /specialties/{id}GET /professionalsGET /professionals/{id}POST /professionals/profileGET /professionals/me/profilePATCH /professionals/me/profileGET /professionals/{id}/availability?date=YYYY-MM-DDGET /professionals/me/availability-rulesPOST /professionals/me/availability-rulesPATCH /professionals/me/availability-rules/{id}DELETE /professionals/me/availability-rules/{id}GET /professionals/me/availability-blocksPOST /professionals/me/availability-blocksPATCH /professionals/me/availability-blocks/{id}DELETE /professionals/me/availability-blocks/{id}POST /appointmentsGET /appointments/meGET /appointments/professional/meGET /appointments/{id}PATCH /appointments/{id}/cancelPATCH /appointments/professional/{id}/confirmPATCH /appointments/professional/{id}/completePATCH /appointments/professional/{id}/no-showPATCH /appointments/professional/{id}/cancelPATCH /appointments/professional/{id}/private-notesGET /client/metricsGET /professional/metricsGET /admin/metricsGET /admin/usersGET /admin/users/{id}PATCH /admin/users/{id}GET /admin/professionalsGET /admin/professionals/{id}PATCH /admin/professionals/{id}GET /admin/appointmentsGET /admin/appointments/{id}PATCH /admin/appointments/{id}/status
- El cliente inicia sesion.
- Consulta el listado publico de profesionales.
- Revisa disponibilidad del profesional.
- Reserva una hora disponible.
- El backend revalida disponibilidad, solapamientos y crea la cita.
- Si corresponde, se genera un meeting mock.
- Se registra o envia una notificacion basica.
- La reserva queda disponible para dashboards, metricas e historial.
- El profesional puede confirmar, cancelar, completar o marcar no show segun transicion valida.
El flujo recomendado con Docker Compose usa el archivo de la raiz:
.env.example
Para ejecucion local fuera de Docker existen ejemplos por subproyecto:
backend/.env.examplefrontend/.env.example
Variables backend relevantes:
APP_NAMEAPP_ENVDEBUGAPI_V1_PREFIXDATABASE_URLSECRET_KEYACCESS_TOKEN_EXPIRE_MINUTESCORS_ORIGINSSMTP_HOSTSMTP_PORTSMTP_USERSMTP_PASSWORDSMTP_FROM_EMAILSMTP_FROM_NAMESMTP_USE_TLSSMTP_TIMEOUT_SECONDSEMAIL_MODEDEFAULT_MEETING_PROVIDERMOCK_MEETING_BASE_URLENABLE_DOCSRATE_LIMIT_ENABLEDRATE_LIMIT_WINDOW_SECONDSRATE_LIMIT_MAX_REQUESTSENABLE_DEMO_SEEDBACKEND_HOSTBACKEND_PORT
Variables Docker Compose relevantes:
POSTGRES_DBPOSTGRES_USERPOSTGRES_PASSWORDPOSTGRES_PORTBACKEND_PORTBACKEND_INTERNAL_PORTFRONTEND_PORT
Variables frontend:
VITE_API_URL
Requisitos:
- Docker.
- Docker Compose v2 recomendado:
docker compose. - Alternativa compatible si el entorno solo tiene Compose v1:
docker-compose.
PowerShell:
Copy-Item .env.example .env
docker compose up --buildGit Bash:
cp .env.example .env
docker compose up --buildSi tu entorno no tiene Compose v2, usa:
docker-compose up --buildServicios:
- Backend:
http://localhost:18000 - Swagger:
http://localhost:18000/api/v1/docs - Health:
http://localhost:18000/health - Ready:
http://localhost:18000/ready - Frontend:
http://localhost:15173 - Mock meeting:
http://localhost:15173/mock-meeting/{meetingId} - PostgreSQL:
localhost:25432
Puertos publicados por defecto:
FRONTEND_PORT=15173BACKEND_PORT=18000POSTGRES_PORT=25432
Si necesitas otros, cambia esos valores en .env antes de ejecutar docker compose up --build.
docker compose ps
docker compose logs --tail=200 backend
docker compose logs --tail=200 frontend
docker compose logs --tail=200 db
curl http://localhost:18000/health
curl http://localhost:18000/readyCon Compose v1:
docker-compose ps
docker-compose logs --tail=200 backend
docker-compose logs --tail=200 frontend
docker-compose logs --tail=200 dbQue revisar:
- si
dbno esta healthy, el backend no iniciara migraciones ni seed; - si
backendno esta healthy, revisaCORS_ORIGINS,DATABASE_URLy logs de bootstrap; - si el frontend carga pero no autentica, valida
VITE_API_URLy el estado debackend. - si
docker composeno existe, intentadocker-compose; - si Docker responde
Acceso denegadoal daemon en Windows, ejecuta la terminal con permisos suficientes o revisa Docker Desktop.
Reinicio seguro sin eliminar volumenes:
docker compose restartNo uses down -v salvo que quieras borrar datos locales y tengas una instruccion explicita para hacerlo.
cd backend
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .env
pytest
alembic upgrade head
python -m app.seed.run
uvicorn app.main:app --reloadEn PowerShell puedes copiar el ejemplo con:
Copy-Item .env.example .envcd frontend
npm install
copy .env.example .env
npm run devEl frontend consume el backend mediante VITE_API_URL. Para Docker, el valor por defecto es http://localhost:18000.
cd backend
alembic upgrade headMigracion incluida:
20260611_0001_initial20260714_0002_catalog_constraints20260714_0003_appointment_active_slot_constraints
Credenciales iniciales:
- Admin:
admin@realmeet.local/Admin123! - Profesional:
professional@realmeet.local/Professional123! - Cliente:
client@realmeet.local/Client123!
Datos iniciales:
- Categorias: Salud, Legal
- Especialidades salud: Psicologia, Medicina General, Nutricion
- Especialidades legal: Derecho Laboral, Derecho Familiar, Derecho Civil
- Profesional demo con disponibilidad de lunes a viernes de 09:00 a 17:00
El seed es idempotente: reutiliza usuarios, categorias, especialidades, perfil profesional, relaciones y reglas de disponibilidad existentes cuando ya fueron creados. No registra passwords en logs.
- Puerto ocupado: cambia
FRONTEND_PORT,BACKEND_PORToPOSTGRES_PORTen.env. - PostgreSQL no saludable: revisa
docker compose logs --tail=200 db. - Migracion fallida: revisa
docker compose logs --tail=200 backend; el backend ejecutaalembic upgrade headantes de iniciar Uvicorn. - Seed fallido: revisa logs backend; el seed hace rollback y registra
seed_failedsin imprimir contrasenas. - Frontend sin conexion: valida
VITE_API_URLyGET http://localhost:18000/ready. - CORS: valida
CORS_ORIGINS; acepta JSON o CSV. - Variables faltantes: backend falla temprano si faltan
SECRET_KEY,DATABASE_URLo CORS queda vacio. - Compose v1 vs v2:
docker composees recomendado;docker-composefunciona como alternativa cuando v2 no esta disponible. - Staging: usa
APP_ENV=staging,DEBUG=false,ENABLE_DEMO_SEED=false,ENABLE_DOCS=falsesi la instancia es publica,CORS_ORIGINSexplicito ySECRET_KEYfuerte de 32+ caracteres.
- Login rechaza usuarios inactivos.
- JWT valida firma, expiracion y
subnumerico. - Token ausente, invalido, vencido o asociado a usuario inactivo responde
401. - Usuario autenticado sin rol permitido responde
403. /auth/meno expone password, hash ni token./users/meusa contrato propio y no permite modificarroleniis_active.- Perfil cliente propio:
GET/PATCH /users/me/profile, solo paraclient. - Perfil profesional propio:
POST /professionals/profile,GET/PATCH /professionals/me/profile, solo paraprofessional, sincategory_id,specialty_ids,price,is_public, verificaciones ni licencia. - Frontend limpia sesion ante
401, restaura sesion con/auth/me, restringe rutas por rol y logout limpia token/usuario. - Backend agrega headers basicos de seguridad:
X-Content-Type-Options,X-Frame-Options,Referrer-Policy,Permissions-PolicyyCache-Control: no-storeen rutas sensibles. - Login y creacion de reservas tienen rate limiting en memoria configurable mediante
RATE_LIMIT_*. - Swagger/OpenAPI se controla con
ENABLE_DOCS; no eliminar la documentacion en desarrollo. - El seed demo se controla con
ENABLE_DEMO_SEED; en staging publico debe estar deshabilitado y las credenciales demo deben rotarse o desactivarse.
Deuda tecnica aceptada:
- El token sigue en
localStorage; migrar a cookiesHttpOnly/SameSitequeda para hardening posterior. - El rate limiter en memoria es solo para una instancia; produccion multi-instancia requiere Redis, gateway o WAF.
npm auditinforma 5 vulnerabilidades:axioshigh,react-router/react-router-domhigh,vitehigh ypostcssmoderate. No se ejecutonpm audit fix --forceporque requiere cambios fuera de rango y fuera de alcance del modulo.
Estos comandos son para el servicio db de Docker Compose y no borran volumenes. Guarda los archivos fuera del repositorio.
Crear backup:
docker-compose exec -T db pg_dump -U realmeet -d realmeet -Fc > backups/realmeet-YYYYMMDD.dumpValidar contenido del backup:
docker-compose exec -T db pg_restore --list < backups/realmeet-YYYYMMDD.dumpRestaurar en una base aislada o staging temporal:
docker-compose exec -T db createdb -U realmeet realmeet_restore_test
docker-compose exec -T db pg_restore -U realmeet -d realmeet_restore_test --clean --if-exists < backups/realmeet-YYYYMMDD.dumpNo restaures sobre la base activa sin backup previo, ventana de mantenimiento y plan de rollback. No uses docker-compose down -v para probar restauraciones.
Politica del proyecto:
- Solo dependencias open source compatibles con uso comercial
- Preferencia por
MIT,BSD-3-Clause,Apache-2.0yPostgreSQL License - Se evitan
GPLyAGPL
Principales dependencias documentadas:
- FastAPI - MIT
- Uvicorn - BSD-3-Clause
- SQLAlchemy - MIT
- Alembic - MIT
- pg8000 - BSD-3-Clause
- Pydantic - MIT
- pydantic-settings - MIT
- PyJWT - MIT
- passlib - BSD
- APScheduler - MIT
- python-dotenv - BSD-3-Clause
- React - MIT
- React DOM - MIT
- Vite - MIT
- TypeScript - Apache-2.0
- Tailwind CSS - MIT
- React Router - MIT
- Axios - MIT
- TanStack Query - MIT
- Zustand - MIT
- PostgreSQL - PostgreSQL License
PATCH /admin/appointments/{id}/status recibe un body con new_status y reason, usando el contrato AppointmentStatusUpdate. No se aceptan campos de notas privadas del profesional en contratos administrativos de reservas.
El cierre del Modulo 8 consolida el MVP para desarrollo local y demo controlada: autenticacion, roles, perfiles, catalogo, disponibilidad, reservas, historial, reuniones mock, notificaciones, dashboards, metricas, backoffice minimo y auditoria administrativa basica.
Readiness:
- Desarrollo local: listo si pasan las validaciones finales documentadas en
specs/modules/module-08-mvp-closure/validation-report.md. - Demo: apto para demo controlada con datos no reales.
- Staging: preparado con checklist previo en
specs/modules/module-08-mvp-closure/staging-checklist.md. - Produccion: no listo; requiere hardening, secretos reales, HTTPS, backups, monitoreo, SAST/SCA, rate limiting y operacion.
- Uso clinico real: no listo; requiere privacidad clinica, consentimiento, retencion, auditoria regulatoria y cumplimiento legal.
Modulo 9 agrega hardening tecnico para staging: settings por entorno, rechazo de secretos inseguros en staging/production, headers HTTP, rate limiting basico, Swagger configurable, seed demo configurable, Docker no root cuando es viable y documentacion de backup/restauracion.
El repositorio tiene commits incrementales por modulo. El Modulo 8 debe cerrarse con un unico commit y sin push salvo instruccion explicita.
- Integraciones reales con Google Meet y Zoom no implementadas.
- WhatsApp, pagos, suscripciones y facturacion quedan diferidos.
- Recuperacion de contrasena, MFA y roles configurables quedan diferidos.
- Pruebas frontend automaticas y E2E completas quedan diferidas.
- El backoffice es minimo y prioriza operacion inicial sobre cobertura total de UX.
- Reprogramacion, recordatorios avanzados y correos transaccionales completos quedan fuera del MVP.
- Produccion y uso clinico real requieren hardening y cumplimiento adicional.