elevenlabs-webhook-nodejs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +27 -0
- package/.dockerignore +6 -0
- package/.env.example +43 -0
- package/BEFORE-PRODUCTION.md +32 -0
- package/Dockerfile +23 -0
- package/SYSTEM_OVERVIEW.md +942 -0
- package/SYSTEM_STATUS.md +332 -0
- package/backup_script/main.py +146 -0
- package/baileys/.dockerignore +7 -0
- package/baileys/Dockerfile +13 -0
- package/baileys/README.md +412 -0
- package/baileys/index.js +499 -0
- package/baileys/package-lock.json +2532 -0
- package/baileys/package.json +25 -0
- package/baileys/server.js +96 -0
- package/baileys/src/config.js +55 -0
- package/baileys/src/middleware/api-key.js +16 -0
- package/baileys/src/routes/accounts.js +51 -0
- package/baileys/src/routes/chats.js +103 -0
- package/baileys/src/routes/webhooks.js +34 -0
- package/baileys/src/services/account-store.js +259 -0
- package/baileys/src/services/webhook-dispatcher.js +161 -0
- package/baileys/src/services/worker-manager.js +597 -0
- package/baileys/src/utils/jid.js +79 -0
- package/baileys/src/utils/logger.js +16 -0
- package/baileys/src/utils/use-mongodb-auth-state.js +122 -0
- package/baileys/worker.js +721 -0
- package/dist/app.d.ts +1 -0
- package/dist/app.js +84 -0
- package/dist/app.js.map +1 -0
- package/dist/config/agentPrompts.json +19 -0
- package/dist/config/database.d.ts +1 -0
- package/dist/config/database.js +26 -0
- package/dist/config/database.js.map +1 -0
- package/dist/config/env.d.ts +41 -0
- package/dist/config/env.js +81 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.js +73 -0
- package/dist/config/index.js.map +1 -0
- package/dist/controllers/webhook.controller.d.ts +10 -0
- package/dist/controllers/webhook.controller.js +128 -0
- package/dist/controllers/webhook.controller.js.map +1 -0
- package/dist/errors/index.d.ts +4 -0
- package/dist/errors/index.js +13 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/hooks/webhookValidator.d.ts +2 -0
- package/dist/hooks/webhookValidator.js +47 -0
- package/dist/hooks/webhookValidator.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/001_session-architecture.d.ts +3 -0
- package/dist/migrations/001_session-architecture.js +119 -0
- package/dist/migrations/001_session-architecture.js.map +1 -0
- package/dist/migrations/002_agent-ref.d.ts +3 -0
- package/dist/migrations/002_agent-ref.js +55 -0
- package/dist/migrations/002_agent-ref.js.map +1 -0
- package/dist/migrations/003_shift-schedule.d.ts +3 -0
- package/dist/migrations/003_shift-schedule.js +48 -0
- package/dist/migrations/003_shift-schedule.js.map +1 -0
- package/dist/migrations/004_invert-shift-to-clinic-hours.d.ts +3 -0
- package/dist/migrations/004_invert-shift-to-clinic-hours.js +27 -0
- package/dist/migrations/004_invert-shift-to-clinic-hours.js.map +1 -0
- package/dist/migrations/005_composite-baileys-chat-ids.d.ts +3 -0
- package/dist/migrations/005_composite-baileys-chat-ids.js +47 -0
- package/dist/migrations/005_composite-baileys-chat-ids.js.map +1 -0
- package/dist/migrations/migration.model.d.ts +18 -0
- package/dist/migrations/migration.model.js +45 -0
- package/dist/migrations/migration.model.js.map +1 -0
- package/dist/migrations/migration.routes.d.ts +2 -0
- package/dist/migrations/migration.routes.js +37 -0
- package/dist/migrations/migration.routes.js.map +1 -0
- package/dist/migrations/migration.runner.d.ts +19 -0
- package/dist/migrations/migration.runner.js +74 -0
- package/dist/migrations/migration.runner.js.map +1 -0
- package/dist/models/ConversationClaim.d.ts +13 -0
- package/dist/models/ConversationClaim.js +44 -0
- package/dist/models/ConversationClaim.js.map +1 -0
- package/dist/models/ConversationEvaluation.d.ts +23 -0
- package/dist/models/ConversationEvaluation.js +92 -0
- package/dist/models/ConversationEvaluation.js.map +1 -0
- package/dist/models/Summary.d.ts +37 -0
- package/dist/models/Summary.js +78 -0
- package/dist/models/Summary.js.map +1 -0
- package/dist/models/Transcription.d.ts +34 -0
- package/dist/models/Transcription.js +71 -0
- package/dist/models/Transcription.js.map +1 -0
- package/dist/models/WhatsAppRecipient.d.ts +23 -0
- package/dist/models/WhatsAppRecipient.js +53 -0
- package/dist/models/WhatsAppRecipient.js.map +1 -0
- package/dist/modules/admin/admin.routes.d.ts +2 -0
- package/dist/modules/admin/admin.routes.js +1966 -0
- package/dist/modules/admin/admin.routes.js.map +1 -0
- package/dist/modules/admin/elevenlabs-test-chat.routes.d.ts +2 -0
- package/dist/modules/admin/elevenlabs-test-chat.routes.js +158 -0
- package/dist/modules/admin/elevenlabs-test-chat.routes.js.map +1 -0
- package/dist/modules/admin/whatsapp-test-chat.routes.d.ts +2 -0
- package/dist/modules/admin/whatsapp-test-chat.routes.js +204 -0
- package/dist/modules/admin/whatsapp-test-chat.routes.js.map +1 -0
- package/dist/modules/agents/agent.model.d.ts +38 -0
- package/dist/modules/agents/agent.model.js +92 -0
- package/dist/modules/agents/agent.model.js.map +1 -0
- package/dist/modules/agents/agent.routes.d.ts +2 -0
- package/dist/modules/agents/agent.routes.js +61 -0
- package/dist/modules/agents/agent.routes.js.map +1 -0
- package/dist/modules/appointment-validation/appointment-validation.model.d.ts +76 -0
- package/dist/modules/appointment-validation/appointment-validation.model.js +118 -0
- package/dist/modules/appointment-validation/appointment-validation.model.js.map +1 -0
- package/dist/modules/appointment-validation/appointment-validation.routes.d.ts +2 -0
- package/dist/modules/appointment-validation/appointment-validation.routes.js +202 -0
- package/dist/modules/appointment-validation/appointment-validation.routes.js.map +1 -0
- package/dist/modules/appointment-validation/appointment-validation.service.d.ts +53 -0
- package/dist/modules/appointment-validation/appointment-validation.service.js +827 -0
- package/dist/modules/appointment-validation/appointment-validation.service.js.map +1 -0
- package/dist/modules/auth/auth.model.d.ts +17 -0
- package/dist/modules/auth/auth.model.js +64 -0
- package/dist/modules/auth/auth.model.js.map +1 -0
- package/dist/modules/auth/auth.routes.d.ts +2 -0
- package/dist/modules/auth/auth.routes.js +202 -0
- package/dist/modules/auth/auth.routes.js.map +1 -0
- package/dist/modules/auth/auth.service.d.ts +28 -0
- package/dist/modules/auth/auth.service.js +183 -0
- package/dist/modules/auth/auth.service.js.map +1 -0
- package/dist/modules/auth/refresh-token.model.d.ts +13 -0
- package/dist/modules/auth/refresh-token.model.js +52 -0
- package/dist/modules/auth/refresh-token.model.js.map +1 -0
- package/dist/modules/billing/billing-alert.model.d.ts +16 -0
- package/dist/modules/billing/billing-alert.model.js +47 -0
- package/dist/modules/billing/billing-alert.model.js.map +1 -0
- package/dist/modules/billing/billing-period-snapshot.model.d.ts +35 -0
- package/dist/modules/billing/billing-period-snapshot.model.js +68 -0
- package/dist/modules/billing/billing-period-snapshot.model.js.map +1 -0
- package/dist/modules/billing/billing.model.d.ts +18 -0
- package/dist/modules/billing/billing.model.js +62 -0
- package/dist/modules/billing/billing.model.js.map +1 -0
- package/dist/modules/billing/billing.routes.d.ts +2 -0
- package/dist/modules/billing/billing.routes.js +63 -0
- package/dist/modules/billing/billing.routes.js.map +1 -0
- package/dist/modules/billing/billing.service.d.ts +69 -0
- package/dist/modules/billing/billing.service.js +498 -0
- package/dist/modules/billing/billing.service.js.map +1 -0
- package/dist/modules/billing/payment.model.d.ts +24 -0
- package/dist/modules/billing/payment.model.js +57 -0
- package/dist/modules/billing/payment.model.js.map +1 -0
- package/dist/modules/calls/call.model.d.ts +41 -0
- package/dist/modules/calls/call.model.js +97 -0
- package/dist/modules/calls/call.model.js.map +1 -0
- package/dist/modules/calls/call.routes.d.ts +2 -0
- package/dist/modules/calls/call.routes.js +103 -0
- package/dist/modules/calls/call.routes.js.map +1 -0
- package/dist/modules/campaigns/campaign.model.d.ts +45 -0
- package/dist/modules/campaigns/campaign.model.js +98 -0
- package/dist/modules/campaigns/campaign.model.js.map +1 -0
- package/dist/modules/campaigns/campaign.routes.d.ts +2 -0
- package/dist/modules/campaigns/campaign.routes.js +323 -0
- package/dist/modules/campaigns/campaign.routes.js.map +1 -0
- package/dist/modules/campaigns/campaign.service.d.ts +11 -0
- package/dist/modules/campaigns/campaign.service.js +86 -0
- package/dist/modules/campaigns/campaign.service.js.map +1 -0
- package/dist/modules/google-calendar/google-calendar.routes.d.ts +2 -0
- package/dist/modules/google-calendar/google-calendar.routes.js +32 -0
- package/dist/modules/google-calendar/google-calendar.routes.js.map +1 -0
- package/dist/modules/inbound-call/inbound-call-config.model.d.ts +20 -0
- package/dist/modules/inbound-call/inbound-call-config.model.js +68 -0
- package/dist/modules/inbound-call/inbound-call-config.model.js.map +1 -0
- package/dist/modules/inbound-call/inbound-call.routes.d.ts +2 -0
- package/dist/modules/inbound-call/inbound-call.routes.js +243 -0
- package/dist/modules/inbound-call/inbound-call.routes.js.map +1 -0
- package/dist/modules/leads/lead.model.d.ts +24 -0
- package/dist/modules/leads/lead.model.js +54 -0
- package/dist/modules/leads/lead.model.js.map +1 -0
- package/dist/modules/leads/lead.routes.d.ts +2 -0
- package/dist/modules/leads/lead.routes.js +201 -0
- package/dist/modules/leads/lead.routes.js.map +1 -0
- package/dist/modules/plans/plan.model.d.ts +25 -0
- package/dist/modules/plans/plan.model.js +59 -0
- package/dist/modules/plans/plan.model.js.map +1 -0
- package/dist/modules/surveys/survey.model.d.ts +30 -0
- package/dist/modules/surveys/survey.model.js +75 -0
- package/dist/modules/surveys/survey.model.js.map +1 -0
- package/dist/modules/surveys/survey.routes.d.ts +2 -0
- package/dist/modules/surveys/survey.routes.js +153 -0
- package/dist/modules/surveys/survey.routes.js.map +1 -0
- package/dist/modules/tenants/tenant.model.d.ts +86 -0
- package/dist/modules/tenants/tenant.model.js +127 -0
- package/dist/modules/tenants/tenant.model.js.map +1 -0
- package/dist/modules/tenants/tenant.routes.d.ts +2 -0
- package/dist/modules/tenants/tenant.routes.js +65 -0
- package/dist/modules/tenants/tenant.routes.js.map +1 -0
- package/dist/modules/users/user.routes.d.ts +2 -0
- package/dist/modules/users/user.routes.js +106 -0
- package/dist/modules/users/user.routes.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs-tool.routes.d.ts +20 -0
- package/dist/modules/webhooks/elevenlabs-tool.routes.js +85 -0
- package/dist/modules/webhooks/elevenlabs-tool.routes.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs-tool.service.d.ts +11 -0
- package/dist/modules/webhooks/elevenlabs-tool.service.js +360 -0
- package/dist/modules/webhooks/elevenlabs-tool.service.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs.routes.d.ts +2 -0
- package/dist/modules/webhooks/elevenlabs.routes.js +34 -0
- package/dist/modules/webhooks/elevenlabs.routes.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs.service.d.ts +6 -0
- package/dist/modules/webhooks/elevenlabs.service.js +512 -0
- package/dist/modules/webhooks/elevenlabs.service.js.map +1 -0
- package/dist/modules/webhooks/unipile.routes.d.ts +2 -0
- package/dist/modules/webhooks/unipile.routes.js +780 -0
- package/dist/modules/webhooks/unipile.routes.js.map +1 -0
- package/dist/modules/whatsapp/appointment.model.d.ts +27 -0
- package/dist/modules/whatsapp/appointment.model.js +58 -0
- package/dist/modules/whatsapp/appointment.model.js.map +1 -0
- package/dist/modules/whatsapp/operator-request.model.d.ts +29 -0
- package/dist/modules/whatsapp/operator-request.model.js +65 -0
- package/dist/modules/whatsapp/operator-request.model.js.map +1 -0
- package/dist/modules/whatsapp/stt-usage.model.d.ts +16 -0
- package/dist/modules/whatsapp/stt-usage.model.js +53 -0
- package/dist/modules/whatsapp/stt-usage.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-chat.model.d.ts +23 -0
- package/dist/modules/whatsapp/whatsapp-chat.model.js +55 -0
- package/dist/modules/whatsapp/whatsapp-chat.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-contact-profile.model.d.ts +23 -0
- package/dist/modules/whatsapp/whatsapp-contact-profile.model.js +54 -0
- package/dist/modules/whatsapp/whatsapp-contact-profile.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-message.model.d.ts +30 -0
- package/dist/modules/whatsapp/whatsapp-message.model.js +52 -0
- package/dist/modules/whatsapp/whatsapp-message.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-session.model.d.ts +33 -0
- package/dist/modules/whatsapp/whatsapp-session.model.js +65 -0
- package/dist/modules/whatsapp/whatsapp-session.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp.routes.d.ts +2 -0
- package/dist/modules/whatsapp/whatsapp.routes.js +1237 -0
- package/dist/modules/whatsapp/whatsapp.routes.js.map +1 -0
- package/dist/plugins/cors.d.ts +3 -0
- package/dist/plugins/cors.js +11 -0
- package/dist/plugins/cors.js.map +1 -0
- package/dist/plugins/jwt.d.ts +3 -0
- package/dist/plugins/jwt.js +22 -0
- package/dist/plugins/jwt.js.map +1 -0
- package/dist/plugins/rawBody.d.ts +3 -0
- package/dist/plugins/rawBody.js +16 -0
- package/dist/plugins/rawBody.js.map +1 -0
- package/dist/plugins/rbac.d.ts +5 -0
- package/dist/plugins/rbac.js +29 -0
- package/dist/plugins/rbac.js.map +1 -0
- package/dist/routes/admin.routes.d.ts +2 -0
- package/dist/routes/admin.routes.js +169 -0
- package/dist/routes/admin.routes.js.map +1 -0
- package/dist/routes/health.routes.d.ts +2 -0
- package/dist/routes/health.routes.js +16 -0
- package/dist/routes/health.routes.js.map +1 -0
- package/dist/routes/webhook.routes.d.ts +2 -0
- package/dist/routes/webhook.routes.js +17 -0
- package/dist/routes/webhook.routes.js.map +1 -0
- package/dist/services/ai/base.ai.d.ts +19 -0
- package/dist/services/ai/base.ai.js +120 -0
- package/dist/services/ai/base.ai.js.map +1 -0
- package/dist/services/ai/gemini.service.d.ts +11 -0
- package/dist/services/ai/gemini.service.js +43 -0
- package/dist/services/ai/gemini.service.js.map +1 -0
- package/dist/services/ai/index.d.ts +2 -0
- package/dist/services/ai/index.js +26 -0
- package/dist/services/ai/index.js.map +1 -0
- package/dist/services/ai/openai.service.d.ts +11 -0
- package/dist/services/ai/openai.service.js +50 -0
- package/dist/services/ai/openai.service.js.map +1 -0
- package/dist/services/elevenlabs.service.d.ts +52 -0
- package/dist/services/elevenlabs.service.js +447 -0
- package/dist/services/elevenlabs.service.js.map +1 -0
- package/dist/services/google-calendar.service.d.ts +60 -0
- package/dist/services/google-calendar.service.js +494 -0
- package/dist/services/google-calendar.service.js.map +1 -0
- package/dist/services/inbound-call-schedule.service.d.ts +11 -0
- package/dist/services/inbound-call-schedule.service.js +162 -0
- package/dist/services/inbound-call-schedule.service.js.map +1 -0
- package/dist/services/netgsm.service.d.ts +41 -0
- package/dist/services/netgsm.service.js +89 -0
- package/dist/services/netgsm.service.js.map +1 -0
- package/dist/services/unipile.service.d.ts +41 -0
- package/dist/services/unipile.service.js +149 -0
- package/dist/services/unipile.service.js.map +1 -0
- package/dist/services/whatsapp-agent.service.d.ts +139 -0
- package/dist/services/whatsapp-agent.service.js +2055 -0
- package/dist/services/whatsapp-agent.service.js.map +1 -0
- package/dist/services/whatsapp.service.d.ts +26 -0
- package/dist/services/whatsapp.service.js +206 -0
- package/dist/services/whatsapp.service.js.map +1 -0
- package/dist/templates/index.d.ts +39 -0
- package/dist/templates/index.js +35 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/receptionist.d.ts +2 -0
- package/dist/templates/receptionist.js +39 -0
- package/dist/templates/receptionist.js.map +1 -0
- package/dist/templates/survey.d.ts +2 -0
- package/dist/templates/survey.js +41 -0
- package/dist/templates/survey.js.map +1 -0
- package/dist/types/index.d.ts +173 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.js +105 -0
- package/dist/utils/logger.js.map +1 -0
- package/docker-compose.nestjs.yml +89 -0
- package/docker-compose.yml +78 -0
- package/docs/AI_AGENT_ENHANCEMENT_PLAN.md +164 -0
- package/docs/API.md +1193 -0
- package/docs/API_ENDPOINTS.md +344 -0
- package/docs/ARCHITECTURE.md +305 -0
- package/docs/AUTH_API.md +252 -0
- package/docs/BILLING_SMS_ALERTS.md +94 -0
- package/docs/CHAT_ASSIGNMENT_SYSTEM.md +118 -0
- package/docs/CLIENT_TOOLS_AND_FEATURES.md +337 -0
- package/docs/ELEVENLABS_WEBHOOK_TOOLS.md +644 -0
- package/docs/FRONTEND_CHECKLIST.md +227 -0
- package/docs/IMPLEMENTATION_STATUS.md +470 -0
- package/docs/MIGRATION_GUIDE.md +96 -0
- package/docs/MISSINGS_REPORT.md +507 -0
- package/docs/NESTJS_MIGRATION_REFERENCE.md +5136 -0
- package/docs/PROJECT_DESCRIPTION.md +1038 -0
- package/docs/SCALING.md +148 -0
- package/docs/SESSION_SUMMARY_2026_03_17.md +135 -0
- package/docs/WHATSAPP_AGENT.md +1086 -0
- package/docs/architecture/00-SYSTEM-OVERVIEW.md +318 -0
- package/docs/architecture/01-DATABASE-SCHEMA.md +2564 -0
- package/docs/architecture/02-AUTHENTICATION.md +1040 -0
- package/docs/architecture/03-MULTI-CLINIC.md +742 -0
- package/docs/architecture/04-WHATSAPP-AGENT.md +608 -0
- package/docs/architecture/05-OPERATOR-WORKFLOW.md +444 -0
- package/docs/architecture/06-BAILEYS-MICROSERVICE.md +616 -0
- package/docs/architecture/07-APPOINTMENTS.md +849 -0
- package/docs/architecture/08-VOICE-CALLS.md +470 -0
- package/docs/architecture/09-OUTBOUND-CAMPAIGNS.md +542 -0
- package/docs/architecture/10-CLIENT-TOOLS.md +665 -0
- package/docs/architecture/11-BILLING.md +458 -0
- package/docs/architecture/12-SECURITY.md +216 -0
- package/docs/architecture/13-LOGGING-AUDIT.md +549 -0
- package/docs/architecture/14-META-BUSINESS-API.md +454 -0
- package/docs/architecture/15-AI-MODULE.md +479 -0
- package/docs/architecture/16-BACKGROUND-JOBS.md +469 -0
- package/docs/architecture/17-REALTIME-LIVECHAT.md +447 -0
- package/docs/architecture/18-FILE-STORAGE.md +410 -0
- package/docs/architecture/19-PATIENTS.md +1034 -0
- package/docs/architecture/20-TREATMENTS-AND-PLANS.md +774 -0
- package/docs/architecture/21-BEFORE-AFTER-PHOTOS.md +519 -0
- package/docs/database.md +456 -0
- package/docs/ornek-randevu-onay.csv +3 -0
- package/ecosystem.config.js +16 -0
- package/elevenlabs-convai-api-reference.md +1171 -0
- package/frontend/.dockerignore +2 -0
- package/frontend/Dockerfile +24 -0
- package/frontend/README.md +75 -0
- package/frontend/components.json +25 -0
- package/frontend/eslint.config.js +23 -0
- package/frontend/index.html +13 -0
- package/frontend/nginx.conf +37 -0
- package/frontend/package-lock.json +8709 -0
- package/frontend/package.json +71 -0
- package/frontend/public/favicon.svg +1 -0
- package/frontend/public/icons.svg +24 -0
- package/frontend/src/App.tsx +125 -0
- package/frontend/src/components/error-boundary.tsx +50 -0
- package/frontend/src/components/shared/activity-timeline.tsx +66 -0
- package/frontend/src/components/shared/appointment-calendar.css +80 -0
- package/frontend/src/components/shared/appointment-calendar.tsx +245 -0
- package/frontend/src/components/shared/chat-bubble.tsx +72 -0
- package/frontend/src/components/shared/combobox.tsx +119 -0
- package/frontend/src/components/shared/confirm-dialog.tsx +57 -0
- package/frontend/src/components/shared/data-table-pagination.tsx +97 -0
- package/frontend/src/components/shared/data-table-toolbar.tsx +39 -0
- package/frontend/src/components/shared/empty-state.tsx +27 -0
- package/frontend/src/components/shared/file-upload.tsx +140 -0
- package/frontend/src/components/shared/index.ts +20 -0
- package/frontend/src/components/shared/language-switcher.tsx +29 -0
- package/frontend/src/components/shared/notification-dropdown.tsx +115 -0
- package/frontend/src/components/shared/page-header.tsx +23 -0
- package/frontend/src/components/shared/stat-card.tsx +37 -0
- package/frontend/src/components/shared/status-badge.tsx +70 -0
- package/frontend/src/components/shared/status-dot.tsx +43 -0
- package/frontend/src/components/ui/alert-dialog.tsx +187 -0
- package/frontend/src/components/ui/alert.tsx +76 -0
- package/frontend/src/components/ui/avatar.tsx +109 -0
- package/frontend/src/components/ui/badge.tsx +52 -0
- package/frontend/src/components/ui/breadcrumb.tsx +125 -0
- package/frontend/src/components/ui/button.tsx +60 -0
- package/frontend/src/components/ui/calendar.tsx +219 -0
- package/frontend/src/components/ui/card.tsx +103 -0
- package/frontend/src/components/ui/chart.tsx +371 -0
- package/frontend/src/components/ui/checkbox.tsx +29 -0
- package/frontend/src/components/ui/collapsible.tsx +19 -0
- package/frontend/src/components/ui/command.tsx +194 -0
- package/frontend/src/components/ui/dialog.tsx +158 -0
- package/frontend/src/components/ui/dropdown-menu.tsx +268 -0
- package/frontend/src/components/ui/input-group.tsx +156 -0
- package/frontend/src/components/ui/input.tsx +20 -0
- package/frontend/src/components/ui/label.tsx +20 -0
- package/frontend/src/components/ui/pagination.tsx +130 -0
- package/frontend/src/components/ui/popover.tsx +90 -0
- package/frontend/src/components/ui/progress.tsx +83 -0
- package/frontend/src/components/ui/radio-group.tsx +36 -0
- package/frontend/src/components/ui/scroll-area.tsx +54 -0
- package/frontend/src/components/ui/select.tsx +199 -0
- package/frontend/src/components/ui/separator.tsx +23 -0
- package/frontend/src/components/ui/sheet.tsx +138 -0
- package/frontend/src/components/ui/sidebar.tsx +723 -0
- package/frontend/src/components/ui/skeleton.tsx +13 -0
- package/frontend/src/components/ui/sonner.tsx +47 -0
- package/frontend/src/components/ui/switch.tsx +30 -0
- package/frontend/src/components/ui/table.tsx +114 -0
- package/frontend/src/components/ui/tabs.tsx +82 -0
- package/frontend/src/components/ui/textarea.tsx +18 -0
- package/frontend/src/components/ui/toggle-group.tsx +89 -0
- package/frontend/src/components/ui/toggle.tsx +43 -0
- package/frontend/src/components/ui/tooltip.tsx +64 -0
- package/frontend/src/hooks/use-mobile.ts +19 -0
- package/frontend/src/i18n/index.ts +20 -0
- package/frontend/src/i18n/locales/en.json +786 -0
- package/frontend/src/i18n/locales/tr.json +786 -0
- package/frontend/src/index.css +134 -0
- package/frontend/src/layouts/admin-layout.tsx +111 -0
- package/frontend/src/layouts/app-header.tsx +130 -0
- package/frontend/src/layouts/app-layout.tsx +19 -0
- package/frontend/src/layouts/app-sidebar.tsx +212 -0
- package/frontend/src/layouts/auth-guard.tsx +31 -0
- package/frontend/src/layouts/mobile-sidebar.tsx +120 -0
- package/frontend/src/lib/api.ts +68 -0
- package/frontend/src/lib/hooks/use-appointments.ts +224 -0
- package/frontend/src/lib/hooks/use-availability-blocks.ts +83 -0
- package/frontend/src/lib/hooks/use-chats.ts +236 -0
- package/frontend/src/lib/hooks/use-clinic-detail.ts +171 -0
- package/frontend/src/lib/hooks/use-clinics.ts +37 -0
- package/frontend/src/lib/hooks/use-doctor-calendar.ts +80 -0
- package/frontend/src/lib/hooks/use-examinations.ts +89 -0
- package/frontend/src/lib/hooks/use-medical-history.ts +52 -0
- package/frontend/src/lib/hooks/use-patients.ts +296 -0
- package/frontend/src/lib/hooks/use-photo-sets.ts +118 -0
- package/frontend/src/lib/hooks/use-treatment-plans.ts +152 -0
- package/frontend/src/lib/hooks/use-treatments.ts +125 -0
- package/frontend/src/lib/hooks/use-users.ts +172 -0
- package/frontend/src/lib/utils.ts +6 -0
- package/frontend/src/main.tsx +17 -0
- package/frontend/src/pages/admin/agents/detail.tsx +774 -0
- package/frontend/src/pages/admin/agents/import.tsx +280 -0
- package/frontend/src/pages/admin/agents/index.tsx +245 -0
- package/frontend/src/pages/admin/ai-playground.tsx +543 -0
- package/frontend/src/pages/appointments/create-appointment-dialog.tsx +390 -0
- package/frontend/src/pages/appointments/index.tsx +860 -0
- package/frontend/src/pages/audit/index.tsx +24 -0
- package/frontend/src/pages/auth/login.tsx +194 -0
- package/frontend/src/pages/billing/index.tsx +24 -0
- package/frontend/src/pages/calendar/index.tsx +704 -0
- package/frontend/src/pages/calendar-connections/index.tsx +295 -0
- package/frontend/src/pages/calls/index.tsx +24 -0
- package/frontend/src/pages/campaigns/index.tsx +24 -0
- package/frontend/src/pages/chats/index.tsx +981 -0
- package/frontend/src/pages/clinics/index.tsx +224 -0
- package/frontend/src/pages/clinics/settings.tsx +412 -0
- package/frontend/src/pages/components-showcase.tsx +773 -0
- package/frontend/src/pages/connections/index.tsx +328 -0
- package/frontend/src/pages/dashboard.tsx +50 -0
- package/frontend/src/pages/leads/index.tsx +24 -0
- package/frontend/src/pages/my-schedule/index.tsx +496 -0
- package/frontend/src/pages/patients/create-patient-dialog.tsx +358 -0
- package/frontend/src/pages/patients/detail.tsx +1195 -0
- package/frontend/src/pages/patients/edit-patient-dialog.tsx +387 -0
- package/frontend/src/pages/patients/examinations-tab.tsx +460 -0
- package/frontend/src/pages/patients/index.tsx +381 -0
- package/frontend/src/pages/patients/medical-history-dialog.tsx +207 -0
- package/frontend/src/pages/patients/photo-sets-tab.tsx +616 -0
- package/frontend/src/pages/patients/timeline-tab.tsx +164 -0
- package/frontend/src/pages/patients/treatment-plans-tab.tsx +598 -0
- package/frontend/src/pages/phone-numbers/detail.tsx +427 -0
- package/frontend/src/pages/phone-numbers/index.tsx +455 -0
- package/frontend/src/pages/platform/index.tsx +454 -0
- package/frontend/src/pages/settings/index.tsx +126 -0
- package/frontend/src/pages/treatments/index.tsx +487 -0
- package/frontend/src/pages/users/doctor-profile.tsx +672 -0
- package/frontend/src/pages/users/edit.tsx +329 -0
- package/frontend/src/pages/users/index.tsx +407 -0
- package/frontend/src/pages/validation/index.tsx +24 -0
- package/frontend/src/stores/auth.store.ts +108 -0
- package/frontend/src/stores/ui.store.ts +41 -0
- package/frontend/tsconfig.app.json +32 -0
- package/frontend/tsconfig.json +13 -0
- package/frontend/tsconfig.node.json +26 -0
- package/frontend/vite.config.ts +29 -0
- package/nestjs/.dockerignore +5 -0
- package/nestjs/.env.docker +64 -0
- package/nestjs/.prettierrc +4 -0
- package/nestjs/Dockerfile +36 -0
- package/nestjs/README.md +98 -0
- package/nestjs/eslint.config.mjs +35 -0
- package/nestjs/nest-cli.json +8 -0
- package/nestjs/package-lock.json +13390 -0
- package/nestjs/package.json +114 -0
- package/nestjs/prisma/migrations/20260409161536_add_message_metadata_fields/migration.sql +1746 -0
- package/nestjs/prisma/migrations/20260410140436_add_agent_ai_fields/migration.sql +36 -0
- package/nestjs/prisma/migrations/20260410175519_add_agent_clinic_assignments/migration.sql +21 -0
- package/nestjs/prisma/migrations/20260412094344_make_agent_tenant_optional/migration.sql +2 -0
- package/nestjs/prisma/migrations/20260412110008_add_admin_chat_sessions/migration.sql +47 -0
- package/nestjs/prisma/migrations/migration_lock.toml +3 -0
- package/nestjs/prisma/schema.prisma +1843 -0
- package/nestjs/prisma/seed.ts +375 -0
- package/nestjs/prisma.config.ts +14 -0
- package/nestjs/src/admin/admin.controller.ts +27 -0
- package/nestjs/src/admin/admin.module.ts +16 -0
- package/nestjs/src/admin/admin.service.ts +91 -0
- package/nestjs/src/admin/ai-chat-session.service.ts +454 -0
- package/nestjs/src/admin/ai-test.controller.ts +191 -0
- package/nestjs/src/admin/superadmin.controller.ts +106 -0
- package/nestjs/src/agents/agents.controller.ts +262 -0
- package/nestjs/src/agents/agents.module.ts +13 -0
- package/nestjs/src/agents/agents.service.ts +733 -0
- package/nestjs/src/agents/dto/create-agent.dto.ts +99 -0
- package/nestjs/src/agents/dto/index.ts +2 -0
- package/nestjs/src/agents/dto/update-agent.dto.ts +148 -0
- package/nestjs/src/app.module.ts +115 -0
- package/nestjs/src/appointment-validation/appointment-validation.controller.ts +194 -0
- package/nestjs/src/appointment-validation/appointment-validation.module.ts +16 -0
- package/nestjs/src/appointment-validation/appointment-validation.service.ts +450 -0
- package/nestjs/src/appointment-validation/dto/create-batch.dto.ts +105 -0
- package/nestjs/src/appointment-validation/dto/index.ts +1 -0
- package/nestjs/src/appointment-validation/processors/validation-dispatch.processor.ts +26 -0
- package/nestjs/src/appointment-validation/processors/validation-sync.processor.ts +23 -0
- package/nestjs/src/appointments/appointments.controller.ts +268 -0
- package/nestjs/src/appointments/appointments.module.ts +13 -0
- package/nestjs/src/appointments/appointments.service.ts +773 -0
- package/nestjs/src/appointments/dto/create-appointment.dto.ts +72 -0
- package/nestjs/src/appointments/dto/index.ts +4 -0
- package/nestjs/src/appointments/dto/query-appointments.dto.ts +60 -0
- package/nestjs/src/appointments/dto/update-appointment.dto.ts +43 -0
- package/nestjs/src/appointments/dto/update-status.dto.ts +18 -0
- package/nestjs/src/appointments/processors/reminder.processor.ts +243 -0
- package/nestjs/src/audit/audit.controller.ts +84 -0
- package/nestjs/src/audit/audit.decorator.ts +20 -0
- package/nestjs/src/audit/audit.interceptor.ts +67 -0
- package/nestjs/src/audit/audit.interfaces.ts +15 -0
- package/nestjs/src/audit/audit.module.ts +12 -0
- package/nestjs/src/audit/audit.service.ts +177 -0
- package/nestjs/src/auth/auth.controller.ts +116 -0
- package/nestjs/src/auth/auth.module.ts +25 -0
- package/nestjs/src/auth/auth.service.ts +612 -0
- package/nestjs/src/auth/dto/change-password.dto.ts +13 -0
- package/nestjs/src/auth/dto/forgot-password.dto.ts +8 -0
- package/nestjs/src/auth/dto/index.ts +6 -0
- package/nestjs/src/auth/dto/login.dto.ts +13 -0
- package/nestjs/src/auth/dto/refresh.dto.ts +8 -0
- package/nestjs/src/auth/dto/register.dto.ts +28 -0
- package/nestjs/src/auth/dto/reset-password.dto.ts +13 -0
- package/nestjs/src/auth/permissions.config.ts +85 -0
- package/nestjs/src/availability-blocks/availability-blocks.controller.ts +83 -0
- package/nestjs/src/availability-blocks/availability-blocks.module.ts +10 -0
- package/nestjs/src/availability-blocks/availability-blocks.service.ts +202 -0
- package/nestjs/src/billing/billing.controller.ts +104 -0
- package/nestjs/src/billing/billing.module.ts +12 -0
- package/nestjs/src/billing/billing.service.ts +398 -0
- package/nestjs/src/billing/dto/index.ts +2 -0
- package/nestjs/src/billing/dto/query-billing.dto.ts +29 -0
- package/nestjs/src/billing/dto/record-payment.dto.ts +60 -0
- package/nestjs/src/billing/processors/alerts.processor.ts +216 -0
- package/nestjs/src/billing/processors/snapshot.processor.ts +181 -0
- package/nestjs/src/calls/calls.controller.ts +92 -0
- package/nestjs/src/calls/calls.module.ts +10 -0
- package/nestjs/src/calls/calls.service.ts +359 -0
- package/nestjs/src/calls/dto/index.ts +1 -0
- package/nestjs/src/calls/dto/query-calls.dto.ts +46 -0
- package/nestjs/src/clinics/clinics.controller.ts +226 -0
- package/nestjs/src/clinics/clinics.module.ts +11 -0
- package/nestjs/src/clinics/clinics.service.ts +203 -0
- package/nestjs/src/clinics/dto/create-clinic.dto.ts +40 -0
- package/nestjs/src/clinics/dto/create-meta-connection.dto.ts +44 -0
- package/nestjs/src/clinics/dto/index.ts +4 -0
- package/nestjs/src/clinics/dto/update-clinic.dto.ts +133 -0
- package/nestjs/src/clinics/dto/update-meta-connection.dto.ts +22 -0
- package/nestjs/src/clinics/meta-connections.service.ts +210 -0
- package/nestjs/src/common/decorators/accessible-clinics.decorator.ts +9 -0
- package/nestjs/src/common/decorators/current-user.decorator.ts +10 -0
- package/nestjs/src/common/decorators/features.decorator.ts +7 -0
- package/nestjs/src/common/decorators/index.ts +4 -0
- package/nestjs/src/common/decorators/permissions.decorator.ts +13 -0
- package/nestjs/src/common/gateways/events.gateway.ts +157 -0
- package/nestjs/src/common/guards/clinic-access.guard.ts +40 -0
- package/nestjs/src/common/guards/features.guard.ts +38 -0
- package/nestjs/src/common/guards/index.ts +5 -0
- package/nestjs/src/common/guards/jwt-auth.guard.ts +54 -0
- package/nestjs/src/common/guards/permissions.guard.ts +50 -0
- package/nestjs/src/common/guards/superadmin.guard.ts +35 -0
- package/nestjs/src/common/interceptors/request-context.interceptor.ts +32 -0
- package/nestjs/src/common/interceptors/superadmin-tenant.interceptor.ts +42 -0
- package/nestjs/src/common/interfaces/jwt-payload.interface.ts +11 -0
- package/nestjs/src/config/config.module.ts +13 -0
- package/nestjs/src/database/database.module.ts +9 -0
- package/nestjs/src/database/prisma.service.ts +20 -0
- package/nestjs/src/database/tenant-context.ts +27 -0
- package/nestjs/src/google-calendar/google-calendar.controller.ts +259 -0
- package/nestjs/src/google-calendar/google-calendar.module.ts +10 -0
- package/nestjs/src/google-calendar/google-calendar.service.ts +811 -0
- package/nestjs/src/integrations/ai/ai.interface.ts +74 -0
- package/nestjs/src/integrations/ai/ai.module.ts +11 -0
- package/nestjs/src/integrations/ai/ai.service.ts +148 -0
- package/nestjs/src/integrations/ai/providers/anthropic.provider.ts +146 -0
- package/nestjs/src/integrations/ai/providers/openai.provider.ts +158 -0
- package/nestjs/src/integrations/elevenlabs/elevenlabs.module.ts +8 -0
- package/nestjs/src/integrations/elevenlabs/elevenlabs.service.ts +226 -0
- package/nestjs/src/integrations/encryption/encryption.module.ts +9 -0
- package/nestjs/src/integrations/encryption/encryption.service.ts +31 -0
- package/nestjs/src/integrations/image/image.module.ts +9 -0
- package/nestjs/src/integrations/image/image.service.ts +61 -0
- package/nestjs/src/integrations/meta-business/meta-business.module.ts +10 -0
- package/nestjs/src/integrations/meta-business/meta-instagram.service.ts +94 -0
- package/nestjs/src/integrations/meta-business/meta-webhook.service.ts +52 -0
- package/nestjs/src/integrations/meta-business/meta-whatsapp.service.ts +254 -0
- package/nestjs/src/integrations/minio/minio.module.ts +9 -0
- package/nestjs/src/integrations/minio/minio.service.ts +88 -0
- package/nestjs/src/integrations/netgsm/netgsm.module.ts +8 -0
- package/nestjs/src/integrations/netgsm/netgsm.service.ts +17 -0
- package/nestjs/src/integrations/tektippay/tektippay.module.ts +8 -0
- package/nestjs/src/integrations/tektippay/tektippay.service.ts +23 -0
- package/nestjs/src/leads/dto/index.ts +2 -0
- package/nestjs/src/leads/dto/query-leads.dto.ts +50 -0
- package/nestjs/src/leads/dto/update-lead.dto.ts +26 -0
- package/nestjs/src/leads/leads.controller.ts +184 -0
- package/nestjs/src/leads/leads.module.ts +10 -0
- package/nestjs/src/leads/leads.service.ts +375 -0
- package/nestjs/src/logging/logging.controller.ts +82 -0
- package/nestjs/src/logging/logging.module.ts +11 -0
- package/nestjs/src/logging/logging.service.ts +180 -0
- package/nestjs/src/main.ts +86 -0
- package/nestjs/src/outbound-campaigns/dto/create-campaign.dto.ts +47 -0
- package/nestjs/src/outbound-campaigns/dto/index.ts +3 -0
- package/nestjs/src/outbound-campaigns/dto/update-campaign.dto.ts +31 -0
- package/nestjs/src/outbound-campaigns/dto/upload-entries.dto.ts +35 -0
- package/nestjs/src/outbound-campaigns/outbound-campaigns.controller.ts +307 -0
- package/nestjs/src/outbound-campaigns/outbound-campaigns.module.ts +13 -0
- package/nestjs/src/outbound-campaigns/outbound-campaigns.service.ts +471 -0
- package/nestjs/src/outbound-campaigns/processors/campaign-dispatch.processor.ts +366 -0
- package/nestjs/src/patients/documents.service.ts +231 -0
- package/nestjs/src/patients/dto/create-examination.dto.ts +34 -0
- package/nestjs/src/patients/dto/create-note.dto.ts +14 -0
- package/nestjs/src/patients/dto/create-patient.dto.ts +86 -0
- package/nestjs/src/patients/dto/create-photo-set.dto.ts +32 -0
- package/nestjs/src/patients/dto/index.ts +10 -0
- package/nestjs/src/patients/dto/update-examination.dto.ts +29 -0
- package/nestjs/src/patients/dto/update-medical-history.dto.ts +47 -0
- package/nestjs/src/patients/dto/update-patient.dto.ts +87 -0
- package/nestjs/src/patients/dto/update-photo-set.dto.ts +28 -0
- package/nestjs/src/patients/dto/upload-document.dto.ts +31 -0
- package/nestjs/src/patients/dto/upload-photo.dto.ts +27 -0
- package/nestjs/src/patients/examinations.service.ts +271 -0
- package/nestjs/src/patients/medical-history.service.ts +149 -0
- package/nestjs/src/patients/notes.service.ts +172 -0
- package/nestjs/src/patients/patients.controller.ts +485 -0
- package/nestjs/src/patients/patients.module.ts +22 -0
- package/nestjs/src/patients/patients.service.ts +412 -0
- package/nestjs/src/patients/photo-sets.service.ts +389 -0
- package/nestjs/src/phone-numbers/dto/create-phone-number.dto.ts +57 -0
- package/nestjs/src/phone-numbers/dto/index.ts +3 -0
- package/nestjs/src/phone-numbers/dto/update-phone-number.dto.ts +38 -0
- package/nestjs/src/phone-numbers/dto/update-schedule.dto.ts +39 -0
- package/nestjs/src/phone-numbers/phone-numbers.controller.ts +125 -0
- package/nestjs/src/phone-numbers/phone-numbers.module.ts +10 -0
- package/nestjs/src/phone-numbers/phone-numbers.service.ts +209 -0
- package/nestjs/src/plans/dto/create-plan.dto.ts +70 -0
- package/nestjs/src/plans/dto/index.ts +2 -0
- package/nestjs/src/plans/dto/update-plan.dto.ts +80 -0
- package/nestjs/src/plans/plans.controller.ts +50 -0
- package/nestjs/src/plans/plans.module.ts +10 -0
- package/nestjs/src/plans/plans.service.ts +115 -0
- package/nestjs/src/platform/dto/create-tenant.dto.ts +36 -0
- package/nestjs/src/platform/dto/index.ts +2 -0
- package/nestjs/src/platform/dto/update-tenant-platform.dto.ts +44 -0
- package/nestjs/src/platform/platform.controller.ts +79 -0
- package/nestjs/src/platform/platform.module.ts +10 -0
- package/nestjs/src/platform/platform.service.ts +301 -0
- package/nestjs/src/queue/queue.module.ts +56 -0
- package/nestjs/src/redis/redis.module.ts +20 -0
- package/nestjs/src/tenants/dto/index.ts +1 -0
- package/nestjs/src/tenants/dto/update-tenant.dto.ts +15 -0
- package/nestjs/src/tenants/tenants.controller.ts +45 -0
- package/nestjs/src/tenants/tenants.module.ts +10 -0
- package/nestjs/src/tenants/tenants.service.ts +41 -0
- package/nestjs/src/tools/adapters/elevenlabs-http.adapter.ts +51 -0
- package/nestjs/src/tools/adapters/elevenlabs-ws.adapter.ts +59 -0
- package/nestjs/src/tools/handlers/calendar.tools.ts +441 -0
- package/nestjs/src/tools/handlers/notification.tools.ts +34 -0
- package/nestjs/src/tools/handlers/operator.tools.ts +303 -0
- package/nestjs/src/tools/handlers/patient.tools.ts +242 -0
- package/nestjs/src/tools/handlers/payment.tools.ts +43 -0
- package/nestjs/src/tools/handlers/validation.tools.ts +152 -0
- package/nestjs/src/tools/tool-registry.service.ts +221 -0
- package/nestjs/src/tools/tool.decorator.ts +16 -0
- package/nestjs/src/tools/tool.interfaces.ts +26 -0
- package/nestjs/src/tools/tools.module.ts +50 -0
- package/nestjs/src/treatments/dto/create-plan-item.dto.ts +27 -0
- package/nestjs/src/treatments/dto/create-treatment-plan.dto.ts +69 -0
- package/nestjs/src/treatments/dto/create-treatment.dto.ts +59 -0
- package/nestjs/src/treatments/dto/index.ts +6 -0
- package/nestjs/src/treatments/dto/update-plan-item.dto.ts +23 -0
- package/nestjs/src/treatments/dto/update-treatment-plan.dto.ts +22 -0
- package/nestjs/src/treatments/dto/update-treatment.dto.ts +70 -0
- package/nestjs/src/treatments/treatment-plans.service.ts +362 -0
- package/nestjs/src/treatments/treatments.controller.ts +265 -0
- package/nestjs/src/treatments/treatments.module.ts +14 -0
- package/nestjs/src/treatments/treatments.service.ts +165 -0
- package/nestjs/src/users/doctor-profiles.service.ts +202 -0
- package/nestjs/src/users/dto/index.ts +4 -0
- package/nestjs/src/users/dto/invite-user.dto.ts +52 -0
- package/nestjs/src/users/dto/update-clinic-assignments.dto.ts +9 -0
- package/nestjs/src/users/dto/update-doctor-profile.dto.ts +49 -0
- package/nestjs/src/users/dto/update-user.dto.ts +41 -0
- package/nestjs/src/users/users.controller.ts +142 -0
- package/nestjs/src/users/users.module.ts +11 -0
- package/nestjs/src/users/users.service.ts +250 -0
- package/nestjs/src/webhooks/elevenlabs-tool.controller.ts +66 -0
- package/nestjs/src/webhooks/elevenlabs-webhook.controller.ts +60 -0
- package/nestjs/src/webhooks/meta-webhook.controller.ts +178 -0
- package/nestjs/src/webhooks/processors/elevenlabs-webhook.processor.ts +28 -0
- package/nestjs/src/webhooks/webhooks.module.ts +17 -0
- package/nestjs/src/whatsapp/chat-context.service.ts +281 -0
- package/nestjs/src/whatsapp/dto/add-blacklist.dto.ts +13 -0
- package/nestjs/src/whatsapp/dto/index.ts +2 -0
- package/nestjs/src/whatsapp/dto/send-message.dto.ts +14 -0
- package/nestjs/src/whatsapp/listeners/meta-message.listener.ts +579 -0
- package/nestjs/src/whatsapp/meta-auth.controller.ts +268 -0
- package/nestjs/src/whatsapp/meta-instagram-auth.controller.ts +244 -0
- package/nestjs/src/whatsapp/operator.service.ts +692 -0
- package/nestjs/src/whatsapp/processors/cost-sweep.processor.ts +130 -0
- package/nestjs/src/whatsapp/processors/grace.processor.ts +191 -0
- package/nestjs/src/whatsapp/processors/message-buffer.processor.ts +138 -0
- package/nestjs/src/whatsapp/processors/message-cleanup.processor.ts +148 -0
- package/nestjs/src/whatsapp/processors/meta-token-refresh.processor.ts +114 -0
- package/nestjs/src/whatsapp/processors/operator-expiry.processor.ts +105 -0
- package/nestjs/src/whatsapp/processors/profile-update.processor.ts +234 -0
- package/nestjs/src/whatsapp/processors/session-cleanup.processor.ts +178 -0
- package/nestjs/src/whatsapp/processors/session-labels.processor.ts +248 -0
- package/nestjs/src/whatsapp/whatsapp-agent.service.ts +2506 -0
- package/nestjs/src/whatsapp/whatsapp-recovery.service.ts +117 -0
- package/nestjs/src/whatsapp/whatsapp.controller.ts +398 -0
- package/nestjs/src/whatsapp/whatsapp.module.ts +51 -0
- package/nestjs/src/whatsapp/whatsapp.service.ts +592 -0
- package/nestjs/test/app.e2e-spec.ts +25 -0
- package/nestjs/test/jest-e2e.json +9 -0
- package/nestjs/tsconfig.build.json +4 -0
- package/nestjs/tsconfig.json +25 -0
- package/nginx.example.conf +18 -0
- package/package.json +47 -0
- package/scripts/addRecipient.ts +48 -0
- package/scripts/listRecipients.ts +31 -0
- package/scripts/migrate-agent-ref.ts +86 -0
- package/scripts/migrate-sessions.ts +183 -0
- package/scripts/promote.ts +27 -0
- package/scripts/retrigger.ts +84 -0
- package/scripts/seed.ts +435 -0
- package/scripts/testSend.ts +63 -0
- package/src/app.ts +85 -0
- package/src/config/agentPrompts.json +19 -0
- package/src/config/database.ts +21 -0
- package/src/config/env.ts +94 -0
- package/src/config/index.ts +86 -0
- package/src/controllers/webhook.controller.ts +150 -0
- package/src/errors/index.ts +9 -0
- package/src/hooks/webhookValidator.ts +55 -0
- package/src/index.ts +68 -0
- package/src/migrations/001_session-architecture.ts +138 -0
- package/src/migrations/002_agent-ref.ts +65 -0
- package/src/migrations/003_shift-schedule.ts +55 -0
- package/src/migrations/004_invert-shift-to-clinic-hours.ts +30 -0
- package/src/migrations/005_composite-baileys-chat-ids.ts +60 -0
- package/src/migrations/migration.model.ts +27 -0
- package/src/migrations/migration.routes.ts +40 -0
- package/src/migrations/migration.runner.ts +112 -0
- package/src/models/ConversationClaim.ts +17 -0
- package/src/models/ConversationEvaluation.ts +91 -0
- package/src/models/Summary.ts +77 -0
- package/src/models/Transcription.ts +68 -0
- package/src/models/WhatsAppRecipient.ts +37 -0
- package/src/modules/admin/admin.routes.ts +2385 -0
- package/src/modules/admin/elevenlabs-test-chat.routes.ts +193 -0
- package/src/modules/admin/whatsapp-test-chat.routes.ts +244 -0
- package/src/modules/agents/agent.model.ts +93 -0
- package/src/modules/agents/agent.routes.ts +65 -0
- package/src/modules/appointment-validation/appointment-validation.model.ts +163 -0
- package/src/modules/appointment-validation/appointment-validation.routes.ts +275 -0
- package/src/modules/appointment-validation/appointment-validation.service.ts +1028 -0
- package/src/modules/auth/auth.model.ts +42 -0
- package/src/modules/auth/auth.routes.ts +199 -0
- package/src/modules/auth/auth.service.ts +210 -0
- package/src/modules/auth/refresh-token.model.ts +26 -0
- package/src/modules/billing/billing-alert.model.ts +28 -0
- package/src/modules/billing/billing-period-snapshot.model.ts +68 -0
- package/src/modules/billing/billing.model.ts +42 -0
- package/src/modules/billing/billing.routes.ts +67 -0
- package/src/modules/billing/billing.service.ts +562 -0
- package/src/modules/billing/payment.model.ts +42 -0
- package/src/modules/calls/call.model.ts +102 -0
- package/src/modules/calls/call.routes.ts +118 -0
- package/src/modules/campaigns/campaign.model.ts +111 -0
- package/src/modules/campaigns/campaign.routes.ts +402 -0
- package/src/modules/campaigns/campaign.service.ts +99 -0
- package/src/modules/google-calendar/google-calendar.routes.ts +31 -0
- package/src/modules/inbound-call/inbound-call-config.model.ts +49 -0
- package/src/modules/inbound-call/inbound-call.routes.ts +289 -0
- package/src/modules/leads/lead.model.ts +40 -0
- package/src/modules/leads/lead.routes.ts +246 -0
- package/src/modules/logs/log.model.ts +27 -0
- package/src/modules/logs/log.routes.ts +102 -0
- package/src/modules/plans/plan.model.ts +45 -0
- package/src/modules/surveys/survey.model.ts +70 -0
- package/src/modules/surveys/survey.routes.ts +187 -0
- package/src/modules/tenants/tenant.model.ts +181 -0
- package/src/modules/tenants/tenant.routes.ts +78 -0
- package/src/modules/users/user.routes.ts +126 -0
- package/src/modules/webhooks/elevenlabs-tool.routes.ts +94 -0
- package/src/modules/webhooks/elevenlabs-tool.service.ts +491 -0
- package/src/modules/webhooks/elevenlabs.routes.ts +34 -0
- package/src/modules/webhooks/elevenlabs.service.ts +565 -0
- package/src/modules/webhooks/unipile.routes.ts +917 -0
- package/src/modules/whatsapp/appointment.model.ts +47 -0
- package/src/modules/whatsapp/operator-request.model.ts +58 -0
- package/src/modules/whatsapp/stt-usage.model.ts +30 -0
- package/src/modules/whatsapp/whatsapp-chat.model.ts +39 -0
- package/src/modules/whatsapp/whatsapp-contact-profile.model.ts +41 -0
- package/src/modules/whatsapp/whatsapp-message.model.ts +41 -0
- package/src/modules/whatsapp/whatsapp-session.model.ts +60 -0
- package/src/modules/whatsapp/whatsapp.routes.ts +1435 -0
- package/src/plugins/cors.ts +7 -0
- package/src/plugins/jwt.ts +18 -0
- package/src/plugins/rawBody.ts +12 -0
- package/src/plugins/rbac.ts +24 -0
- package/src/routes/admin.routes.ts +208 -0
- package/src/routes/health.routes.ts +12 -0
- package/src/routes/webhook.routes.ts +12 -0
- package/src/services/ai/base.ai.ts +132 -0
- package/src/services/ai/gemini.service.ts +41 -0
- package/src/services/ai/index.ts +24 -0
- package/src/services/ai/openai.service.ts +48 -0
- package/src/services/elevenlabs.service.ts +532 -0
- package/src/services/google-calendar.service.ts +656 -0
- package/src/services/inbound-call-schedule.service.ts +174 -0
- package/src/services/netgsm.service.ts +128 -0
- package/src/services/unipile.service.ts +200 -0
- package/src/services/whatsapp-agent.service.ts +2479 -0
- package/src/services/whatsapp.service.ts +245 -0
- package/src/templates/index.ts +71 -0
- package/src/templates/receptionist.ts +44 -0
- package/src/templates/survey.ts +44 -0
- package/src/types/index.ts +218 -0
- package/src/utils/logger.ts +83 -0
- package/tsconfig.json +19 -0
- package/web/.dockerignore +4 -0
- package/web/Dockerfile +18 -0
- package/web/README.md +73 -0
- package/web/components.json +23 -0
- package/web/eslint.config.js +23 -0
- package/web/index.html +14 -0
- package/web/nginx.conf +18 -0
- package/web/package-lock.json +10292 -0
- package/web/package.json +48 -0
- package/web/public/favicon.ico +0 -0
- package/web/public/vite.svg +1 -0
- package/web/src/App.tsx +191 -0
- package/web/src/assets/react.svg +1 -0
- package/web/src/components/Layout.tsx +261 -0
- package/web/src/components/LeadConversation.tsx +251 -0
- package/web/src/components/ProtectedRoute.tsx +20 -0
- package/web/src/components/conversation-review/CardAudioPlayer.tsx +200 -0
- package/web/src/components/conversation-review/CardEvaluation.tsx +351 -0
- package/web/src/components/conversation-review/CardMetadata.tsx +44 -0
- package/web/src/components/conversation-review/ConversationCard.tsx +95 -0
- package/web/src/components/conversation-review/ReviewContainer.tsx +120 -0
- package/web/src/components/conversation-review/ReviewFilters.tsx +88 -0
- package/web/src/components/empty-state.tsx +15 -0
- package/web/src/components/page-header.tsx +19 -0
- package/web/src/components/page-loader.tsx +32 -0
- package/web/src/components/pagination.tsx +38 -0
- package/web/src/components/stat-card.tsx +27 -0
- package/web/src/components/status-badge.tsx +125 -0
- package/web/src/components/ui/alert.tsx +66 -0
- package/web/src/components/ui/badge.tsx +48 -0
- package/web/src/components/ui/button.tsx +64 -0
- package/web/src/components/ui/card.tsx +92 -0
- package/web/src/components/ui/checkbox.tsx +32 -0
- package/web/src/components/ui/dialog.tsx +158 -0
- package/web/src/components/ui/dropdown-menu.tsx +255 -0
- package/web/src/components/ui/input.tsx +21 -0
- package/web/src/components/ui/label.tsx +22 -0
- package/web/src/components/ui/progress.tsx +29 -0
- package/web/src/components/ui/select.tsx +188 -0
- package/web/src/components/ui/separator.tsx +28 -0
- package/web/src/components/ui/sheet.tsx +123 -0
- package/web/src/components/ui/skeleton.tsx +13 -0
- package/web/src/components/ui/sonner.tsx +35 -0
- package/web/src/components/ui/table.tsx +116 -0
- package/web/src/components/ui/tabs.tsx +89 -0
- package/web/src/components/ui/textarea.tsx +18 -0
- package/web/src/components/ui/tooltip.tsx +57 -0
- package/web/src/components/whatsapp/ChatDetail.tsx +417 -0
- package/web/src/components/whatsapp/ChatHeader.tsx +78 -0
- package/web/src/components/whatsapp/ChatList.tsx +107 -0
- package/web/src/components/whatsapp/ChatListItem.tsx +60 -0
- package/web/src/components/whatsapp/MessageBubble.tsx +46 -0
- package/web/src/components/whatsapp/MessageInput.tsx +63 -0
- package/web/src/components/whatsapp/MessageStream.tsx +135 -0
- package/web/src/components/whatsapp/SessionDivider.tsx +65 -0
- package/web/src/components/whatsapp/SessionHistory.tsx +119 -0
- package/web/src/components/whatsapp/settings/AiSettingsTab.tsx +268 -0
- package/web/src/components/whatsapp/settings/CalendarTab.tsx +339 -0
- package/web/src/components/whatsapp/settings/ConnectionTab.tsx +236 -0
- package/web/src/components/whatsapp/settings/NotificationsTab.tsx +109 -0
- package/web/src/components/whatsapp/settings/OperatorTab.tsx +303 -0
- package/web/src/contexts/AuthContext.tsx +103 -0
- package/web/src/index.css +130 -0
- package/web/src/lib/api.ts +92 -0
- package/web/src/lib/utils.ts +6 -0
- package/web/src/main.tsx +10 -0
- package/web/src/pages/AppointmentDetail.tsx +206 -0
- package/web/src/pages/AppointmentValidation.tsx +157 -0
- package/web/src/pages/AppointmentValidationDetail.tsx +617 -0
- package/web/src/pages/AppointmentValidationNew.tsx +1005 -0
- package/web/src/pages/Appointments.tsx +283 -0
- package/web/src/pages/Billing.tsx +126 -0
- package/web/src/pages/CallDetail.tsx +293 -0
- package/web/src/pages/CallSettings.tsx +313 -0
- package/web/src/pages/Calls.tsx +188 -0
- package/web/src/pages/CampaignDetail.tsx +216 -0
- package/web/src/pages/CampaignNew.tsx +277 -0
- package/web/src/pages/CampaignResults.tsx +185 -0
- package/web/src/pages/Campaigns.tsx +171 -0
- package/web/src/pages/Dashboard.tsx +336 -0
- package/web/src/pages/InboundSchedule.tsx +246 -0
- package/web/src/pages/LeadDetail.tsx +183 -0
- package/web/src/pages/Leads.tsx +258 -0
- package/web/src/pages/Login.tsx +99 -0
- package/web/src/pages/Register.tsx +129 -0
- package/web/src/pages/Settings.tsx +133 -0
- package/web/src/pages/SurveyDetail.tsx +232 -0
- package/web/src/pages/SurveyPreview.tsx +179 -0
- package/web/src/pages/Surveys.tsx +207 -0
- package/web/src/pages/Users.tsx +199 -0
- package/web/src/pages/WhatsApp.tsx +147 -0
- package/web/src/pages/WhatsAppSettings.tsx +215 -0
- package/web/src/pages/admin/AdminBaileysMessageLog.tsx +331 -0
- package/web/src/pages/admin/AdminBaileysRawMessages.tsx +318 -0
- package/web/src/pages/admin/AdminConversationReview.tsx +116 -0
- package/web/src/pages/admin/AdminCredits.tsx +467 -0
- package/web/src/pages/admin/AdminElevenLabsAgentDetail.tsx +332 -0
- package/web/src/pages/admin/AdminElevenLabsAgents.tsx +164 -0
- package/web/src/pages/admin/AdminElevenLabsBatchCallDetail.tsx +214 -0
- package/web/src/pages/admin/AdminElevenLabsBatchCalls.tsx +293 -0
- package/web/src/pages/admin/AdminElevenLabsConversationDetail.tsx +230 -0
- package/web/src/pages/admin/AdminElevenLabsConversations.tsx +228 -0
- package/web/src/pages/admin/AdminElevenLabsInboundCalls.tsx +293 -0
- package/web/src/pages/admin/AdminElevenLabsPhoneNumbers.tsx +506 -0
- package/web/src/pages/admin/AdminElevenLabsTestChat.tsx +258 -0
- package/web/src/pages/admin/AdminElevenLabsWebhooks.tsx +289 -0
- package/web/src/pages/admin/AdminEvaluationDashboard.tsx +520 -0
- package/web/src/pages/admin/AdminLeads.tsx +339 -0
- package/web/src/pages/admin/AdminLogs.tsx +283 -0
- package/web/src/pages/admin/AdminMigrations.tsx +247 -0
- package/web/src/pages/admin/AdminPlans.tsx +313 -0
- package/web/src/pages/admin/AdminSystem.tsx +391 -0
- package/web/src/pages/admin/AdminTenantBillableItems.tsx +464 -0
- package/web/src/pages/admin/AdminTenantDetail.tsx +1317 -0
- package/web/src/pages/admin/AdminTenants.tsx +274 -0
- package/web/src/pages/admin/AdminWhatsApp.tsx +618 -0
- package/web/src/pages/admin/AdminWhatsAppTestChat.tsx +328 -0
- package/web/src/types/index.ts +242 -0
- package/web/tsconfig.app.json +32 -0
- package/web/tsconfig.json +13 -0
- package/web/tsconfig.node.json +26 -0
- package/web/vite.config.ts +23 -0
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
# 13. Logging and Audit Trail
|
|
2
|
+
|
|
3
|
+
> Application logging for debugging/monitoring and audit logging for compliance/accountability.
|
|
4
|
+
> Last updated: 2026-04-02
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Application Logging (Pino)
|
|
9
|
+
|
|
10
|
+
### Why Pino
|
|
11
|
+
|
|
12
|
+
- **Native to Fastify**: NestJS Fastify adapter uses Pino natively -- zero additional overhead.
|
|
13
|
+
- **5x faster than Winston**: Matters at scale. Pino avoids synchronous string formatting.
|
|
14
|
+
- **Structured JSON by default**: Every log entry is a parseable JSON object.
|
|
15
|
+
- **`pino-pretty` for dev**: Human-readable console output during development.
|
|
16
|
+
- **Async write**: Never blocks the event loop.
|
|
17
|
+
|
|
18
|
+
The current system uses Winston with a custom MongoDB transport. The migration replaces this with Pino + PostgreSQL.
|
|
19
|
+
|
|
20
|
+
### Architecture
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
NestJS App
|
|
24
|
+
|
|
|
25
|
+
+-- Pino Logger (via @nestjs/platform-fastify built-in)
|
|
26
|
+
| +-- Console transport (pretty-print in dev, JSON in prod)
|
|
27
|
+
| +-- PostgreSQL transport (async, batched -- replaces MongoDB)
|
|
28
|
+
| +-- File transport (optional, for log rotation/archival)
|
|
29
|
+
|
|
|
30
|
+
+-- Request Logger (Fastify hook -- auto on every request)
|
|
31
|
+
| +-- method, url, status, duration, userId, tenantId, clinicId, requestId
|
|
32
|
+
|
|
|
33
|
+
+-- Correlation ID (X-Request-Id header or auto-generated UUID)
|
|
34
|
+
+-- Propagated to all service calls, queue jobs, external API calls
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Log Levels
|
|
38
|
+
|
|
39
|
+
| Level | When to Use | Example |
|
|
40
|
+
|-------|------------|---------|
|
|
41
|
+
| `fatal` | Process cannot continue | Database connection lost, unrecoverable state |
|
|
42
|
+
| `error` | Operation failed, needs attention | ElevenLabs WS disconnect, Google Calendar API 500, payment failed |
|
|
43
|
+
| `warn` | Unexpected but handled | Retry triggered, rate limit approaching, token refresh failed then succeeded |
|
|
44
|
+
| `info` | Business events | Session created, appointment booked, call completed, batch submitted |
|
|
45
|
+
| `debug` | Developer troubleshooting | WS message received, tool call params, queue job started |
|
|
46
|
+
| `trace` | Extreme detail | Raw HTTP payloads, full WS frames (dev only) |
|
|
47
|
+
|
|
48
|
+
**Production:** `info` and above go to PostgreSQL. `debug` and `trace` stay in console/file only -- they are too noisy for the database.
|
|
49
|
+
|
|
50
|
+
**Development:** `debug` and above to console (via `pino-pretty`).
|
|
51
|
+
|
|
52
|
+
### Structured Log Format
|
|
53
|
+
|
|
54
|
+
Every log entry includes auto-injected context. No string interpolation -- all data is structured.
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
{
|
|
58
|
+
// Auto-injected by Pino
|
|
59
|
+
level: 'info',
|
|
60
|
+
time: 1711700000000,
|
|
61
|
+
pid: 12345,
|
|
62
|
+
hostname: 'api-1',
|
|
63
|
+
|
|
64
|
+
// Injected by request context (AsyncLocalStorage)
|
|
65
|
+
requestId: 'req_abc123', // Correlation ID
|
|
66
|
+
tenantId: 'tenant_xyz', // null for platform routes
|
|
67
|
+
clinicId: 'clinic_456', // null if not clinic-scoped
|
|
68
|
+
userId: 'user_789', // null for unauthenticated
|
|
69
|
+
|
|
70
|
+
// Log-specific
|
|
71
|
+
msg: 'Appointment booked',
|
|
72
|
+
service: 'calendar.tools',
|
|
73
|
+
data: {
|
|
74
|
+
appointmentId: '...',
|
|
75
|
+
patientPhone: '+905551234567',
|
|
76
|
+
startTime: '2026-04-15T09:00:00Z',
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### AsyncLocalStorage for Request Context Propagation
|
|
82
|
+
|
|
83
|
+
A correlation ID and user context are propagated across the entire request lifecycle without passing parameters through every function call. This is achieved via Node.js `AsyncLocalStorage`.
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
@Injectable()
|
|
87
|
+
export class RequestContextInterceptor implements NestInterceptor {
|
|
88
|
+
constructor(private readonly als: AsyncLocalStorage<RequestContext>) {}
|
|
89
|
+
|
|
90
|
+
intercept(context: ExecutionContext, next: CallHandler) {
|
|
91
|
+
const request = context.switchToHttp().getRequest();
|
|
92
|
+
const ctx: RequestContext = {
|
|
93
|
+
requestId: request.headers['x-request-id'] || randomUUID(),
|
|
94
|
+
tenantId: request.user?.tenantId ?? null,
|
|
95
|
+
clinicId: null, // Set later by ClinicAccessGuard
|
|
96
|
+
userId: request.user?.sub ?? null,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
return new Observable((subscriber) => {
|
|
100
|
+
this.als.run(ctx, () => {
|
|
101
|
+
next.handle().subscribe(subscriber);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Usage anywhere in the codebase:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
const ctx = this.als.getStore();
|
|
112
|
+
this.logger.info({ ...ctx, msg: 'Appointment booked', data: { appointmentId } });
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The correlation ID (`requestId`) follows a request through service calls, queue jobs, and external API calls, making it possible to trace an entire flow from a single ID.
|
|
116
|
+
|
|
117
|
+
### PostgreSQL Log Storage
|
|
118
|
+
|
|
119
|
+
Only `info` and above go to PostgreSQL. The `logs` table serves the admin dashboard.
|
|
120
|
+
|
|
121
|
+
```prisma
|
|
122
|
+
model Log {
|
|
123
|
+
log_id String @id @default(uuid())
|
|
124
|
+
log_level String // fatal, error, warn, info
|
|
125
|
+
log_message String
|
|
126
|
+
log_service String @default("api") // api, whatsapp-agent, billing, etc.
|
|
127
|
+
log_meta Json @default("{}") // Structured data payload
|
|
128
|
+
log_request_id String? // Correlation ID
|
|
129
|
+
log_tenant_id String?
|
|
130
|
+
log_clinic_id String?
|
|
131
|
+
log_user_id String?
|
|
132
|
+
log_timestamp DateTime @default(now())
|
|
133
|
+
|
|
134
|
+
@@index([log_level])
|
|
135
|
+
@@index([log_timestamp])
|
|
136
|
+
@@index([log_level, log_timestamp(sort: Desc)])
|
|
137
|
+
@@index([log_tenant_id, log_timestamp(sort: Desc)])
|
|
138
|
+
@@index([log_request_id])
|
|
139
|
+
@@index([log_service, log_timestamp(sort: Desc)])
|
|
140
|
+
@@map("logs")
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Async Batched PostgreSQL Writer
|
|
145
|
+
|
|
146
|
+
Logs are never written synchronously to PostgreSQL. The writer buffers entries and flushes in batches to avoid per-log write overhead.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
@Injectable()
|
|
150
|
+
export class PgLogTransport {
|
|
151
|
+
private buffer: LogEntry[] = [];
|
|
152
|
+
private readonly MAX_BUFFER = 100;
|
|
153
|
+
private readonly FLUSH_INTERVAL = 5_000; // 5 seconds
|
|
154
|
+
|
|
155
|
+
constructor(private readonly prisma: PrismaService) {
|
|
156
|
+
setInterval(() => this.flush(), this.FLUSH_INTERVAL);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
write(entry: LogEntry) {
|
|
160
|
+
this.buffer.push(entry);
|
|
161
|
+
if (this.buffer.length >= this.MAX_BUFFER) {
|
|
162
|
+
this.flush();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private async flush() {
|
|
167
|
+
if (this.buffer.length === 0) return;
|
|
168
|
+
const batch = this.buffer.splice(0);
|
|
169
|
+
await this.prisma.log.createMany({ data: batch }).catch(() => {
|
|
170
|
+
// Never let logging failure crash the app
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Flush triggers:**
|
|
177
|
+
|
|
178
|
+
- Buffer reaches 100 entries.
|
|
179
|
+
- 5-second interval timer fires.
|
|
180
|
+
- Whichever comes first.
|
|
181
|
+
|
|
182
|
+
A failed flush is silently swallowed. Application stability always takes priority over log persistence.
|
|
183
|
+
|
|
184
|
+
### Log Cleanup
|
|
185
|
+
|
|
186
|
+
BullMQ repeatable job `log:cleanup` runs daily at 03:00 (Europe/Istanbul). Deletes logs older than the configured retention period.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
const retentionDays = tenant?.settings?.log_retention_days ?? 30;
|
|
190
|
+
await this.prisma.log.deleteMany({
|
|
191
|
+
where: {
|
|
192
|
+
tenantId,
|
|
193
|
+
timestamp: { lt: subDays(new Date(), retentionDays) },
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Default retention: **30 days**. Per-tenant override possible via `tenant.settings.log_retention_days`.
|
|
199
|
+
|
|
200
|
+
### Log Endpoints
|
|
201
|
+
|
|
202
|
+
| Method | Path | Permission | Description |
|
|
203
|
+
|--------|------|-----------|-------------|
|
|
204
|
+
| GET | `/admin/logs` | `audit:read` | Paginated, filterable by level, service, tenant, clinic, requestId, date range |
|
|
205
|
+
| GET | `/admin/logs/stats` | `audit:read` | Count by level (cached 30s in Redis) |
|
|
206
|
+
| DELETE | `/admin/logs` | superadmin only | Delete logs older than specified date |
|
|
207
|
+
| GET | `/admin/logs/request/:requestId` | `audit:read` | All logs for a single request (trace a full flow end-to-end) |
|
|
208
|
+
|
|
209
|
+
### Business Event Catalog (30+ Events)
|
|
210
|
+
|
|
211
|
+
| Service | Event | Level | Data |
|
|
212
|
+
|---------|-------|-------|------|
|
|
213
|
+
| **Auth** | Login success | info | userId, email, ip |
|
|
214
|
+
| **Auth** | Login failure | warn | email, ip, reason |
|
|
215
|
+
| **Auth** | Token refreshed / revoked | info | userId |
|
|
216
|
+
| **WhatsApp** | Session created | info | chatId, sessionId |
|
|
217
|
+
| **WhatsApp** | Session resolved | info | chatId, sessionId, resolvedBy |
|
|
218
|
+
| **WhatsApp** | AI response sent | info | chatId, messageLength, durationMs |
|
|
219
|
+
| **WhatsApp** | WS connection opened | info | chatId, agentId |
|
|
220
|
+
| **WhatsApp** | WS connection closed | info | chatId, agentId, reason |
|
|
221
|
+
| **WhatsApp** | Message buffer triggered | debug | sessionId, messageCount |
|
|
222
|
+
| **Tools** | Tool executed | info | toolName, channel, durationMs, isError, toollog_clinic_id |
|
|
223
|
+
| **Operator** | Request created | info | refCode, sessionId |
|
|
224
|
+
| **Operator** | Request responded | info | refCode, sessionId |
|
|
225
|
+
| **Operator** | Request expired | info | refCode, sessionId |
|
|
226
|
+
| **Calendar** | Slot reserved | info | appointmentId, patientPhone, startTime |
|
|
227
|
+
| **Calendar** | Slot cancelled | info | appointmentId, patientPhone |
|
|
228
|
+
| **ElevenLabs** | Webhook received | info | conversationId, agentId, status |
|
|
229
|
+
| **ElevenLabs** | Post-call summary generated | info | callId, model, tokenUsage |
|
|
230
|
+
| **Billing** | Charge logged | info | tenantId, callId, amount |
|
|
231
|
+
| **Billing** | Alert sent | warn | tenantId, alertType, threshold |
|
|
232
|
+
| **Campaigns** | Call dispatched | info | campaignId, entryId |
|
|
233
|
+
| **Campaigns** | Call completed | info | campaignId, entryId, status |
|
|
234
|
+
| **Validation** | Batch submitted | info | batchId, totalEntries |
|
|
235
|
+
| **Validation** | Batch completed | info | batchId, completedCount |
|
|
236
|
+
| **Bridge** | Message sent | info | provider, chatId |
|
|
237
|
+
| **Bridge** | Message failed | error | provider, chatId, error |
|
|
238
|
+
| **Meta** | Webhook received | info | wabaId, messageType |
|
|
239
|
+
| **NetGSM** | SMS sent | info | phones, jobId |
|
|
240
|
+
| **NetGSM** | SMS failed | error | phones, error |
|
|
241
|
+
| **Payments** | Payment link created | info | paymentId, amount |
|
|
242
|
+
| **Payments** | Payment completed | info | paymentId, amount, status |
|
|
243
|
+
| **WhatsApp** | Message cleanup executed | info | jobName: `whatsapp:message-cleanup`, deletedCount, retentionDays |
|
|
244
|
+
| **Patient** | Patient created | info | patientId, phone, clinicId |
|
|
245
|
+
| **Patient** | Patient updated | info | patientId, changes |
|
|
246
|
+
| **Patient** | Patient merged | info | primaryPatientId, mergedPatientId |
|
|
247
|
+
| **Queue** | Job failed after retries | error | queue, jobId, error, attempts |
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Audit Logging
|
|
252
|
+
|
|
253
|
+
### Purpose
|
|
254
|
+
|
|
255
|
+
Track **who did what, when, and what changed**. Audit logs are separate from application logs. They answer questions like: "Who changed the grace period from 180 to 300, and when?"
|
|
256
|
+
|
|
257
|
+
Audit logs serve three purposes:
|
|
258
|
+
|
|
259
|
+
- **Compliance**: Regulatory requirements (KVKK) demand traceability of data access and changes.
|
|
260
|
+
- **Accountability**: Clinic owners can see what their staff did and when.
|
|
261
|
+
- **Forensics**: Investigating incidents after the fact.
|
|
262
|
+
|
|
263
|
+
### Key Properties
|
|
264
|
+
|
|
265
|
+
- **Immutable**: Audit logs are append-only. They are never updated.
|
|
266
|
+
- **Never auto-deleted**: Unlike application logs, audit logs are not subject to cleanup jobs. Retention is permanent (or years per regulation).
|
|
267
|
+
- **Synchronous writes**: Audit events are written to PostgreSQL synchronously. They must not be lost, even at the cost of a small latency increase.
|
|
268
|
+
- **Real-time push**: New audit events are emitted via WebSocket to the dashboard for live monitoring.
|
|
269
|
+
|
|
270
|
+
### Architecture
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
User Action (HTTP request)
|
|
274
|
+
|
|
|
275
|
+
+-- AuditInterceptor (NestJS interceptor on mutating endpoints)
|
|
276
|
+
| +-- Captures: before state -> after state -> diff
|
|
277
|
+
|
|
|
278
|
+
+-- EventEmitter (for non-HTTP actions)
|
|
279
|
+
+-- e.g., AI booking appointment, operator request expiry
|
|
280
|
+
|
|
281
|
+
|
|
|
282
|
+
v
|
|
283
|
+
|
|
284
|
+
AuditService.log(event)
|
|
285
|
+
|
|
|
286
|
+
+-- Write to PostgreSQL (audit_logs table) -- synchronous, never batched
|
|
287
|
+
+-- Emit WebSocket event to dashboard (real-time audit feed)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Prisma Model
|
|
291
|
+
|
|
292
|
+
```prisma
|
|
293
|
+
model AuditLog {
|
|
294
|
+
id String @id @default(uuid())
|
|
295
|
+
tenantId String? // null for platform actions (sales creating tenant)
|
|
296
|
+
clinicId String? // null for tenant-level actions
|
|
297
|
+
userId String? // null for system actions (cron, AI)
|
|
298
|
+
userEmail String? // Denormalized -- survives user deletion
|
|
299
|
+
userRole String? // Role at time of action
|
|
300
|
+
action String // e.g., 'tenant.settings.updated'
|
|
301
|
+
entity String // e.g., 'Tenant', 'Appointment'
|
|
302
|
+
entityId String // ID of affected record
|
|
303
|
+
changes Json? // {field: {old: x, new: y}} -- null for non-update actions
|
|
304
|
+
metadata Json? // Extra context: {ip, userAgent, requestId, reason}
|
|
305
|
+
createdAt DateTime @default(now())
|
|
306
|
+
|
|
307
|
+
// NO updatedAt -- audit logs are immutable
|
|
308
|
+
|
|
309
|
+
@@index([tenantId, createdAt(sort: Desc)])
|
|
310
|
+
@@index([clinicId, createdAt(sort: Desc)])
|
|
311
|
+
@@index([entity, entityId])
|
|
312
|
+
@@index([userId, createdAt(sort: Desc)])
|
|
313
|
+
@@index([action, createdAt(sort: Desc)])
|
|
314
|
+
@@map("audit_logs")
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**Note:** `userEmail` and `userRole` are denormalized (copied at write time). This ensures the audit trail remains accurate even if the user is later deleted or their role changes.
|
|
319
|
+
|
|
320
|
+
### AuditService
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
@Injectable()
|
|
324
|
+
export class AuditService {
|
|
325
|
+
constructor(
|
|
326
|
+
private readonly prisma: PrismaService,
|
|
327
|
+
private readonly eventEmitter: EventEmitter2,
|
|
328
|
+
) {}
|
|
329
|
+
|
|
330
|
+
async log(event: AuditEvent): Promise<void> {
|
|
331
|
+
const entry = await this.prisma.auditLog.create({
|
|
332
|
+
data: {
|
|
333
|
+
tenantId: event.tenantId,
|
|
334
|
+
clinicId: event.clinicId,
|
|
335
|
+
userId: event.userId,
|
|
336
|
+
userEmail: event.userEmail,
|
|
337
|
+
userRole: event.userRole,
|
|
338
|
+
action: event.action,
|
|
339
|
+
entity: event.entity,
|
|
340
|
+
entityId: event.entityId,
|
|
341
|
+
changes: event.changes ?? undefined,
|
|
342
|
+
metadata: {
|
|
343
|
+
ip: event.ip,
|
|
344
|
+
userAgent: event.userAgent,
|
|
345
|
+
requestId: event.requestId,
|
|
346
|
+
...(event.reason && { reason: event.reason }),
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// Push to dashboard in real-time
|
|
352
|
+
this.eventEmitter.emit('audit.created', entry);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
static diff(
|
|
356
|
+
before: Record<string, any>,
|
|
357
|
+
after: Record<string, any>,
|
|
358
|
+
): Record<string, { old: any; new: any }> | null {
|
|
359
|
+
const changes: Record<string, { old: any; new: any }> = {};
|
|
360
|
+
for (const key of new Set([...Object.keys(before), ...Object.keys(after)])) {
|
|
361
|
+
if (JSON.stringify(before[key]) !== JSON.stringify(after[key])) {
|
|
362
|
+
changes[key] = { old: before[key], new: after[key] };
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return Object.keys(changes).length > 0 ? changes : null;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
The `diff()` method compares two object snapshots and produces a `{ field: { old, new } }` change record. It uses JSON serialization for deep comparison.
|
|
371
|
+
|
|
372
|
+
### @Auditable() Decorator
|
|
373
|
+
|
|
374
|
+
The `@Auditable()` decorator auto-wraps controller methods with before/after capture. It eliminates the need to manually call `AuditService.log()` on every mutating endpoint.
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
export function Auditable(action: string, entity: string) {
|
|
378
|
+
return applyDecorators(
|
|
379
|
+
SetMetadata('audit:action', action),
|
|
380
|
+
SetMetadata('audit:entity', entity),
|
|
381
|
+
UseInterceptors(AuditInterceptor),
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Usage:
|
|
386
|
+
@Put(':id')
|
|
387
|
+
@Auditable('clinic.settings.updated', 'Clinic')
|
|
388
|
+
async updateClinic(@Param('id') id: string, @Body() dto: UpdateClinicDto) {
|
|
389
|
+
return this.clinicsService.update(id, dto);
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**AuditInterceptor behavior:**
|
|
394
|
+
|
|
395
|
+
1. **Before**: Fetch current state of the entity (by ID from route params).
|
|
396
|
+
2. **Execute**: Run the controller handler.
|
|
397
|
+
3. **After**: Fetch new state, compute diff via `AuditService.diff()`.
|
|
398
|
+
4. **Write**: Create audit log entry with the changes.
|
|
399
|
+
|
|
400
|
+
### Complete Action Catalog (30+ Actions)
|
|
401
|
+
|
|
402
|
+
**Auth Actions:**
|
|
403
|
+
|
|
404
|
+
| Action | Trigger |
|
|
405
|
+
|--------|---------|
|
|
406
|
+
| `user.login` | Successful login |
|
|
407
|
+
| `user.login.failed` | Failed login attempt (track brute force) |
|
|
408
|
+
| `user.logout` | Logout |
|
|
409
|
+
| `user.password.changed` | Password change |
|
|
410
|
+
| `user.password.reset` | Password reset via token |
|
|
411
|
+
| `user.2fa.enabled` | 2FA enabled |
|
|
412
|
+
| `user.2fa.disabled` | 2FA disabled |
|
|
413
|
+
|
|
414
|
+
**User Management:**
|
|
415
|
+
|
|
416
|
+
| Action | Trigger |
|
|
417
|
+
|--------|---------|
|
|
418
|
+
| `user.created` | New user invited |
|
|
419
|
+
| `user.updated` | Name, role, or active status changed |
|
|
420
|
+
| `user.deleted` | User deactivated/removed |
|
|
421
|
+
| `user.clinics.updated` | Clinic assignments changed |
|
|
422
|
+
|
|
423
|
+
**Tenant and Clinic:**
|
|
424
|
+
|
|
425
|
+
| Action | Trigger |
|
|
426
|
+
|--------|---------|
|
|
427
|
+
| `tenant.created` | New tenant onboarded (by sales/superadmin) |
|
|
428
|
+
| `tenant.settings.updated` | Global settings changed |
|
|
429
|
+
| `tenant.features.toggled` | Feature flags changed |
|
|
430
|
+
| `tenant.deactivated` | Tenant deactivated |
|
|
431
|
+
| `tenant.reactivated` | Tenant reactivated |
|
|
432
|
+
| `clinic.created` | New clinic created |
|
|
433
|
+
| `clinic.updated` | Clinic settings changed |
|
|
434
|
+
| `clinic.deleted` | Clinic deleted |
|
|
435
|
+
|
|
436
|
+
**Phone Numbers:**
|
|
437
|
+
|
|
438
|
+
| Action | Trigger |
|
|
439
|
+
|--------|---------|
|
|
440
|
+
| `phone.created` | Phone number added |
|
|
441
|
+
| `phone.updated` | Phone number settings changed |
|
|
442
|
+
| `phone.deleted` | Phone number removed |
|
|
443
|
+
| `phone.whatsapp.connected` | WhatsApp connection established |
|
|
444
|
+
| `phone.whatsapp.disconnected` | WhatsApp disconnected |
|
|
445
|
+
|
|
446
|
+
**WhatsApp:**
|
|
447
|
+
|
|
448
|
+
| Action | Trigger |
|
|
449
|
+
|--------|---------|
|
|
450
|
+
| `session.taken_over` | Human takes over from AI |
|
|
451
|
+
| `session.released` | Human releases back to AI |
|
|
452
|
+
| `session.resolved.manual` | Manual resolution |
|
|
453
|
+
| `chat.message.sent.human` | Human sent message in live chat |
|
|
454
|
+
| `blacklist.added` | Number blacklisted |
|
|
455
|
+
| `blacklist.removed` | Number removed from blacklist |
|
|
456
|
+
|
|
457
|
+
**Calendar:**
|
|
458
|
+
|
|
459
|
+
| Action | Trigger |
|
|
460
|
+
|--------|---------|
|
|
461
|
+
| `calendar.connected` | Google Calendar OAuth completed |
|
|
462
|
+
| `calendar.disconnected` | Google Calendar disconnected |
|
|
463
|
+
| `appointment.created` | Appointment booked (by AI or human) |
|
|
464
|
+
| `appointment.cancelled` | Appointment cancelled (by AI or human) |
|
|
465
|
+
| `appointment.rescheduled` | Appointment rescheduled |
|
|
466
|
+
|
|
467
|
+
**Campaigns and Validation:**
|
|
468
|
+
|
|
469
|
+
| Action | Trigger |
|
|
470
|
+
|--------|---------|
|
|
471
|
+
| `campaign.created` | New outbound campaign created |
|
|
472
|
+
| `campaign.started` | Campaign started |
|
|
473
|
+
| `campaign.stopped` | Campaign stopped |
|
|
474
|
+
| `batch.created` | Validation batch created |
|
|
475
|
+
| `batch.submitted` | Validation batch submitted for calling |
|
|
476
|
+
| `batch.cancelled` | Validation batch cancelled |
|
|
477
|
+
|
|
478
|
+
**Patient and Clinical:**
|
|
479
|
+
|
|
480
|
+
| Action | Trigger |
|
|
481
|
+
|--------|---------|
|
|
482
|
+
| `patient.created` | New patient record created |
|
|
483
|
+
| `patient.updated` | Patient info changed |
|
|
484
|
+
| `patient.merged` | Duplicate patient records merged |
|
|
485
|
+
| `treatment_plan.created` | New treatment plan created for patient |
|
|
486
|
+
| `treatment_plan.completed` | Treatment plan marked as completed |
|
|
487
|
+
| `examination.created` | New examination record created |
|
|
488
|
+
|
|
489
|
+
**Compliance (KVKK):**
|
|
490
|
+
|
|
491
|
+
| Action | Trigger |
|
|
492
|
+
|--------|---------|
|
|
493
|
+
| `kvkk.export.requested` | Data export requested |
|
|
494
|
+
| `kvkk.deletion.requested` | Data deletion requested |
|
|
495
|
+
| `kvkk.deletion.completed` | Data deletion executed |
|
|
496
|
+
|
|
497
|
+
**Platform (Sales/Superadmin):**
|
|
498
|
+
|
|
499
|
+
| Action | Trigger |
|
|
500
|
+
|--------|---------|
|
|
501
|
+
| `platform.tenant.created` | Sales created new tenant |
|
|
502
|
+
| `platform.tenant.plan.changed` | Plan changed by sales |
|
|
503
|
+
| `platform.tenant.deactivated` | Tenant deactivated by sales |
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## Key Differences: Application Logs vs. Audit Logs
|
|
508
|
+
|
|
509
|
+
| | Application Logs | Audit Logs |
|
|
510
|
+
|---|---|---|
|
|
511
|
+
| **Purpose** | Debugging, monitoring, alerting | Compliance, accountability, forensics |
|
|
512
|
+
| **Who reads** | Developers, ops | Clinic owners, compliance officers |
|
|
513
|
+
| **Retention** | 30 days (configurable per tenant) | Permanent (or years per regulation) |
|
|
514
|
+
| **Write mode** | Async, batched (buffer 100, flush every 5s) | Synchronous -- must not be lost |
|
|
515
|
+
| **Content** | What happened technically | Who did what to which record, with before/after diff |
|
|
516
|
+
| **Deletable** | Yes (BullMQ cleanup job) | No (immutable, append-only) |
|
|
517
|
+
| **Filterable by** | level, service, requestId, date | user, action, entity, tenant, date range |
|
|
518
|
+
| **Stored in** | `logs` table | `audit_logs` table |
|
|
519
|
+
| **Real-time push** | No | Yes (WebSocket to dashboard) |
|
|
520
|
+
| **Includes diff** | No | Yes (`changes` field with `{old, new}` per field) |
|
|
521
|
+
| **User identity** | Optional (`userId` from context) | Required (denormalized `userEmail`, `userRole`) |
|
|
522
|
+
|
|
523
|
+
---
|
|
524
|
+
|
|
525
|
+
## Endpoints
|
|
526
|
+
|
|
527
|
+
### Application Log Endpoints
|
|
528
|
+
|
|
529
|
+
| Method | Path | Permission | Description |
|
|
530
|
+
|--------|------|-----------|-------------|
|
|
531
|
+
| GET | `/admin/logs` | `audit:read` | Paginated, filterable by level, service, tenant, clinic, requestId, date range |
|
|
532
|
+
| GET | `/admin/logs/stats` | `audit:read` | Count by level (cached 30s in Redis) |
|
|
533
|
+
| DELETE | `/admin/logs` | superadmin only | Delete logs older than specified date |
|
|
534
|
+
| GET | `/admin/logs/request/:requestId` | `audit:read` | All logs for a single request (end-to-end trace) |
|
|
535
|
+
|
|
536
|
+
### Audit Log Endpoints
|
|
537
|
+
|
|
538
|
+
| Method | Path | Permission | Description |
|
|
539
|
+
|--------|------|-----------|-------------|
|
|
540
|
+
| GET | `/audit-logs` | `audit:read` | Tenant-scoped audit trail (owner/admin sees their tenant) |
|
|
541
|
+
| GET | `/audit-logs/entity/:entity/:entityId` | `audit:read` | Full history of a specific record |
|
|
542
|
+
| GET | `/audit-logs/user/:userId` | `audit:read` | All actions by a specific user |
|
|
543
|
+
| GET | `/platform/audit-logs` | superadmin/sales | Cross-tenant audit trail |
|
|
544
|
+
|
|
545
|
+
**Query parameters (both endpoints):** `action`, `entity`, `userId`, `clinicId`, `from`, `to`, `page`, `limit`
|
|
546
|
+
|
|
547
|
+
### Audit Log Archival
|
|
548
|
+
|
|
549
|
+
Audit logs are never auto-deleted. For very large tenants, old audit logs (older than 2 years) can be archived to MinIO as compressed JSON and purged from PostgreSQL. This is a manual superadmin operation, not an automatic process.
|