diff --git a/.cursor/plans/enterprise_auth_service_c4783a66.plan.md b/.cursor/plans/enterprise_auth_service_c4783a66.plan.md deleted file mode 100644 index f87cb1b0..00000000 --- a/.cursor/plans/enterprise_auth_service_c4783a66.plan.md +++ /dev/null @@ -1,771 +0,0 @@ ---- -name: Enterprise Auth Service -overview: Refactor toàn bộ auth-service thành hệ thống enterprise-grade phục vụ 100+ triệu users với kiến trúc phù hợp GoodGo Platform, sử dụng template và cấu trúc monorepo hiện tại. -todos: - - id: backup-current - content: Backup auth-service hiện tại trước khi xóa - status: pending - - id: delete-auth-service - content: Xóa toàn bộ auth-service hiện tại - status: pending - - id: copy-template - content: Copy template service và rename thành auth-service - status: pending - - id: setup-base-structure - content: Setup cấu trúc base với các modules cơ bản - status: pending - - id: implement-advanced-schema - content: Tạo Prisma schema cho RBAC, Social Login, Sessions - status: pending - - id: implement-multi-layer-cache - content: Implement multi-layer cache với Redis và in-memory - status: pending - - id: implement-rbac-module - content: Tạo module RBAC với permissions, roles, policies - status: pending - - id: implement-social-auth - content: Tạo module social auth (Google, Facebook, GitHub) - status: pending - - id: implement-oidc-module - content: Implement OIDC provider và client - status: pending - - id: implement-jwt-service - content: Tạo JWT service với access/refresh/id tokens - status: pending - - id: implement-cookie-service - content: Implement secure cookie management - status: pending - - id: implement-mfa-module - content: Tạo module MFA với TOTP và WebAuthn - status: pending - - id: implement-zero-trust - content: Implement zero-trust security middleware - status: pending - - id: setup-event-sourcing - content: Setup event sourcing cho audit logs - status: pending - - id: implement-rate-limiting - content: Dynamic rate limiting theo role - status: pending - - id: setup-monitoring - content: Setup monitoring với Prometheus và Grafana - status: pending - - id: write-tests - content: Viết unit và integration tests - status: pending - - id: update-docker-compose - content: Update docker-compose.yml với services mới - status: pending - - id: write-documentation - content: Viết documentation và API specs - status: pending ---- - -# Enterprise Auth Service - Implementation Plan - -## 1. Phân tích thách thức và giải pháp cho scale lớn - -### Performance Challenges - -- **100M+ users** = ~10-50K requests/second peak time -- **Token validation** phải < 10ms (in-memory cache) -- **Login/Register** phải < 100ms (với DB write) -- **Social login** phải handle timeout từ providers - -### Security Challenges - -- **Distributed attacks** (DDoS, brute force từ nhiều regions) -- **Token hijacking** và replay attacks -- **Data breaches** với 100M+ records -- **Compliance** (GDPR, SOC2, ISO 27001) - -### Availability Challenges - -- **99.999% uptime** = max 5.26 phút downtime/năm -- **Multi-region failover** < 30 seconds -- **Zero-downtime deployments** -- **Database replication lag** < 100ms - -## 2. Kiến trúc tổng quan - -```mermaid -graph TB - subgraph clients [Client Layer] - web[Web Apps] - mobile[Mobile Apps] - api[API Clients] - end - - subgraph cdn [CDN Layer] - cloudflare[Cloudflare] - fastly[Fastly Cache] - end - - subgraph gateway [API Gateway Layer] - kong1[Kong Gateway Region 1] - kong2[Kong Gateway Region 2] - kong3[Kong Gateway Region 3] - end - - subgraph auth [Auth Service Cluster] - subgraph region1 [US Region] - auth1[Auth Service Pods] - cache1[Redis Cluster] - db1[PostgreSQL Primary] - end - - subgraph region2 [EU Region] - auth2[Auth Service Pods] - cache2[Redis Cluster] - db2[PostgreSQL Replica] - end - - subgraph region3 [APAC Region] - auth3[Auth Service Pods] - cache3[Redis Cluster] - db3[PostgreSQL Replica] - end - end - - subgraph external [External Services] - oidc[OIDC Providers] - social[Social Providers] - sms[SMS Gateway] - email[Email Service] - end - - subgraph monitoring [Observability] - datadog[Datadog APM] - elastic[ELK Stack] - pagerduty[PagerDuty] - end - - clients --> cdn - cdn --> gateway - gateway --> auth - auth --> external - auth --> monitoring -``` - -## 3. Microservices Architecture - -```mermaid -graph LR - subgraph authCore [Auth Core Services] - authAPI[Auth API Service] - tokenService[Token Service] - sessionService[Session Service] - mfaService[MFA Service] - end - - subgraph rbacServices [RBAC Services] - permissionService[Permission Service] - roleService[Role Service] - policyService[Policy Service] - end - - subgraph socialServices [Social Services] - socialAuth[Social Auth Service] - oidcProvider[OIDC Provider] - oidcClient[OIDC Client] - end - - subgraph supportServices [Support Services] - auditService[Audit Service] - notificationService[Notification Service] - analyticsService[Analytics Service] - end - - subgraph dataLayer [Data Layer] - postgresCluster[PostgreSQL Cluster] - redisCluster[Redis Cluster] - elasticSearch[ElasticSearch] - kafka[Kafka Event Bus] - end - - authAPI --> tokenService - authAPI --> sessionService - authAPI --> mfaService - authAPI --> rbacServices - authAPI --> socialServices - - authCore --> kafka - rbacServices --> kafka - socialServices --> kafka - kafka --> supportServices - - authCore --> dataLayer - rbacServices --> dataLayer - socialServices --> dataLayer - supportServices --> dataLayer -``` - -## 4. Cấu trúc dự án với GoodGo monorepo - -``` -services/ -└── auth-service/ # Single service với modules - ├── Dockerfile - ├── package.json - ├── prisma/ - │ ├── schema.prisma # Advanced schema với RBAC - │ └── migrations/ - ├── src/ - │ ├── config/ - │ │ ├── app.config.ts - │ │ ├── database.config.ts - │ │ ├── redis.config.ts - │ │ ├── jwt.config.ts - │ │ └── social.config.ts - │ ├── core/ # Core utilities - │ │ ├── cache/ - │ │ │ ├── multi-layer-cache.ts - │ │ │ └── cache.service.ts - │ │ ├── security/ - │ │ │ ├── zero-trust.validator.ts - │ │ │ └── encryption.service.ts - │ │ └── events/ - │ │ ├── event-bus.ts - │ │ └── audit.service.ts - │ ├── modules/ - │ │ ├── auth/ # Core authentication - │ │ │ ├── auth.controller.ts - │ │ │ ├── auth.service.ts - │ │ │ ├── auth.dto.ts - │ │ │ └── strategies/ - │ │ ├── rbac/ # RBAC system - │ │ │ ├── rbac.controller.ts - │ │ │ ├── rbac.service.ts - │ │ │ ├── permission.service.ts - │ │ │ ├── role.service.ts - │ │ │ ├── policy.engine.ts - │ │ │ └── rbac.dto.ts - │ │ ├── social/ # Social authentication - │ │ │ ├── social.controller.ts - │ │ │ ├── social.service.ts - │ │ │ ├── providers/ - │ │ │ │ ├── google.provider.ts - │ │ │ │ ├── facebook.provider.ts - │ │ │ │ └── github.provider.ts - │ │ │ └── circuit-breaker.ts - │ │ ├── oidc/ # OIDC implementation - │ │ │ ├── oidc.controller.ts - │ │ │ ├── oidc-provider.service.ts - │ │ │ ├── oidc-client.service.ts - │ │ │ └── multi-tenant.service.ts - │ │ ├── token/ # Token management - │ │ │ ├── jwt.service.ts - │ │ │ ├── cookie.service.ts - │ │ │ └── token-rotation.service.ts - │ │ ├── session/ # Session management - │ │ │ ├── session.service.ts - │ │ │ └── distributed-session.ts - │ │ ├── mfa/ # Multi-factor auth - │ │ │ ├── mfa.controller.ts - │ │ │ ├── mfa.service.ts - │ │ │ ├── totp.service.ts - │ │ │ └── webauthn.service.ts - │ │ └── health/ - │ │ └── health.controller.ts - │ ├── middlewares/ - │ │ ├── auth.middleware.ts - │ │ ├── rbac.middleware.ts - │ │ ├── rate-limit.middleware.ts - │ │ ├── zero-trust.middleware.ts - │ │ └── error.middleware.ts - │ ├── repositories/ - │ │ ├── base.repository.ts - │ │ ├── user.repository.ts - │ │ ├── role.repository.ts - │ │ └── session.repository.ts - │ ├── routes/ - │ │ └── index.ts - │ └── main.ts - └── tests/ - ├── unit/ - ├── integration/ - └── load/ -``` - -## 5. Database Architecture - -### 5.1 Sharding Strategy - -```mermaid -graph TD - subgraph shardRouter [Shard Router] - router[Vitess/Citus Router] - end - - subgraph shard1 [Shard 1: Users 0-33M] - master1[PostgreSQL Primary] - replica1a[Replica 1A] - replica1b[Replica 1B] - end - - subgraph shard2 [Shard 2: Users 33M-66M] - master2[PostgreSQL Primary] - replica2a[Replica 2A] - replica2b[Replica 2B] - end - - subgraph shard3 [Shard 3: Users 66M-100M+] - master3[PostgreSQL Primary] - replica3a[Replica 3A] - replica3b[Replica 3B] - end - - router --> shard1 - router --> shard2 - router --> shard3 -``` - -### 5.2 Schema Design - -```prisma -// Optimized for sharding and performance -model User { - id String @id @default(cuid()) // Use CUID for better distribution - shardKey Int // For sharding (hash of userId % shard_count) - email String - username String? - passwordHash String? - - // Denormalized for performance - primaryRole String? // Cache primary role - permissionCache Json? // Cache computed permissions - lastLoginAt DateTime? - loginCount Int @default(0) - - @@unique([shardKey, email]) - @@index([shardKey, id]) - @@index([email]) - @@map("users") -} - -// Separate table for hot data -model UserSession { - id String @id - userId String - shardKey Int - deviceId String - ipAddress String - userAgent String - expiresAt DateTime - - @@index([userId, deviceId]) - @@index([expiresAt]) - @@map("user_sessions") -} - -// Event sourcing for audit -model AuthEvent { - id String @id @default(cuid()) - userId String - eventType String // LOGIN, LOGOUT, MFA_ENABLED, etc. - eventData Json - ipAddress String - userAgent String - timestamp DateTime @default(now()) - - @@index([userId, timestamp]) - @@index([eventType, timestamp]) - @@map("auth_events") -} -``` - -## 6. Caching Strategy - -### 6.1 Multi-layer Cache - -```typescript -// [services/auth-core/token-service/src/cache/multi-layer-cache.ts] - -export class MultiLayerCache { - private l1Cache: NodeCache; // In-memory (10MB) - private l2Cache: RedisCluster; // Redis (100GB) - private l3Cache: CDNCache; // CDN Edge (unlimited) - - async get(key: string): Promise { - // L1: Local memory (< 1ms) - let value = this.l1Cache.get(key); - if (value) return value; - - // L2: Redis cluster (< 5ms) - value = await this.l2Cache.get(key); - if (value) { - this.l1Cache.set(key, value, 60); // Cache 1 min - return value; - } - - // L3: CDN edge cache (< 20ms) - value = await this.l3Cache.get(key); - if (value) { - await this.warmUpCache(key, value); - return value; - } - - return null; - } -} -``` - -### 6.2 Cache Invalidation - -```mermaid -sequenceDiagram - participant User - participant AuthAPI - participant Cache - participant DB - participant EventBus - - User->>AuthAPI: Update Permission - AuthAPI->>DB: Write to DB - AuthAPI->>EventBus: Publish PERMISSION_CHANGED - EventBus->>Cache: Invalidate user cache - EventBus->>Cache: Invalidate permission cache - Cache-->>AuthAPI: Cache cleared - AuthAPI-->>User: Success -``` - -## 7. Security Implementation - -### 7.1 Zero-Trust Architecture - -```typescript -// [services/auth-core/auth-api/src/security/zero-trust.ts] - -export class ZeroTrustValidator { - async validateRequest(req: Request): Promise { - const checks = await Promise.all([ - this.validateDevice(req), // Device fingerprinting - this.validateLocation(req), // Geo-location check - this.validateBehavior(req), // ML-based behavior analysis - this.validateToken(req), // Token validation - this.validateRateLimit(req), // Rate limiting - ]); - - const riskScore = this.calculateRiskScore(checks); - - if (riskScore > 0.8) { - // High risk - require MFA - return { requireMFA: true }; - } else if (riskScore > 0.5) { - // Medium risk - additional logging - await this.auditLog(req, 'MEDIUM_RISK'); - } - - return { allowed: true }; - } -} -``` - -### 7.2 Advanced RBAC with ABAC - -```typescript -// [services/auth-rbac/policy-service/src/models/policy.ts] - -export class PolicyEngine { - async evaluate(context: PolicyContext): Promise { - // Attribute-based access control - const policies = await this.loadPolicies(context.resource); - - for (const policy of policies) { - if (!this.evaluateCondition(policy.condition, context)) { - return false; - } - } - - // Role-based check - const hasRole = await this.checkRole( - context.userId, - policy.requiredRole - ); - - // Permission check with scope - const hasPermission = await this.checkPermission( - context.userId, - context.resource, - context.action, - context.scope - ); - - // Time-based access - const inTimeWindow = this.checkTimeWindow( - policy.timeRestriction - ); - - return hasRole && hasPermission && inTimeWindow; - } -} -``` - -## 8. Social Login với Circuit Breaker - -```typescript -// [services/auth-social/social-auth-service/src/providers/social-provider.ts] - -export class SocialAuthProvider { - private circuitBreaker: CircuitBreaker; - - constructor(provider: string) { - this.circuitBreaker = new CircuitBreaker({ - timeout: 3000, // 3s timeout - errorThreshold: 50, // 50% error rate - resetTimeout: 30000, // Reset after 30s - }); - } - - async authenticate(code: string): Promise { - return this.circuitBreaker.execute(async () => { - // Fallback to cached profile if provider is down - try { - return await this.provider.getProfile(code); - } catch (error) { - const cached = await this.getCachedProfile(code); - if (cached) { - this.logger.warn('Using cached profile', { provider }); - return cached; - } - throw error; - } - }); - } -} -``` - -## 9. OIDC Provider với Multi-tenancy - -```typescript -// [services/auth-social/oidc-provider/src/provider/multi-tenant.ts] - -export class MultiTenantOIDCProvider { - async getConfiguration(tenantId: string): Promise { - const tenant = await this.tenantService.get(tenantId); - - return { - issuer: `https://auth.goodgo.com/${tenantId}`, - clients: tenant.clients, - claims: tenant.customClaims, - features: { - introspection: { enabled: true }, - revocation: { enabled: true }, - deviceFlow: { enabled: tenant.features.deviceFlow }, - mTLS: { - enabled: tenant.security.mtls, - certificateAuth: true - } - }, - jwks: await this.keyRotation.getCurrentKeys(tenantId), - ttl: this.getTTLConfig(tenant.security.level) - }; - } -} -``` - -## 10. Implementation Phases - -### Phase 1: Core Refactoring (2 tuần) - -- Tách auth-service thành microservices -- Implement sharding cho database -- Setup Redis Cluster -- Basic monitoring với Datadog - -### Phase 2: Performance Optimization (2 tuần) - -- Implement multi-layer caching -- Optimize database queries -- Add connection pooling -- Load testing với K6 - -### Phase 3: Security Enhancement (2 tuần) - -- Zero-trust architecture -- Advanced RBAC với ABAC -- MFA với TOTP/WebAuthn -- Audit logging với ElasticSearch - -### Phase 4: High Availability (2 tuần) - -- Multi-region deployment -- Database replication -- Disaster recovery plan -- Chaos engineering tests - -### Phase 5: Social & OIDC (1 tuần) - -- Social login với circuit breaker -- OIDC provider multi-tenant -- Federation với enterprise IdPs -- SSO implementation - -### Phase 6: Monitoring & Optimization (1 tuần) - -- Complete observability stack -- Performance tuning -- Security hardening -- Documentation & training - -## 11. Implementation Steps Chi Tiết - -### Step 1: Backup và Setup Base (30 phút) - -```bash -# Backup current auth-service -cp -r services/auth-service services/auth-service.backup - -# Delete current service -rm -rf services/auth-service - -# Copy template -cp -r services/_template services/auth-service - -# Update package.json name -``` - -### Step 2: Prisma Schema Setup (1 giờ) - -- Tạo schema với User, Role, Permission, Session, SocialAccount -- Setup indexes cho performance -- Add sharding support fields - -### Step 3: Core Modules Implementation (2 ngày) - -- **Auth Module**: Login, Register, Logout, RefreshToken -- **RBAC Module**: Roles, Permissions, Policies -- **Token Module**: JWT service với rotation -- **Session Module**: Distributed session management - -### Step 4: Advanced Features (3 ngày) - -- **Social Auth**: Google, Facebook, GitHub với Passport.js -- **OIDC**: Provider và Client implementation -- **MFA**: TOTP và WebAuthn -- **Zero-Trust**: Device fingerprinting, geo-location - -### Step 5: Performance Optimization (2 ngày) - -- **Multi-layer Cache**: Memory → Redis → CDN -- **Database Optimization**: Connection pooling, indexes -- **Rate Limiting**: Dynamic theo role -- **Load Testing**: K6 tests cho 10K req/s - -### Step 6: Security & Monitoring (1 ngày) - -- **Audit Logging**: Event sourcing pattern -- **Monitoring**: Prometheus metrics -- **Security Headers**: Helmet.js -- **Testing**: Unit & Integration tests - -### Step 7: Deployment (1 ngày) - -- Update docker-compose.yml -- Configure Traefik routing -- Setup environment variables -- Documentation - -## 12. Key Technologies - -### Core Stack (Phù hợp với GoodGo) - -- **Express.js**: Web framework (giữ nguyên theo template) -- **Prisma**: ORM với PostgreSQL/Neon -- **Redis**: Caching layer -- **TypeScript**: Type safety -- **Zod**: Validation - -### Authentication Libraries - -- **jsonwebtoken**: JWT handling -- **passport**: Social auth strategies -- **bcryptjs**: Password hashing -- **speakeasy**: TOTP for MFA -- **@simplewebauthn/server**: WebAuthn - -### Security Libraries - -- **helmet**: Security headers -- **express-rate-limit**: Rate limiting -- **ioredis**: Redis client -- **node-cache**: In-memory cache -- **fingerprint.js**: Device fingerprinting - -### Monitoring (Existing trong GoodGo) - -- **Prometheus**: Metrics (existing) -- **Grafana**: Dashboards (existing) -- **Loki**: Logging (existing) -- **@goodgo/logger**: Custom logger -- **@goodgo/tracing**: OpenTelemetry - -## 13. Performance Targets (Realistic cho Start) - -### Phase 1: MVP (Current Infrastructure) - -- **Authentication**: < 200ms p99 -- **Token Validation**: < 50ms p99 -- **Permission Check**: < 100ms p99 -- **Throughput**: 1,000 req/s -- **Availability**: 99.9% uptime - -### Phase 2: Scale Up (3-6 months) - -- **Authentication**: < 100ms p99 -- **Token Validation**: < 20ms p99 -- **Throughput**: 10,000 req/s -- **Availability**: 99.99% uptime - -### Phase 3: Enterprise (1+ year) - -- **Authentication**: < 50ms p99 -- **Token Validation**: < 10ms p99 -- **Throughput**: 50,000 req/s -- **Availability**: 99.999% uptime - -## 14. File Structure to Create - -```bash -services/auth-service/ -├── package.json # Dependencies -├── tsconfig.json # TypeScript config -├── .env.example # Environment template -├── Dockerfile # Docker build -├── jest.config.ts # Test configuration -├── prisma/ -│ └── schema.prisma # Database schema -├── src/ -│ ├── main.ts # Entry point -│ ├── config/*.ts # Configurations -│ ├── core/* # Core utilities -│ ├── modules/* # Feature modules -│ ├── middlewares/*.ts # Express middlewares -│ ├── repositories/*.ts # Data access -│ └── routes/index.ts # Route definitions -└── tests/ - ├── unit/* # Unit tests - └── integration/* # Integration tests -``` - -## 15. Timeline Thực Tế - -### Week 1: Foundation - -- **Day 1-2**: Setup base structure, Prisma schema -- **Day 3-4**: Core auth module (login, register, JWT) -- **Day 5**: Basic RBAC (roles, permissions) - -### Week 2: Advanced Features - -- **Day 1-2**: Social authentication -- **Day 3-4**: OIDC implementation -- **Day 5**: MFA và security features - -### Week 3: Optimization & Deployment - -- **Day 1-2**: Performance optimization, caching -- **Day 3**: Testing và bug fixes -- **Day 4-5**: Documentation và deployment - -**Total: 3 tuần cho MVP production-ready** \ No newline at end of file diff --git a/.cursor/plans/iam_service_migration_plan_fc0d64b3.plan.md b/.cursor/plans/iam_service_migration_plan_fc0d64b3.plan.md new file mode 100644 index 00000000..47d55073 --- /dev/null +++ b/.cursor/plans/iam_service_migration_plan_fc0d64b3.plan.md @@ -0,0 +1,1390 @@ +--- +name: IAM Service Migration Plan +overview: Kế hoạch chi tiết để chuyển đổi auth-service thành IAM service với các module mở rộng cho Identity Management, Access Management và Governance +todos: + - id: phase1-rename + content: "Phase 1: Rename service directory and update package.json, environment variables, main.ts, and deployment configs" + status: completed + - id: phase1-docs + content: "Phase 1: Update README.md, ARCHITECTURE files, and create IAM_PROPOSAL.md" + status: completed + - id: phase1-deploy + content: "Phase 1: Update docker-compose.yml and Kubernetes configs for iam-service" + status: completed + - id: phase2-schema + content: "Phase 2: Add Identity Management models (Organization, Group, UserProfile, IdentityVerification) to Prisma schema" + status: completed + - id: phase2-schema-access + content: "Phase 2: Add Access Management models (AccessRequest, AccessReview, AccessReviewItem) to Prisma schema" + status: completed + - id: phase2-schema-governance + content: "Phase 2: Add Governance models (ComplianceReport, PolicyTemplate, RiskScore) to Prisma schema" + status: completed + - id: phase2-migration + content: "Phase 2: Create and run Prisma migration, update seed script, generate Prisma client" + status: completed + - id: phase3-repositories + content: "Phase 3: Create repositories for Organization, Group, UserProfile, IdentityVerification, AccessRequest, AccessReview" + status: completed + - id: phase3-dtos + content: "Phase 3: Create DTOs (Zod schemas) for Identity, Access, and Governance modules" + status: completed + - id: phase4-user-lifecycle + content: "Phase 4: Implement User Lifecycle Management (service, controller, module) with CRUD, bulk operations, deactivation" + status: completed + - id: phase4-profile + content: "Phase 4: Implement Profile Management (service, controller, module) with avatar upload support" + status: completed + - id: phase4-verification + content: "Phase 4: Implement Identity Verification (service, controller, module) for email, phone, document verification" + status: completed + - id: phase4-org-group + content: "Phase 4: Implement Organization & Group Management (services, controllers, modules) with hierarchy support" + status: completed + - id: phase5-access-request + content: "Phase 5: Implement Access Request & Approval system (service, controller, module) with workflow support" + status: completed + - id: phase5-access-review + content: "Phase 5: Implement Access Review & Certification system (service, controller, module) with periodic reviews" + status: completed + - id: phase5-access-analytics + content: "Phase 5: Implement Access Analytics (service, controller, module) with usage stats and risk analysis" + status: completed + - id: phase6-compliance + content: "Phase 6: Implement Compliance Reporting (service, controller, module) with GDPR, SOC2, ISO27001 support" + status: completed + - id: phase6-policy + content: "Phase 6: Implement Policy Governance (service, controller, module) with versioning and templates" + status: completed + - id: phase6-risk + content: "Phase 6: Implement Risk Management (service, controller, module) with risk scoring and analysis" + status: completed + - id: phase6-reporting + content: "Phase 6: Implement Reporting Dashboard (service, controller, module) with access summary and security events" + status: completed + - id: phase7-routes + content: "Phase 7: Update routes/index.ts to integrate all new Identity, Access, and Governance endpoints while maintaining backward compatibility" + status: completed + - id: phase8-unit-tests + content: "Phase 8: Write unit tests for all repositories, services, and controllers" + status: pending + - id: phase8-integration-tests + content: "Phase 8: Write E2E tests for Identity, Access, and Governance workflows" + status: pending + - id: phase9-swagger + content: "Phase 9: Update Swagger/OpenAPI documentation with all new endpoints and schemas" + status: pending + - id: phase9-docs + content: "Phase 9: Update README, ARCHITECTURE docs, and create MIGRATION_GUIDE.md" + status: completed + - id: phase10-deploy + content: "Phase 10: Deploy to staging, run tests, then deploy to production with monitoring" + status: pending +--- + +# Kế Hoạch Chuyển Đổi Auth Service → IAM Service + +## Tổng Quan + +Plan này mô tả chi tiết các bước để chuyển đổi `auth-service` hiện tại thành `iam-service` với các tính năng mở rộng về Identity Management, Access Management, và Governance & Compliance. + +## Phạm Vi + +- **Rename service**: auth-service → iam-service +- **Database schema**: Thêm các models mới cho Identity, Access Management, Governance +- **Modules mới**: Identity, Access, Governance modules +- **Backward compatibility**: Giữ nguyên các API endpoints hiện tại +- **Deployment**: Update docker-compose, Kubernetes configs + +--- + +## Phase 1: Foundation & Renaming (Week 1) + +### 1.1 Service Rename + +**Tasks:** + +1. Rename service directory + + - `services/auth-service` → `services/iam-service` + +2. Update `package.json` + + - File: `services/iam-service/package.json` + - Change `name`: `"@goodgo/auth-service"` → `"@goodgo/iam-service"` + - Change `description`: Update to "Enterprise IAM (Identity and Access Management) Service" + +3. Update environment variables + + - File: `services/iam-service/.env.example` + - Change `SERVICE_NAME=auth-service` → `SERVICE_NAME=iam-service` + - Keep all other variables unchanged for backward compatibility + +4. Update `main.ts` + + - File: `services/iam-service/src/main.ts` + - Update service name in tracing initialization: `'auth-service'` → `'iam-service'` + +5. Update Dockerfile (if exists) + + - File: `services/iam-service/Dockerfile` + - Update any hardcoded service names + +### 1.2 Update Documentation Files + +**Tasks:** + +1. Update README.md + + - File: `services/iam-service/README.md` + - Change title: "Auth Service" → "IAM Service" + - Update description to include IAM scope + - Add migration notes section + +2. Update ARCHITECTURE files + + - Files: `services/iam-service/ARCHITECTURE.vi.md`, `ARCHITECTURE.en.md` + - Update service name references + - Add new IAM architecture sections (placeholder for now) + +3. Create IAM_PROPOSAL.md + + - File: `services/iam-service/IAM_PROPOSAL.md` + - Document IAM architecture proposal + - Include module structure and database schema changes + +### 1.3 Update Deployment Configurations + +**Tasks:** + +1. Update docker-compose.yml + + - File: `deployments/local/docker-compose.yml` + - Rename service: `auth-service` → `iam-service` + - Update container_name: `auth-service-local` → `iam-service-local` + - Update SERVICE_NAME env var + - Update Traefik labels: + - Router rule: Add `/api/v1/identity/*`, `/api/v1/access/*`, `/api/v1/governance/*` + - Keep existing `/api/v1/auth/*` routes for backward compatibility + +2. Update Kubernetes configs + + - Files: + - `deployments/staging/kubernetes/auth-service.yaml` → `iam-service.yaml` + - `deployments/production/kubernetes/auth-service.yaml` → `iam-service.yaml` + - Update all metadata names + - Update image name: `goodgo/auth-service` → `goodgo/iam-service` + - Update service names in ingress configs + +3. Update environment example files + + - Files: + - `deployments/local/env.local.example` + - `deployments/staging/env.staging.example` + - `deployments/production/env.production.example` + - Add new IAM-specific environment variables (with defaults) + +--- + +## Phase 2: Database Schema Extension (Week 2) + +### 2.1 Prisma Schema Extension + +**File**: `services/iam-service/prisma/schema.prisma` + +**Tasks:** + +1. **Add Identity Management Models** +```prisma +// Organization model +model Organization { + id String @id @default(cuid()) + name String + domain String? @unique + parentId String? + settings Json? + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + users User[] + groups Group[] + policies Policy[] + parent Organization? @relation("OrganizationHierarchy", fields: [parentId], references: [id]) + children Organization[] @relation("OrganizationHierarchy") + + @@index([domain]) + @@map("organizations") +} + +// Group model +model Group { + id String @id @default(cuid()) + name String + organizationId String? + description String? + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + organization Organization? @relation(fields: [organizationId], references: [id]) + members GroupMember[] + permissions GroupPermission[] + + @@unique([organizationId, name]) + @@index([organizationId]) + @@map("groups") +} + +// GroupMember model +model GroupMember { + id String @id @default(cuid()) + userId String + groupId String + role String @default("member") // member, admin + joinedAt DateTime @default(now()) + expiresAt DateTime? + + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + group Group @relation(fields: [groupId], references: [id], onDelete: Cascade) + + @@unique([userId, groupId]) + @@index([userId]) + @@index([groupId]) + @@map("group_members") +} + +// GroupPermission model +model GroupPermission { + id String @id @default(cuid()) + groupId String + permissionId String + createdAt DateTime @default(now()) + + group Group @relation(fields: [groupId], references: [id], onDelete: Cascade) + permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade) + + @@unique([groupId, permissionId]) + @@index([groupId]) + @@map("group_permissions") +} + +// UserProfile model +model UserProfile { + id String @id @default(cuid()) + userId String @unique + firstName String? + lastName String? + phone String? + phoneVerified Boolean @default(false) + avatarUrl String? + customFields Json? // Extended attributes + preferences Json? // User preferences + metadata Json? // Additional metadata + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@index([phone]) + @@map("user_profiles") +} + +// IdentityVerification model +model IdentityVerification { + id String @id @default(cuid()) + userId String + type VerificationType + status VerificationStatus @default(PENDING) + method String? + token String? @unique // OTP token, verification code + verifiedAt DateTime? + expiresAt DateTime? + metadata Json? // Verification details + createdAt DateTime @default(now()) + + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@index([userId, type]) + @@index([token]) + @@index([status]) + @@map("identity_verifications") +} + +enum VerificationType { + EMAIL + PHONE + DOCUMENT + BIOMETRIC +} + +enum VerificationStatus { + PENDING + VERIFIED + REJECTED + EXPIRED +} +``` + +2. **Add Access Management Models** +```prisma +// AccessRequest model +model AccessRequest { + id String @id @default(cuid()) + userId String + resource String + action String + reason String? + status RequestStatus @default(PENDING) + requestedAt DateTime @default(now()) + reviewedAt DateTime? + reviewedBy String? + expiresAt DateTime? + metadata Json? + + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + approvers AccessRequestApprover[] + + @@index([userId]) + @@index([status]) + @@index([resource]) + @@map("access_requests") +} + +enum RequestStatus { + PENDING + APPROVED + REJECTED + EXPIRED + CANCELLED +} + +// AccessRequestApprover model +model AccessRequestApprover { + id String @id @default(cuid()) + requestId String + approverId String + status ApprovalStatus @default(PENDING) + comments String? + reviewedAt DateTime? + + request AccessRequest @relation(fields: [requestId], references: [id], onDelete: Cascade) + + @@unique([requestId, approverId]) + @@index([approverId]) + @@map("access_request_approvers") +} + +enum ApprovalStatus { + PENDING + APPROVED + REJECTED +} + +// AccessReview model +model AccessReview { + id String @id @default(cuid()) + name String + description String? + type ReviewType + status ReviewStatus @default(DRAFT) + startDate DateTime + endDate DateTime + createdBy String + createdAt DateTime @default(now()) + completedAt DateTime? + + items AccessReviewItem[] + + @@index([status]) + @@index([type]) + @@map("access_reviews") +} + +enum ReviewType { + PERIODIC + ADHOC + CERTIFICATION +} + +enum ReviewStatus { + DRAFT + ACTIVE + COMPLETED + CANCELLED +} + +// AccessReviewItem model +model AccessReviewItem { + id String @id @default(cuid()) + reviewId String + userId String + resource String + access Json // Current access details + status ReviewItemStatus @default(PENDING) + reviewedBy String? + reviewedAt DateTime? + comments String? + + review AccessReview @relation(fields: [reviewId], references: [id], onDelete: Cascade) + + @@index([reviewId]) + @@index([userId]) + @@index([status]) + @@map("access_review_items") +} + +enum ReviewItemStatus { + PENDING + APPROVED + REVOKED + NO_CHANGE +} +``` + +3. **Add Governance Models** +```prisma +// ComplianceReport model +model ComplianceReport { + id String @id @default(cuid()) + type ComplianceType + name String + periodStart DateTime + periodEnd DateTime + status ReportStatus @default(DRAFT) + data Json? + generatedAt DateTime? + generatedBy String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([type]) + @@index([status]) + @@map("compliance_reports") +} + +enum ComplianceType { + GDPR + SOC2 + ISO27001 + HIPAA + CUSTOM +} + +enum ReportStatus { + DRAFT + GENERATED + PUBLISHED + ARCHIVED +} + +// PolicyTemplate model +model PolicyTemplate { + id String @id @default(cuid()) + name String + category PolicyCategory + description String? + content Json // Policy template structure + version String @default("1.0.0") + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([category]) + @@index([isActive]) + @@map("policy_templates") +} + +enum PolicyCategory { + SECURITY + ACCESS + COMPLIANCE + DATA + PRIVACY +} + +// RiskScore model +model RiskScore { + id String @id @default(cuid()) + userId String + score Int // 0-100 + level RiskLevel + factors Json // Risk factors + calculatedAt DateTime @default(now()) + + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@index([userId]) + @@index([score]) + @@index([level]) + @@map("risk_scores") +} + +enum RiskLevel { + LOW + MEDIUM + HIGH + CRITICAL +} +``` + +4. **Update Existing User Model** +```prisma +// Add to existing User model +model User { + // ... existing fields ... + + // New relations + organizationId String? + organization Organization? @relation(fields: [organizationId], references: [id]) + profile UserProfile? + verifications IdentityVerification[] + accessRequests AccessRequest[] + riskScores RiskScore[] + groupMembers GroupMember[] +} +``` + + +### 2.2 Create Migration + +**Tasks:** + +1. Generate Prisma migration + + - Command: `cd services/iam-service && pnpm prisma migrate dev --name add_iam_models` + - This will create migration file in `prisma/migrations/` + +2. Update seed script + + - File: `services/iam-service/prisma/seed.ts` + - Add seed data for new models (organizations, groups, etc.) + +3. Update Prisma Client + + - Command: `pnpm prisma:generate` + - Verify types are generated correctly + +--- + +## Phase 3: Core Infrastructure Extensions (Week 3) + +### 3.1 Repository Layer Extensions + +**Tasks:** + +1. **Create Organization Repository** + + - File: `services/iam-service/src/repositories/organization.repository.ts` + - Extend `BaseRepository` from `modules/common/repository.ts` + - Methods: + - `findById(id: string)` + - `findByDomain(domain: string)` + - `findChildren(parentId: string)` + - `create(data: CreateOrganizationInput)` + - `update(id: string, data: UpdateOrganizationInput)` + - `delete(id: string)` + +2. **Create Group Repository** + + - File: `services/iam-service/src/repositories/group.repository.ts` + - Methods: + - `findById(id: string)` + - `findByOrganization(organizationId: string)` + - `findUserGroups(userId: string)` + - `addMember(groupId: string, userId: string, role: string)` + - `removeMember(groupId: string, userId: string)` + - `getMembers(groupId: string)` + +3. **Create User Profile Repository** + + - File: `services/iam-service/src/repositories/user-profile.repository.ts` + - Methods: + - `findByUserId(userId: string)` + - `create(userId: string, data: CreateProfileInput)` + - `update(userId: string, data: UpdateProfileInput)` + - `updateAvatar(userId: string, avatarUrl: string)` + +4. **Create Identity Verification Repository** + + - File: `services/iam-service/src/repositories/identity-verification.repository.ts` + - Methods: + - `findByToken(token: string)` + - `findByUserAndType(userId: string, type: VerificationType)` + - `create(data: CreateVerificationInput)` + - `updateStatus(id: string, status: VerificationStatus)` + +5. **Create Access Request Repository** + + - File: `services/iam-service/src/repositories/access-request.repository.ts` + - Methods: + - `findById(id: string)` + - `findByUser(userId: string)` + - `findPendingByUser(userId: string)` + - `create(data: CreateAccessRequestInput)` + - `updateStatus(id: string, status: RequestStatus)` + +6. **Create Access Review Repository** + + - File: `services/iam-service/src/repositories/access-review.repository.ts` + - Methods: + - `findById(id: string)` + - `findActive()` + - `findByStatus(status: ReviewStatus)` + - `create(data: CreateAccessReviewInput)` + - `getItems(reviewId: string)` + +7. **Update Repository Index** + + - File: `services/iam-service/src/repositories/index.ts` + - Export all new repositories + +### 3.2 DTO Definitions + +**Tasks:** + +1. **Identity DTOs** + + - File: `services/iam-service/src/modules/identity/identity.dto.ts` + - Zod schemas: + - `CreateOrganizationDto` + - `UpdateOrganizationDto` + - `CreateGroupDto` + - `UpdateGroupDto` + - `CreateUserProfileDto` + - `UpdateUserProfileDto` + - `VerificationRequestDto` + - `VerifyCodeDto` + +2. **Access DTOs** + + - File: `services/iam-service/src/modules/access/access.dto.ts` + - Zod schemas: + - `CreateAccessRequestDto` + - `ApproveAccessRequestDto` + - `RejectAccessRequestDto` + - `CreateAccessReviewDto` + - `ReviewAccessItemDto` + +3. **Governance DTOs** + + - File: `services/iam-service/src/modules/governance/governance.dto.ts` + - Zod schemas: + - `GenerateComplianceReportDto` + - `CreatePolicyTemplateDto` + - `CalculateRiskScoreDto` + +--- + +## Phase 4: Identity Management Module (Week 4-5) + +### 4.1 User Lifecycle Management + +**Tasks:** + +1. **Create User Management Service** + + - File: `services/iam-service/src/modules/identity/user/user.service.ts` + - Extend existing `AuthService` functionality + - Add methods: + - `getUser(userId: string)` + - `updateUser(userId: string, data: UpdateUserInput)` + - `deleteUser(userId: string)` (soft delete) + - `deactivateUser(userId: string)` + - `reactivateUser(userId: string)` + - `bulkImportUsers(file: Buffer, organizationId?: string)` + - `bulkExportUsers(filters: UserFilters)` + - `searchUsers(query: string, filters: UserFilters)` + +2. **Create User Management Controller** + + - File: `services/iam-service/src/modules/identity/user/user.controller.ts` + - Endpoints: + - `GET /api/v1/identity/users` + - `GET /api/v1/identity/users/:id` + - `PUT /api/v1/identity/users/:id` + - `DELETE /api/v1/identity/users/:id` + - `POST /api/v1/identity/users/:id/deactivate` + - `POST /api/v1/identity/users/:id/reactivate` + - `POST /api/v1/identity/users/bulk-import` + - `GET /api/v1/identity/users/bulk-export` + +3. **Create User Module** + + - File: `services/iam-service/src/modules/identity/user/user.module.ts` + - Wire up dependencies + +4. **Create Index File** + + - File: `services/iam-service/src/modules/identity/user/index.ts` + +### 4.2 Profile Management + +**Tasks:** + +1. **Create Profile Service** + + - File: `services/iam-service/src/modules/identity/profile/profile.service.ts` + - Methods: + - `getProfile(userId: string)` + - `updateProfile(userId: string, data: UpdateProfileInput)` + - `uploadAvatar(userId: string, file: Buffer, mimetype: string)` + - `deleteAvatar(userId: string)` + - `updatePreferences(userId: string, preferences: Json)` + +2. **Create Profile Controller** + + - File: `services/iam-service/src/modules/identity/profile/profile.controller.ts` + - Endpoints: + - `GET /api/v1/identity/users/:id/profile` + - `PUT /api/v1/identity/users/:id/profile` + - `POST /api/v1/identity/users/:id/profile/avatar` + - `DELETE /api/v1/identity/users/:id/profile/avatar` + +3. **Create Profile Module** + + - File: `services/iam-service/src/modules/identity/profile/profile.module.ts` + +### 4.3 Identity Verification + +**Tasks:** + +1. **Create Verification Service** + + - File: `services/iam-service/src/modules/identity/verification/verification.service.ts` + - Methods: + - `requestEmailVerification(userId: string)` + - `verifyEmail(token: string)` + - `requestPhoneVerification(userId: string, phone: string)` + - `verifyPhone(token: string)` + - `requestDocumentVerification(userId: string, document: Buffer)` + - `getVerificationStatus(userId: string, type: VerificationType)` + +2. **Create Verification Controller** + + - File: `services/iam-service/src/modules/identity/verification/verification.controller.ts` + - Endpoints: + - `POST /api/v1/identity/verification/email/request` + - `POST /api/v1/identity/verification/email/verify` + - `POST /api/v1/identity/verification/phone/request` + - `POST /api/v1/identity/verification/phone/verify` + - `POST /api/v1/identity/verification/document/upload` + - `GET /api/v1/identity/verification/:id/status` + +3. **Create Verification Module** + + - File: `services/iam-service/src/modules/identity/verification/verification.module.ts` + +4. **Add Email/SMS Service Integration** + + - Create config: `services/iam-service/src/config/notification.config.ts` + - Integrate with email service (SMTP) and SMS service + +### 4.4 Organization & Group Management + +**Tasks:** + +1. **Create Organization Service** + + - File: `services/iam-service/src/modules/identity/organization/organization.service.ts` + - Methods: + - `create(data: CreateOrganizationInput)` + - `getById(id: string)` + - `getByDomain(domain: string)` + - `update(id: string, data: UpdateOrganizationInput)` + - `delete(id: string)` + - `getChildren(parentId: string)` + - `getUsers(organizationId: string)` + - `addUser(organizationId: string, userId: string)` + - `removeUser(organizationId: string, userId: string)` + +2. **Create Organization Controller** + + - File: `services/iam-service/src/modules/identity/organization/organization.controller.ts` + - Endpoints: + - `GET /api/v1/identity/organizations` + - `POST /api/v1/identity/organizations` + - `GET /api/v1/identity/organizations/:id` + - `PUT /api/v1/identity/organizations/:id` + - `DELETE /api/v1/identity/organizations/:id` + - `GET /api/v1/identity/organizations/:id/users` + +3. **Create Group Service** + + - File: `services/iam-service/src/modules/identity/group/group.service.ts` + - Methods: + - `create(organizationId: string, data: CreateGroupInput)` + - `getById(id: string)` + - `getByOrganization(organizationId: string)` + - `update(id: string, data: UpdateGroupInput)` + - `delete(id: string)` + - `addMember(groupId: string, userId: string, role: string)` + - `removeMember(groupId: string, userId: string)` + - `getMembers(groupId: string)` + - `assignPermission(groupId: string, permissionId: string)` + - `revokePermission(groupId: string, permissionId: string)` + +4. **Create Group Controller** + + - File: `services/iam-service/src/modules/identity/group/group.controller.ts` + - Endpoints: + - `GET /api/v1/identity/organizations/:id/groups` + - `POST /api/v1/identity/organizations/:id/groups` + - `GET /api/v1/identity/groups/:id` + - `PUT /api/v1/identity/groups/:id` + - `DELETE /api/v1/identity/groups/:id` + - `GET /api/v1/identity/groups/:id/members` + - `POST /api/v1/identity/groups/:id/members` + - `DELETE /api/v1/identity/groups/:id/members/:userId` + +5. **Create Modules** + + - Files: + - `services/iam-service/src/modules/identity/organization/organization.module.ts` + - `services/iam-service/src/modules/identity/group/group.module.ts` + +6. **Create Identity Module Index** + + - File: `services/iam-service/src/modules/identity/index.ts` + - Export all identity modules + +--- + +## Phase 5: Access Management Module (Week 6-7) + +### 5.1 Access Request & Approval + +**Tasks:** + +1. **Create Access Request Service** + + - File: `services/iam-service/src/modules/access/request/request.service.ts` + - Methods: + - `createRequest(userId: string, data: CreateAccessRequestInput)` + - `getRequest(id: string)` + - `getUserRequests(userId: string)` + - `approveRequest(requestId: string, approverId: string, comments?: string)` + - `rejectRequest(requestId: string, approverId: string, comments?: string)` + - `cancelRequest(requestId: string, userId: string)` + - `getPendingApprovals(approverId: string)` + +2. **Create Access Request Controller** + + - File: `services/iam-service/src/modules/access/request/request.controller.ts` + - Endpoints: + - `GET /api/v1/access/requests` + - `POST /api/v1/access/requests` + - `GET /api/v1/access/requests/:id` + - `PUT /api/v1/access/requests/:id/approve` + - `PUT /api/v1/access/requests/:id/reject` + - `DELETE /api/v1/access/requests/:id` + +3. **Create Access Request Module** + + - File: `services/iam-service/src/modules/access/request/request.module.ts` + +### 5.2 Access Review & Certification + +**Tasks:** + +1. **Create Access Review Service** + + - File: `services/iam-service/src/modules/access/review/review.service.ts` + - Methods: + - `createReview(data: CreateAccessReviewInput)` + - `getReview(id: string)` + - `startReview(id: string)` + - `completeReview(id: string)` + - `getReviewItems(reviewId: string)` + - `reviewItem(itemId: string, reviewerId: string, status: ReviewItemStatus, comments?: string)` + - `getUserReviewItems(userId: string, reviewId: string)` + - `generateReviewItems(reviewId: string)` // Auto-generate based on current access + +2. **Create Access Review Controller** + + - File: `services/iam-service/src/modules/access/review/review.controller.ts` + - Endpoints: + - `GET /api/v1/access/reviews` + - `POST /api/v1/access/reviews` + - `GET /api/v1/access/reviews/:id` + - `PUT /api/v1/access/reviews/:id` + - `POST /api/v1/access/reviews/:id/start` + - `POST /api/v1/access/reviews/:id/complete` + - `GET /api/v1/access/reviews/:id/items` + - `PUT /api/v1/access/reviews/:id/items/:itemId/review` + +3. **Create Access Review Module** + + - File: `services/iam-service/src/modules/access/review/review.module.ts` + +### 5.3 Access Analytics + +**Tasks:** + +1. **Create Access Analytics Service** + + - File: `services/iam-service/src/modules/access/analytics/analytics.service.ts` + - Methods: + - `getUsageStats(period: DateRange)` + - `getPermissionDistribution()` + - `getUserAccessSummary(userId: string)` + - `getRiskAnalysis(filters: RiskFilters)` + - `getAccessTrends(period: DateRange)` + +2. **Create Access Analytics Controller** + + - File: `services/iam-service/src/modules/access/analytics/analytics.controller.ts` + - Endpoints: + - `GET /api/v1/access/analytics/usage` + - `GET /api/v1/access/analytics/permissions` + - `GET /api/v1/access/analytics/users/:id/summary` + - `GET /api/v1/access/analytics/risks` + +3. **Create Access Analytics Module** + + - File: `services/iam-service/src/modules/access/analytics/analytics.module.ts` + +4. **Create Access Module Index** + + - File: `services/iam-service/src/modules/access/index.ts` + - Export all access modules + +--- + +## Phase 6: Governance Module (Week 8-9) + +### 6.1 Compliance Reporting + +**Tasks:** + +1. **Create Compliance Service** + + - File: `services/iam-service/src/modules/governance/compliance/compliance.service.ts` + - Methods: + - `generateReport(type: ComplianceType, periodStart: Date, periodEnd: Date)` + - `getReport(id: string)` + - `getReports(filters: ReportFilters)` + - `exportReport(id: string, format: 'pdf' | 'csv' | 'json')` + - `publishReport(id: string)` + - `getGDPRReport(userId: string)` + - `getSOC2Report(periodStart: Date, periodEnd: Date)` + +2. **Create Compliance Controller** + + - File: `services/iam-service/src/modules/governance/compliance/compliance.controller.ts` + - Endpoints: + - `GET /api/v1/governance/compliance/reports` + - `POST /api/v1/governance/compliance/reports/generate` + - `GET /api/v1/governance/compliance/reports/:id` + - `GET /api/v1/governance/compliance/reports/:id/export` + - `POST /api/v1/governance/compliance/reports/:id/publish` + +3. **Create Compliance Module** + + - File: `services/iam-service/src/modules/governance/compliance/compliance.module.ts` + +### 6.2 Policy Governance + +**Tasks:** + +1. **Create Policy Governance Service** + + - File: `services/iam-service/src/modules/governance/policy/policy-governance.service.ts` + - Extend existing `Policy` model from RBAC + - Methods: + - `createTemplate(data: CreatePolicyTemplateInput)` + - `getTemplates(category?: PolicyCategory)` + - `createPolicyFromTemplate(templateId: string, data: CreatePolicyInput)` + - `getPolicyVersions(policyId: string)` + - `rollbackPolicy(policyId: string, version: string)` + - `testPolicy(policyId: string, testData: Json)` + - `validatePolicy(policy: Policy)` + +2. **Create Policy Governance Controller** + + - File: `services/iam-service/src/modules/governance/policy/policy-governance.controller.ts` + - Endpoints: + - `GET /api/v1/governance/policies/templates` + - `POST /api/v1/governance/policies/templates` + - `GET /api/v1/governance/policies/:id/versions` + - `POST /api/v1/governance/policies/:id/test` + - `POST /api/v1/governance/policies/:id/rollback` + +3. **Create Policy Governance Module** + + - File: `services/iam-service/src/modules/governance/policy/policy-governance.module.ts` + +### 6.3 Risk Management + +**Tasks:** + +1. **Create Risk Service** + + - File: `services/iam-service/src/modules/governance/risk/risk.service.ts` + - Methods: + - `calculateRiskScore(userId: string)` + - `getRiskScore(userId: string)` + - `getRiskScores(filters: RiskFilters)` + - `getRiskFactors(userId: string)` + - `getHighRiskUsers(threshold: number)` + - `updateRiskScore(userId: string, factors: RiskFactors)` + +2. **Create Risk Controller** + + - File: `services/iam-service/src/modules/governance/risk/risk.controller.ts` + - Endpoints: + - `GET /api/v1/governance/risk/scores` + - `GET /api/v1/governance/risk/scores/:userId` + - `POST /api/v1/governance/risk/calculate` + - `GET /api/v1/governance/risk/dashboard` + +3. **Create Risk Module** + + - File: `services/iam-service/src/modules/governance/risk/risk.module.ts` + +### 6.4 Reporting Dashboard + +**Tasks:** + +1. **Create Reporting Service** + + - File: `services/iam-service/src/modules/governance/reporting/reporting.service.ts` + - Methods: + - `getAccessSummary(period: DateRange)` + - `getUserActivity(userId: string, period: DateRange)` + - `getSecurityEvents(period: DateRange, filters: EventFilters)` + - `getComplianceStatus()` + - `getRiskOverview()` + +2. **Create Reporting Controller** + + - File: `services/iam-service/src/modules/governance/reporting/reporting.controller.ts` + - Endpoints: + - `GET /api/v1/governance/reports/access-summary` + - `GET /api/v1/governance/reports/user-activity` + - `GET /api/v1/governance/reports/security-events` + - `GET /api/v1/governance/reports/compliance-status` + - `GET /api/v1/governance/reports/risk-overview` + +3. **Create Reporting Module** + + - File: `services/iam-service/src/modules/governance/reporting/reporting.module.ts` + +4. **Create Governance Module Index** + + - File: `services/iam-service/src/modules/governance/index.ts` + - Export all governance modules + +--- + +## Phase 7: Routes Integration (Week 10) + +### 7.1 Update Routes + +**File**: `services/iam-service/src/routes/index.ts` + +**Tasks:** + +1. **Add Identity Routes** + ```typescript + // Import identity controllers + import { userController } from '../modules/identity/user/user.controller'; + import { profileController } from '../modules/identity/profile/profile.controller'; + import { verificationController } from '../modules/identity/verification/verification.controller'; + import { organizationController } from '../modules/identity/organization/organization.controller'; + import { groupController } from '../modules/identity/group/group.controller'; + + // Add routes with authentication middleware + // User routes + router.get(`/api/${apiVersion}/identity/users`, authenticate(), userController.list.bind(userController)); + router.post(`/api/${apiVersion}/identity/users`, authenticate(), requirePermission('identity', 'create'), userController.create.bind(userController)); + // ... more user routes + + // Profile routes + router.get(`/api/${apiVersion}/identity/users/:id/profile`, authenticate(), profileController.get.bind(profileController)); + // ... more profile routes + + // Verification routes + router.post(`/api/${apiVersion}/identity/verification/email/request`, authenticate(), verificationController.requestEmail.bind(verificationController)); + // ... more verification routes + + // Organization routes + router.get(`/api/${apiVersion}/identity/organizations`, authenticate(), organizationController.list.bind(organizationController)); + // ... more organization routes + + // Group routes + router.get(`/api/${apiVersion}/identity/organizations/:id/groups`, authenticate(), groupController.list.bind(groupController)); + // ... more group routes + ``` + +2. **Add Access Routes** + ```typescript + // Import access controllers + import { accessRequestController } from '../modules/access/request/request.controller'; + import { accessReviewController } from '../modules/access/review/review.controller'; + import { accessAnalyticsController } from '../modules/access/analytics/analytics.controller'; + + // Access request routes + router.get(`/api/${apiVersion}/access/requests`, authenticate(), accessRequestController.list.bind(accessRequestController)); + // ... more access request routes + + // Access review routes + router.get(`/api/${apiVersion}/access/reviews`, authenticate(), accessReviewController.list.bind(accessReviewController)); + // ... more access review routes + + // Access analytics routes + router.get(`/api/${apiVersion}/access/analytics/usage`, authenticate(), accessAnalyticsController.usage.bind(accessAnalyticsController)); + // ... more analytics routes + ``` + +3. **Add Governance Routes** + ```typescript + // Import governance controllers + import { complianceController } from '../modules/governance/compliance/compliance.controller'; + import { policyGovernanceController } from '../modules/governance/policy/policy-governance.controller'; + import { riskController } from '../modules/governance/risk/risk.controller'; + import { reportingController } from '../modules/governance/reporting/reporting.controller'; + + // Compliance routes + router.get(`/api/${apiVersion}/governance/compliance/reports`, authenticate(), complianceController.list.bind(complianceController)); + // ... more compliance routes + + // Policy governance routes + router.get(`/api/${apiVersion}/governance/policies/templates`, authenticate(), policyGovernanceController.getTemplates.bind(policyGovernanceController)); + // ... more policy routes + + // Risk routes + router.get(`/api/${apiVersion}/governance/risk/scores`, authenticate(), riskController.list.bind(riskController)); + // ... more risk routes + + // Reporting routes + router.get(`/api/${apiVersion}/governance/reports/access-summary`, authenticate(), reportingController.accessSummary.bind(reportingController)); + // ... more reporting routes + ``` + +4. **Keep Backward Compatibility** + + - Keep all existing `/api/v1/auth/*` routes unchanged + - Keep all existing `/api/v1/rbac/*` routes unchanged + - Keep all existing `/api/v1/mfa/*` routes unchanged + - Keep all existing `/api/v1/sessions/*` routes unchanged + +--- + +## Phase 8: Testing (Week 11) + +### 8.1 Unit Tests + +**Tasks:** + +1. **Repository Tests** + + - Files: + - `services/iam-service/src/repositories/__tests__/organization.repository.test.ts` + - `services/iam-service/src/repositories/__tests__/group.repository.test.ts` + - `services/iam-service/src/repositories/__tests__/user-profile.repository.test.ts` + - `services/iam-service/src/repositories/__tests__/identity-verification.repository.test.ts` + - `services/iam-service/src/repositories/__tests__/access-request.repository.test.ts` + - `services/iam-service/src/repositories/__tests__/access-review.repository.test.ts` + +2. **Service Tests** + + - Files: + - `services/iam-service/src/modules/identity/**/__tests__/*.service.test.ts` + - `services/iam-service/src/modules/access/**/__tests__/*.service.test.ts` + - `services/iam-service/src/modules/governance/**/__tests__/*.service.test.ts` + +3. **Controller Tests** + + - Files: + - `services/iam-service/src/modules/identity/**/__tests__/*.controller.test.ts` + - `services/iam-service/src/modules/access/**/__tests__/*.controller.test.ts` + - `services/iam-service/src/modules/governance/**/__tests__/*.controller.test.ts` + +### 8.2 Integration Tests + +**Tasks:** + +1. **E2E Tests** + + - File: `services/iam-service/src/__tests__/identity.e2e.ts` + - Test user lifecycle workflows + - Test profile management + - Test identity verification flows + - Test organization & group management + + - File: `services/iam-service/src/__tests__/access.e2e.ts` + - Test access request/approval flows + - Test access review workflows + - Test access analytics + + - File: `services/iam-service/src/__tests__/governance.e2e.ts` + - Test compliance report generation + - Test policy governance + - Test risk scoring + +### 8.3 Update Test Setup + +**File**: `services/iam-service/src/__tests__/setupTests.ts` + +**Tasks:** + +- Update test database setup to include new models +- Update test fixtures for new entities +- Add test utilities for new modules + +--- + +## Phase 9: Documentation & API Docs (Week 12) + +### 9.1 Update OpenAPI/Swagger + +**File**: `services/iam-service/src/docs/swagger.ts` + +**Tasks:** + +1. Add Swagger tags for new modules: + + - `Identity` + - `Access` + - `Governance` + +2. Add API documentation for all new endpoints +3. Add request/response schemas +4. Add examples for each endpoint + +### 9.2 Update README + +**File**: `services/iam-service/README.md` + +**Tasks:** + +1. Update feature list with IAM capabilities +2. Add architecture overview +3. Add API endpoint documentation +4. Add migration guide from auth-service +5. Update setup instructions + +### 9.3 Update Architecture Docs + +**Files**: + +- `services/iam-service/ARCHITECTURE.vi.md` +- `services/iam-service/ARCHITECTURE.en.md` + +**Tasks:** + +1. Update service architecture diagrams +2. Add IAM module architecture +3. Add database schema documentation +4. Add API flow diagrams +5. Add deployment architecture + +### 9.4 Create Migration Guide + +**File**: `services/iam-service/MIGRATION_GUIDE.md` + +**Tasks:** + +1. Document steps to migrate from auth-service +2. Document breaking changes (if any) +3. Document backward compatibility notes +4. Document database migration steps +5. Document environment variable changes + +--- + +## Phase 10: Deployment & Rollout (Week 13) + +### 10.1 Final Deployment Updates + +**Tasks:** + +1. **Update Docker Image Build** + + - Ensure Dockerfile builds correctly + - Update image tags if needed + +2. **Update Environment Variables** + + - Review all environment variables + - Add new required variables for IAM features + - Update example files + +3. **Update Health Checks** + + - Verify health check endpoints work + - Add health checks for new dependencies (if any) + +### 10.2 Staging Deployment + +**Tasks:** + +1. Deploy to staging environment +2. Run smoke tests +3. Verify all endpoints work +4. Check backward compatibility +5. Run load tests + +### 10.3 Production Rollout + +**Tasks:** + +1. Create deployment plan +2. Deploy to production +3. Monitor metrics and logs +4. Verify backward compatibility +5. Gradual rollout if needed + +--- + +## Dependencies & Prerequisites + +### External Dependencies + +- Email service (SMTP) for email verification +- SMS service for phone verification +- File storage service for document/avatar uploads +- Object storage for file attachments + +### Internal Dependencies + +- All existing auth-service dependencies remain +- No breaking changes to existing APIs +- Database migrations are additive only + +--- + +## Risk Mitigation + +### Backward Compatibility + +- All existing `/api/v1/auth/*` routes remain functional +- Existing database schema is preserved +- Existing clients continue to work without changes + +### Rollback Plan + +- Keep auth-service as backup during migration +- Database migrations are reversible +- Can deploy both services simultaneously during transition + +### Testing Strategy + +- Comprehensive unit tests for all new modules +- Integration tests for workflows +- E2E tests for critical paths +- Load testing before production + +--- + +## Success Criteria + +1. ✅ Service renamed successfully +2. ✅ All new database models created and migrated +3. ✅ All new modules implemented and tested +4. ✅ All new API endpoints functional +5. ✅ Backward compatibility maintained +6. ✅ Documentation complete +7. ✅ Deployed to staging and verified +8. ✅ Production deployment successful \ No newline at end of file diff --git a/.cursor/skills/security/SKILL.md b/.cursor/skills/security/SKILL.md new file mode 100644 index 00000000..7d1eb814 --- /dev/null +++ b/.cursor/skills/security/SKILL.md @@ -0,0 +1,796 @@ +--- +name: security +description: Security best practices and patterns for GoodGo microservices platform. Use when implementing authentication, authorization, data protection, input validation, rate limiting, secrets management, or security testing across all services. +--- + +# Security Patterns for GoodGo Microservices + +## When to Use This Skill + +Use this skill when: +- Implementing authentication and authorization in any service +- Protecting sensitive data (PII, credentials, tokens) +- Validating user inputs and file uploads +- Implementing rate limiting and DDoS protection +- Setting up audit logging and security monitoring +- Encrypting data at rest and in transit +- Managing secrets and credentials +- Implementing security testing +- Handling security incidents +- Designing secure API endpoints + +## Core Security Principles + +1. **Defense in Depth**: Multiple layers of security controls +2. **Least Privilege**: Grant minimum required permissions +3. **Fail Secure**: Default to deny access +4. **Separation of Duties**: Critical operations require multiple approvals +5. **Audit Everything**: Log all security-relevant events +6. **Encrypt Sensitive Data**: PII, tokens, credentials must be encrypted +7. **Validate All Inputs**: Never trust user input +8. **Principle of Least Exposure**: Minimize attack surface +9. **Secure by Default**: Security built-in, not bolted on +10. **Assume Breach**: Design for detection and response + +## Authentication & Authorization + +### JWT Token Validation + +```typescript +// src/middlewares/auth.middleware.ts +import { Request, Response, NextFunction } from 'express'; +import { jwtService } from '@goodgo/auth-sdk'; +import { logger } from '@goodgo/logger'; + +export const authenticate = () => { + return async (req: Request, res: Response, next: NextFunction) => { + try { + // Extract token from Authorization header or cookie + let token: string | null = null; + + const authHeader = req.headers.authorization; + if (authHeader?.startsWith('Bearer ')) { + token = authHeader.substring(7); + } else if (req.cookies?.access_token) { + token = req.cookies.access_token; + } + + if (!token) { + return res.status(401).json({ + success: false, + error: { code: 'AUTH_REQUIRED', message: 'Authentication required' } + }); + } + + // Verify token + const payload = await jwtService.verifyAccessToken(token); + + // Attach user to request + req.user = { + id: payload.sub, + userId: payload.sub, + email: payload.email, + roles: payload.roles || [], + permissions: payload.permissions || [] + }; + + next(); + } catch (error) { + logger.warn('Authentication failed', { error: error.message }); + return res.status(401).json({ + success: false, + error: { code: 'INVALID_TOKEN', message: 'Invalid or expired token' } + }); + } + }; +}; +``` + +### Role-Based Authorization + +```typescript +// src/middlewares/rbac.middleware.ts +export const requireRole = (...allowedRoles: string[]) => { + return (req: Request, res: Response, next: NextFunction) => { + if (!req.user) { + return res.status(401).json({ + success: false, + error: { code: 'AUTH_REQUIRED', message: 'Authentication required' } + }); + } + + const userRoles = req.user.roles || []; + const hasRole = userRoles.some(role => allowedRoles.includes(role)); + + if (!hasRole) { + logger.warn('Access denied - insufficient role', { + userId: req.user.id, + userRoles, + requiredRoles: allowedRoles + }); + + return res.status(403).json({ + success: false, + error: { code: 'FORBIDDEN', message: 'Insufficient permissions' } + }); + } + + next(); + }; +}; + +// Permission-based authorization +export const requirePermission = (resource: string, action: string) => { + return async (req: Request, res: Response, next: NextFunction) => { + if (!req.user) { + return res.status(401).json({ + success: false, + error: { code: 'AUTH_REQUIRED', message: 'Authentication required' } + }); + } + + const permission = `${resource}:${action}`; + const hasPermission = req.user.permissions?.includes(permission); + + if (!hasPermission) { + logger.warn('Access denied - insufficient permission', { + userId: req.user.id, + required: permission + }); + + return res.status(403).json({ + success: false, + error: { code: 'FORBIDDEN', message: 'Insufficient permissions' } + }); + } + + next(); + }; +}; + +// Usage in routes +router.post( + '/api/v1/users', + authenticate(), + requirePermission('users', 'create'), + userController.create +); +``` + +### Resource Ownership Validation + +```typescript +// Ensure users can only access their own resources +export const requireOwnership = (resourceIdParam: string = 'id') => { + return (req: Request, res: Response, next: NextFunction) => { + const resourceId = req.params[resourceIdParam]; + const userId = req.user?.id; + + if (resourceId !== userId) { + logger.warn('Access denied - resource ownership mismatch', { + userId, + resourceId + }); + + return res.status(403).json({ + success: false, + error: { code: 'FORBIDDEN', message: 'Access denied' } + }); + } + + next(); + }; +}; +``` + +## Data Protection + +### Encryption Service + +```typescript +// src/core/security/encryption.service.ts +import crypto from 'crypto'; + +const ALGORITHM = 'aes-256-gcm'; +const IV_LENGTH = 16; +const TAG_LENGTH = 16; + +export class EncryptionService { + private getKey(): Buffer { + const secret = process.env.ENCRYPTION_KEY; + if (!secret || secret.length < 32) { + throw new Error('ENCRYPTION_KEY must be at least 32 characters'); + } + return crypto.scryptSync(secret, 'salt', 32); + } + + encrypt(text: string): string { + const key = this.getKey(); + const iv = crypto.randomBytes(IV_LENGTH); + const cipher = crypto.createCipheriv(ALGORITHM, key, iv); + + let encrypted = cipher.update(text, 'utf8', 'hex'); + encrypted += cipher.final('hex'); + const tag = cipher.getAuthTag(); + + return `${iv.toString('hex')}:${tag.toString('hex')}:${encrypted}`; + } + + decrypt(encryptedText: string): string { + const [ivHex, tagHex, encrypted] = encryptedText.split(':'); + const iv = Buffer.from(ivHex, 'hex'); + const tag = Buffer.from(tagHex, 'hex'); + + const key = this.getKey(); + const decipher = crypto.createDecipheriv(ALGORITHM, key, iv); + decipher.setAuthTag(tag); + + let decrypted = decipher.update(encrypted, 'hex', 'utf8'); + decrypted += decipher.final('utf8'); + return decrypted; + } +} + +// Usage: Encrypt PII before storing +const encryption = new EncryptionService(); +const encryptedPhone = encryption.encrypt(user.phone); +``` + +### Password Hashing + +```typescript +// Always use bcrypt with appropriate cost factor +import bcrypt from 'bcrypt'; + +const SALT_ROUNDS = 12; // Production: 12, Development: 10 + +export class PasswordService { + async hash(password: string): Promise { + return bcrypt.hash(password, SALT_ROUNDS); + } + + async verify(password: string, hash: string): Promise { + return bcrypt.compare(password, hash); + } + + // Never log passwords + sanitizeForLogging(data: any): any { + const sanitized = { ...data }; + if (sanitized.password) sanitized.password = '[REDACTED]'; + if (sanitized.passwordHash) sanitized.passwordHash = '[REDACTED]'; + return sanitized; + } +} +``` + +### Token Hashing + +```typescript +// Hash tokens before storing in database +import crypto from 'crypto'; + +export class TokenService { + hashToken(token: string): string { + const salt = process.env.TOKEN_SALT || 'default-salt-change-in-production'; + return crypto + .createHash('sha256') + .update(token + salt) + .digest('hex'); + } + + generateSecureToken(length: number = 32): string { + return crypto.randomBytes(length).toString('hex'); + } +} +``` + +## Input Validation + +### Zod Schema Validation + +```typescript +// Always validate inputs with Zod +import { z } from 'zod'; + +// DTO with validation +export const CreateUserDto = z.object({ + email: z.string().email('Invalid email format'), + password: z.string() + .min(8, 'Password must be at least 8 characters') + .regex(/[A-Z]/, 'Password must contain uppercase letter') + .regex(/[a-z]/, 'Password must contain lowercase letter') + .regex(/[0-9]/, 'Password must contain number') + .regex(/[^A-Za-z0-9]/, 'Password must contain special character'), + phone: z.string() + .regex(/^\+[1-9]\d{1,14}$/, 'Invalid phone format (E.164)') + .optional(), + name: z.string().min(1).max(255) +}); + +// In controller +export class UserController { + async create(req: Request, res: Response) { + try { + const dto = CreateUserDto.parse(req.body); + const user = await this.service.create(dto); + res.status(201).json({ success: true, data: user }); + } catch (error) { + if (error instanceof z.ZodError) { + return res.status(400).json({ + success: false, + error: { + code: 'VALIDATION_ERROR', + message: 'Invalid input data', + details: error.errors + } + }); + } + throw error; + } + } +} +``` + +### File Upload Validation + +```typescript +// Validate file uploads +import fileType from 'file-type'; + +export class FileValidationService { + private readonly MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB + private readonly ALLOWED_TYPES = ['image/jpeg', 'image/png', 'application/pdf']; + + async validateFile(file: Express.Multer.File): Promise { + // Size check + if (file.size > this.MAX_FILE_SIZE) { + throw new HttpError(400, 'FILE_TOO_LARGE', 'File exceeds maximum size'); + } + + // Type check + if (!this.ALLOWED_TYPES.includes(file.mimetype)) { + throw new HttpError(400, 'INVALID_FILE_TYPE', 'File type not allowed'); + } + + // Content validation (prevent MIME type spoofing) + const type = await fileType.fromBuffer(file.buffer); + if (!type || !this.ALLOWED_TYPES.includes(type.mime)) { + throw new HttpError(400, 'INVALID_FILE_CONTENT', 'File content mismatch'); + } + + // TODO: Add virus scanning for production + } +} +``` + +### SQL Injection Prevention + +```typescript +// Always use Prisma parameterized queries (automatic) +// Never use string concatenation for queries + +// ❌ BAD - Never do this +const query = `SELECT * FROM users WHERE email = '${email}'`; + +// ✅ GOOD - Use Prisma +const user = await prisma.user.findUnique({ + where: { email } +}); + +// ✅ GOOD - For dynamic queries +const where: any = {}; +if (email) where.email = email; +if (status) where.status = status; + +const users = await prisma.user.findMany({ where }); +``` + +## Rate Limiting + +```typescript +// Implement rate limiting for all endpoints +import rateLimit from 'express-rate-limit'; +import RedisStore from 'rate-limit-redis'; +import Redis from 'ioredis'; + +const redis = new Redis(process.env.REDIS_URL); + +// Standard rate limit +export const standardLimiter = rateLimit({ + store: new RedisStore({ + client: redis, + prefix: 'rl:standard:' + }), + windowMs: 15 * 60 * 1000, // 15 minutes + max: 100, // 100 requests per window + message: 'Too many requests, please try again later', + standardHeaders: true, + legacyHeaders: false +}); + +// Strict rate limit for sensitive operations +export const strictLimiter = rateLimit({ + store: new RedisStore({ + client: redis, + prefix: 'rl:strict:' + }), + windowMs: 60 * 60 * 1000, // 1 hour + max: 10, + message: 'Rate limit exceeded for this operation' +}); + +// Login-specific rate limit +export const loginLimiter = rateLimit({ + store: new RedisStore({ + client: redis, + prefix: 'rl:login:' + }), + windowMs: 15 * 60 * 1000, + max: 5, // 5 login attempts per 15 minutes + skipSuccessfulRequests: true, + message: 'Too many login attempts, please try again later' +}); + +// Usage +router.post('/api/v1/auth/login', loginLimiter, authController.login); +router.post('/api/v1/users', authenticate(), strictLimiter, userController.create); +``` + +## Error Handling Security + +```typescript +// Sanitize error messages to prevent information disclosure +export class SecureErrorHandler { + handleError(error: Error, req: Request, res: Response) { + const isDev = process.env.NODE_ENV === 'development'; + const isProd = process.env.NODE_ENV === 'production'; + + // Log full error internally + logger.error('Request error', { + error: error.message, + stack: error.stack, + path: req.path, + method: req.method, + userId: req.user?.id + }); + + // Don't expose user existence + if (error.message.includes('user not found') || + error.message.includes('invalid credentials')) { + return res.status(401).json({ + success: false, + error: { + code: 'INVALID_CREDENTIALS', + message: 'Invalid email or password' + } + }); + } + + // Validation errors - safe to expose + if (error instanceof z.ZodError) { + return res.status(400).json({ + success: false, + error: { + code: 'VALIDATION_ERROR', + message: 'Invalid input data', + details: error.errors + } + }); + } + + // Generic errors for production + if (isProd) { + return res.status(500).json({ + success: false, + error: { + code: 'INTERNAL_ERROR', + message: 'An error occurred. Please try again later.' + } + }); + } + + // Detailed errors only in development + return res.status(500).json({ + success: false, + error: { + code: 'INTERNAL_ERROR', + message: error.message, + stack: isDev ? error.stack : undefined + } + }); + } +} +``` + +## Secrets Management + +```typescript +// Never hardcode secrets +// Always use environment variables with validation +import { z } from 'zod'; + +const secretsSchema = z.object({ + JWT_SECRET: z.string().min(32, 'JWT_SECRET must be at least 32 characters'), + JWT_REFRESH_SECRET: z.string().min(32), + DATABASE_URL: z.string().url(), + REDIS_URL: z.string().url().optional(), + ENCRYPTION_KEY: z.string().min(32).optional() +}); + +export const secrets = secretsSchema.parse(process.env); + +// For production, use secret management: +// - AWS Secrets Manager +// - HashiCorp Vault +// - Kubernetes Secrets +// - Azure Key Vault + +// Rotate secrets regularly (quarterly recommended) +``` + +## Audit Logging + +```typescript +// Log all security-relevant events +export class AuditService { + async logSecurityEvent( + event: string, + userId: string | null, + details: Record, + req?: Request + ) { + await this.prisma.auditLog.create({ + data: { + event, + userId, + type: 'SECURITY', + details: this.sanitizeDetails(details), + ipAddress: req?.ip || details.ipAddress, + userAgent: req?.get('user-agent'), + timestamp: new Date() + } + }); + } + + // Sanitize PII from logs + private sanitizeDetails(details: Record): Record { + const sensitive = ['password', 'token', 'secret', 'ssn', 'creditCard']; + const sanitized = { ...details }; + + for (const key of sensitive) { + if (sanitized[key]) { + sanitized[key] = '[REDACTED]'; + } + } + + return sanitized; + } +} + +// Usage +await auditService.logSecurityEvent('LOGIN_SUCCESS', user.id, { + email: user.email, + ipAddress: req.ip +}, req); + +await auditService.logSecurityEvent('PERMISSION_DENIED', user.id, { + resource: 'users', + action: 'delete', + targetId: targetUserId +}, req); +``` + +## Security Headers + +```typescript +// Add security headers middleware +import helmet from 'helmet'; + +app.use(helmet({ + contentSecurityPolicy: { + directives: { + defaultSrc: ["'self'"], + styleSrc: ["'self'", "'unsafe-inline'"], + scriptSrc: ["'self'"], + imgSrc: ["'self'", "data:", "https:"] + } + }, + hsts: { + maxAge: 31536000, + includeSubDomains: true, + preload: true + } +})); + +// Additional headers +app.use((req, res, next) => { + res.setHeader('X-Content-Type-Options', 'nosniff'); + res.setHeader('X-Frame-Options', 'DENY'); + res.setHeader('X-XSS-Protection', '1; mode=block'); + res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin'); + next(); +}); +``` + +## CORS Configuration + +```typescript +// Configure CORS securely +import cors from 'cors'; + +const allowedOrigins = process.env.CORS_ORIGIN?.split(',') || []; + +app.use(cors({ + origin: (origin, callback) => { + if (!origin || allowedOrigins.includes(origin)) { + callback(null, true); + } else { + callback(new Error('Not allowed by CORS')); + } + }, + credentials: true, + methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], + allowedHeaders: ['Content-Type', 'Authorization'], + exposedHeaders: ['X-Request-ID'], + maxAge: 86400 // 24 hours +})); +``` + +## Security Testing + +```typescript +// Security test patterns +describe('Security Tests', () => { + it('should prevent SQL injection', async () => { + const maliciousInput = "'; DROP TABLE users; --"; + const response = await request(app) + .get(`/api/v1/users?search=${encodeURIComponent(maliciousInput)}`) + .set('Authorization', `Bearer ${token}`); + + expect(response.status).not.toBe(500); + // Should return 400 or empty results, not crash + }); + + it('should prevent XSS attacks', async () => { + const xssPayload = ''; + const response = await request(app) + .post('/api/v1/users') + .send({ email: xssPayload, password: 'test123' }); + + // Response should sanitize or reject + expect(response.body.data?.email).not.toContain('