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.
- package/.env.staging.example +19 -0
- package/.firebaserc +6 -0
- package/.github/workflows/auto-merge-to-main.yml +28 -0
- package/.github/workflows/ci.yml +27 -0
- package/.github/workflows/npxhub-publish.yml +170 -0
- package/.prettierignore +4 -0
- package/.prettierrc.json +7 -0
- package/README.md +142 -0
- package/SRS.md +448 -0
- package/apphosting.staging.yaml +48 -0
- package/apphosting.yaml +50 -0
- package/bin/evaldoc.cjs +105 -0
- package/cors.json +8 -0
- package/docs/ARCHITECTURE.md +769 -0
- package/docs/ARCHITECTURE_SUMMARY.md +323 -0
- package/docs/DEPLOYMENT.md +86 -0
- package/docs/DEPLOYMENT_STEPS.md +373 -0
- package/docs/DEPLOY_FIRESTORE_RULES.md +239 -0
- package/docs/DEPLOY_STORAGE_RULES.md +82 -0
- package/docs/DOCTOR_TUTORIAL.md +467 -0
- package/docs/FIREBASE_STORAGE_CORS_FIX.md +131 -0
- package/docs/FIXES_APPLIED.md +128 -0
- package/docs/IMPLEMENTATION.md +498 -0
- package/docs/IMPLEMENTATION_COMPLETE.md +317 -0
- package/docs/LLM-SETUP.md +216 -0
- package/docs/MANUAL_TEST_GUIDE.md +327 -0
- package/docs/PATIENT_GUIDE.md +451 -0
- package/docs/PLATFORM_OVERVIEW.md +194 -0
- package/docs/QUICKSTART.md +252 -0
- package/docs/QUICK_REFERENCE.md +222 -0
- package/docs/READY_TO_TEST.md +383 -0
- package/docs/RUN.md +237 -0
- package/docs/START_TESTING.md +130 -0
- package/docs/STRIPE_CONNECT_SETUP.md +454 -0
- package/docs/SYSTEM_READY.md +345 -0
- package/docs/THREADS_IMPLEMENTATION_COMPLETE.md +431 -0
- package/docs/THREAD_IMPLEMENTATION_GUIDE.md +345 -0
- package/docs/firebasefiles.md +21 -0
- package/docs/homepage.md +1208 -0
- package/docs/payments.md +159 -0
- package/eslint.config.js +76 -0
- package/firebase.json +27 -0
- package/firestore.indexes.json +88 -0
- package/firestore.rules +125 -0
- package/functions/package-lock.json +2884 -0
- package/functions/package.json +20 -0
- package/functions/src/analytics.js +101 -0
- package/functions/src/audit.js +28 -0
- package/functions/src/auth.js +19 -0
- package/functions/src/drafts.js +128 -0
- package/functions/src/feedback.js +164 -0
- package/functions/src/firebase-init.js +29 -0
- package/functions/src/i18n.js +134 -0
- package/functions/src/limits.js +27 -0
- package/functions/src/llm.js +271 -0
- package/functions/src/ner.js +162 -0
- package/functions/src/notifications.js +273 -0
- package/functions/src/orgs.js +127 -0
- package/functions/src/patient-api.js +545 -0
- package/functions/src/payment.js +830 -0
- package/functions/src/safety.js +188 -0
- package/functions/src/stripe-config.js +33 -0
- package/functions/src/topics.js +94 -0
- package/functions/src/triage.js +191 -0
- package/functions/src/utils.js +28 -0
- package/functions/src/validate.js +177 -0
- package/functions/test-firebase.js +36 -0
- package/jest.config.js +18 -0
- package/package.json +52 -0
- package/public/404.html +93 -0
- package/public/app/analytics.html +336 -0
- package/public/app/analytics.js +177 -0
- package/public/app/app.css +1400 -0
- package/public/app/app.js +1754 -0
- package/public/app/config.js +14 -0
- package/public/app/inbox-threads.js +843 -0
- package/public/app/inbox.html +598 -0
- package/public/app/inbox.js +397 -0
- package/public/app/index.html +612 -0
- package/public/assets/logo.jpg +0 -0
- package/public/chat.html +137 -0
- package/public/css/chat.css +870 -0
- package/public/css/landing-enhance.css +298 -0
- package/public/css/styles.css +1198 -0
- package/public/favicon.svg +5 -0
- package/public/find-doctor.html +220 -0
- package/public/index.html +399 -0
- package/public/js/chat-threads.js +513 -0
- package/public/js/chat.js +832 -0
- package/public/js/search.js +41 -0
- package/public/privacy.html +101 -0
- package/public/robots.txt +6 -0
- package/public/site.webmanifest +12 -0
- package/public/terms.html +110 -0
- package/scripts/create-test-provider.js +55 -0
- package/scripts/deploy-staging.sh +51 -0
- package/scripts/fix-provider.js +39 -0
- package/scripts/quick-test.sh +37 -0
- package/scripts/test-chat.sh +54 -0
- package/scripts/test-multi-turn.js +137 -0
- package/scripts/test-ner-simple.js +28 -0
- package/scripts/test-ner.js +60 -0
- package/scripts/test-stripe-connect.js +304 -0
- package/scripts/test-webhook-secret.sh +24 -0
- package/server.js +3864 -0
- package/storage.rules +22 -0
- package/test-api.json +1 -0
- package/tests/emulator/README.md +38 -0
- package/tests/emulator/counters.emulator.test.js +81 -0
- package/tests/integration/api-account-selfserve.test.js +312 -0
- package/tests/integration/api-admin-digest.test.js +202 -0
- package/tests/integration/api-chat-satisfaction.test.js +259 -0
- package/tests/integration/api-doctor-drafts.test.js +236 -0
- package/tests/integration/api-doctor-inbox.test.js +401 -0
- package/tests/integration/api-org.test.js +328 -0
- package/tests/integration/api-payment.test.js +664 -0
- package/tests/integration/api-provider-settings.test.js +475 -0
- package/tests/integration/api-qr.test.js +121 -0
- package/tests/integration/api-security.test.js +241 -0
- package/tests/integration/api-stripe-search.test.js +303 -0
- package/tests/integration/api-webhook-deletion.test.js +231 -0
- package/tests/mocks/firebase-admin.js +220 -0
- package/tests/unit/analytics.test.js +151 -0
- package/tests/unit/audit-bugs.test.js +203 -0
- package/tests/unit/chat-ui-logic.test.js +283 -0
- package/tests/unit/drafts.test.js +104 -0
- package/tests/unit/feedback.test.js +148 -0
- package/tests/unit/i18n.test.js +229 -0
- package/tests/unit/llm-retry.test.js +122 -0
- package/tests/unit/notifications.test.js +155 -0
- package/tests/unit/orgs.test.js +328 -0
- package/tests/unit/payment.test.js +889 -0
- package/tests/unit/safety-edge-cases.test.js +509 -0
- package/tests/unit/safety-srs-compliance.test.js +252 -0
- package/tests/unit/safety.test.js +291 -0
- package/tests/unit/server-helpers.test.js +774 -0
- package/tests/unit/topics-limits.test.js +158 -0
- package/tests/unit/triage.test.js +152 -0
- package/tests/unit/validate.test.js +408 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
# Manual Testing Guide - Stripe Connect Payment System
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
✅ Server running: `http://localhost:54112`
|
|
6
|
+
✅ Stripe keys configured in `.env`
|
|
7
|
+
✅ Firebase project access
|
|
8
|
+
|
|
9
|
+
## Test Flow
|
|
10
|
+
|
|
11
|
+
### Part 1: Provider Setup (Using Existing Provider)
|
|
12
|
+
|
|
13
|
+
Since you already have providers in your system, let's use one for testing.
|
|
14
|
+
|
|
15
|
+
#### 1. Sign into Provider Dashboard
|
|
16
|
+
|
|
17
|
+
1. Go to: http://localhost:54112/app
|
|
18
|
+
2. Sign in with an existing provider account
|
|
19
|
+
3. You should see the dashboard
|
|
20
|
+
|
|
21
|
+
#### 2. Enable Stripe Connect
|
|
22
|
+
|
|
23
|
+
Open your browser's Developer Console (F12) and run:
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
// Get your Firebase ID token
|
|
27
|
+
firebase.auth().currentUser.getIdToken().then(token => {
|
|
28
|
+
console.log('Token:', token);
|
|
29
|
+
|
|
30
|
+
// Create Connect account
|
|
31
|
+
fetch('http://localhost:54112/api/stripe/create-connect-account', {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: {
|
|
34
|
+
'Authorization': `Bearer ${token}`,
|
|
35
|
+
'Content-Type': 'application/json'
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
.then(r => r.json())
|
|
39
|
+
.then(data => {
|
|
40
|
+
console.log('✓ Connect Account Created:', data);
|
|
41
|
+
// Save account ID
|
|
42
|
+
window.stripeAccountId = data.accountId;
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### 3. Get Onboarding Link
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
firebase.auth().currentUser.getIdToken().then(token => {
|
|
51
|
+
fetch('http://localhost:54112/api/stripe/create-account-link', {
|
|
52
|
+
method: 'POST',
|
|
53
|
+
headers: {
|
|
54
|
+
'Authorization': `Bearer ${token}`,
|
|
55
|
+
'Content-Type': 'application/json'
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
.then(r => r.json())
|
|
59
|
+
.then(data => {
|
|
60
|
+
console.log('✓ Onboarding Link:', data.url);
|
|
61
|
+
// Open in new tab
|
|
62
|
+
window.open(data.url, '_blank');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### 4. Complete Stripe Onboarding
|
|
68
|
+
|
|
69
|
+
1. Click the onboarding link that opens
|
|
70
|
+
2. **Use test mode details**:
|
|
71
|
+
- Business type: Individual
|
|
72
|
+
- Country: United States
|
|
73
|
+
- Name: Test Provider
|
|
74
|
+
- DOB: 01/01/1990
|
|
75
|
+
- SSN: 000-00-0000 (test mode)
|
|
76
|
+
- Address: Any valid US address
|
|
77
|
+
- Bank: Use test routing number `110000000`
|
|
78
|
+
- Account: Any 10-12 digits
|
|
79
|
+
|
|
80
|
+
3. Complete all steps
|
|
81
|
+
4. You'll be redirected back to `/app?onboarding=complete`
|
|
82
|
+
|
|
83
|
+
#### 5. Set Subscription Pricing
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
firebase.auth().currentUser.getIdToken().then(token => {
|
|
87
|
+
fetch('http://localhost:54112/api/stripe/set-pricing', {
|
|
88
|
+
method: 'POST',
|
|
89
|
+
headers: {
|
|
90
|
+
'Authorization': `Bearer ${token}`,
|
|
91
|
+
'Content-Type': 'application/json'
|
|
92
|
+
},
|
|
93
|
+
body: JSON.stringify({
|
|
94
|
+
currency: 'usd',
|
|
95
|
+
prices: {
|
|
96
|
+
day: 5.00,
|
|
97
|
+
week: 20.00,
|
|
98
|
+
month: 50.00
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
.then(r => r.json())
|
|
103
|
+
.then(data => {
|
|
104
|
+
console.log('✓ Pricing Set:', data);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Part 2: Patient Subscription
|
|
110
|
+
|
|
111
|
+
#### 6. Get Provider Info
|
|
112
|
+
|
|
113
|
+
First, get the provider's handle. In the console:
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
// Get current provider data
|
|
117
|
+
fetch('http://localhost:54112/api/me', {
|
|
118
|
+
headers: {
|
|
119
|
+
'Authorization': `Bearer ${await firebase.auth().currentUser.getIdToken()}`
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
.then(r => r.json())
|
|
123
|
+
.then(data => {
|
|
124
|
+
console.log('Provider Handle:', data.handle);
|
|
125
|
+
window.providerHandle = data.handle;
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### 7. Create Checkout Session (as Patient)
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
// Simulate patient with session ID
|
|
133
|
+
const patientSessionId = `test-patient-${Date.now()}`;
|
|
134
|
+
|
|
135
|
+
fetch('http://localhost:54112/api/payment/create-checkout-session', {
|
|
136
|
+
method: 'POST',
|
|
137
|
+
headers: {
|
|
138
|
+
'Content-Type': 'application/json'
|
|
139
|
+
},
|
|
140
|
+
body: JSON.stringify({
|
|
141
|
+
handle: window.providerHandle, // Use provider handle from step 6
|
|
142
|
+
sessionId: patientSessionId,
|
|
143
|
+
interval: 'month' // or 'week' or 'day'
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
.then(r => r.json())
|
|
147
|
+
.then(data => {
|
|
148
|
+
console.log('✓ Checkout Session:', data);
|
|
149
|
+
console.log('Open this URL:', data.url);
|
|
150
|
+
window.open(data.url, '_blank');
|
|
151
|
+
// Save for later
|
|
152
|
+
window.patientSessionId = patientSessionId;
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
#### 8. Complete Payment
|
|
157
|
+
|
|
158
|
+
1. Click the checkout URL that opens
|
|
159
|
+
2. **Use test card**:
|
|
160
|
+
- Card number: `4242 4242 4242 4242`
|
|
161
|
+
- Expiry: Any future date (e.g., `12/34`)
|
|
162
|
+
- CVC: Any 3 digits (e.g., `123`)
|
|
163
|
+
- ZIP: Any 5 digits (e.g., `12345`)
|
|
164
|
+
|
|
165
|
+
3. Complete payment
|
|
166
|
+
4. You'll be redirected to `/payment-success?session_id=...`
|
|
167
|
+
|
|
168
|
+
#### 9. Check Access (After Payment)
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
fetch('http://localhost:54112/api/payment/check-access', {
|
|
172
|
+
method: 'POST',
|
|
173
|
+
headers: {
|
|
174
|
+
'Content-Type': 'application/json'
|
|
175
|
+
},
|
|
176
|
+
body: JSON.stringify({
|
|
177
|
+
handle: window.providerHandle,
|
|
178
|
+
sessionId: window.patientSessionId
|
|
179
|
+
})
|
|
180
|
+
})
|
|
181
|
+
.then(r => r.json())
|
|
182
|
+
.then(data => {
|
|
183
|
+
console.log('✓ Access Status:', data);
|
|
184
|
+
// Should show: { hasAccess: true, type: 'subscription' }
|
|
185
|
+
});
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Part 3: Verify in Firestore
|
|
189
|
+
|
|
190
|
+
Check your Firestore database:
|
|
191
|
+
|
|
192
|
+
1. **providers/{uid}** - Should have:
|
|
193
|
+
- `stripeAccountId`: "acct_..."
|
|
194
|
+
- `stripeOnboardingStatus`: "COMPLETE"
|
|
195
|
+
- `chargesEnabled`: true
|
|
196
|
+
- `payoutsEnabled`: true
|
|
197
|
+
- `stripePriceIds`: { day: "price_...", week: "price_...", month: "price_..." }
|
|
198
|
+
|
|
199
|
+
2. **patients/{sessionId}** - Should have:
|
|
200
|
+
- `stripeCustomerId`: "cus_..."
|
|
201
|
+
|
|
202
|
+
3. **subscriptions** - Should have a document with:
|
|
203
|
+
- `providerId`: provider UID
|
|
204
|
+
- `patientId`: session ID
|
|
205
|
+
- `status`: "active"
|
|
206
|
+
- `stripeSubscriptionId`: "sub_..."
|
|
207
|
+
|
|
208
|
+
4. **access/{providerId}_{patientId}** - Should have:
|
|
209
|
+
- `status`: "ACTIVE"
|
|
210
|
+
- `stripeSubscriptionId`: "sub_..."
|
|
211
|
+
|
|
212
|
+
### Part 4: Verify Revenue
|
|
213
|
+
|
|
214
|
+
#### 10. Check Revenue in Provider Dashboard
|
|
215
|
+
|
|
216
|
+
```javascript
|
|
217
|
+
firebase.auth().currentUser.getIdToken().then(token => {
|
|
218
|
+
fetch('http://localhost:54112/api/payment/revenue', {
|
|
219
|
+
headers: {
|
|
220
|
+
'Authorization': `Bearer ${token}`
|
|
221
|
+
}
|
|
222
|
+
})
|
|
223
|
+
.then(r => r.json())
|
|
224
|
+
.then(data => {
|
|
225
|
+
console.log('✓ Revenue Analytics:', data);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### 11. Check Transaction History
|
|
231
|
+
|
|
232
|
+
```javascript
|
|
233
|
+
firebase.auth().currentUser.getIdToken().then(token => {
|
|
234
|
+
fetch('http://localhost:54112/api/payment/transactions', {
|
|
235
|
+
headers: {
|
|
236
|
+
'Authorization': `Bearer ${token}`
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
.then(r => r.json())
|
|
240
|
+
.then(data => {
|
|
241
|
+
console.log('✓ Transactions:', data);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Part 5: Verify in Stripe Dashboard
|
|
247
|
+
|
|
248
|
+
1. Go to: https://dashboard.stripe.com/test/connect/accounts
|
|
249
|
+
2. You should see the provider's Connect account
|
|
250
|
+
3. Click on it to see details
|
|
251
|
+
|
|
252
|
+
4. Go to: https://dashboard.stripe.com/test/subscriptions
|
|
253
|
+
5. You should see the patient's subscription
|
|
254
|
+
6. Note the **25% application fee** is listed
|
|
255
|
+
|
|
256
|
+
7. Go to: https://dashboard.stripe.com/test/balance
|
|
257
|
+
8. You should see your 25% platform fee in the balance
|
|
258
|
+
|
|
259
|
+
## Expected Results
|
|
260
|
+
|
|
261
|
+
✅ Provider has Stripe Connect account created
|
|
262
|
+
✅ Provider completes onboarding
|
|
263
|
+
✅ Provider sets subscription prices
|
|
264
|
+
✅ Patient can create checkout session
|
|
265
|
+
✅ Patient completes payment
|
|
266
|
+
✅ Access is granted automatically
|
|
267
|
+
✅ Revenue shows in provider dashboard
|
|
268
|
+
✅ Platform receives 25% fee
|
|
269
|
+
✅ Provider receives 75% in their Connect account
|
|
270
|
+
|
|
271
|
+
## Troubleshooting
|
|
272
|
+
|
|
273
|
+
### "Provider has not set up payments yet"
|
|
274
|
+
- Run step 2 to create Connect account
|
|
275
|
+
- Complete Stripe onboarding (step 4)
|
|
276
|
+
|
|
277
|
+
### "Provider payment account not yet approved"
|
|
278
|
+
- Complete all Stripe onboarding steps
|
|
279
|
+
- Check `chargesEnabled` is true in Firestore
|
|
280
|
+
|
|
281
|
+
### "month subscription not available"
|
|
282
|
+
- Run step 5 to set pricing
|
|
283
|
+
- Check `stripePriceIds.month` exists in Firestore
|
|
284
|
+
|
|
285
|
+
### Access still shows `hasAccess: false`
|
|
286
|
+
- Wait for webhooks to process (usually instant)
|
|
287
|
+
- Check webhook secret is configured
|
|
288
|
+
- Manually check `access` collection in Firestore
|
|
289
|
+
|
|
290
|
+
## Clean Up Test Data
|
|
291
|
+
|
|
292
|
+
```javascript
|
|
293
|
+
// Cancel subscription
|
|
294
|
+
fetch('http://localhost:54112/api/payment/cancel-subscription', {
|
|
295
|
+
method: 'POST',
|
|
296
|
+
headers: {
|
|
297
|
+
'Content-Type': 'application/json'
|
|
298
|
+
},
|
|
299
|
+
body: JSON.stringify({
|
|
300
|
+
subscriptionId: 'sub_...', // From Firestore or Stripe dashboard
|
|
301
|
+
cancelAtPeriodEnd: false // Cancel immediately
|
|
302
|
+
})
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Next Steps
|
|
307
|
+
|
|
308
|
+
Once testing is successful:
|
|
309
|
+
|
|
310
|
+
1. **Set up webhooks properly**:
|
|
311
|
+
- Go to https://dashboard.stripe.com/test/webhooks
|
|
312
|
+
- Add endpoint: `https://your-domain.com/api/payment/webhook`
|
|
313
|
+
- Copy webhook secret to `.env`
|
|
314
|
+
|
|
315
|
+
2. **Switch to live mode**:
|
|
316
|
+
- Use live API keys (`pk_live_...` and `sk_live_...`)
|
|
317
|
+
- Complete business verification
|
|
318
|
+
- Update webhook URL to production
|
|
319
|
+
|
|
320
|
+
3. **Add UI components** (optional):
|
|
321
|
+
- Onboarding button in provider dashboard
|
|
322
|
+
- Subscription picker for patients
|
|
323
|
+
- Revenue charts
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
**Note**: Since we don't have webhook secret yet, access control won't update automatically. You can manually update the `access` collection in Firestore for testing purposes.
|