328 Commits

Author SHA1 Message Date
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
wangdl
4a69d14047 test: add integration tests for snapshot-builder.service (API-AI-068)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 44s
- 59 tests covering buildSnapshot full flow + all computational methods
- buildSnapshot: defaults, privacy flags, priority rules, DB persistence, error logging
- Scope routing: material vs knowledge_base session queries
- Computational methods: weightedQuizScore, weightedReviewScore, AIScore,
  weakPointSeverity, quizTrend, compositeMastery, classifyMasteryLevel
- Quality: normalizeQualityPreference, getScoreWeights presets
- Device: mapPlatformCategory, computeSwitchFrequency, mapDeviceTaskSuitability
- Helpers: modeOf, buildAllowedFields, countBy, computeSignals

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 12:23:52 +08:00
wangdl
3e43b2b52d test: add unit tests for runtime-internal.controller (API-AI-067)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 43s
- 12 tests covering all 9 endpoints + instanceId extraction
- instanceId: from header / default "unknown"
- pollJobs: limit default 5, capabilities pass-through
- lockJob/heartbeatJob: runtimeInstanceId fallback from dto→header
- getSnapshot: direct delegation
- resolveCredential: all fields + undefined credentialId
- submitResult/submitFailure: entire dto pass-through
- submitInvocationLogs: logs array extraction

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 12:19:06 +08:00
wangdl
5fbd437232 test: add unit tests for credential-encryption.service (API-AI-066)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
- 17 tests covering encrypt/decrypt/hash/mask/redact + config error
- encrypt↔decrypt round-trip, random IV, base64, empty, unicode
- hash: deterministic, different inputs, empty string
- mask: long keys (4+****+4), short keys (2+****), edge cases
- redact: sk- token replacement, no-op, short sk- skip, empty
- Missing CREDENTIAL_ENCRYPTION_KEY throws on encrypt/decrypt

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 12:16:53 +08:00
wangdl
4713758344 test: add unit tests for platform-budget.service (API-AI-065)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
- 15 tests covering all 6 public methods
- checkPlatformBudget: healthy, auto-create, circuit-open, half-open limit,
  half-open pass, token exceeded, cost exceeded
- recordSuccess: upsert with reset circuit to closed
- recordFailure: increment failedCount, open circuit at threshold, first-day create
- Admin: transitionToHalfOpen / closeCircuit
- getBudgetState: state + limits, auto-create fallback

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 12:15:20 +08:00
wangdl
c433b3dc5d refactor: split shared mockFindUnique into settings/usage mocks in quota tests
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 43s
- userAiSettings.findUnique → mockSettingsFindUnique
- userAiUsageDaily.findUnique → mockUsageFindUnique
- Eliminates order-dependency of mockResolvedValueOnce chains

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 12:14:33 +08:00
wangdl
9c7247aa90 test: add unit tests for user-ai-quota.service (API-AI-064)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 48s
- 15 tests covering all 4 public methods
- checkQuota: pass under limits, defaults, null usage, job/token exceeded
- incrementJobCount: correct upsert params, apiKeyMode routing
- recordTokenUsage: all token fields, costEstimate default=0
- getUsage: both modes parallel, defaults for null records, mixed

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 12:12:57 +08:00
wangdl
1a5e040ed8 test: add unit tests for user-ai.controller (API-AI-063)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
- 34 tests covering all 28 endpoints
- Profile: GET/PUT with null→{} fallback
- Settings: GET/PUT delegation
- Credentials: CRUD + test (6 endpoints)
- Analysis Jobs: create/cancel/get/list with query filters
- Publish: quiz + flashcard
- Analysis Results: getAnalysis/listAnalyses/listRecommendations/listWeakPoints
- Quizzes: get/getQuestions/list with filters
- Reanalysis/Notifications/Feedback/Flashcards
- Fix: getProfile ?? {} now awaits before null-coalescing

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 11:57:38 +08:00
wangdl
e16b970a2c docs: sync internal API protocol with heartbeat & snapshot changes
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 49s
- 4.3 Heartbeat: 204→200, add { jobId, lockUntil, cancelRequested } response
- 4.4 Get Snapshot: auto-rebuild replaces SNAPSHOT_EXPIRED/SNAPSHOT_NOT_FOUND
- 3. Error codes: drop SNAPSHOT_EXPIRED, mark SNAPSHOT_NOT_FOUND as deprecated
- 4.7 Submit Failure: add JOB_CANCELLED handling rule

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 11:54:48 +08:00
wangdl
b0e9796acb fix: use ConfigService for DeepSeek base URL in testCredential
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 43s
- Replace hardcoded 'https://api.deepseek.com/v1/models' with config lookup
- Single source of truth via ai.deepseek.baseUrl (DEEPSEEK_BASE_URL env)
- Add ConfigService dep to UserAiService constructor + test mock

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 11:47:59 +08:00
wangdl
cb24e5fb96 fix: job-reaper batch-loop instead of single take:500 to avoid missing jobs
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
- Replace single findMany(take:500) with cursor-based while loop
- REAP_BATCH_SIZE=500 constant; processes all stuck running + expired jobs
- Prevents missing jobs when >500 are stuck simultaneously
- Update tests: reset mocks before custom chains, explicit call ordering

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 11:45:36 +08:00
wangdl
c0594c518d test: add concurrent resolveSnapshot race test (API-AI-R01)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
- Simulates two concurrent getSnapshot calls with no valid snapshot
- Documents the known race: both trigger buildSnapshot, second update overwrites first
- Verifies both calls complete without error (accepted-risk behavior)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 11:41:35 +08:00
wangdl
7725b3d2ea perf: replace N+1 dedup queries with batch pre-fetch in convertCandidates
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
- convertQuizCandidates: batch findMany all stems before loop, dedup in-memory
- convertFlashcardCandidates: batch findMany all fronts before loop, dedup in-memory
- 50 items now = 1 query instead of 50
- Update tests: mock findMany instead of per-item findFirst

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 11:40:41 +08:00
wangdl
c2e5590718 fix: add observability to fire-and-forget persistResult & notifyJobComplete
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 44s
- Add static counters: persistResultFailures, notifyFailures
- Replace .catch(() => {}) with logger.error + counter increment
- Add error-path unit tests for both counter increments
- Reset counters in beforeEach for test isolation

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 11:38:30 +08:00
wangdl
7aea03f6e0 fix: clarify quota check is read-only, prevent refactoring pitfalls
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
- Rename checkAndReserve→checkQuota (method only reads, does not reserve)
- Add doc comment: incrementJobCount is the actual quota reservation
- Update user-ai.service.spec.ts references
- Add comments for apiKeyMode/credentialId reassignment in budget fallback

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 11:36:01 +08:00
wangdl
c88af39673 feat: AI Runtime 完整业务逻辑实现
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
- runtime-internal.service: resolveSnapshot 自动重建、persistResult 5种jobType持久化、validateOutput 校验、convertQuizCandidates/convertFlashcardCandidates 候选转换、notifyJobComplete 通知、JOB_CANCELLED处理、heartbeat 双阶段更新+取消检测
- user-ai.service: createAnalysisJob 11步流程、cancelJob、publishQuiz/publishFlashcard、getAnalysis/listAnalyses等
- user-ai.controller: 20+ 用户API端点
- 新增服务: SnapshotBuilderService、PriorityRulesService、SnapshotCleanupService、JobReaperService
- 新增模块: admin-learning (CRUD管理)
- Prisma schema: cancelRequestedAt/cancelledAt/sourceBlockIds 字段、expiresAt 索引
- 文档: ai-runtime-user-api.md、Issue 记录

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-18 11:22:03 +08:00
wangdl
eba9632a4e test: sync runtime-internal.service tests with current implementation (API-AI-062)
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 11:12:02 +08:00
wangdl
02979e3c24 test: add unit tests for runtime-internal.service (API-AI-062)
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-18 11:03:23 +08:00
wangdl
012e26b950 feat: API-Runtime 版本兼容协议 (API-AI-072)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
- pollJobs: 记录/更新 RuntimeInstance (capabilities + heartbeat)
- submitResult: 校验 schemaVersion 匹配 job.outputSchemaVersion
- heartbeat: 首次调用设置 startedAt
- 错误码: RESULT_SCHEMA_UNSUPPORTED + RUNTIME_VERSION_INCOMPATIBLE

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:42:02 +08:00
wangdl
00ac32a103 feat: 平台 AI 预算、成本熔断与全局限流 (API-AI-071)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 45s
- PlatformBudgetService: checkPlatformBudget / recordSuccess / recordFailure
- 熔断器: closed → open (连续失败N次) → half_open (限制任务数) → closed
- 平台日 token 预算 + 成本预算检查
- Admin 接口: transitionToHalfOpen / closeCircuit / getBudgetState
- PlatformAiBudgetDaily 已存在于 Prisma schema

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:40:47 +08:00
wangdl
cc2ccbad59 fix: audit fixes for Runtime Internal API
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
1. heartbeat: locked→running transition on first heartbeat
2. submitResult: validate job is locked/running before accepting
3. submitFailure: validate job is locked/running before accepting
4. resolveCredentialForJob: update lastUsedAt on credential
5. pollJobs: filter by capabilities (snapshotVersion + outputSchemaVersion)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:38:44 +08:00
wangdl
5cbf20046a feat: 用户 AI 消费额度与日限流 (API-AI-070)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 43s
- UserAiQuotaService: checkAndReserve / incrementJobCount / recordTokenUsage
- 创建 Job 前检查 maxDailyAiJobs + maxDailyTokenBudget
- Runtime 调用后更新 UserAiUsageDaily token 消耗
- user_deepseek_key 不计入平台 token 预算
- 超限返回 DAILY_JOB_LIMIT_EXCEEDED / DAILY_TOKEN_BUDGET_EXCEEDED

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:25:18 +08:00
wangdl
43e6e9029c feat: Runtime Internal API (API-AI-028~034)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 46s
- RuntimeInternalController: 7 个 /internal/runtime/* 端点
- RuntimeInternalService: Poll/Lock/Heartbeat/Snapshot/Credential/Result/Fail/Log
- 复用 InternalAuthGuard + x-runtime-instance-id 追踪
- Job lock 防并发 (updateMany WHERE status=pending)
- Result 幂等 (resultIdempotencyKey)
- Failure retryable/non-retryable 处理

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 21:23:52 +08:00
wangdl
87fe180874 fix: add missing User relation on AiLearningAnalysis model
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 47s
Prisma validation error P1012: User.aiAnalysisResultsNew missing
opposite relation on AiLearningAnalysis.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 20:52:19 +08:00
wangdl
4cf2aa99fd feat: 用户 AI 设置与 Key 管理 API (API-AI-011~015)
Some checks failed
Deploy API Server / build-and-deploy (push) Failing after 10s
- UserAiController: GET/PUT /ai/profile, GET/PUT /ai/settings
- UserAiController: CRUD /ai/model-credentials, POST test
- UserAiService: Profile upsert, Settings默认创建, Key 生命周期
- CredentialEncryptionService: AES-256-GCM 加解密, SHA-256 hash, mask脱敏, 日志redact
- AiRuntimeModule 注册到 AppModule

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 20:39:29 +08:00
wangdl
6888fe1d12 feat: AI Runtime Prisma Schema (API-AI-004~010 + 070/071/075)
Some checks failed
Deploy API Server / build-and-deploy (push) Failing after 11s
新增 18 个模型:
- P0: UserLearningProfile, UserAiSettings, UserModelCredential
- P0: AiRuntimeJob, AiRuntimeResult, LearningAnalysisSnapshot
- P0: ModelInvocationLog, UserAiUsageDaily, PlatformAiBudgetDaily
- P0: RuntimeInstance
- P1 预留: AiLearningAnalysis, WeakPointCandidate,
  NextActionRecommendation, QuestionGenerationPlan,
  FlashcardGenerationPlan, Flashcard, AiArtifactFeedback

User 模型补充新表 relation 字段。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 20:38:00 +08:00
wangdl
e6cbe16a11 feat: AI 数据权限、隐私授权与用户设置设计 (API-AI-003)
All checks were successful
Deploy API Server / build-and-deploy (push) Successful in 42s
定义 7 项用户授权开关、12 项用户设置字段、4 层硬约束、8 级优先级体系、
设备信息限制规则、Snapshot 过滤伪代码、DeepSeek Prompt 发送规则。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 20:36:40 +08:00
wangdl
045e0b2501 feat: AI Job 状态机与任务调度设计 (API-AI-002)
Some checks failed
Deploy API Server / build-and-deploy (push) Has been cancelled
定义 5 种 Job 类型、7 种状态、完整状态流转图、数据库字段、防并发锁定
机制、retryable/non-retryable 分类、超时释放、幂等规则、Poll 调度策略。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-11 20:35:59 +08:00