355 Commits

Author SHA1 Message Date
wangdl
616d7099ce fix: correct Feynman empty-DTO test to match actual behavior
Some checks failed
Deploy API Server / build-and-deploy (push) Has been cancelled
2026-06-19 22:37:29 +08:00
wangdl
5d332336eb feat(M-AI-01-09): add HTTP E2E tests (Feynman/ActiveRecall/DocumentImport)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
- NEW test/m-ai-01-09-api-e2e.worker-int-spec.ts: real HTTP endpoints
  with JWT auth → Controller → BullMQ → Worker → MySQL
- Feynman: POST /api/ai-analysis/feynman (200/401/400)
- Active Recall: POST /api/active-recalls/:id/submit (200/401/404)
- Document Import: POST /api/imports (200/401)
- generateJWT() in integration-harness.ts (TokenService format)
- httpPost() supports optional Bearer token
- Save test credentials to devops-projects/凭据配置/测试API凭据.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 22:36:17 +08:00
wangdl
bbef7eac1d fix(M-AI-01-09): strengthen SIGKILL recovery + Document Import assertions
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
- SIGKILL: enqueue job BEFORE kill, wait for pickup, verify recovery
- Document Import: track before/after KnowledgeItem IDs to prove
  Worker created them (not direct DB INSERT)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 22:23:42 +08:00
wangdl
5bde0a3656 fix(M-AI-01-09): enqueue jobs via BullMQ instead of MySQL INSERT
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
Worker consumes from BullMQ Redis, not MySQL polling.
Replace all dbExec(INSERT INTO AiAnalysisJob) with enqueueJob()
which uses real BullMQ Queue.add() to the test Redis.

Add setRedisConfig() + enqueueJob() to integration harness.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 22:20:45 +08:00
wangdl
bda7f9d80a fix: BigInt comparison in MySQL test
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 49s
2026-06-19 22:15:39 +08:00
wangdl
cb9b56f0dc fix: remove status from AiAnalysisResult query (column doesn't exist)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 48s
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 22:14:07 +08:00
wangdl
6e7f4b0219 fix: add updatedAt=NOW() to all INSERTs for NOT NULL columns
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 48s
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
EOF
)
2026-06-19 22:12:20 +08:00
wangdl
533b525496 fix: schema field corrections for AiAnalysisJob + User
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
- User INSERT: add updatedAt=NOW() (NOT NULL, no default)
- AiAnalysisJob: retryCount→progress (column doesn't exist)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 22:10:07 +08:00
wangdl
cc7a6842ed fix: standardize dbExec/dbQuery param passing as arrays
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 22:08:17 +08:00
wangdl
ffea415613 feat(M-AI-01-09): replace mock E2E with real API/Worker integration test
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 49s
- NEW test/helpers/mock-ai-provider.ts: Mock AI HTTP server with
  normal/timeout/429/500/invalid-json behavior controls
- NEW test/helpers/integration-harness.ts: spawn real API/Worker
  processes, HTTP helpers, PrismaClient-based DB helpers
- NEW test/m-ai-01-09.worker-int-spec.ts: real integration test
  using actual MySQL/Redis/BullMQ/HTTP (Active Recall, Feynman,
  Document Import, SIGKILL recovery, provider faults, idempotency)
- NEW test/jest-worker-integration.json: Jest config with NO mocks
- DELETE test/m-ai-01-09.e2e-spec.ts: removed mock-based pseudo-e2e
- UPDATE test/run-integration-ci.sh: uses real integration config
- UPDATE package.json: test:integration:worker uses real config

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 22:06:52 +08:00
wangdl
762a9c1791 fix: use TestingModule as application context, fix $executeRaw
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
- TestingModule.compile() returns an application context directly
- Use $executeRaw tagged template instead of $executeRawUnsafe
- Add jest.setTimeout(30000) for integration tests

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 21:54:31 +08:00
wangdl
cfa882a9e9 fix: rename integration test to .e2e-spec.ts for jest-e2e.json matching
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 21:52:40 +08:00
wangdl
421689cdcd feat: M-AI-01-09 integration test suite + CI runner
Some checks failed
Deploy API Server / build-and-deploy (push) Has been cancelled
- test/m-ai-01-09-integration.spec.ts: Active Recall/Feynman/Document Import
  E2E tests with real MySQL/Redis/BullMQ
- test/run-integration-ci.sh: CI script (MySQL→Prisma→Build→API→Worker→Test)
- npm run test:integration:worker: one-command integration test
- Includes Active Recall chain audit (actual code paths with file:line)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 21:52:04 +08:00
wangdl
347e0487d9 fix: remove non-existent POST /api/notifications/test from integration script
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 44s
Notification jobs are triggered implicitly by notifyJobComplete() during
Active Recall analysis, not by a dedicated test endpoint. Script now
checks Worker logs and DB records instead.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 21:38:12 +08:00
wangdl
24ceb1353e fix: remove ProtectSystem/ReadWritePaths from systemd units
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
ProtectSystem=strict requires /run/systemd/unit-root paths to exist
which fails on production. Worker only needs network access (Redis/MySQL).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 21:26:47 +08:00
wangdl
bd60c2786f fix: correct require paths for dist/src output + systemd user
Some checks failed
Deploy API Server / build-and-deploy (push) Has been cancelled
- worker.main.ts: require('../../package.json') for dist/src/ location
- worker-heartbeat.service.ts: require('../../../package.json') + try/catch
- systemd units: User=ubuntu (www-data not present on production)
- EnvironmentFile: /opt/zhixi/env/.env.production

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 21:26:05 +08:00
wangdl
cdc228ccf0 fix: break circular dependency between queue-definitions and queue-service
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
Extract queue name constants to queue.constants.ts to resolve
the require cycle that caused 'Cannot read properties of undefined'
at startup. Both queue-definitions.ts and queue.service.ts now
import from the shared constants file.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 21:24:33 +08:00
wangdl
4fb652d273 feat: M-AI-01 Worker 进程边界与部署收口(全 8 个 Issue)
Some checks failed
Deploy API Server / build-and-deploy (push) Failing after 39s
M-AI-01-01: ADR-001 统一 AI 架构决策记录 + 附录 A 依赖闭包审计
M-AI-01-02: Worker 执行依赖闭包审计(附录 A 文档)
M-AI-01-03: 分离 AppModule/WorkerModule Processor 注册
M-AI-01-04: 统一 Queue Definition Registry + 环境变量覆盖
M-AI-01-05: 独立 Worker 启动与生命周期(instanceId/校验/优雅关闭)
M-AI-01-06: Docker + systemd 部署拓扑(unit 文件 + 回滚文档)
M-AI-01-07: Worker Heartbeat(Redis TTL 90s)+ Admin 在线状态 API
M-AI-01-08: 集成验收脚本

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 21:22:48 +08:00
wangdl
56315e454b docs: fix appendix A line numbers and NotificationWorker dependency chain
- AiAnalysisWorker in worker.module.ts: line 62→64
- NotificationWorker: verified complete dependency chain (NotificationsService→NotificationsRepository+EventBusService(@Optional))
- Removed resolved "unconfirmed" item from section 六

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 20:31:08 +08:00
wangdl
54bc505f7a docs: add ADR-001 unified AI architecture decision record
Freeze the architecture decision for 8-batch unified AI migration.
Covers current/target topology, API/Worker process boundaries,
5 Processors, Heavy Runtime disposition, phase-1 non-goals,
rollback principles, and cross-batch constraints.

Includes Appendix A: worker dependency closure audit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 20:10:35 +08:00
wangdl
d7647cbc3d fix: move all-sources route before :id to avoid conflict
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 48s
2026-06-19 15:38:32 +08:00
wangdl
178666627b feat: add GET /admin-api/knowledge-bases/all-sources
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
2026-06-19 15:31:03 +08:00
wangdl
1abc89be23 fix: add enrichWithNames to chat sessions API
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
2026-06-19 13:30:09 +08:00
wangdl
9a392ba274 fix: add enrichWithNames to content-safety checks
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 48s
2026-06-19 13:27:10 +08:00
wangdl
0203ccfd1f fix: translate learning record titles to Chinese
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 49s
2026-06-19 13:20:29 +08:00
wangdl
0ea36a7073 feat(API-ADMIN-010): add enrichWithNames to admin list controllers
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 50s
- New shared helper: src/common/helpers/name-resolver.ts
- Applied to: reviews, users/members, files, knowledge-bases, imports
- Learning service refactored to use shared helper

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 13:04:55 +08:00
wangdl
ff4135b7c6 feat: add enrichWithNames to admin learning API
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 50s
All list endpoints now return userName, kbName, materialName
resolved from User, KnowledgeBase, KnowledgeSource tables.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 12:41:46 +08:00
wangdl
af8d95cdb6 fix: add try-catch + error logging to processBatch
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 48s
Prevents 500 from crashing the entire batch. Logs the actual error
to server log for debugging.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 12:18:46 +08:00
wangdl
fb7ee358ce fix: add knowledgeBaseId to ReadingEventUploadItemDto + increase Max delta
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
iOS sends knowledgeBaseId in batch upload but DTO didn't have it,
causing forbidNonWhitelisted to reject with 400.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-19 12:15:56 +08:00
wangdl
43293a48e6 fix: return 'id' instead of 'jobId' in POST /imports response
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
iOS ImportStatusResponse expects 'id' field. The mismatch caused
DecodingError.keyNotFound on the client side.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 22:27:02 +08:00
wangdl
aef8e2a416 fix: make import lock unique per attempt + release in finally
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
- Add timestamp to lock key to prevent blocking retries
- Wrap create logic in try-finally to always release lock
- Reduce lock TTL from 30min to 5min

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 22:17:59 +08:00
wangdl
433e0095ee debug: add detailed logging to DocumentImportService.createImport
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 49s
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 22:16:17 +08:00
wangdl
4f614f9d1f fix: extract userId from JWT in POST /imports controller
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
DocumentImport.userId is a required foreign key, but the iOS app
doesn't send it. Extract from JWT via @CurrentUser() decorator
and pass to service.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 22:13:10 +08:00
wangdl
0867b4f39a feat(API-AI-082): add POST /sources/:id/parse trigger endpoint
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
Allows users to manually retry source parsing by creating a new
DocumentImport job and enqueuing it. Returns jobId for polling.

Route: POST /knowledge-bases/:kbId/sources/:id/parse

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 21:56:31 +08:00
wangdl
939adcebd3 feat(API-AI-081): add KnowledgeItem.sourceId FK to KnowledgeSource
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 43s
- Prisma schema: add sourceId field + @relation to KnowledgeSource
- KnowledgeSource: add items[] reverse relation + @index on sourceId
- KnowledgeItemsRepository: accept sourceId in create()
- ImportCandidateService.accept(): pass sourceId to create()
- DocumentImport worker: pass sourceId alongside sourceRef

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 21:54:58 +08:00
wangdl
76bdba330d fix(API-AI-080): enqueue import job + pass sourceId in KnowledgeSource pipeline
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 43s
KnowledgeSourceService.addSource() was creating Source + DocumentImport
records but never enqueuing the job for processing. Also the worker
wasn't linking created KnowledgeItems back to their source.

Changes:
- Inject QueueService + RedisService into KnowledgeSourceService
- Enqueue document-import job after creating Source + DocumentImport
- Set Redis status keys (matching DocumentImportService pattern)
- Worker: resolve sourceId from job data or DocumentImport record
- Worker: pass sourceRef when creating KnowledgeItems

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 21:51:49 +08:00
wangdl
137fe36a72 fix: enable implicit conversion in StrictValidationPipe
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
Query string params (page=1&limit=5) arrive as strings but DTOs expect
@IsInt(). enableImplicitConversion tells class-transformer to auto-cast
types based on the DTO decorators.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 19:27:40 +08:00
wangdl
82e3a60101 refactor: merge admin/learning into admin-api/learning, restore API isolation
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
- Move AdminLearningService + DTOs to learning-session module
- Merge 21 new endpoints into existing admin-api/learning controller
- Add analysis and ai-usage methods to unified service
- Delete admin-learning module (no longer needed)
- Revert JwtAuthGuard /api/admin bypass (was breaking isolation)
- Fix: /api/* now exclusively serves user/iOS traffic again

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 19:26:37 +08:00
wangdl
04da939a22 fix: correct admin path bypass in global JwtAuthGuard
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
request.path includes the global 'api' prefix, so /admin/learning
routes appear as /api/admin/learning. Bypass /api/admin in addition
to existing /admin-api and /internal paths.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 19:00:38 +08:00
wangdl
bc11adfbac fix: allow /admin/ paths through global JwtAuthGuard
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
Global JwtAuthGuard was blocking /admin/learning/* requests before
AdminAuthGuard could process x-api-key. Now bypasses all /admin/*
paths (not just /admin-api/*), letting controller-level admin auth
handle those routes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 18:58:56 +08:00
wangdl
ed2dcb02f6 feat: add AdminApiKey permanent token for automated testing
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 50s
- Add AdminApiKey model (keyHash, expiresAt nullable for permanent)
- Extend AdminAuthGuard to accept x-api-key header as fallback auth
- Seed creates test-admin@zhixi.com with permanent SUPER_ADMIN API key
- Key format: zxat_<64 hex chars>, stored as SHA-256 hash

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 18:52:04 +08:00
wangdl
c3fd6a221f fix: add missing /api/admin/learning/knowledge-bases endpoint
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
Dashboard filter dropdown calls this to populate KB selector.
Returns knowledge bases that have reading event data with real titles.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 18:40:40 +08:00
wangdl
c0a8f7ef27 perf: add missing indexes + fix learning admin query performance
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
- Add 10 missing DB indexes across 5 tables (LearningSession,
  ReadingEvent, MaterialReadingProgress, DailyLearningActivity,
  LearningRecord) to eliminate full-table scans on count queries
- Dashboard: accept knowledgeBaseId/dateRange filters from frontend
- getAnomalies: add skip-based pagination, remove redundant counts
- Remove duplicate AdminReadingController to fix route collision
  on admin/learning prefix

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 18:20:44 +08:00
wangdl
1ed86b3ab3 docs: add API-OPS-001 missing production env keys issue
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 15:38:48 +08:00
wangdl
161018dcb5 fix: align heavy-runtime env vars with Rust RUNTIME_ prefix
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
- MAX_CONCURRENCY → RUNTIME_MAX_CONCURRENCY
- POLL_INTERVAL_MS → RUNTIME_POLL_INTERVAL_MS
- JOB_TIMEOUT_SECONDS → RUNTIME_JOB_TIMEOUT_SECONDS

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 14:12:20 +08:00
wangdl
c99626e5de ci: add database migration automation workflow (API-AI-079)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 43s
- 3-stage: validate → dry-run → deploy-migration
- validate: prisma format check, client generation verification
- dry-run: MySQL service container, db push + migrate deploy + status
- deploy-migration: manual trigger, SSH migrate deploy with pre/post status
- Triggered on schema.prisma or migrations/** changes

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 14:02:48 +08:00
wangdl
781645de84 ci: add health check + rollback hint to deploy step
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
- Record previous docker images before deploy
- Health check loop: 12 attempts × 5s = 60s total
- On failure: warning + previous images printed for manual rollback

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 14:01:33 +08:00
wangdl
f33812cf7b ci: add GitHub Actions CI/CD pipeline (API-AI-078)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
- 5-stage pipeline: lint → test → build → docker-build → deploy
- lint: ESLint with npx prisma generate
- test: Jest with passWithNoTests, artifact upload
- build: NestJS build + dist verification
- docker-build: multi-stage Docker build for api + worker
- deploy: main-only, docker push + SSH deploy with prisma migrate

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 13:57:46 +08:00
wangdl
094f00553a feat: production docker-compose with health checks + resource limits (API-AI-077)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
- Add health checks: api (GET /health), worker, heavy-runtime, nginx
- Add resource limits (deploy.resources) for all 6 services
- Add heavy-runtime service (Rust AI Worker)
- Add INTERNAL_API_KEY + CREDENTIAL_ENCRYPTION_KEY env vars
- nginx health check via GET /health

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 13:53:24 +08:00
wangdl
5c7b8d1855 docs: add API reference with error codes, rate limiting, changelog (API-AI-076)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
- Complete error code enumeration: Internal API + User API + Runtime errors
- Rate limiting: user quota, platform circuit breaker, global throttle
- Changelog: v1.0.0 initial → v1.1.0 current with all changes
- Integration examples: heartbeat cancel detection, job creation idempotency

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 13:49:45 +08:00