cdp-lite-sdk 0.1.7 → 0.1.8
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/README.md +1 -1
- package/package.json +1 -2
- package/SECURITY.md +0 -513
package/README.md
CHANGED
|
@@ -218,7 +218,7 @@ const cdp = new CdpLiteSdk({
|
|
|
218
218
|
});
|
|
219
219
|
```
|
|
220
220
|
|
|
221
|
-
**📖 See [SECURITY.md](
|
|
221
|
+
**📖 See [SECURITY.md](https://gitlab.ovp.vn/dlc/vc-cdp-sdk/blob/master/sdk-js/SECURITY.md) for complete security documentation.**
|
|
222
222
|
|
|
223
223
|
---
|
|
224
224
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cdp-lite-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "CDP Lite SDK for tracking events and users - Customer Data Platform",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
"files": [
|
|
17
17
|
"dist",
|
|
18
18
|
"README.md",
|
|
19
|
-
"SECURITY.md",
|
|
20
19
|
"LICENSE"
|
|
21
20
|
],
|
|
22
21
|
"scripts": {
|
package/SECURITY.md
DELETED
|
@@ -1,513 +0,0 @@
|
|
|
1
|
-
# 🔒 CDP Lite SDK - Security Documentation
|
|
2
|
-
|
|
3
|
-
Comprehensive security features for protecting user data and API communications.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 🎯 Security Features
|
|
8
|
-
|
|
9
|
-
### 1. **Request Signatures (HMAC-SHA256)**
|
|
10
|
-
Mọi request đều được ký bằng HMAC để đảm bảo tính toàn vẹn và xác thực.
|
|
11
|
-
|
|
12
|
-
### 2. **Traits Encryption (AES-256-CBC)**
|
|
13
|
-
Thông tin nhạy cảm của user được mã hóa trước khi gửi.
|
|
14
|
-
|
|
15
|
-
### 3. **Dynamic Keys**
|
|
16
|
-
Keys được generate động dựa trên timestamp để tăng bảo mật.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 🔐 How It Works
|
|
21
|
-
|
|
22
|
-
### Request Signing
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
X-Signatures = Base64(HMAC-SHA256(X-Source + "|" + X-Timestamp + "|" + Payload))
|
|
26
|
-
HMAC Key = Secret Key
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
**Example:**
|
|
30
|
-
```javascript
|
|
31
|
-
const source = "Fiza";
|
|
32
|
-
const timestamp = "1767583520";
|
|
33
|
-
const payload = '{"event":"view_home","properties":{...}}';
|
|
34
|
-
const message = source + "|" + timestamp + "|" + payload;
|
|
35
|
-
const signature = Base64(HMAC-SHA256(message, secretKey));
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### Traits Encryption
|
|
39
|
-
|
|
40
|
-
```
|
|
41
|
-
AES Key = SHA256(SecretKey + X-Timestamp)
|
|
42
|
-
Encrypted Traits = Base64(AES-256-CBC(Traits, AES Key))
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
**Sensitive Fields:**
|
|
46
|
-
- `full_name`, `first_name`, `last_name`
|
|
47
|
-
- `idcard`, `old_idcard`
|
|
48
|
-
- `phone`, `email`
|
|
49
|
-
- `gender`, `dob`
|
|
50
|
-
- `address`, `religion`
|
|
51
|
-
|
|
52
|
-
**Example:**
|
|
53
|
-
```javascript
|
|
54
|
-
const timestamp = "1767583520";
|
|
55
|
-
const aesKey = SHA256(secretKey + timestamp);
|
|
56
|
-
const traits = {
|
|
57
|
-
full_name: "Nguyen Van A",
|
|
58
|
-
email: "user@example.com",
|
|
59
|
-
phone: "0901234567"
|
|
60
|
-
};
|
|
61
|
-
const encryptedTraits = Base64(AES-256-CBC(JSON.stringify(traits), aesKey));
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
---
|
|
65
|
-
|
|
66
|
-
## 🚀 Quick Start
|
|
67
|
-
|
|
68
|
-
### Initialization with Security
|
|
69
|
-
|
|
70
|
-
```javascript
|
|
71
|
-
import CdpLiteSdk from 'cdp-lite-sdk';
|
|
72
|
-
|
|
73
|
-
const cdp = new CdpLiteSdk({
|
|
74
|
-
apiKey: 'your-api-key',
|
|
75
|
-
secretKey: 'your-secret-key', // Required for security features
|
|
76
|
-
source: 'YourApp',
|
|
77
|
-
serviceName: 'YourService',
|
|
78
|
-
enableEncryption: true, // Enable encryption (default: true)
|
|
79
|
-
debug: true
|
|
80
|
-
});
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Identify User with Auto-Encryption
|
|
84
|
-
|
|
85
|
-
```javascript
|
|
86
|
-
// SDK automatically encrypts sensitive fields
|
|
87
|
-
cdp.identify('user_123', {
|
|
88
|
-
// Sensitive fields (will be encrypted)
|
|
89
|
-
full_name: 'Nguyen Van A',
|
|
90
|
-
first_name: 'A',
|
|
91
|
-
last_name: 'Nguyen Van',
|
|
92
|
-
email: 'user@example.com',
|
|
93
|
-
phone: '0901234567',
|
|
94
|
-
idcard: '001234567890',
|
|
95
|
-
dob: '1990-01-01',
|
|
96
|
-
gender: 'male',
|
|
97
|
-
address: '123 ABC Street, Hanoi',
|
|
98
|
-
religion: 'Buddhism',
|
|
99
|
-
|
|
100
|
-
// Non-sensitive fields (won't be encrypted)
|
|
101
|
-
age: 30,
|
|
102
|
-
city: 'Hanoi',
|
|
103
|
-
subscription: 'premium'
|
|
104
|
-
});
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Track Event with Signature
|
|
108
|
-
|
|
109
|
-
```javascript
|
|
110
|
-
// Request automatically signed with HMAC
|
|
111
|
-
cdp.track('purchase_completed', {
|
|
112
|
-
order_id: 'ORDER123',
|
|
113
|
-
amount: 99.99,
|
|
114
|
-
currency: 'VND'
|
|
115
|
-
});
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## 📋 Configuration Options
|
|
121
|
-
|
|
122
|
-
### Security Configuration
|
|
123
|
-
|
|
124
|
-
```javascript
|
|
125
|
-
const cdp = new CdpLiteSdk({
|
|
126
|
-
// Required for security
|
|
127
|
-
apiKey: 'string', // API Key
|
|
128
|
-
secretKey: 'string', // Secret Key for HMAC & encryption
|
|
129
|
-
|
|
130
|
-
// Optional
|
|
131
|
-
enableEncryption: boolean, // Enable traits encryption (default: true)
|
|
132
|
-
source: 'string', // Source identifier
|
|
133
|
-
serviceName: 'string', // Service name
|
|
134
|
-
debug: boolean // Show encryption logs
|
|
135
|
-
});
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Environment Variables (Recommended)
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
# .env
|
|
142
|
-
CDP_API_KEY=your-api-key
|
|
143
|
-
CDP_SECRET_KEY=your-secret-key
|
|
144
|
-
CDP_SOURCE=YourApp
|
|
145
|
-
CDP_SERVICE_NAME=YourService
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
```javascript
|
|
149
|
-
const cdp = new CdpLiteSdk({
|
|
150
|
-
apiKey: process.env.CDP_API_KEY,
|
|
151
|
-
secretKey: process.env.CDP_SECRET_KEY,
|
|
152
|
-
source: process.env.CDP_SOURCE,
|
|
153
|
-
serviceName: process.env.CDP_SERVICE_NAME
|
|
154
|
-
});
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
---
|
|
158
|
-
|
|
159
|
-
## 🔧 Advanced Usage
|
|
160
|
-
|
|
161
|
-
### Manual Encryption Control
|
|
162
|
-
|
|
163
|
-
```javascript
|
|
164
|
-
// Disable auto-encryption
|
|
165
|
-
const cdp = new CdpLiteSdk({
|
|
166
|
-
apiKey: 'your-api-key',
|
|
167
|
-
secretKey: 'your-secret-key',
|
|
168
|
-
enableEncryption: false // Disable encryption
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// Traits won't be encrypted
|
|
172
|
-
cdp.identify('user_123', {
|
|
173
|
-
email: 'user@example.com' // Sent as plain text
|
|
174
|
-
});
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### Partial Sensitive Data
|
|
178
|
-
|
|
179
|
-
```javascript
|
|
180
|
-
// Only fields in sensitive list will be encrypted
|
|
181
|
-
cdp.identify('user_123', {
|
|
182
|
-
// These WILL be encrypted
|
|
183
|
-
email: 'user@example.com',
|
|
184
|
-
phone: '0901234567',
|
|
185
|
-
|
|
186
|
-
// These WON'T be encrypted
|
|
187
|
-
username: 'user123',
|
|
188
|
-
city: 'Hanoi',
|
|
189
|
-
age: 30
|
|
190
|
-
});
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### Verify Encryption
|
|
194
|
-
|
|
195
|
-
```javascript
|
|
196
|
-
const cdp = new CdpLiteSdk({
|
|
197
|
-
apiKey: 'your-api-key',
|
|
198
|
-
secretKey: 'your-secret-key',
|
|
199
|
-
debug: true // See encryption logs
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
// Check console for encryption status
|
|
203
|
-
cdp.identify('user_123', {
|
|
204
|
-
email: 'test@example.com'
|
|
205
|
-
});
|
|
206
|
-
// Console: [CDP Lite SDK] User identified { userId: 'user_123', traitsEncrypted: true }
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
---
|
|
210
|
-
|
|
211
|
-
## 🛡️ Security Best Practices
|
|
212
|
-
|
|
213
|
-
### 1. **Protect Secret Keys**
|
|
214
|
-
|
|
215
|
-
```javascript
|
|
216
|
-
// ❌ BAD - Hardcoded keys
|
|
217
|
-
const cdp = new CdpLiteSdk({
|
|
218
|
-
apiKey: 'abc123',
|
|
219
|
-
secretKey: 'my-secret-key'
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
// ✅ GOOD - Use environment variables
|
|
223
|
-
const cdp = new CdpLiteSdk({
|
|
224
|
-
apiKey: process.env.CDP_API_KEY,
|
|
225
|
-
secretKey: process.env.CDP_SECRET_KEY
|
|
226
|
-
});
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### 2. **Never Commit Keys**
|
|
230
|
-
|
|
231
|
-
```bash
|
|
232
|
-
# .gitignore
|
|
233
|
-
.env
|
|
234
|
-
.env.local
|
|
235
|
-
.env.*.local
|
|
236
|
-
config/secrets.js
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### 3. **Use Different Keys per Environment**
|
|
240
|
-
|
|
241
|
-
```javascript
|
|
242
|
-
// Development
|
|
243
|
-
const cdp = new CdpLiteSdk({
|
|
244
|
-
apiKey: process.env.DEV_CDP_API_KEY,
|
|
245
|
-
secretKey: process.env.DEV_CDP_SECRET_KEY,
|
|
246
|
-
baseUrl: 'https://stg-ingestlog.vietcredit.com.vn',
|
|
247
|
-
isTest: true
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
// Production
|
|
251
|
-
const cdp = new CdpLiteSdk({
|
|
252
|
-
apiKey: process.env.PROD_CDP_API_KEY,
|
|
253
|
-
secretKey: process.env.PROD_CDP_SECRET_KEY,
|
|
254
|
-
baseUrl: 'https://vconnect.vietcredit.com.vn',
|
|
255
|
-
isTest: false
|
|
256
|
-
});
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
### 4. **Rotate Keys Regularly**
|
|
260
|
-
|
|
261
|
-
Update your secret keys periodically and deploy new versions.
|
|
262
|
-
|
|
263
|
-
### 5. **Validate on Server Side**
|
|
264
|
-
|
|
265
|
-
Server should validate:
|
|
266
|
-
- X-Signatures match
|
|
267
|
-
- X-Timestamp is recent (prevent replay attacks)
|
|
268
|
-
- Decrypt traits and validate format
|
|
269
|
-
|
|
270
|
-
---
|
|
271
|
-
|
|
272
|
-
## 🔍 How to Test Security
|
|
273
|
-
|
|
274
|
-
### Test Signature Generation
|
|
275
|
-
|
|
276
|
-
```javascript
|
|
277
|
-
const cdp = new CdpLiteSdk({
|
|
278
|
-
apiKey: 'test-key',
|
|
279
|
-
secretKey: 'test-secret',
|
|
280
|
-
debug: true // See signatures in console
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
cdp.track('test_event', { test: true });
|
|
284
|
-
// Check Network tab > Headers > X-Signatures
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
### Test Traits Encryption
|
|
288
|
-
|
|
289
|
-
```javascript
|
|
290
|
-
const cdp = new CdpLiteSdk({
|
|
291
|
-
apiKey: 'test-key',
|
|
292
|
-
secretKey: 'test-secret',
|
|
293
|
-
debug: true
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
cdp.identify('user_123', {
|
|
297
|
-
email: 'test@example.com',
|
|
298
|
-
phone: '0901234567'
|
|
299
|
-
});
|
|
300
|
-
// Check Network tab > Payload > traits (should be Base64 string)
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### Verify in Browser DevTools
|
|
304
|
-
|
|
305
|
-
1. Open DevTools > Network tab
|
|
306
|
-
2. Trigger an identify or track call
|
|
307
|
-
3. Check request:
|
|
308
|
-
- Headers: `X-Signatures` should have Base64 value
|
|
309
|
-
- Payload: `traits` should be encrypted Base64 string
|
|
310
|
-
|
|
311
|
-
---
|
|
312
|
-
|
|
313
|
-
## 🧪 Example: Complete Secure Flow
|
|
314
|
-
|
|
315
|
-
```javascript
|
|
316
|
-
import CdpLiteSdk from 'cdp-lite-sdk';
|
|
317
|
-
|
|
318
|
-
// 1. Initialize with security
|
|
319
|
-
const cdp = new CdpLiteSdk({
|
|
320
|
-
apiKey: process.env.CDP_API_KEY,
|
|
321
|
-
secretKey: process.env.CDP_SECRET_KEY,
|
|
322
|
-
source: 'MySecureApp',
|
|
323
|
-
serviceName: 'UserService',
|
|
324
|
-
enableEncryption: true,
|
|
325
|
-
debug: process.env.NODE_ENV === 'development'
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
// 2. User registration - sensitive data encrypted
|
|
329
|
-
async function handleUserRegistration(userData) {
|
|
330
|
-
try {
|
|
331
|
-
// Identify with encrypted traits
|
|
332
|
-
await cdp.identify(userData.id, {
|
|
333
|
-
// Encrypted fields
|
|
334
|
-
full_name: userData.fullName,
|
|
335
|
-
email: userData.email,
|
|
336
|
-
phone: userData.phone,
|
|
337
|
-
idcard: userData.idCard,
|
|
338
|
-
dob: userData.dateOfBirth,
|
|
339
|
-
address: userData.address,
|
|
340
|
-
|
|
341
|
-
// Non-encrypted metadata
|
|
342
|
-
signup_source: 'web',
|
|
343
|
-
referrer: document.referrer
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
// Track registration event (signed)
|
|
347
|
-
cdp.track('user_registered', {
|
|
348
|
-
method: 'email',
|
|
349
|
-
timestamp: new Date().toISOString()
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
console.log('User registered securely');
|
|
353
|
-
} catch (error) {
|
|
354
|
-
console.error('Registration failed:', error);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// 3. Sensitive action with loan info
|
|
359
|
-
async function handleLoanApplication(loanData) {
|
|
360
|
-
const loanCode = 'LOAN_' + Date.now();
|
|
361
|
-
|
|
362
|
-
// Update user with income info (encrypted)
|
|
363
|
-
await cdp.setUserAttributes({
|
|
364
|
-
income: loanData.monthlyIncome,
|
|
365
|
-
employment: loanData.employmentType
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
// Track application (signed)
|
|
369
|
-
cdp.track('loan_application_submitted', {
|
|
370
|
-
amount: loanData.amount,
|
|
371
|
-
term: loanData.term,
|
|
372
|
-
purpose: loanData.purpose
|
|
373
|
-
}, {
|
|
374
|
-
loanCode: loanCode
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// 4. Logout - clear data
|
|
379
|
-
function handleLogout() {
|
|
380
|
-
cdp.track('user_logged_out');
|
|
381
|
-
cdp.flush(); // Send remaining events
|
|
382
|
-
cdp.reset(); // Clear user data
|
|
383
|
-
}
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
---
|
|
387
|
-
|
|
388
|
-
## 🔐 Encryption Algorithm Details
|
|
389
|
-
|
|
390
|
-
### AES-256-CBC
|
|
391
|
-
|
|
392
|
-
- **Algorithm:** AES (Advanced Encryption Standard)
|
|
393
|
-
- **Mode:** CBC (Cipher Block Chaining)
|
|
394
|
-
- **Key Length:** 256 bits
|
|
395
|
-
- **IV:** 128 bits (randomly generated per encryption)
|
|
396
|
-
- **Key Derivation:** SHA-256 hash of (SecretKey + Timestamp)
|
|
397
|
-
|
|
398
|
-
### HMAC-SHA256
|
|
399
|
-
|
|
400
|
-
- **Algorithm:** HMAC (Hash-based Message Authentication Code)
|
|
401
|
-
- **Hash Function:** SHA-256
|
|
402
|
-
- **Input:** X-Source + "|" + X-Timestamp + "|" + Payload
|
|
403
|
-
- **Output:** Base64-encoded signature
|
|
404
|
-
|
|
405
|
-
---
|
|
406
|
-
|
|
407
|
-
## 📊 Performance Impact
|
|
408
|
-
|
|
409
|
-
### Encryption Overhead
|
|
410
|
-
|
|
411
|
-
- **Traits Encryption:** ~1-5ms per identify call
|
|
412
|
-
- **Request Signing:** ~1-2ms per request
|
|
413
|
-
- **Impact:** Minimal for typical use cases
|
|
414
|
-
- **Optimization:** Batching reduces overhead
|
|
415
|
-
|
|
416
|
-
### Browser Support
|
|
417
|
-
|
|
418
|
-
- ✅ Chrome 37+
|
|
419
|
-
- ✅ Firefox 34+
|
|
420
|
-
- ✅ Safari 11+
|
|
421
|
-
- ✅ Edge 79+
|
|
422
|
-
- ✅ Node.js 12+
|
|
423
|
-
|
|
424
|
-
Uses Web Crypto API (browser) and crypto module (Node.js).
|
|
425
|
-
|
|
426
|
-
---
|
|
427
|
-
|
|
428
|
-
## 🐛 Troubleshooting
|
|
429
|
-
|
|
430
|
-
### Issue: Signature Mismatch
|
|
431
|
-
|
|
432
|
-
**Error:** Server rejects request with signature error
|
|
433
|
-
|
|
434
|
-
**Solution:**
|
|
435
|
-
1. Verify secret key is correct
|
|
436
|
-
2. Check timestamp synchronization
|
|
437
|
-
3. Ensure payload format matches server expectations
|
|
438
|
-
|
|
439
|
-
```javascript
|
|
440
|
-
// Enable debug to see signature
|
|
441
|
-
const cdp = new CdpLiteSdk({
|
|
442
|
-
secretKey: 'your-secret',
|
|
443
|
-
debug: true
|
|
444
|
-
});
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
### Issue: Encryption Fails
|
|
448
|
-
|
|
449
|
-
**Error:** Traits not encrypted
|
|
450
|
-
|
|
451
|
-
**Solution:**
|
|
452
|
-
1. Check secret key is provided
|
|
453
|
-
2. Verify browser supports Web Crypto API
|
|
454
|
-
3. Enable debug mode to see errors
|
|
455
|
-
|
|
456
|
-
```javascript
|
|
457
|
-
const cdp = new CdpLiteSdk({
|
|
458
|
-
secretKey: 'your-secret',
|
|
459
|
-
enableEncryption: true,
|
|
460
|
-
debug: true // See encryption errors
|
|
461
|
-
});
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
### Issue: Empty Traits
|
|
465
|
-
|
|
466
|
-
**Error:** Traits field is empty string
|
|
467
|
-
|
|
468
|
-
**Cause:** No sensitive fields provided
|
|
469
|
-
|
|
470
|
-
**Solution:** Include at least one sensitive field:
|
|
471
|
-
|
|
472
|
-
```javascript
|
|
473
|
-
// This won't encrypt (no sensitive fields)
|
|
474
|
-
cdp.identify('user_123', {
|
|
475
|
-
age: 30,
|
|
476
|
-
city: 'Hanoi'
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
// This will encrypt
|
|
480
|
-
cdp.identify('user_123', {
|
|
481
|
-
email: 'user@example.com', // Sensitive field
|
|
482
|
-
age: 30,
|
|
483
|
-
city: 'Hanoi'
|
|
484
|
-
});
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
---
|
|
488
|
-
|
|
489
|
-
## 🔒 Security Checklist
|
|
490
|
-
|
|
491
|
-
- [ ] Secret key stored in environment variables
|
|
492
|
-
- [ ] Different keys for dev/staging/production
|
|
493
|
-
- [ ] Keys not committed to version control
|
|
494
|
-
- [ ] HTTPS used for all requests
|
|
495
|
-
- [ ] Encryption enabled in production
|
|
496
|
-
- [ ] Debug mode disabled in production
|
|
497
|
-
- [ ] Keys rotated periodically
|
|
498
|
-
- [ ] Server validates signatures
|
|
499
|
-
- [ ] Server decrypts and validates traits
|
|
500
|
-
- [ ] Timestamp checked for replay attacks
|
|
501
|
-
|
|
502
|
-
---
|
|
503
|
-
|
|
504
|
-
## 📞 Need Help?
|
|
505
|
-
|
|
506
|
-
- 📖 [Main Documentation](README.md)
|
|
507
|
-
- 🐛 [Report Security Issues](mailto:vinv@vega.com.vn)
|
|
508
|
-
|
|
509
|
-
**⚠️ Security Disclosure:** If you find a security vulnerability, please email vinv@vega.com.vn instead of creating a public issue.
|
|
510
|
-
|
|
511
|
-
---
|
|
512
|
-
|
|
513
|
-
Made with 🔒 by Your Team
|