evaldoc 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.
Files changed (139) hide show
  1. package/.env.staging.example +19 -0
  2. package/.firebaserc +6 -0
  3. package/.github/workflows/auto-merge-to-main.yml +28 -0
  4. package/.github/workflows/ci.yml +27 -0
  5. package/.github/workflows/npxhub-publish.yml +170 -0
  6. package/.prettierignore +4 -0
  7. package/.prettierrc.json +7 -0
  8. package/README.md +142 -0
  9. package/SRS.md +448 -0
  10. package/apphosting.staging.yaml +48 -0
  11. package/apphosting.yaml +50 -0
  12. package/bin/evaldoc.cjs +105 -0
  13. package/cors.json +8 -0
  14. package/docs/ARCHITECTURE.md +769 -0
  15. package/docs/ARCHITECTURE_SUMMARY.md +323 -0
  16. package/docs/DEPLOYMENT.md +86 -0
  17. package/docs/DEPLOYMENT_STEPS.md +373 -0
  18. package/docs/DEPLOY_FIRESTORE_RULES.md +239 -0
  19. package/docs/DEPLOY_STORAGE_RULES.md +82 -0
  20. package/docs/DOCTOR_TUTORIAL.md +467 -0
  21. package/docs/FIREBASE_STORAGE_CORS_FIX.md +131 -0
  22. package/docs/FIXES_APPLIED.md +128 -0
  23. package/docs/IMPLEMENTATION.md +498 -0
  24. package/docs/IMPLEMENTATION_COMPLETE.md +317 -0
  25. package/docs/LLM-SETUP.md +216 -0
  26. package/docs/MANUAL_TEST_GUIDE.md +327 -0
  27. package/docs/PATIENT_GUIDE.md +451 -0
  28. package/docs/PLATFORM_OVERVIEW.md +194 -0
  29. package/docs/QUICKSTART.md +252 -0
  30. package/docs/QUICK_REFERENCE.md +222 -0
  31. package/docs/READY_TO_TEST.md +383 -0
  32. package/docs/RUN.md +237 -0
  33. package/docs/START_TESTING.md +130 -0
  34. package/docs/STRIPE_CONNECT_SETUP.md +454 -0
  35. package/docs/SYSTEM_READY.md +345 -0
  36. package/docs/THREADS_IMPLEMENTATION_COMPLETE.md +431 -0
  37. package/docs/THREAD_IMPLEMENTATION_GUIDE.md +345 -0
  38. package/docs/firebasefiles.md +21 -0
  39. package/docs/homepage.md +1208 -0
  40. package/docs/payments.md +159 -0
  41. package/eslint.config.js +76 -0
  42. package/firebase.json +27 -0
  43. package/firestore.indexes.json +88 -0
  44. package/firestore.rules +125 -0
  45. package/functions/package-lock.json +2884 -0
  46. package/functions/package.json +20 -0
  47. package/functions/src/analytics.js +101 -0
  48. package/functions/src/audit.js +28 -0
  49. package/functions/src/auth.js +19 -0
  50. package/functions/src/drafts.js +128 -0
  51. package/functions/src/feedback.js +164 -0
  52. package/functions/src/firebase-init.js +29 -0
  53. package/functions/src/i18n.js +134 -0
  54. package/functions/src/limits.js +27 -0
  55. package/functions/src/llm.js +271 -0
  56. package/functions/src/ner.js +162 -0
  57. package/functions/src/notifications.js +273 -0
  58. package/functions/src/orgs.js +127 -0
  59. package/functions/src/patient-api.js +545 -0
  60. package/functions/src/payment.js +830 -0
  61. package/functions/src/safety.js +188 -0
  62. package/functions/src/stripe-config.js +33 -0
  63. package/functions/src/topics.js +94 -0
  64. package/functions/src/triage.js +191 -0
  65. package/functions/src/utils.js +28 -0
  66. package/functions/src/validate.js +177 -0
  67. package/functions/test-firebase.js +36 -0
  68. package/jest.config.js +18 -0
  69. package/package.json +52 -0
  70. package/public/404.html +93 -0
  71. package/public/app/analytics.html +336 -0
  72. package/public/app/analytics.js +177 -0
  73. package/public/app/app.css +1400 -0
  74. package/public/app/app.js +1754 -0
  75. package/public/app/config.js +14 -0
  76. package/public/app/inbox-threads.js +843 -0
  77. package/public/app/inbox.html +598 -0
  78. package/public/app/inbox.js +397 -0
  79. package/public/app/index.html +612 -0
  80. package/public/assets/logo.jpg +0 -0
  81. package/public/chat.html +137 -0
  82. package/public/css/chat.css +870 -0
  83. package/public/css/landing-enhance.css +298 -0
  84. package/public/css/styles.css +1198 -0
  85. package/public/favicon.svg +5 -0
  86. package/public/find-doctor.html +220 -0
  87. package/public/index.html +399 -0
  88. package/public/js/chat-threads.js +513 -0
  89. package/public/js/chat.js +832 -0
  90. package/public/js/search.js +41 -0
  91. package/public/privacy.html +101 -0
  92. package/public/robots.txt +6 -0
  93. package/public/site.webmanifest +12 -0
  94. package/public/terms.html +110 -0
  95. package/scripts/create-test-provider.js +55 -0
  96. package/scripts/deploy-staging.sh +51 -0
  97. package/scripts/fix-provider.js +39 -0
  98. package/scripts/quick-test.sh +37 -0
  99. package/scripts/test-chat.sh +54 -0
  100. package/scripts/test-multi-turn.js +137 -0
  101. package/scripts/test-ner-simple.js +28 -0
  102. package/scripts/test-ner.js +60 -0
  103. package/scripts/test-stripe-connect.js +304 -0
  104. package/scripts/test-webhook-secret.sh +24 -0
  105. package/server.js +3864 -0
  106. package/storage.rules +22 -0
  107. package/test-api.json +1 -0
  108. package/tests/emulator/README.md +38 -0
  109. package/tests/emulator/counters.emulator.test.js +81 -0
  110. package/tests/integration/api-account-selfserve.test.js +312 -0
  111. package/tests/integration/api-admin-digest.test.js +202 -0
  112. package/tests/integration/api-chat-satisfaction.test.js +259 -0
  113. package/tests/integration/api-doctor-drafts.test.js +236 -0
  114. package/tests/integration/api-doctor-inbox.test.js +401 -0
  115. package/tests/integration/api-org.test.js +328 -0
  116. package/tests/integration/api-payment.test.js +664 -0
  117. package/tests/integration/api-provider-settings.test.js +475 -0
  118. package/tests/integration/api-qr.test.js +121 -0
  119. package/tests/integration/api-security.test.js +241 -0
  120. package/tests/integration/api-stripe-search.test.js +303 -0
  121. package/tests/integration/api-webhook-deletion.test.js +231 -0
  122. package/tests/mocks/firebase-admin.js +220 -0
  123. package/tests/unit/analytics.test.js +151 -0
  124. package/tests/unit/audit-bugs.test.js +203 -0
  125. package/tests/unit/chat-ui-logic.test.js +283 -0
  126. package/tests/unit/drafts.test.js +104 -0
  127. package/tests/unit/feedback.test.js +148 -0
  128. package/tests/unit/i18n.test.js +229 -0
  129. package/tests/unit/llm-retry.test.js +122 -0
  130. package/tests/unit/notifications.test.js +155 -0
  131. package/tests/unit/orgs.test.js +328 -0
  132. package/tests/unit/payment.test.js +889 -0
  133. package/tests/unit/safety-edge-cases.test.js +509 -0
  134. package/tests/unit/safety-srs-compliance.test.js +252 -0
  135. package/tests/unit/safety.test.js +291 -0
  136. package/tests/unit/server-helpers.test.js +774 -0
  137. package/tests/unit/topics-limits.test.js +158 -0
  138. package/tests/unit/triage.test.js +152 -0
  139. package/tests/unit/validate.test.js +408 -0
@@ -0,0 +1,769 @@
1
+ # EvalDoc Technical Architecture
2
+
3
+ ## ๐Ÿ“ System Architecture Overview
4
+
5
+ EvalDoc is a full-stack web application built for scalability, reliability, and ease of maintenance in resource-constrained environments.
6
+
7
+ ---
8
+
9
+ ## ๐Ÿ—๏ธ Architecture Diagram
10
+
11
+ ```
12
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
13
+ โ”‚ CLIENT LAYER โ”‚
14
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
15
+ โ”‚ Landing Page โ”‚ Patient Chat โ”‚ Doctor Dashboard โ”‚
16
+ โ”‚ (index.html) โ”‚ (chat.html) โ”‚ (app/index.html) โ”‚
17
+ โ”‚ โ”‚ โ”‚ (app/inbox.html) โ”‚
18
+ โ”‚ โ”‚ โ”‚ (app/analytics.html) โ”‚
19
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
20
+ โ”‚ โ”‚ โ”‚
21
+ โ–ผ โ–ผ โ–ผ
22
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
23
+ โ”‚ APPLICATION LAYER โ”‚
24
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
25
+ โ”‚ Node.js + Express Server (server.js) โ”‚
26
+ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
27
+ โ”‚ โ”‚ Routes: โ”‚ โ”‚
28
+ โ”‚ โ”‚ - /api/provider (Public provider info) โ”‚ โ”‚
29
+ โ”‚ โ”‚ - /api/chat (Patient messaging) โ”‚ โ”‚
30
+ โ”‚ โ”‚ - /api/conversations (Doctor inbox) โ”‚ โ”‚
31
+ โ”‚ โ”‚ - /api/analytics (Platform metrics) โ”‚ โ”‚
32
+ โ”‚ โ”‚ - /api/me (Doctor profile) โ”‚ โ”‚
33
+ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
34
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
35
+ โ”‚ โ”‚
36
+ โ–ผ โ–ผ
37
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
38
+ โ”‚ AI SERVICES โ”‚ โ”‚ DATABASE LAYER โ”‚
39
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
40
+ โ”‚ DeepSeek API (Primary) โ”‚ โ”‚ Firebase Firestore โ”‚
41
+ โ”‚ Google Gemini (Fallback)โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
42
+ โ”‚ โ”‚ โ”‚ โ”‚ Collections: โ”‚ โ”‚
43
+ โ”‚ functions/src/llm.js โ”‚ โ”‚ โ”‚ - providers โ”‚ โ”‚
44
+ โ”‚ โ”‚ โ”‚ โ”‚ - conversations โ”‚ โ”‚
45
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ - messages (sub) โ”‚ โ”‚
46
+ โ”‚ โ”‚ - safetyEvents โ”‚ โ”‚
47
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ - analytics โ”‚ โ”‚
48
+ โ”‚ AUTHENTICATION โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
49
+ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ โ”‚
50
+ โ”‚ Firebase Auth โ”‚ โ”‚ Firebase Admin SDK โ”‚
51
+ โ”‚ - Email/Password โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
52
+ โ”‚ - Token-based โ”‚
53
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
54
+ ```
55
+
56
+ ---
57
+
58
+ ## ๐Ÿ—‚๏ธ File Structure
59
+
60
+ ```
61
+ EvalDoc/
62
+ โ”œโ”€โ”€ public/ # Static assets (hosted on Firebase)
63
+ โ”‚ โ”œโ”€โ”€ index.html # Landing page
64
+ โ”‚ โ”œโ”€โ”€ chat.html # Patient chat interface
65
+ โ”‚ โ”‚
66
+ โ”‚ โ”œโ”€โ”€ assets/ # Media files
67
+ โ”‚ โ”‚ โ””โ”€โ”€ logo.jpg # Brand logo
68
+ โ”‚ โ”‚
69
+ โ”‚ โ”œโ”€โ”€ css/ # Stylesheets
70
+ โ”‚ โ”‚ โ”œโ”€โ”€ chat.css # Patient chat styles
71
+ โ”‚ โ”‚ โ””โ”€โ”€ styles.css # Landing page styles
72
+ โ”‚ โ”‚
73
+ โ”‚ โ”œโ”€โ”€ js/ # Client-side scripts
74
+ โ”‚ โ”‚ โ”œโ”€โ”€ chat.js # Patient chat logic
75
+ โ”‚ โ”‚ โ””โ”€โ”€ search.js # Doctor search
76
+ โ”‚ โ”‚
77
+ โ”‚ โ””โ”€โ”€ app/ # Doctor dashboard
78
+ โ”‚ โ”œโ”€โ”€ index.html # Dashboard home
79
+ โ”‚ โ”œโ”€โ”€ inbox.html # Conversation inbox
80
+ โ”‚ โ”œโ”€โ”€ analytics.html # Analytics dashboard
81
+ โ”‚ โ”œโ”€โ”€ app.css # Dashboard styles
82
+ โ”‚ โ”œโ”€โ”€ app.js # Dashboard logic
83
+ โ”‚ โ”œโ”€โ”€ inbox.js # Inbox logic
84
+ โ”‚ โ”œโ”€โ”€ analytics.js # Analytics logic
85
+ โ”‚ โ””โ”€โ”€ config.js # Firebase configuration
86
+ โ”‚
87
+ โ”œโ”€โ”€ functions/ # Firebase Cloud Functions
88
+ โ”‚ โ””โ”€โ”€ src/
89
+ โ”‚ โ”œโ”€โ”€ index.js # Cloud Functions entry
90
+ โ”‚ โ”œโ”€โ”€ llm.js # AI integration
91
+ โ”‚ โ””โ”€โ”€ patient-api.js # Patient API handlers
92
+ โ”‚
93
+ โ”œโ”€โ”€ server.js # Local development server
94
+ โ”œโ”€โ”€ firestore.rules # Database security rules
95
+ โ”œโ”€โ”€ firebase.json # Firebase configuration
96
+ โ””โ”€โ”€ .env # Environment variables
97
+
98
+ Documentation/
99
+ โ”œโ”€โ”€ PLATFORM_OVERVIEW.md # Platform summary
100
+ โ”œโ”€โ”€ DOCTOR_TUTORIAL.md # Doctor user guide
101
+ โ”œโ”€โ”€ PATIENT_GUIDE.md # Patient user guide
102
+ โ””โ”€โ”€ ARCHITECTURE.md # This file
103
+ ```
104
+
105
+ ---
106
+
107
+ ## ๐Ÿ’พ Database Schema
108
+
109
+ ### Firestore Collections
110
+
111
+ #### 1. **providers**
112
+ Doctor profiles and settings
113
+
114
+ ```javascript
115
+ {
116
+ id: "auto-generated",
117
+ ownerId: "firebase-auth-uid",
118
+ handle: "dr-sarah-amina", // Unique URL identifier
119
+ displayName: "Dr. Sarah Amina",
120
+ email: "sarah@example.com",
121
+ specialty: "Family Medicine",
122
+ country: "US",
123
+ locale: "en",
124
+ photoUrl: "https://...",
125
+ logoUrl: "https://...",
126
+ brandPrimaryColor: "#4fb3a4",
127
+ brandSecondaryColor: "#297B56",
128
+ welcomeMessage: "Welcome! How can I help?",
129
+ enabledTopics: [
130
+ "medication_info_safety",
131
+ "general_health_info",
132
+ ...
133
+ ],
134
+ status: "published", // draft | published | suspended
135
+ monthlyChatCount: 45,
136
+ monthlyChatCountMonth: "2026-01",
137
+ createdAt: Timestamp,
138
+ updatedAt: Timestamp
139
+ }
140
+ ```
141
+
142
+ #### 2. **conversations**
143
+ Chat sessions between patients and providers
144
+
145
+ ```javascript
146
+ {
147
+ id: "auto-generated",
148
+ providerId: "provider-doc-id",
149
+ sessionId: "anonymous-session-id", // Patient identifier
150
+ handle: "dr-sarah-amina",
151
+ topic: "general_health_info",
152
+
153
+ // Client info (optional)
154
+ clientName: "John Doe",
155
+ clientEmail: "john@example.com",
156
+ clientPhone: "+256123456789",
157
+
158
+ // Status
159
+ isEscalated: false,
160
+ escalationReason: null, // "red_flag" | null
161
+
162
+ // Message summaries
163
+ lastUserMessage: "What should I do...",
164
+ lastAssistantMessage: "For a fever...",
165
+ lastMessageAt: Timestamp,
166
+
167
+ // Timestamps
168
+ createdAt: Timestamp,
169
+ updatedAt: Timestamp
170
+ }
171
+ ```
172
+
173
+ #### 3. **messages** (subcollection of conversations)
174
+ Individual messages in a conversation
175
+
176
+ ```javascript
177
+ conversations/{conversationId}/messages/{messageId}
178
+ {
179
+ id: "auto-generated",
180
+ role: "user", // user | assistant
181
+ content: "What should I do about...",
182
+ safetyFlags: ["pii_detected"], // Array of safety flags
183
+ createdAt: Timestamp
184
+ }
185
+ ```
186
+
187
+ #### 4. **safetyEvents**
188
+ Tracked safety incidents and escalations
189
+
190
+ ```javascript
191
+ {
192
+ id: "auto-generated",
193
+ providerId: "provider-doc-id",
194
+ conversationId: "conversation-id",
195
+ eventType: "escalated", // escalated | blocked_input | blocked_output | pii_detected
196
+ details: {
197
+ flags: ["severe_pain", "chest_pain"],
198
+ reason: "red_flag"
199
+ },
200
+ createdAt: Timestamp
201
+ }
202
+ ```
203
+
204
+ ---
205
+
206
+ ## ๐Ÿ”Œ API Endpoints
207
+
208
+ ### Public Endpoints (No Auth Required)
209
+
210
+ #### `GET /api/provider?handle={handle}`
211
+ Get public provider information
212
+
213
+ **Query Params**:
214
+ - `handle` (required): Doctor's unique handle
215
+
216
+ **Response**:
217
+ ```json
218
+ {
219
+ "handle": "dr-sarah-amina",
220
+ "displayName": "Dr. Sarah Amina",
221
+ "specialty": "Family Medicine",
222
+ "welcomeMessage": "Welcome!",
223
+ "brandPrimaryColor": "#4fb3a4",
224
+ "enabledTopics": ["medication_info_safety", ...],
225
+ "status": "published"
226
+ }
227
+ ```
228
+
229
+ #### `POST /api/chat`
230
+ Send patient message and get AI response
231
+
232
+ **Body**:
233
+ ```json
234
+ {
235
+ "handle": "dr-sarah-amina",
236
+ "sessionId": "anonymous-uuid",
237
+ "message": "What should I do about fever?",
238
+ "topic": "general_health_info",
239
+ "clientName": "John Doe", // Optional
240
+ "clientEmail": "john@email.com", // Optional
241
+ "clientPhone": "+256123456789" // Optional
242
+ }
243
+ ```
244
+
245
+ **Response**:
246
+ ```json
247
+ {
248
+ "conversationId": "conv-id",
249
+ "response": "For a fever, you should...",
250
+ "escalation": false,
251
+ "safetyFlags": []
252
+ }
253
+ ```
254
+
255
+ ### Protected Endpoints (Auth Required)
256
+
257
+ #### `GET /api/me`
258
+ Get current logged-in doctor's profile
259
+
260
+ **Headers**: `Authorization: Bearer {firebase-token}`
261
+
262
+ **Response**: Full provider object
263
+
264
+ #### `GET /api/conversations?limit=100`
265
+ Get all conversations for logged-in doctor
266
+
267
+ **Headers**: `Authorization: Bearer {firebase-token}`
268
+
269
+ **Query Params**:
270
+ - `limit` (optional): Max conversations to return (default: 30, max: 100)
271
+
272
+ **Response**:
273
+ ```json
274
+ {
275
+ "conversations": [
276
+ {
277
+ "id": "conv-id",
278
+ "sessionId": "session-uuid",
279
+ "clientName": "John Doe",
280
+ "lastUserMessage": "What should...",
281
+ "lastMessageAt": Timestamp,
282
+ "isEscalated": false,
283
+ ...
284
+ }
285
+ ]
286
+ }
287
+ ```
288
+
289
+ #### `GET /api/conversation/:id`
290
+ Get single conversation with full message history
291
+
292
+ **Headers**: `Authorization: Bearer {firebase-token}`
293
+
294
+ **Response**:
295
+ ```json
296
+ {
297
+ "id": "conv-id",
298
+ "sessionId": "session-uuid",
299
+ "messages": [
300
+ {
301
+ "role": "user",
302
+ "message": "What should I do?",
303
+ "createdAt": Timestamp
304
+ },
305
+ {
306
+ "role": "assistant",
307
+ "message": "For a fever...",
308
+ "createdAt": Timestamp
309
+ }
310
+ ],
311
+ ...
312
+ }
313
+ ```
314
+
315
+ #### `GET /api/analytics?period=month`
316
+ Get platform-wide analytics
317
+
318
+ **Headers**: `Authorization: Bearer {firebase-token}`
319
+
320
+ **Query Params**:
321
+ - `period` (optional): today | week | month | quarter | all
322
+
323
+ **Response**:
324
+ ```json
325
+ {
326
+ "summary": {
327
+ "totalDoctors": 15,
328
+ "activeDoctors": 12,
329
+ "totalConversations": 450,
330
+ "uniquePatients": 320
331
+ },
332
+ "doctors": [
333
+ {
334
+ "displayName": "Dr. Sarah",
335
+ "conversationCount": 45,
336
+ "uniquePatients": 32,
337
+ "messageCount": 180
338
+ }
339
+ ],
340
+ "period": "month"
341
+ }
342
+ ```
343
+
344
+ ---
345
+
346
+ ## ๐Ÿค– AI Integration
347
+
348
+ ### LLM Service (`functions/src/llm.js`)
349
+
350
+ #### AI Provider Priority
351
+ 1. **DeepSeek** (Primary) - Better medical accuracy
352
+ 2. **Google Gemini** (Fallback) - Backup if DeepSeek fails
353
+ 3. **Generic Response** - If both fail
354
+
355
+ #### Function: `generateResponse()`
356
+
357
+ ```javascript
358
+ async function generateResponse({ topicConfig, message, provider }) {
359
+ // 1. Try DeepSeek
360
+ try {
361
+ return await callDeepSeek({ topicConfig, message, provider });
362
+ } catch (error) {
363
+ console.error('DeepSeek failed:', error);
364
+ }
365
+
366
+ // 2. Fallback to Gemini
367
+ try {
368
+ return await callGemini({ topicConfig, message, provider });
369
+ } catch (error) {
370
+ console.error('Gemini failed:', error);
371
+ }
372
+
373
+ // 3. Generic fallback
374
+ return genericResponse(topicConfig);
375
+ }
376
+ ```
377
+
378
+ #### Safety Features
379
+
380
+ **Input Analysis**:
381
+ - PII detection (emails, phone numbers, addresses)
382
+ - Red flag keywords (chest pain, severe bleeding, etc.)
383
+ - Escalation triggers
384
+
385
+ **Output Analysis**:
386
+ - Medical advice blocking
387
+ - Diagnosis blocking
388
+ - Prescription blocking
389
+ - Dosing recommendations blocking
390
+
391
+ **Red Flag Keywords**:
392
+ ```javascript
393
+ const RED_FLAGS = [
394
+ 'chest pain', 'difficulty breathing', 'severe bleeding',
395
+ 'loss of consciousness', 'suicidal', 'kill myself',
396
+ 'severe pain', 'can\'t breathe', 'heart attack'
397
+ ];
398
+ ```
399
+
400
+ ---
401
+
402
+ ## ๐Ÿ” Security
403
+
404
+ ### Authentication Flow
405
+
406
+ ```
407
+ 1. Doctor signs up/in
408
+ โ†“
409
+ 2. Firebase Auth creates user
410
+ โ†“
411
+ 3. Frontend gets ID token
412
+ โ†“
413
+ 4. Token sent in Authorization header
414
+ โ†“
415
+ 5. Backend verifies token
416
+ โ†“
417
+ 6. Request proceeds if valid
418
+ ```
419
+
420
+ ### Firestore Security Rules
421
+
422
+ ```javascript
423
+ rules_version = '2';
424
+ service cloud.firestore {
425
+ match /databases/{database}/documents {
426
+
427
+ // Helper functions
428
+ function isSignedIn() {
429
+ return request.auth != null;
430
+ }
431
+
432
+ function isOwner(uid) {
433
+ return isSignedIn() && request.auth.uid == uid;
434
+ }
435
+
436
+ // Providers collection
437
+ match /providers/{providerId} {
438
+ allow read: if true; // Public read
439
+ allow create: if isSignedIn();
440
+ allow update, delete: if isOwner(resource.data.ownerId);
441
+ }
442
+
443
+ // Conversations collection
444
+ match /conversations/{conversationId} {
445
+ allow read: if isSignedIn(); // Doctors can read all
446
+ allow create: if true; // Anyone can create (patients)
447
+ allow update, delete: if false; // No direct updates
448
+
449
+ // Messages subcollection
450
+ match /messages/{messageId} {
451
+ allow read: if isSignedIn();
452
+ allow create: if true;
453
+ allow update, delete: if false;
454
+ }
455
+ }
456
+
457
+ // Safety events (admin only)
458
+ match /safetyEvents/{eventId} {
459
+ allow read: if isSignedIn();
460
+ allow create: if true;
461
+ allow update, delete: if false;
462
+ }
463
+ }
464
+ }
465
+ ```
466
+
467
+ ### Data Protection
468
+
469
+ 1. **PII Redaction**: Automatically removes sensitive info from logs
470
+ 2. **Encrypted Storage**: All Firestore data encrypted at rest
471
+ 3. **Token Validation**: Every protected request validates Firebase token
472
+ 4. **Rate Limiting**: Monthly chat limits per provider
473
+ 5. **Session Management**: Anonymous sessions for patient privacy
474
+
475
+ ---
476
+
477
+ ## ๐Ÿš€ Deployment
478
+
479
+ ### Local Development
480
+
481
+ ```bash
482
+ # 1. Install dependencies
483
+ npm install
484
+
485
+ # 2. Set environment variables
486
+ cp .env.example .env
487
+ # Edit .env with your API keys
488
+
489
+ # 3. Start development server
490
+ npm run dev
491
+ # Server runs on http://localhost:8080
492
+ ```
493
+
494
+ ### Environment Variables
495
+
496
+ ```bash
497
+ # .env file
498
+ DEEPSEEK_API_KEY=your_deepseek_key
499
+ GEMINI_API_KEY=your_gemini_key
500
+ FIREBASE_SERVICE_ACCOUNT=path/to/service-account.json
501
+ ```
502
+
503
+ ### Production Deployment
504
+
505
+ ```bash
506
+ # 1. Build and deploy to Firebase
507
+ firebase deploy
508
+
509
+ # This deploys:
510
+ # - Hosting (static files in public/)
511
+ # - Cloud Functions (functions/src/index.js)
512
+ # - Firestore rules (firestore.rules)
513
+ ```
514
+
515
+ ### Hosting Configuration (`firebase.json`)
516
+
517
+ ```json
518
+ {
519
+ "hosting": {
520
+ "public": "public",
521
+ "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
522
+ "rewrites": [
523
+ {
524
+ "source": "**",
525
+ "function": "api"
526
+ }
527
+ ]
528
+ },
529
+ "functions": {
530
+ "source": "functions"
531
+ }
532
+ }
533
+ ```
534
+
535
+ ---
536
+
537
+ ## ๐Ÿ“Š Data Flow
538
+
539
+ ### Patient Chat Flow
540
+
541
+ ```
542
+ 1. Patient opens doctor's unique link
543
+ โ†’ GET /api/provider?handle=dr-sarah-amina
544
+
545
+ 2. Page loads with doctor's branding and topics
546
+
547
+ 3. Patient selects topic and types message
548
+
549
+ 4. Frontend sends POST /api/chat
550
+ {
551
+ handle: "dr-sarah-amina",
552
+ sessionId: "anon-uuid",
553
+ message: "What should I do about fever?",
554
+ topic: "general_health_info"
555
+ }
556
+
557
+ 5. Backend processes:
558
+ a. Validates provider exists and is published
559
+ b. Checks monthly usage limits
560
+ c. Analyzes message for safety (PII, red flags)
561
+ d. Saves user message to Firestore
562
+ e. Calls AI (DeepSeek โ†’ Gemini fallback)
563
+ f. Analyzes AI response for safety
564
+ g. Saves AI response to Firestore
565
+ h. Returns response to patient
566
+
567
+ 6. Patient sees AI response instantly
568
+
569
+ 7. If escalated:
570
+ a. Safety event logged
571
+ b. Conversation marked as escalated
572
+ c. Doctor sees alert in inbox
573
+ ```
574
+
575
+ ### Doctor Inbox Flow
576
+
577
+ ```
578
+ 1. Doctor signs in
579
+ โ†’ Firebase Auth validates
580
+
581
+ 2. Opens inbox
582
+ โ†’ GET /api/conversations
583
+
584
+ 3. Backend returns:
585
+ - All conversations for this doctor
586
+ - Sorted by last message time
587
+ - With escalation flags
588
+
589
+ 4. Doctor clicks conversation
590
+ โ†’ GET /api/conversation/:id
591
+
592
+ 5. Backend returns:
593
+ - Full conversation details
594
+ - All messages (user + AI)
595
+ - Patient contact info if provided
596
+
597
+ 6. Doctor reviews and can reply (coming soon)
598
+ ```
599
+
600
+ ---
601
+
602
+ ## ๐ŸŽจ Frontend Architecture
603
+
604
+ ### Tech Stack
605
+ - **Vanilla JavaScript**: No frameworks, fast loading
606
+ - **CSS3**: Modern styling with CSS Grid and Flexbox
607
+ - **Firebase SDK**: Client-side auth and real-time updates
608
+
609
+ ### Key Components
610
+
611
+ #### Patient Chat (`public/chat.html` + `public/js/chat.js`)
612
+ - Topic selection dropdown
613
+ - Message composer
614
+ - Chat message display
615
+ - Session management
616
+ - AI response rendering
617
+
618
+ #### Doctor Dashboard (`public/app/index.html` + `public/app/app.js`)
619
+ - Authentication UI
620
+ - Profile onboarding
621
+ - Topic configuration
622
+ - Branding customization
623
+ - Link sharing tools
624
+
625
+ #### Doctor Inbox (`public/app/inbox.html` + `public/app/inbox.js`)
626
+ - Conversation list with filters
627
+ - Message history viewer
628
+ - Patient contact display
629
+ - Escalation alerts
630
+ - Reply interface (coming soon)
631
+
632
+ #### Analytics (`public/app/analytics.html` + `public/app/analytics.js`)
633
+ - Summary statistics cards
634
+ - Doctor performance table
635
+ - Time period filtering
636
+ - Data visualization
637
+
638
+ ---
639
+
640
+ ## ๐Ÿ”ง Configuration
641
+
642
+ ### Topics Configuration
643
+
644
+ Topics are defined in server code and can be enabled/disabled per doctor:
645
+
646
+ ```javascript
647
+ const TOPICS = {
648
+ medication_info_safety: {
649
+ name: "Medication Information & Safety",
650
+ systemPrompt: "You are a helpful medical assistant...",
651
+ disclaimer: "This is not medical advice...",
652
+ redFlags: ["chest pain", "difficulty breathing", ...]
653
+ },
654
+ general_health_info: {
655
+ name: "General Health Information",
656
+ ...
657
+ },
658
+ ...
659
+ };
660
+ ```
661
+
662
+ ### AI Model Configuration
663
+
664
+ ```javascript
665
+ // DeepSeek Configuration
666
+ {
667
+ apiKey: process.env.DEEPSEEK_API_KEY,
668
+ model: 'deepseek-chat',
669
+ temperature: 0.7,
670
+ maxTokens: 800
671
+ }
672
+
673
+ // Gemini Configuration
674
+ {
675
+ apiKey: process.env.GEMINI_API_KEY,
676
+ model: 'gemini-1.5-flash',
677
+ temperature: 0.7,
678
+ maxOutputTokens: 800
679
+ }
680
+ ```
681
+
682
+ ---
683
+
684
+ ## ๐Ÿ“ˆ Scalability Considerations
685
+
686
+ ### Current Limits
687
+ - **Monthly chats per doctor**: Configurable (default: 1000)
688
+ - **Message history**: 100 messages per conversation
689
+ - **Concurrent users**: Limited by Firebase Spark plan
690
+
691
+ ### Scaling Strategy
692
+ 1. **Horizontal Scaling**: Firebase auto-scales Cloud Functions
693
+ 2. **Database Sharding**: Firestore automatically distributes data
694
+ 3. **CDN**: Static assets served via Firebase CDN
695
+ 4. **Caching**: Implement Redis for frequently accessed data
696
+ 5. **Load Balancing**: Firebase handles automatically
697
+
698
+ ### Performance Optimizations
699
+ - Lazy loading of conversation messages
700
+ - Pagination for large datasets
701
+ - Debounced search inputs
702
+ - Optimistic UI updates
703
+ - Service worker for offline support (future)
704
+
705
+ ---
706
+
707
+ ## ๐Ÿงช Testing Strategy
708
+
709
+ ### Manual Testing Checklist
710
+ - [ ] Patient can open doctor link
711
+ - [ ] Chat interface loads correctly
712
+ - [ ] AI responds to messages
713
+ - [ ] Messages saved to database
714
+ - [ ] Doctor inbox shows conversations
715
+ - [ ] Escalations flagged correctly
716
+ - [ ] Analytics display accurately
717
+
718
+ ### Future Automated Testing
719
+ - Unit tests for API endpoints
720
+ - Integration tests for AI service
721
+ - E2E tests for critical user flows
722
+ - Load testing for scalability
723
+
724
+ ---
725
+
726
+ ## ๐Ÿ“ Monitoring & Logging
727
+
728
+ ### Current Logging
729
+ - Console logs in server.js
730
+ - Firebase Functions logs
731
+ - Client-side error tracking (future)
732
+
733
+ ### Key Metrics to Track
734
+ - Response time (API latency)
735
+ - AI success/failure rates
736
+ - Escalation frequency
737
+ - User engagement (messages per session)
738
+ - Doctor response times
739
+
740
+ ---
741
+
742
+ ## ๐Ÿ”ฎ Future Architecture Plans
743
+
744
+ ### Planned Enhancements
745
+
746
+ 1. **Real-time Updates**: WebSocket for live inbox refresh
747
+ 2. **Push Notifications**: FCM for doctor alerts
748
+ 3. **Payment Integration**: Stripe for subscriptions
749
+ 4. **Advanced Analytics**: BigQuery for complex queries
750
+ 5. **Multi-language**: i18n support
751
+ 6. **Microservices**: Separate AI service
752
+ 7. **CDN Optimization**: Cloudflare integration
753
+ 8. **Monitoring**: Sentry for error tracking
754
+
755
+ ---
756
+
757
+ ## ๐Ÿ“š Related Documentation
758
+
759
+ - [PLATFORM_OVERVIEW.md](./PLATFORM_OVERVIEW.md) - High-level platform description
760
+ - [DOCTOR_TUTORIAL.md](./DOCTOR_TUTORIAL.md) - Doctor user guide
761
+ - [PATIENT_GUIDE.md](./PATIENT_GUIDE.md) - Patient user guide
762
+ - [Firebase Documentation](https://firebase.google.com/docs)
763
+ - [DeepSeek API Docs](https://platform.deepseek.com/docs)
764
+ - [Gemini API Docs](https://ai.google.dev/docs)
765
+
766
+ ---
767
+
768
+ *Last Updated: January 2026*
769
+ *Version: 1.0*