chore: organize docs — move 37 files from root into docs/ subfolders
Root now contains only essential files: README.md, CLAUDE.md, CHANGELOG.md, CONTRIBUTING.md Reorganized into: docs/audits/ — all audit reports & checklists (71 files) docs/architecture/ — codebase overview, implementation plan docs/guides/ — auth guide, implementation checklist docs/load-testing/ — k6 load test guides & endpoints docs/security/ — payment & security reviews Also removed 5 untracked debug/investigation files and cleaned up playwright-report/ & test-results/ artifacts. Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
This commit is contained in:
192
docs/QUICK_REFERENCE.md
Normal file
192
docs/QUICK_REFERENCE.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# GoodGo Platform - Authentication Quick Reference
|
||||
|
||||
## 🔑 Key Points at a Glance
|
||||
|
||||
### Password Hashing
|
||||
```
|
||||
Algorithm: bcrypt
|
||||
Salt Rounds: 12 (env: BCRYPT_ROUNDS)
|
||||
Min Length: 8 characters
|
||||
Example: bcrypt.hash('password', 12)
|
||||
```
|
||||
|
||||
### Phone Numbers (Vietnamese)
|
||||
```
|
||||
Valid Formats: 0900000001, 84900000001, +84900000001
|
||||
Normalized: +84900000001
|
||||
Regex: /^(?:\+84|84|0)(3[2-9]|5[2689]|7[06-9]|8[1-9]|9[0-9])\d{7}$/
|
||||
File: apps/api/src/modules/shared/utils/vietnam-phone.validator.ts
|
||||
```
|
||||
|
||||
### Email
|
||||
```
|
||||
Regex: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||||
Normalization: lowercase + trim
|
||||
Storage: admin@goodgo.vn
|
||||
```
|
||||
|
||||
### PII Encryption
|
||||
```
|
||||
Algorithm: AES-256-GCM
|
||||
Key: 32 bytes (64 hex chars)
|
||||
Encrypted: email, phone, kycData
|
||||
Searchable: email → emailHash (HMAC-SHA256)
|
||||
phone → phoneHash (HMAC-SHA256)
|
||||
Env Var: FIELD_ENCRYPTION_KEY
|
||||
```
|
||||
|
||||
### User Login
|
||||
```
|
||||
Username: phone (normalized)
|
||||
Password: plain text
|
||||
Lookup: by phoneHash (unique index)
|
||||
Required: isActive = true, passwordHash ≠ null
|
||||
Response: tokens (or MFA challenge)
|
||||
```
|
||||
|
||||
### User Roles
|
||||
```
|
||||
BUYER - Search, inquire, offer (default)
|
||||
SELLER - Create listings
|
||||
AGENT - Professional agent
|
||||
ADMIN - Full access
|
||||
```
|
||||
|
||||
### MFA
|
||||
```
|
||||
TOTP: otplib (RFC 6238)
|
||||
Period: 30 seconds
|
||||
Digits: 6
|
||||
Backup Codes: 10 × 8 chars (A-Z no OI, 2-9 no 01)
|
||||
Hashing: HMAC-SHA256 (not bcrypt)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Creating a Login-Capable Admin User
|
||||
|
||||
### 5-Step Process
|
||||
|
||||
**1. Normalize phone**
|
||||
```typescript
|
||||
phone = '0900000001' → '+84900000001'
|
||||
```
|
||||
|
||||
**2. Derive HMAC key**
|
||||
```typescript
|
||||
hmacKey = crypto.hkdfSync('sha256', Buffer.from(encryptionKey, 'hex'),
|
||||
Buffer.alloc(0), Buffer.from('goodgo-field-hash', 'utf8'), 32)
|
||||
```
|
||||
|
||||
**3. Compute hashes**
|
||||
```typescript
|
||||
phoneHash = crypto.createHmac('sha256', hmacKey).update('+84900000001').digest('hex')
|
||||
emailHash = crypto.createHmac('sha256', hmacKey).update('admin@goodgo.vn').digest('hex')
|
||||
```
|
||||
|
||||
**4. Hash password**
|
||||
```typescript
|
||||
passwordHash = await bcrypt.hash('AdminPassword123', 12)
|
||||
```
|
||||
|
||||
**5. Create user**
|
||||
```typescript
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
id: 'admin-seed-001',
|
||||
phone: '+84900000001',
|
||||
phoneHash,
|
||||
email: 'admin@goodgo.vn',
|
||||
emailHash,
|
||||
passwordHash,
|
||||
fullName: 'Admin',
|
||||
role: 'ADMIN',
|
||||
kycStatus: 'VERIFIED',
|
||||
isActive: true,
|
||||
totpEnabled: false,
|
||||
totpBackupCodes: [],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Test Login
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"phone": "0900000001",
|
||||
"password": "AdminPassword123"
|
||||
}'
|
||||
```
|
||||
|
||||
**Success Response:**
|
||||
```json
|
||||
{
|
||||
"requiresMfa": false,
|
||||
"tokens": {
|
||||
"accessToken": "eyJ...",
|
||||
"refreshToken": "eyJ...",
|
||||
"expiresIn": 3600
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Common Issues
|
||||
|
||||
| Issue | Fix |
|
||||
|-------|-----|
|
||||
| User can't login | Check: `passwordHash` ≠ null, `isActive` = true |
|
||||
| "Invalid phone" | Phone must match regex (mobile only) |
|
||||
| Hash mismatch | Verify `FIELD_ENCRYPTION_KEY` is consistent |
|
||||
| MFA issue | Verify `MFA_BACKUP_CODE_SECRET` env var |
|
||||
| PII not encrypted | Verify key is exactly 32 bytes (64 hex chars) |
|
||||
|
||||
---
|
||||
|
||||
## 📁 Key Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `hashed-password.vo.ts` | bcrypt hashing |
|
||||
| `vietnam-phone.validator.ts` | Phone validation |
|
||||
| `field-encryption.ts` | AES-256-GCM encryption |
|
||||
| `local.strategy.ts` | Login endpoint |
|
||||
| `mfa.service.ts` | TOTP / backup codes |
|
||||
| `user.entity.ts` | User domain model |
|
||||
| `prisma-user.repository.ts` | User persistence |
|
||||
| `seed.ts` | Seed script |
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Checklist for Seed User
|
||||
|
||||
- [ ] Password ≥ 8 chars
|
||||
- [ ] Phone matches regex
|
||||
- [ ] Phone normalized: +84...
|
||||
- [ ] Phone hashed: HMAC-SHA256
|
||||
- [ ] Email lowercased
|
||||
- [ ] Email hashed: HMAC-SHA256
|
||||
- [ ] Password hashed: bcrypt (12 rounds)
|
||||
- [ ] `isActive: true`
|
||||
- [ ] `passwordHash` ≠ null
|
||||
- [ ] `totpEnabled: false`
|
||||
- [ ] `totpBackupCodes: []`
|
||||
|
||||
---
|
||||
|
||||
## 📚 Full Documentation Files
|
||||
|
||||
1. **AUTHENTICATION_GUIDE.md** - Complete technical reference
|
||||
2. **AUTH_IMPLEMENTATION_CHECKLIST.md** - Implementation checklist & troubleshooting
|
||||
3. **SEED_GENERATION_SCRIPT.ts** - Ready-to-use seed script
|
||||
4. **QUICK_REFERENCE.md** - This file
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** April 12, 2026
|
||||
**Status:** ✅ Production-Ready
|
||||
Reference in New Issue
Block a user