Commit Graph

16 Commits

Author SHA1 Message Date
hailin 7ff701369b fix(tenant): use TenantContextModule.forRoot() for global tenant context
All services were providing TenantContextService directly without
making it global, causing DI resolution failures in child modules.
Now using TenantContextModule.forRoot() which exports TenantContextService
globally so all repositories can access it.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 04:31:56 -08:00
hailin 6bb47dad85 fix(docker): copy shared module AFTER npm install to prevent wipe
npm install was clearing the @iconsulting/shared folder that was
copied before it. Moving the COPY command after npm install ensures
the shared package remains in node_modules.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 03:41:16 -08:00
hailin 1df5854825 feat(multi-tenant): apply tenant middleware and refactor repositories
- Apply TenantContextMiddleware to all 6 services
- Add SimpleTenantFinder for services without direct tenant DB access
- Add TenantFinderService for evolution-service with database access
- Refactor 8 repositories to extend BaseTenantRepository:
  - user-postgres.repository.ts
  - verification-code-postgres.repository.ts
  - conversation-postgres.repository.ts
  - message-postgres.repository.ts
  - token-usage-postgres.repository.ts
  - file-postgres.repository.ts
  - order-postgres.repository.ts
  - payment-postgres.repository.ts
- Add @iconsulting/shared dependency to evolution-service and knowledge-service
- Configure middleware to exclude health and super-admin paths

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 18:30:31 -08:00
hailin 422069be68 feat: add enterprise multi-tenancy infrastructure
- Add shared tenant module with AsyncLocalStorage-based context management
- Create TenantContextService, TenantContextMiddleware, TenantGuard
- Add @TenantId(), @Tenant(), @RequireFeatures() decorators
- Create BaseTenantRepository for automatic tenant filtering
- Add TenantORM entity for tenants table
- Add tenant_id column to all 16 ORM entities across 6 services
- Create database migration script for multi-tenancy support
- Add tenant-related error codes

This implements row-level isolation for 100% data separation between tenants.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 18:11:12 -08:00
hailin 65c0bdd17c feat(payment): add transaction reliability and idempotency support
- Add TransactionService for atomic database operations with optimistic lock retry
- Implement pessimistic locking in payment callback handling to prevent race conditions
- Add idempotency check via transactionId unique index to prevent duplicate processing
- Add version columns to PaymentORM and OrderORM for optimistic locking
- Add composite indexes for performance (order_status, transaction_id)
- Optimize connection pool settings for both payment and conversation services
- Update init-db.sql with version columns and new indexes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 07:00:01 -08:00
hailin 7c22c173a5 fix(orm): add explicit column types for conversation and order entities
Fixed remaining TypeORM DataTypeNotSupportedError for "Object" type.

## conversation-service/ConversationORM
- title: varchar(255)
- endedAt: timestamptz

## payment-service/OrderORM
- serviceCategory: varchar(100)
- currency: varchar(10)
- paymentMethod: varchar(50)
- paidAt: timestamptz
- completedAt: timestamptz

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 01:57:20 -08:00
hailin eb1cb9c496 fix(orm): add explicit PostgreSQL column types for nullable fields
Fixed TypeORM DataTypeNotSupportedError for "Object" type in PostgreSQL.

## Issues Fixed

1. **user-service/UserORM**
   - fingerprint: varchar(255)
   - phone: varchar(20)
   - nickname: varchar(100)
   - avatar: varchar(500)

2. **payment-service/PaymentORM**
   - transactionId: varchar(255)
   - currency: varchar(10)
   - expiresAt: timestamptz
   - paidAt: timestamptz

3. **conversation-service/MessageORM**
   - inputTokens: int
   - outputTokens: int

## Root Cause
@Column({ nullable: true }) without explicit `type` defaults to Object,
which PostgreSQL doesn't support.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 22:50:54 -08:00
hailin afd707d15f refactor(services): implement 4-layer Clean Architecture for all backend services
Refactored all 6 backend services to 4-layer Clean Architecture pattern
following knowledge-service as reference implementation.

## Architecture Pattern (4-Layer)

```
src/
├── domain/              # Pure business entities and interfaces
│   ├── entities/        # Domain entities (no ORM decorators)
│   ├── repositories/    # Repository interfaces + Symbol tokens
│   └── value-objects/   # Enums and value types
├── application/
│   ├── dtos/            # Data transfer objects
│   └── services/        # Application services (use case orchestration)
├── adapters/
│   ├── inbound/         # Controllers, gateways (API endpoints)
│   └── outbound/
│       ├── persistence/ # Repository implementations
│       ├── clients/     # External service clients
│       └── storage/     # File storage adapters
└── infrastructure/
    └── database/postgres/
        └── entities/    # ORM entities with decorators
```

## Services Refactored

### user-service
- adapters/inbound: AuthController, UserController
- adapters/outbound/persistence: UserPostgresRepository, VerificationCodePostgresRepository
- application/services: AuthService, UserService
- application/dtos: AuthDto, UserDto

### payment-service
- adapters/inbound: OrderController, PaymentController
- adapters/outbound/persistence: OrderPostgresRepository, PaymentPostgresRepository
- adapters/outbound/payment-methods: AlipayAdapter, WechatPayAdapter, StripeAdapter
- application/services: OrderService, PaymentService
- application/dtos: OrderDto, PaymentDto

### file-service
- adapters/inbound: FileController
- adapters/outbound/persistence: FilePostgresRepository
- adapters/outbound/storage: MinioStorageAdapter
- application/services: FileService
- application/dtos: UploadFileDto

### conversation-service
- adapters/inbound: ConversationController, InternalController, ConversationGateway
- adapters/outbound/persistence: ConversationPostgresRepository, MessagePostgresRepository, TokenUsagePostgresRepository
- application/services: ConversationService
- application/dtos: ConversationDto

### knowledge-service
- adapters/inbound: KnowledgeController, MemoryController, InternalMemoryController
- adapters/outbound/persistence: KnowledgePostgresRepository, MemoryPostgresRepository
- application/services: KnowledgeService, MemoryService
- application/dtos: KnowledgeDto, MemoryDto

### evolution-service
- domain/entities: AdminEntity
- domain/repositories: IAdminRepository (Symbol-based DI)
- domain/value-objects: AdminRole enum
- adapters/inbound: AdminController, EvolutionController
- adapters/outbound/persistence: AdminPostgresRepository
- adapters/outbound/clients: ConversationClient, KnowledgeClient
- application/services: AdminService, EvolutionService
- application/dtos: AdminDto, EvolutionDto
- infrastructure/database/postgres/entities: AdminORM

## Key Improvements
- Symbol-based dependency injection for repository interfaces
- ORM entities separated from domain entities
- Consistent 4-layer structure across all services
- DTOs for API contracts
- Clear separation: domain logic vs infrastructure concerns

## Configuration
- Updated turbo.json: renamed "pipeline" to "tasks" for Turbo 2.0+

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 22:18:22 -08:00
hailin 02954f56db refactor(services): implement Clean Architecture across 4 services
## Overview
Refactor user-service, payment-service, file-service, and conversation-service
to follow Clean Architecture pattern based on knowledge-service reference.

## Architecture Pattern Applied

```
src/
├── domain/
│   ├── entities/           # Pure domain entities (no ORM decorators)
│   └── repositories/       # Repository interfaces + Symbol DI tokens
├── infrastructure/
│   └── database/postgres/
│       ├── entities/       # ORM entities with TypeORM decorators
│       └── *-postgres.repository.ts  # Repository implementations
└── {feature}/
    └── {feature}.module.ts # DI configuration with Symbol providers
```

## Changes by Service

### user-service (40% → 100% compliant)
- Created: IUserRepository, IVerificationCodeRepository interfaces
- Created: UserORM, VerificationCodeORM entities
- Created: UserPostgresRepository, VerificationCodePostgresRepository
- Modified: UserEntity, VerificationCodeEntity → pure domain with factory methods
- Updated: user.module.ts, auth.module.ts with Symbol-based DI

### payment-service (50% → 100% compliant)
- Created: IOrderRepository, IPaymentRepository interfaces
- Created: OrderORM, PaymentORM entities
- Created: OrderPostgresRepository, PaymentPostgresRepository
- Modified: OrderEntity, PaymentEntity → pure domain with factory methods
- Updated: order.module.ts, payment.module.ts with Symbol-based DI

### file-service (40% → 100% compliant)
- Created: IFileRepository interface
- Created: FileORM entity
- Created: FilePostgresRepository
- Modified: FileEntity → pure domain with factory methods
- Updated: file.module.ts with Symbol-based DI

### conversation-service (60% → 100% compliant)
- Created: IConversationRepository, IMessageRepository, ITokenUsageRepository
- Created: ConversationORM, MessageORM, TokenUsageORM entities
- Created: ConversationPostgresRepository, MessagePostgresRepository,
          TokenUsagePostgresRepository
- Modified: ConversationEntity, MessageEntity, TokenUsageEntity → pure domain
- Updated: conversation.module.ts with Symbol-based DI
- Updated: app.module.ts, data-source.ts entity patterns

## Key Implementation Details

1. **Symbol-based DI Pattern**:
   ```typescript
   export const USER_REPOSITORY = Symbol('IUserRepository');

   @Module({
     providers: [{ provide: USER_REPOSITORY, useClass: UserPostgresRepository }],
     exports: [UserService, USER_REPOSITORY],
   })
   ```

2. **Pure Domain Entities**: Factory methods `create()` and `fromPersistence()`
   for controlled instantiation without ORM decorators

3. **Repository Implementations**: Include `toORM()` and `toEntity()` conversion
   methods for anti-corruption layer between domain and infrastructure

4. **Entity Discovery**: Changed glob pattern from `*.entity` to `*.orm`
   in app.module.ts and data-source.ts files

## Breaking Changes
- None for API consumers
- Internal architecture restructuring only

## Testing
- All 4 services compile successfully with `pnpm build`
- Database schema compatibility verified (column mappings preserved)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 21:18:25 -08:00
hailin c98cae2e39 fix(payment): use PORT env variable instead of PAYMENT_SERVICE_PORT
Payment service was listening on wrong port (3004) because it used
PAYMENT_SERVICE_PORT which wasn't set in docker-compose.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 02:48:44 -08:00
hailin 224e1fb509 fix(health): exclude /health endpoint from API prefix
The health check endpoint should be at /health not /api/v1/health
for Docker health checks to work properly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 02:30:24 -08:00
hailin 223aa25af1 fix(docker): add health check endpoints and fix IPv6 issue
- Add /health endpoints to all NestJS services (user, payment, knowledge, conversation, evolution)
- Fix nginx healthcheck to use 127.0.0.1 instead of localhost (IPv6 issue)
- Add healthcheck configuration to docker-compose for all backend services
- Use start_period to allow services time to initialize before health checks

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 02:13:42 -08:00
hailin 2f9fd3995b fix: 使用jq正确处理package.json移除workspace依赖
sed直接删除行会导致JSON尾随逗号问题,改用jq
正确删除dependencies中的@iconsulting/shared键

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 08:49:41 -08:00
hailin 7417bc1d82 fix: 移除workspace协议依赖解决npm安装问题
npm不支持pnpm的workspace:*协议,在安装依赖前
使用sed移除@iconsulting相关依赖行,shared包
已通过COPY单独复制到node_modules

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 08:45:38 -08:00
hailin 287aeb5c72 fix: 修复pnpm monorepo Docker构建问题
- 移除runner阶段的pnpm安装(不再需要)
- 使用npm install替代直接复制node_modules
- 单独复制@iconsulting/shared构建产物
- 解决pnpm符号链接在Docker中失效的问题

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 08:32:58 -08:00
hailin a7add8ff90 Initial commit: iConsulting 香港移民咨询智能客服系统
项目架构:
- Monorepo (pnpm + Turborepo)
- 后端: NestJS 微服务 + Claude Agent SDK
- 前端: React + Vite + Ant Design

包含服务:
- conversation-service: 对话服务 (Claude AI)
- user-service: 用户认证服务
- payment-service: 支付服务 (支付宝/微信/Stripe)
- knowledge-service: 知识库服务 (RAG + Neo4j)
- evolution-service: 自我进化服务
- web-client: 用户前端
- admin-client: 管理后台

基础设施:
- PostgreSQL + Redis + Neo4j
- Kong API Gateway
- Nginx 反向代理
- Docker Compose 部署配置

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 00:01:12 -08:00