sms-verification-api 0.9.1
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.example +20 -0
- package/DEPLOYMENT.md +151 -0
- package/README.md +475 -0
- package/docs/app/(home)/layout.tsx +7 -0
- package/docs/app/(home)/page.tsx +38 -0
- package/docs/app/docs/[[...slug]]/page.tsx +59 -0
- package/docs/app/docs/layout.tsx +12 -0
- package/docs/app/docs-og/[...slug]/route.ts +24 -0
- package/docs/app/globals.css +587 -0
- package/docs/app/layout.config.tsx +13 -0
- package/docs/app/layout.tsx +27 -0
- package/docs/app/logo.tsx +35 -0
- package/docs/content/docs/API_AUTHENTICATION.md +91 -0
- package/docs/content/docs/DEPLOYMENT.md +181 -0
- package/docs/content/docs/api/post.mdx +35 -0
- package/docs/content/docs/api/verify.mdx +34 -0
- package/docs/content/docs/meta.json +8 -0
- package/docs/content/docs/verify-legal-name.md +339 -0
- package/docs/lib/source.ts +14 -0
- package/docs/mdx-components.tsx +12 -0
- package/docs/next.config.mjs +51 -0
- package/docs/openapi.json +329 -0
- package/docs/package.json +37 -0
- package/docs/postcss.config.mjs +5 -0
- package/docs/scripts/generate-docs.mjs +23 -0
- package/docs/source.config.ts +5 -0
- package/docs/tsconfig.json +29 -0
- package/docs/worker.js +35 -0
- package/docs/wrangler.toml +26 -0
- package/examples/client.js +119 -0
- package/examples/demo.html +325 -0
- package/examples/libphonenumber-example.js +120 -0
- package/openapi.json +329 -0
- package/package.json +71 -0
- package/scripts/deploy.sh +63 -0
- package/src/identity-verification-server.ts +553 -0
- package/src/index.js +8 -0
- package/src/sns.js +236 -0
- package/src/verify-phone-server.js +448 -0
- package/src/verify-phone.ts +551 -0
- package/test/api.test.js +201 -0
- package/test/integration.test.js +152 -0
- package/test/metadata-test.js +73 -0
- package/test/server.test.js +143 -0
- package/test/setup.js +32 -0
- package/test/utils.test.js +186 -0
- package/test/verify.test.js +23 -0
- package/test/voip.test.js +112 -0
- package/vitest.config.js +10 -0
- package/wrangler.toml +27 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Identity Verification API Demo
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
A comprehensive identity verification system that uses TrestleIQ APIs to validate phone numbers, addresses, and generate knowledge-based authentication questions.
|
|
6
|
+
|
|
7
|
+
## 🚀 Quick Start
|
|
8
|
+
|
|
9
|
+
### Prerequisites
|
|
10
|
+
- Node.js or Bun runtime
|
|
11
|
+
- TrestleIQ API key
|
|
12
|
+
|
|
13
|
+
### Installation
|
|
14
|
+
```bash
|
|
15
|
+
# Install dependencies
|
|
16
|
+
npm install hono @hono/zod-openapi zod
|
|
17
|
+
# or
|
|
18
|
+
bun add hono @hono/zod-openapi zod
|
|
19
|
+
|
|
20
|
+
# Set your TrestleIQ API key
|
|
21
|
+
export TRESTLE_API_KEY=your_api_key_here
|
|
22
|
+
|
|
23
|
+
# Run the server
|
|
24
|
+
bun run server.js
|
|
25
|
+
# or
|
|
26
|
+
node server.js
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Server Endpoints
|
|
30
|
+
- 🏠 `http://localhost:3000` - Server root
|
|
31
|
+
- 📊 `http://localhost:3000/health` - Health check
|
|
32
|
+
- 📚 `http://localhost:3000/swagger` - Interactive API documentation
|
|
33
|
+
- 🔍 `http://localhost:3000/doc` - OpenAPI specification
|
|
34
|
+
- 🎮 `http://localhost:3000/demo` - Live demo with sample data
|
|
35
|
+
- ✅ `POST http://localhost:3000/verify-identity` - Main verification endpoint
|
|
36
|
+
|
|
37
|
+
## 🎯 How It Works
|
|
38
|
+
|
|
39
|
+
### The Verification Process
|
|
40
|
+
|
|
41
|
+
1. **Input Collection**: Accept phone number, legal name, and current address
|
|
42
|
+
2. **Multi-API Lookup**: Query TrestleIQ APIs in parallel for comprehensive data
|
|
43
|
+
3. **Historical Analysis**: Extract previous addresses, phone numbers, and associated names
|
|
44
|
+
4. **Scoring Algorithm**: Calculate confidence score (0-100) based on data matches
|
|
45
|
+
5. **Question Generation**: Create knowledge-based questions from historical data
|
|
46
|
+
6. **Recommendations**: Provide actionable next steps based on verification results
|
|
47
|
+
|
|
48
|
+
### Scoring System (100 Points Total)
|
|
49
|
+
|
|
50
|
+
| Category | Max Points | Criteria |
|
|
51
|
+
|----------|------------|----------|
|
|
52
|
+
| **Phone Validation** | 30 | Valid number (15 pts) + Line type (10 pts) + Non-commercial (5 pts) |
|
|
53
|
+
| **Name Matching** | 40 | Exact match (40 pts) or Partial match (20 pts) |
|
|
54
|
+
| **Address Validation** | 30 | Valid address (15 pts) + Active delivery (10 pts) + Residential (5 pts) |
|
|
55
|
+
|
|
56
|
+
### Score Interpretation
|
|
57
|
+
- **🔴 0-29**: High risk - Request additional ID documents
|
|
58
|
+
- **🟡 30-59**: Medium risk - Manual review recommended
|
|
59
|
+
- **🟢 60-79**: Low risk - Standard verification process
|
|
60
|
+
- **✅ 80-100**: Very low risk - High confidence verification
|
|
61
|
+
|
|
62
|
+
## 📝 API Usage Examples
|
|
63
|
+
|
|
64
|
+
### Sample Request
|
|
65
|
+
```bash
|
|
66
|
+
curl -X POST http://localhost:3000/verify-identity \
|
|
67
|
+
-H "Content-Type: application/json" \
|
|
68
|
+
-d '{
|
|
69
|
+
"phone_number": "2069735100",
|
|
70
|
+
"legal_name": "John Smith",
|
|
71
|
+
"current_address": {
|
|
72
|
+
"street_line_1": "123 Main St",
|
|
73
|
+
"city": "Seattle",
|
|
74
|
+
"state_code": "WA",
|
|
75
|
+
"postal_code": "98101",
|
|
76
|
+
"country_code": "US"
|
|
77
|
+
}
|
|
78
|
+
}'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Sample Response
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"verification_score": 75,
|
|
85
|
+
"name_match_found": true,
|
|
86
|
+
"phone_validated": true,
|
|
87
|
+
"address_validated": true,
|
|
88
|
+
"questions": [
|
|
89
|
+
{
|
|
90
|
+
"id": "addr_1703123456789",
|
|
91
|
+
"question": "Which of the following addresses have you lived at in the past?",
|
|
92
|
+
"type": "address_history",
|
|
93
|
+
"options": [
|
|
94
|
+
"456 Oak Ave, Seattle, WA",
|
|
95
|
+
"789 Pine St, Tacoma, WA",
|
|
96
|
+
"123 Fake St, Nowhere, CA",
|
|
97
|
+
"101 False Blvd, Bogus, NY",
|
|
98
|
+
"202 Phony Way, Unreal, WA"
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "phone_1703123456790",
|
|
103
|
+
"question": "Which of the following phone numbers have you previously used?",
|
|
104
|
+
"type": "phone_history",
|
|
105
|
+
"options": [
|
|
106
|
+
"2065551234",
|
|
107
|
+
"4255559876",
|
|
108
|
+
"5551234567",
|
|
109
|
+
"8889876543",
|
|
110
|
+
"None of the above"
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"id": "name_1703123456791",
|
|
115
|
+
"question": "Are any of the following names associated with you (maiden name, nickname, etc.)?",
|
|
116
|
+
"type": "name_verification",
|
|
117
|
+
"options": [
|
|
118
|
+
"J. Smith",
|
|
119
|
+
"Johnny Smith",
|
|
120
|
+
"John S. Smith",
|
|
121
|
+
"Jon Smith",
|
|
122
|
+
"None of the above"
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"historical_data": {
|
|
127
|
+
"previous_addresses": [
|
|
128
|
+
"456 Oak Ave, Seattle, WA",
|
|
129
|
+
"789 Pine St, Tacoma, WA",
|
|
130
|
+
"321 Cedar Ln, Bellevue, WA"
|
|
131
|
+
],
|
|
132
|
+
"previous_phones": [
|
|
133
|
+
"2065551234",
|
|
134
|
+
"4255559876"
|
|
135
|
+
],
|
|
136
|
+
"associated_names": [
|
|
137
|
+
"J. Smith",
|
|
138
|
+
"Johnny Smith",
|
|
139
|
+
"John S. Smith"
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
"recommendations": [
|
|
143
|
+
"Proceed with standard verification process",
|
|
144
|
+
"Consider asking verification questions to increase confidence"
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## 🧠 Smart Features
|
|
150
|
+
|
|
151
|
+
### Dynamic Question Generation
|
|
152
|
+
The system intelligently creates multiple-choice questions by:
|
|
153
|
+
- **Mixing real historical data** with plausible decoy options
|
|
154
|
+
- **Randomizing question order** to prevent pattern recognition
|
|
155
|
+
- **Balancing difficulty** - not too easy, not impossible
|
|
156
|
+
- **Including safety options** like "None of the above"
|
|
157
|
+
|
|
158
|
+
### Historical Data Analysis
|
|
159
|
+
Extracts comprehensive historical information:
|
|
160
|
+
- **Previous addresses** from phone and person records
|
|
161
|
+
- **Associated phone numbers** across different time periods
|
|
162
|
+
- **Name variations** including nicknames, initials, and maiden names
|
|
163
|
+
- **Cross-references data** across multiple API sources for accuracy
|
|
164
|
+
|
|
165
|
+
### Risk-Based Recommendations
|
|
166
|
+
Provides actionable recommendations based on verification results:
|
|
167
|
+
- **Document requests** for low-scoring verifications
|
|
168
|
+
- **VOIP warnings** for non-fixed internet phone numbers
|
|
169
|
+
- **Manual review triggers** for medium-confidence scores
|
|
170
|
+
- **Approval suggestions** for high-confidence verifications
|
|
171
|
+
|
|
172
|
+
## 🔧 Advanced Configuration
|
|
173
|
+
|
|
174
|
+
### Environment Variables
|
|
175
|
+
```bash
|
|
176
|
+
TRESTLE_API_KEY=your_trestle_api_key # Required: TrestleIQ API key
|
|
177
|
+
PORT=3000 # Optional: Server port (default: 3000)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Custom Scoring Weights
|
|
181
|
+
You can modify the scoring algorithm by adjusting the point values in the `calculateVerificationScore` function:
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
// Phone validation scoring
|
|
185
|
+
if (phoneResult?.is_valid) {
|
|
186
|
+
score += 15 // Base validation points
|
|
187
|
+
if (phoneResult.line_type === 'Mobile' || phoneResult.line_type === 'Landline') {
|
|
188
|
+
score += 10 // Reliable line type bonus
|
|
189
|
+
}
|
|
190
|
+
if (!phoneResult.is_commercial) {
|
|
191
|
+
score += 5 // Residential number bonus
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Question Customization
|
|
197
|
+
Modify question generation in `generateVerificationQuestions`:
|
|
198
|
+
- Adjust number of real vs. fake options
|
|
199
|
+
- Change question phrasing
|
|
200
|
+
- Add new question types
|
|
201
|
+
- Customize difficulty levels
|
|
202
|
+
|
|
203
|
+
## 🎮 Try the Demo
|
|
204
|
+
|
|
205
|
+
Visit `http://localhost:3000/demo` to see a live example with sample data, or use the interactive Swagger UI at `http://localhost:3000/swagger` to test with your own data.
|
|
206
|
+
|
|
207
|
+
### Demo Scenarios
|
|
208
|
+
|
|
209
|
+
#### High Confidence Scenario (Score: 85+)
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"phone_number": "2069735100",
|
|
213
|
+
"legal_name": "Waidong L Syrws",
|
|
214
|
+
"current_address": {
|
|
215
|
+
"street_line_1": "100 Syrws St",
|
|
216
|
+
"city": "Lynden",
|
|
217
|
+
"state_code": "WA",
|
|
218
|
+
"postal_code": "98264"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
#### Medium Confidence Scenario (Score: 50-70)
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"phone_number": "5551234567",
|
|
227
|
+
"legal_name": "Jane Doe",
|
|
228
|
+
"current_address": {
|
|
229
|
+
"street_line_1": "789 Unknown Ave",
|
|
230
|
+
"city": "Somewhere",
|
|
231
|
+
"state_code": "CA",
|
|
232
|
+
"postal_code": "90210"
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### Low Confidence Scenario (Score: 20-40)
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"phone_number": "1234567890",
|
|
241
|
+
"legal_name": "Fake Person",
|
|
242
|
+
"current_address": {
|
|
243
|
+
"street_line_1": "123 Nonexistent St",
|
|
244
|
+
"city": "Nowhere",
|
|
245
|
+
"state_code": "XX",
|
|
246
|
+
"postal_code": "00000"
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## 🛡️ Security & Privacy
|
|
252
|
+
|
|
253
|
+
- **No data storage**: All verification data is processed in-memory only
|
|
254
|
+
- **API key protection**: TrestleIQ API key stored securely in environment variables
|
|
255
|
+
- **CORS enabled**: Configurable cross-origin request handling
|
|
256
|
+
- **Error handling**: Comprehensive error handling without data leakage
|
|
257
|
+
- **Rate limiting**: Inherits TrestleIQ API rate limits for responsible usage
|
|
258
|
+
|
|
259
|
+
## 🔗 Integration Examples
|
|
260
|
+
|
|
261
|
+
### React Frontend Integration
|
|
262
|
+
```javascript
|
|
263
|
+
const verifyIdentity = async (personData) => {
|
|
264
|
+
const response = await fetch('/verify-identity', {
|
|
265
|
+
method: 'POST',
|
|
266
|
+
headers: { 'Content-Type': 'application/json' },
|
|
267
|
+
body: JSON.stringify(personData)
|
|
268
|
+
})
|
|
269
|
+
return response.json()
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Usage
|
|
273
|
+
const result = await verifyIdentity({
|
|
274
|
+
phone_number: "2069735100",
|
|
275
|
+
legal_name: "John Smith",
|
|
276
|
+
current_address: { /* address data */ }
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
if (result.verification_score >= 80) {
|
|
280
|
+
// High confidence - proceed with onboarding
|
|
281
|
+
} else if (result.questions.length > 0) {
|
|
282
|
+
// Show verification questions
|
|
283
|
+
} else {
|
|
284
|
+
// Request additional documentation
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Node.js Backend Integration
|
|
289
|
+
```javascript
|
|
290
|
+
import { verifyIdentity } from './verification-functions.js'
|
|
291
|
+
|
|
292
|
+
app.post('/onboard-user', async (req, res) => {
|
|
293
|
+
try {
|
|
294
|
+
const verification = await verifyIdentity(req.body, process.env.TRESTLE_API_KEY)
|
|
295
|
+
|
|
296
|
+
// Store verification result
|
|
297
|
+
await db.users.update(req.body.userId, {
|
|
298
|
+
verification_score: verification.verification_score,
|
|
299
|
+
verification_status: verification.verification_score >= 70 ? 'approved' : 'pending',
|
|
300
|
+
questions: verification.questions
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
res.json(verification)
|
|
304
|
+
} catch (error) {
|
|
305
|
+
res.status(500).json({ error: 'Verification failed' })
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## 📊 API Response Details
|
|
311
|
+
|
|
312
|
+
### Verification Questions Types
|
|
313
|
+
- **`address_history`**: Multiple choice questions about previous addresses
|
|
314
|
+
- **`phone_history`**: Questions about previously used phone numbers
|
|
315
|
+
- **`name_verification`**: Questions about name variations and associations
|
|
316
|
+
|
|
317
|
+
### Recommendation Categories
|
|
318
|
+
- **Identity Documents**: When additional ID verification is needed
|
|
319
|
+
- **Manual Review**: When human verification should be considered
|
|
320
|
+
- **Technical Warnings**: VOIP numbers, invalid addresses, etc.
|
|
321
|
+
- **Process Guidance**: Next steps based on confidence level
|
|
322
|
+
|
|
323
|
+
## 🤝 Contributing
|
|
324
|
+
|
|
325
|
+
This demo showcases the core functionality. For production use, consider:
|
|
326
|
+
- Adding database persistence for verification results
|
|
327
|
+
- Implementing user authentication and session management
|
|
328
|
+
- Adding webhook support for async verification workflows
|
|
329
|
+
- Enhancing question complexity and variety
|
|
330
|
+
- Adding support for international phone numbers and addresses
|
|
331
|
+
|
|
332
|
+
## 📞 Support
|
|
333
|
+
|
|
334
|
+
For TrestleIQ API questions, visit [TrestleIQ Documentation](https://api.trestleiq.com)
|
|
335
|
+
For implementation questions, check the inline code comments and Swagger documentation.
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
**Ready to verify identities?** Start the server and visit the demo endpoint! 🎯
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createMDXSource } from 'fumadocs-mdx';
|
|
2
|
+
import { loader } from 'fumadocs-core/source';
|
|
3
|
+
import { attachFile, createOpenAPI } from 'fumadocs-openapi/server';
|
|
4
|
+
import { docs, meta } from '@/.source';
|
|
5
|
+
|
|
6
|
+
export const source = loader({
|
|
7
|
+
baseUrl: '/docs',
|
|
8
|
+
source: createMDXSource(docs, meta),
|
|
9
|
+
pageTree: {
|
|
10
|
+
attachFile,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const openapi = createOpenAPI();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
|
2
|
+
import type { MDXComponents } from 'mdx/types';
|
|
3
|
+
import { openapi } from '@/lib/source';
|
|
4
|
+
import { APIPage } from 'fumadocs-openapi/ui';
|
|
5
|
+
|
|
6
|
+
export function getMDXComponents(components?: MDXComponents): MDXComponents {
|
|
7
|
+
return {
|
|
8
|
+
...defaultMdxComponents,
|
|
9
|
+
APIPage: (props) => <APIPage {...openapi.getAPIPageProps(props)} />,
|
|
10
|
+
...components,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { createMDX } from 'fumadocs-mdx/next';
|
|
2
|
+
|
|
3
|
+
const withMDX = createMDX();
|
|
4
|
+
|
|
5
|
+
/** @type {import('next').NextConfig} */
|
|
6
|
+
const nextConfig = {
|
|
7
|
+
output: 'export',
|
|
8
|
+
trailingSlash: true,
|
|
9
|
+
images: {
|
|
10
|
+
unoptimized: true,
|
|
11
|
+
},
|
|
12
|
+
experimental: {
|
|
13
|
+
optimizePackageImports: ['@fumadocs/ui', 'lucide-react'],
|
|
14
|
+
},
|
|
15
|
+
webpack: (config, { dev, isServer }) => {
|
|
16
|
+
if (!dev && !isServer) {
|
|
17
|
+
// Optimize bundle size for production
|
|
18
|
+
config.optimization = {
|
|
19
|
+
...config.optimization,
|
|
20
|
+
splitChunks: {
|
|
21
|
+
chunks: 'all',
|
|
22
|
+
cacheGroups: {
|
|
23
|
+
vendor: {
|
|
24
|
+
test: /[\\/]node_modules[\\/]/,
|
|
25
|
+
name: 'vendors',
|
|
26
|
+
chunks: 'all',
|
|
27
|
+
},
|
|
28
|
+
common: {
|
|
29
|
+
name: 'common',
|
|
30
|
+
minChunks: 2,
|
|
31
|
+
chunks: 'all',
|
|
32
|
+
enforce: true,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Enable tree shaking
|
|
39
|
+
config.optimization.usedExports = true;
|
|
40
|
+
config.optimization.sideEffects = false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return config;
|
|
44
|
+
},
|
|
45
|
+
// Disable features that increase bundle size
|
|
46
|
+
compress: true,
|
|
47
|
+
poweredByHeader: false,
|
|
48
|
+
generateEtags: false,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export default withMDX(nextConfig);
|