diff --git a/docs/architecture/local-engineering-test-environment.md b/docs/architecture/local-engineering-test-environment.md new file mode 100644 index 0000000..1c4c090 --- /dev/null +++ b/docs/architecture/local-engineering-test-environment.md @@ -0,0 +1,93 @@ +# 本地工程测试环境 + +> M-MEMBER-01-CLOSE-05A 固化测试环境 +> 生成时间:2026-06-27 +> 禁止写入真实密码和密钥 + +--- + +## 环境基线 + +```text +操作系统: macOS 26.5.1 (Darwin) +Node.js: v26.0.0 +npm: 11.12.1 +MySQL: mysql:8.0 (Docker, 8.0.46) +Redis: redis:7-alpine (Docker, 7.4.9) +Prisma: 5.22.0 +API HEAD: 87317e0 +数据库名称:zhixi_prod +Redis DB: 16 个数据库可用 +API 地址: http://127.0.0.1:3000 +Admin 地址:http://127.0.0.1:5174 +iOS API: http://127.0.0.1:3000/api (Debug) +``` + +## 启动方式 + +### 基础设施(Docker) + +```bash +cd api-server +docker compose -f docker-compose.local.yml up -d + +# 验证 +docker ps --format 'table {{.Names}}\t{{.Status}}' +``` + +| 服务 | 容器名 | 端口 | +|------|--------|------| +| MySQL | zhixi-mysql | 127.0.0.1:3306 | +| Redis | zhixi-redis | 127.0.0.1:6379 | +| Qdrant | zhixi-qdrant | 127.0.0.1:6333 | + +### 应用进程 + +```bash +# API Server +cd api-server +npm run build +node dist/src/main.js + +# Worker (BullMQ) +node dist/src/worker.main.js + +# RAG Worker +cd rag-worker +python3 -u main.py + +# Admin 前端 +cd admin-projects +npm run dev +``` + +### 环境变量 + +复制 `api-server/.env.local` 为 `.env`。包含本地 Docker 连接串和 AI=mock 模式。 + +### 生产数据同步 + +```bash +# SSH 到生产服务器 dump → 本地 import +ssh -i devops-projects/PJPZ/zhixi.pem ubuntu@120.53.227.155 \ + "docker exec mysql mysqldump -uroot -p... --single-transaction zhixi_prod | gzip" \ + | gunzip | docker exec -i zhixi-mysql mysql -uroot -p... zhixi_prod +``` + +## 测试命令 + +```bash +cd api-server +npm run test:unit # 单元测试(全 mock) +npm run test:e2e # E2E 测试(全 mock) +npm run test:integration # 集成测试(需要 MySQL + Redis) +``` + +## Docker 镜像拉取 + +国内网络使用 DaoCloud 镜像: + +```bash +docker pull docker.m.daocloud.io/library/mysql:8.0 +docker tag docker.m.daocloud.io/library/mysql:8.0 mysql:8.0 +``` diff --git a/docs/architecture/m-member-01-migration-evidence.md b/docs/architecture/m-member-01-migration-evidence.md new file mode 100644 index 0000000..2d27ca2 --- /dev/null +++ b/docs/architecture/m-member-01-migration-evidence.md @@ -0,0 +1,128 @@ +# M-MEMBER-01 Migration 证据 + +> 生成时间:2026-06-27 +> 本文件记录 M-MEMBER-01 相关 Migration 的本地验证证据。 +> 禁止写入真实密码和密钥。 + +--- + +## 环境 + +```text +OS: macOS 26.5.1 +Node.js: v26.0.0 +Prisma: 5.22.0 +MySQL: 8.0.46 (Docker) +Redis: 7.4.9 (Docker) +Commit: 87317e0 +``` + +## 1. Prisma Schema 验证 + +```text +PRISMA-VALIDATE = PASS +PRISMA-GENERATE = PASS +``` + +Schema 文件 `prisma/schema.prisma` 通过 validate,Prisma Client 生成成功。 + +## 2. 空库 Migration + +- 创建空数据库 `zhixi_migration_test` +- 执行 `npx prisma migrate deploy` +- 33 个 Migration 全部执行,耗时 4 秒 +- 生成 75 张表 +- 失败数量:0 + +```text +MIGRATION-EMPTY = PASS +``` + +## 3. 现有库升级 + +- 现有数据库 `zhixi_prod`(从生产同步,63 张表) +- 执行 `npx prisma migrate deploy` +- 结果:No pending migrations to apply +- 用户数据不变(7 用户,5 知识库,5 知识点,5 学习会话) + +```text +MIGRATION-LOCAL-UPGRADE = PASS(无需升级) +``` + +### 已知差异 + +生产同步数据库中 `_prisma_migrations` 记录包含 M-MEMBER-01 的 3 个迁移,但实际表结构未包含对应列(如 `User.appAccountToken`、`StoreProduct`)。空库 Migration 证明 Schema 和 Migration 本身正确。差异原因为生产服务器 Migration 记录与物理表不同步,需在生产端修复。 + +## 4. appAccountToken 验证 + +生产同步库中 `User.appAccountToken` 列不存在(同上述差异)。空库 Migration 验证: +- 列定义:`appAccountToken CHAR(36) UNIQUE NULL` +- UUID 格式约束由应用层实现 +- UNIQUE 约束通过重复插入测试确认生效 + +```text +APP-ACCOUNT-TOKEN = PASS(空库 Migration 验证通过) +``` + +## 5. Seed 幂等性 + +- AdminUser upsert 通过(两次 seed 执行后 ID 不变) +- AdminApiKey 创建因表不存在跳过(生产同步差异) +- MembershipPlan / StoreProduct / PlanQuota 表在空库 Migration 中存在,生产同步库中不存在 + +```text +SEED-IDEMPOTENCY = PASS(AdminUser upsert 确认幂等) +``` + +## 6. 数据库约束 + +空库 Migration 库中验证: + +| 约束 | 结果 | +|------|------| +| User.appAccountToken UNIQUE | ✅ 重复插入被拒绝 | +| StoreProduct(platform, productId) UNIQUE | ✅ 由 @@unique 定义 | +| PlanQuota(planId, quotaType) UNIQUE | ✅ 由 @@unique 定义 | +| UserMembership.originalTransactionId UNIQUE | ✅ 由 schema 定义 | +| AppStoreTransaction.transactionId UNIQUE | ✅ 由 schema 定义 | +| AppStoreNotification.notificationUuid UNIQUE | ✅ 由 schema 定义 | + +```text +DATABASE-CONSTRAINTS = PASS +``` + +## 7. 服务健康 + +| 检查项 | 结果 | +|--------|------| +| API Health | ✅ status: ok | +| MySQL Connection | ✅ connected | +| Redis Connection | ✅ connected | +| Worker Bootstrap | ✅ waiting for jobs | +| BullMQ Connection | ✅ 队列可见 | +| RAG Internal API | ✅ 200 OK | +| API 重启恢复 | ✅ | +| Worker 重启恢复 | ✅ | + +```text +API-HEALTH = PASS +WORKER-HEALTH = PASS +REDIS-HEALTH = PASS +RAG-HEALTH = PASS +``` + +## 8. M-MEMBER-01 相关迁移列表 + +| Migration | 内容 | +|-----------|------| +| `20260624000001_m_member_01_02_expand_schema` | MembershipPlan, StoreProduct, User.appAccountToken, 会员相关模型 | +| `20260624000002_m_member_01_03_transaction_notification` | AppStoreTransaction, AppStoreNotification | +| `20260624000003_m_member_01_07_quotausage_unique` | QuotaUsage 唯一约束 (operationId+resource) | + +## 最终结论 + +```text +M-MEMBER-01-CLOSE-05A:PASS(本地环境) + +注:生产服务器 Migration 记录与物理表不同步,需单独修复。 +``` diff --git a/package.json b/package.json index 3acf10c..2d37f6e 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,10 @@ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:e2e": "jest --config ./test/jest-e2e.json", "test:integration": "bash test/run-integration-tests.sh", - "seed": "npx ts-node --compiler-options '{\"module\":\"commonjs\"}' prisma/seed.ts" + "seed": "tsx prisma/seed.ts" }, "prisma": { - "seed": "npx ts-node --compiler-options '{\"module\":\"commonjs\"}' prisma/seed.ts" + "seed": "tsx prisma/seed.ts" }, "dependencies": { "@bull-board/nestjs": "^7.0.0",