merge: 集成V2.6 性能增强与小宝后台化
# Conflicts: # apps/server/prisma/schema.prisma # apps/server/src/app.module.ts # apps/web/components/layout/Sidebar.tsx # docs/architecture.md # docs/decisions.md # docs/roadmap.md
This commit is contained in:
@@ -157,6 +157,27 @@ V2.5 控制面新增三类横切能力:
|
||||
- V2.6 在关系表主源稳定后做大数据性能增强和小宝预警后台化;性能基础不后置,增强项包括压测、慢查询治理、缓存/摘要、后台任务、幂等和失败重试。
|
||||
- V2.7 面向企业级协作与管理治理,V2.8 面向生产硬化与运维闭环;生产部署基线已经存在,V2.8 重点是备份恢复演练、发布 smoke test、监控告警、日志检索、迁移回滚和运维手册。
|
||||
|
||||
## Background Job Runtime Layer (V2.6)
|
||||
|
||||
V2.6 introduces a database-backed background job runtime for server-side refresh work that must not depend on a user opening a page.
|
||||
|
||||
- Storage: `background_jobs` stores `type`, `payload`, `dedupe_key`, `status`, `attempts`, `max_attempts`, `available_at`, `locked_by`, `locked_until`, and `last_error`.
|
||||
- Dedupe: active jobs (`queued` / `running`) are unique by `(type, dedupe_key)` when `dedupe_key` is present. Services still check first and recover from unique conflicts to stay idempotent under concurrent enqueue.
|
||||
- Lease: `JobLockService.claimNext()` uses `FOR UPDATE SKIP LOCKED` and treats expired `running` rows as claimable, so a crashed worker can be recovered by a later worker.
|
||||
- Retry: failed handlers are requeued while `attempts < max_attempts`; terminal failures keep `last_error` and move to `failed`.
|
||||
- Worker boundary: `BackgroundJobWorker` is a small handler registry and single-job runner. Domain modules register typed handlers and only write through their own services.
|
||||
|
||||
This runtime is intentionally DB-backed first. Redis is already available in deployment, but V2.6 jobs need transactional dedupe with domain writes more than high-throughput queue semantics.
|
||||
|
||||
## Runtime Ops Dashboard (V2.6)
|
||||
|
||||
V2.6 adds an Ops runtime surface for local operators and future production admins:
|
||||
|
||||
- Backend: `OpsModule` exposes `GET /api/v1/ops/runtime`, reading recent in-memory slow API request events, recent in-memory slow Prisma query events, `background_jobs` queue rows, and dirty `xiaobao_risk_summaries` count.
|
||||
- Capture: `ApiTimingInterceptor` and `PrismaService` still log slow events, and also append redacted bounded previews into the Ops runtime buffer. SQL query parameters are not exposed; request query strings and key-like values are stripped or redacted.
|
||||
- Jobs: the dashboard summarizes queued/running/succeeded/failed jobs by type and shows recent terminal failures with redacted `lastError`.
|
||||
- Permissions: the frontend route is guarded by `ops:view`. Backend RBAC is represented by `OpsPermissionAdapter` until the V2.5 RBAC contract lands, so the replacement point is explicit instead of hard-coupled to temporary role data.
|
||||
|
||||
## 生产部署层(2026-07-01)
|
||||
|
||||
当前仓库已补齐云服务器生产部署基线:
|
||||
@@ -260,7 +281,16 @@ The rule surface stays in pure frontend engines:
|
||||
|
||||
Managers with `xiaobao.warning:manage` can see all unfinished versions. Non-managers with `xiaobao.warning:view` can only see unfinished versions where the current user is in `version.members`.
|
||||
|
||||
AI explains rule results only. It writes interpretation cache to `xiaobao-risk-insights` and never mutates Version, Requirement, DevTask, TestCase, Bug, or Member data. Risk snapshots are saved to `xiaobao-risk-snapshots` when the page is opened. The first version uses page-triggered analysis rather than a background scheduled Agent.
|
||||
AI explains rule results only. It writes interpretation cache to `xiaobao-risk-insights` and never mutates Version, Requirement, DevTask, TestCase, Bug, or Member data. Risk snapshots are saved to `xiaobao-risk-snapshots` when the page is opened.
|
||||
|
||||
V2.6 moves the current risk summary refresh to the server:
|
||||
|
||||
- `XiaobaoRiskService.refreshSummary(versionId)` recomputes deterministic rule output from Version, DevTask, TestCase, Bug, WorkActivity, and TaskWorklog relation rows, then upserts `xiaobao_risk_summaries` with `dirty=false`.
|
||||
- `XiaobaoRiskWorker` registers the `xiaobao.summary.refresh` background job handler, so dirty summaries can be refreshed without opening `/xiaobao-warning`.
|
||||
- Domain writes that produce work activity already mark the affected version dirty; V2.6 also enqueues a deduped refresh job. Plain update/delete paths for version plans, dev tasks, test cases, and bugs explicitly mark the version dirty as well.
|
||||
- `XiaobaoAiService` evaluates the refreshed summary and enqueues `xiaobao.ai.interpret` when policy allows. The worker reloads the latest summary, skips stale signatures, calls the existing `AiService.interpretRisk()` prompt path, and writes only `xiaobao_risk_insights`.
|
||||
- AI interpretation cache uses the summary `riskSignature`, exact cache reuse, a six-hour cooldown, and risk-level escalation bypass. Until the server has full daily trend snapshots, `attention` summaries trigger server-side AI only when release is within one day and unfinished work remains.
|
||||
- Frontend `/xiaobao-warning` still consumes V2.2 summary reads first and only falls back to AppData calculation when summaries are empty or unavailable.
|
||||
|
||||
Per-user warning read state is saved to `xiaobao-warning-views`. The read marker stores `userId + versionId + risk signature`, so the sidebar can turn the Xiaobao badge blue when any visible risk has a completed unread update, then return to the red risk-count badge after the user opens every updated warning. AI interpretation that is still generating only shows the "updating" notice and must not produce the blue update badge yet.
|
||||
## V2.2 Partitioned Domain Data Layer (2026-07-03)
|
||||
|
||||
@@ -623,3 +623,60 @@
|
||||
- Xiaobao risk snapshots/insights 的 AppData key 进入 `read_only_archive`,关系表写入和后台化归 V2.6;`xiaobao-warning-views` 读状态 API 归 V2.7。
|
||||
|
||||
**理由**:冻结写入能立即切断新的双主源风险,同时保留旧 JSON 的审计和回滚价值。把权限和审计合并到领域 mutation 装饰器,可以确保后续新增写接口默认带服务端 guard 和 audit event。审计覆盖对历史数据只告警,避免为了“补齐历史审计”伪造事件。auth header adapter 给 V2.5 一个可测试的服务端权限边界,但不把它包装成最终安全方案,后续 JWT/企业 RBAC 可以替换 adapter 而不改领域 controller 合同。
|
||||
|
||||
## 48. V2.6 后台任务先采用 PostgreSQL Lease 队列
|
||||
|
||||
**问题**:小宝风险摘要、AI 解读和后续通知都需要在用户不打开页面时后台刷新。直接把这些逻辑放在页面 effect 中会导致无人访问时数据不更新;直接引入 Redis queue 又会增加一套可靠性、幂等和迁移运维面。
|
||||
|
||||
**决策**:
|
||||
- 新增 `background_jobs` 表和 `JobsModule`,作为 V2.6 后台任务运行时。
|
||||
- Job 行包含 `type`、`payload`、`dedupe_key`、`status`、`attempts`、`max_attempts`、`available_at`、`locked_by`、`locked_until`、`last_error`。
|
||||
- 同一 `type + dedupe_key` 在 `queued/running` 状态下唯一;服务层先查 active job,遇到并发唯一冲突再回读,保证 enqueue 幂等。
|
||||
- Worker claim 使用数据库事务、`FOR UPDATE SKIP LOCKED` 和 lease 时间;`running` 且 `locked_until` 过期的 job 可以被新 worker 回收。
|
||||
- Handler 失败时按 `attempts < max_attempts` 重回 `queued` 并设置下一次 `available_at`;达到上限后进入 `failed`,只记录错误,不修改业务实体。
|
||||
- `BackgroundJobWorker` 只负责 handler 注册和单次执行,业务副作用仍放在各领域 service 内,避免队列层知道小宝、通知或审计细节。
|
||||
|
||||
**理由**:PostgreSQL 队列足够支撑 V2.6 的低频后台刷新,同时能和领域写入共享事务边界、唯一约束和迁移流程。等 V2.7 通知或更高吞吐任务落地后,如确实需要 Redis/专用队列,再通过同一 `JobsService` 接口替换底层实现,而不是现在提前引入第二套事实源。
|
||||
|
||||
## 49. V2.6 小宝风险摘要改为服务端后台刷新
|
||||
|
||||
**问题**:小宝预警最初由页面加载完整前端 store 后计算并保存快照/缓存。这样会导致没人打开页面时 `xiaobao_risk_summaries` 不刷新,侧边栏和 V2.2 快读只能看到旧风险。
|
||||
|
||||
**决策**:
|
||||
- 新增 `XiaobaoModule`,包含 `XiaobaoRiskService`、`XiaobaoRiskWorker` 和最小 controller。
|
||||
- 服务端先移植确定性规则的核心口径:剩余开发/测试/Bug 工作量、关键缺陷、阻塞项、失败用例、预测延期、置信度和 risk signature。
|
||||
- `XiaobaoRiskService.markDirtyAndEnqueue(versionId)` 负责 upsert dirty summary 并排入 `xiaobao.summary.refresh`,dedupe key 使用 `versionId`。
|
||||
- `XiaobaoRiskWorker` 通过 V2.6 `BackgroundJobWorker` 注册 handler,执行时只刷新 `xiaobao_risk_summaries`,不修改 Version、Requirement、DevTask、TestCase、Bug 或 Member。
|
||||
- 领域写入侧继续通过 `WorkActivityService.markXiaobaoSummaryDirty()` 收口;普通 update/delete 没有 activity 证据时显式标脏,避免风险摘要漏刷新。
|
||||
|
||||
**理由**:把 deterministic summary 放到服务端后,读路径不再依赖页面打开,且所有前端仍可沿用 V2.2 summary API。AI 解读仍是后续独立队列,只消费 summary/signature 并写 insight cache;本决策不让 AI 或后台 worker 直接改业务实体。
|
||||
|
||||
## 50. V2.6 小宝 AI 解读改为服务端队列,只写 insight cache
|
||||
|
||||
**问题**:小宝 AI 解读原先由 `/xiaobao-warning` 页面触发。即使 V2.6 已经把 deterministic summary 刷新移到服务端,如果 AI 解读仍依赖页面打开,高风险版本在无人访问时仍不会产生新的解释缓存,也不利于后续 V2.7 通知使用同一解读结果。
|
||||
|
||||
**决策**:
|
||||
- 新增 `XiaobaoAiModule`,通过 `XiaobaoAiService` 和 `XiaobaoAiWorker` 注册 `xiaobao.ai.interpret` job。
|
||||
- `XiaobaoRiskService.refreshSummary()` upsert summary 后调用 `XiaobaoAiService.evaluateSummary()`,按 policy 判断是否排入 AI 解读 job。
|
||||
- AI 触发策略复用页面规则的核心边界:`at_risk`、`likely_delayed`、`blocked` 可触发;精确 `riskSignature` 命中时复用缓存;同版本最近 6 小时内已有解读时 cooldown;风险等级升级可绕过 cooldown。
|
||||
- 服务端当前没有完整前端趋势快照上下文,因此 `attention` 只在“距离预期发版日小于等于 1 天且仍有未完成工作”时触发。趋势、置信度下降和明细信号变化的完整 attention 策略等待服务端趋势快照补齐后再扩展。
|
||||
- Worker 执行时重新读取 `xiaobao_risk_summaries`,若 job payload 的 `riskSignature` 已过期则跳过,避免为旧风险写新解释。
|
||||
- AI 调用只走现有 `AiService.interpretRisk()` 和 risk prompt/provider 抽象,不新增 SDK 调用、不绕过 AI 配置。
|
||||
- AI 成功后只写 `xiaobao_risk_insights`,缓存保存时间使用服务端 `now`,不信任模型返回的 `generatedAt` 作为缓存新鲜度;失败抛错交给 background job retry。
|
||||
- Worker 不修改 Version、Requirement、DevTask、TestCase、Bug、Member 等业务实体,也不写通知。V2.7 通知如需消费结果,应通过 insight cache 或 adapter 读取。
|
||||
|
||||
**理由**:AI 解读是对确定性规则结果的解释层,不是业务事实源。把它做成 summary 后置队列,能让无人打开页面时也生成解释,同时通过 signature/cooldown/escalation 控制成本和重复调用。只写 cache 能保持 AI 与业务实体解耦,后续通知和审计可以复用缓存,而不是让 AI worker 直接参与业务状态流转。
|
||||
|
||||
## 51. V2.6 运维看板先做轻量运行时快照,RBAC 通过 adapter 衔接
|
||||
|
||||
**问题**:V2.6 增加了性能 harness、后台 job runtime、小宝 summary refresh 和 AI 解读队列。如果没有一个运行时入口,慢请求、慢查询、job 堆积和 dirty summary 数只能从日志或数据库手工排查。与此同时,V2.5 后端 RBAC/audit 合同尚未落地,不能为了看板临时硬编码一套后端权限结构。
|
||||
|
||||
**决策**:
|
||||
- 新增 `OpsModule`,提供 `GET /api/v1/ops/runtime`,返回慢请求、慢 Prisma 查询、后台任务队列、失败任务和 dirty summary 数。
|
||||
- 慢请求继续由 `ApiTimingInterceptor` 识别;慢查询继续由 `PrismaService` query event 识别。二者额外写入进程内 ring buffer,作为轻量 dashboard 数据源。
|
||||
- 看板只保留最近事件,不做长期审计。长期审计和多实例聚合等待 V2.5 audit 或后续 observability 方案。
|
||||
- 请求 URL 去掉 query string;SQL 只展示截断后的 query preview;`sk-*`、token、secret、password、authorization 等 key-like 文本统一 redacted;不展示 AI provider apiKey、请求参数或环境变量。
|
||||
- Job 队列从 `background_jobs` 最近 200 行聚合,按 type 展示 queued/running/succeeded/failed,并展示最近 failed job 的脱敏 `lastError`。
|
||||
- 前端 `/admin/ops` 使用 `RouteGuard permission="ops:view"`;权限字典新增 `ops:view`,但不默认授给非管理员 preset。后端通过 `OpsPermissionAdapter` 保留 `ops:view` 校验入口,待 V2.5 RBAC guard 落地后替换。
|
||||
|
||||
**理由**:当前目标是让 V2.6 的性能和后台化能力可观察,而不是建设完整监控平台。进程内 ring buffer 成本低、对生产数据无额外写放大;结合脱敏规则可避免把 secrets 带进管理端。权限 adapter 明确了未来替换点,避免 Ops 看板和未定型 RBAC/audit 合同互相绑死。
|
||||
|
||||
79
docs/performance-hot-queries.md
Normal file
79
docs/performance-hot-queries.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# V2.6 Hot Query Budget And Index Audit
|
||||
|
||||
This document records the V2.6 query budget for the large-data harness and the index contracts that keep hot APIs on partition keys.
|
||||
|
||||
## Commands
|
||||
|
||||
Offline contract audit:
|
||||
|
||||
```bash
|
||||
node scripts/explain-hot-queries.mjs --dry-run
|
||||
```
|
||||
|
||||
Database explain audit:
|
||||
|
||||
```bash
|
||||
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ftb_pm pnpm perf:explain
|
||||
```
|
||||
|
||||
Strict plan mode is available for seeded medium/large databases:
|
||||
|
||||
```bash
|
||||
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ftb_pm pnpm perf:explain -- --strict-plan
|
||||
```
|
||||
|
||||
`--strict-plan` fails on sequential scans. It is useful after the medium fixture is seeded and analyzed, but not required for empty or tiny local databases where PostgreSQL may choose a sequential scan correctly.
|
||||
|
||||
## Budgets
|
||||
|
||||
| Area | Query Shape | Budget |
|
||||
| --- | --- | --- |
|
||||
| `health/version` | no database query | HTTP p95 <= 500ms |
|
||||
| Requirement pool | `requirements.product_id` + optional filters/search, cursor, `created_at` sort | HTTP p95 <= 1000ms |
|
||||
| Version detail | root version plus child rows by `version_id` | HTTP p95 <= 1500ms |
|
||||
| Workspace | owner/assignee unfinished rows | HTTP p95 <= 1200ms |
|
||||
| Xiaobao warnings | non-`on_track` summaries by score | HTTP p95 <= 1000ms |
|
||||
| Xiaobao dirty queue | `dirty=true` summaries ordered by `updated_at` | background batch <= 100 rows |
|
||||
| Audit search adapter | V2.5 audit table pending; `ai_logs` is the current AI audit surface | explain-only contract |
|
||||
|
||||
## Required Index Contracts
|
||||
|
||||
V2.6 keeps the existing partition prefixes:
|
||||
|
||||
- Requirement pool queries must include `productId`; `requirements` is hash-partitioned by `product_id`.
|
||||
- Version detail child queries must include `versionId`; `dev_tasks`, `test_cases`, and `bugs` are hash-partitioned by `version_id`.
|
||||
- Append evidence tables stay range-partitioned by `created_at`; background workers must still filter by `version_id`, `user_id`, or date before scanning.
|
||||
|
||||
Added in migration `20260708030000_v26_hot_query_indexes`:
|
||||
|
||||
| Index | Purpose |
|
||||
| --- | --- |
|
||||
| `projects_product_created_at_idx` | product-scoped project list |
|
||||
| `versions_product_created_at_idx` | product-scoped version list |
|
||||
| `versions_product_project_created_at_idx` | project-scoped version list |
|
||||
| `version_plans_owner_open_due_idx` | workspace plan queue |
|
||||
| `dev_tasks_assignee_open_priority_idx` | workspace dev task queue |
|
||||
| `test_cases_assignee_open_priority_idx` | workspace test case queue |
|
||||
| `bugs_version_status_priority_updated_at_idx` | version detail bug ordering |
|
||||
| `bugs_assignee_open_priority_idx` | workspace bug queue |
|
||||
| `test_cases_version_round_status_updated_at_desc_idx` | version detail test case ordering |
|
||||
| `xiaobao_risk_summaries_warning_score_idx` | manager Xiaobao warning list |
|
||||
| `xiaobao_risk_summaries_dirty_updated_at_idx` | background Xiaobao dirty summary queue |
|
||||
| `work_activities_version_occurred_at_idx` | Xiaobao evidence recompute |
|
||||
|
||||
Existing V2.2 indexes remain part of the contract, including requirement pool indexes, version child indexes, workspace partial indexes, task worklog date indexes, Xiaobao snapshot/insight indexes, and `ai_logs` operation/status indexes.
|
||||
|
||||
## Audit Adapter Note
|
||||
|
||||
The V2.5 RBAC/audit contract is not present in this branch. V2.6 therefore documents `audit.searchAdapter` as an adapter target instead of inventing a temporary audit table. When audit lands, the expected query shape should be:
|
||||
|
||||
```sql
|
||||
SELECT *
|
||||
FROM audit_events
|
||||
WHERE product_id = $1
|
||||
AND created_at >= $2
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 100;
|
||||
```
|
||||
|
||||
Expected future index: `(product_id, created_at DESC)` plus actor/resource indexes required by the audit module. Until then, `ai_logs_operation_created_at_idx` and `ai_logs_status_created_at_idx` cover AI operation audit searches only.
|
||||
104
docs/performance.md
Normal file
104
docs/performance.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# V2.6 Performance Harness
|
||||
|
||||
V2.6 adds a deterministic large-data fixture and a small HTTP performance harness for the current hot paths. The goal is to make performance regressions visible before adding more background jobs and Xiaobao automation.
|
||||
|
||||
## Fixture Sizes
|
||||
|
||||
The fixture script creates only `perf-*` rows and can be rerun safely. It covers:
|
||||
|
||||
- products
|
||||
- projects
|
||||
- versions
|
||||
- requirements
|
||||
- version plans
|
||||
- dev tasks
|
||||
- test cases
|
||||
- bugs
|
||||
- work activities
|
||||
- Xiaobao risk summaries
|
||||
|
||||
Preset sizes:
|
||||
|
||||
| Size | Purpose |
|
||||
| --- | --- |
|
||||
| `small` | Local smoke fixture. Fast dry-run and minimal database seed. |
|
||||
| `medium` | Default performance gate for V2.6 hot APIs. |
|
||||
| `large` | Stress fixture for query/index audit work. |
|
||||
|
||||
Stable anchors used by the harness:
|
||||
|
||||
```text
|
||||
productId=perf-product-001
|
||||
versionId=perf-version-001-001-001
|
||||
userId=perf-user-dev-01
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
Dry-run without database access:
|
||||
|
||||
```bash
|
||||
node scripts/seed-large-dataset.mjs --size small --dry-run
|
||||
node scripts/perf-check.mjs --base-url http://localhost:3001/api/v1 --dry-run
|
||||
```
|
||||
|
||||
Seed a database:
|
||||
|
||||
```bash
|
||||
pnpm perf:seed -- --size small
|
||||
```
|
||||
|
||||
Run the hot-path harness against a running NestJS API:
|
||||
|
||||
```bash
|
||||
pnpm perf:check -- --base-url http://localhost:3001/api/v1
|
||||
```
|
||||
|
||||
Audit SQL plans and hot-path indexes:
|
||||
|
||||
```bash
|
||||
pnpm perf:explain -- --dry-run
|
||||
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ftb_pm pnpm perf:explain
|
||||
```
|
||||
|
||||
## Hot Probes
|
||||
|
||||
`perf-check` measures p50 and p95 latency, records HTTP status code counts, and exits non-zero when a request fails or p95 exceeds the current query budget.
|
||||
|
||||
| Probe | Endpoint | p95 Budget |
|
||||
| --- | --- | ---: |
|
||||
| Runtime version | `/health/version` | 500ms |
|
||||
| Requirement pool | `/v2.2/requirements?productId=perf-product-001&q=REQ&limit=50` | 1000ms |
|
||||
| Version detail | `/v2.2/versions/perf-version-001-001-001/detail-data` | 1500ms |
|
||||
| Workspace | `/v2.2/workspace?userId=perf-user-dev-01` | 1200ms |
|
||||
| Xiaobao warning | `/v2.2/xiaobao-warning?manager=true` | 1000ms |
|
||||
|
||||
The medium fixture is the V2.6 acceptance target. Large fixture runs are for index audit and explain-plan work, not for every local commit.
|
||||
|
||||
See `docs/performance-hot-queries.md` for query budgets, partition-key contracts, and required indexes.
|
||||
|
||||
## Runtime Ops Dashboard
|
||||
|
||||
`/admin/ops` provides the V2.6 runtime view for checking whether the hot paths and background workers stay healthy after fixture/perf runs.
|
||||
|
||||
It reads `GET /api/v1/ops/runtime` and shows:
|
||||
|
||||
- recent slow API requests captured by `ApiTimingInterceptor`
|
||||
- recent slow Prisma query previews captured by `PrismaService`
|
||||
- `background_jobs` totals and per-type queued/running/succeeded/failed counts
|
||||
- recent failed jobs with redacted `lastError`
|
||||
- dirty `xiaobao_risk_summaries` count
|
||||
|
||||
Access is guarded in the frontend by `ops:view`. Backend RBAC is currently an explicit `OpsPermissionAdapter` placeholder until the V2.5 RBAC contract lands.
|
||||
|
||||
Secret handling:
|
||||
|
||||
- request query strings are stripped before display
|
||||
- SQL is shown only as a bounded query preview, without Prisma parameters
|
||||
- key-like text such as `sk-*`, token, secret, password, and authorization is redacted
|
||||
|
||||
## Notes
|
||||
|
||||
- `seed-large-dataset` uses deterministic IDs and dates so repeated runs are comparable.
|
||||
- Non-dry-run seeding deletes and recreates only `perf-*` rows.
|
||||
- The harness intentionally depends on public API endpoints instead of calling Prisma directly; it measures the same path the frontend uses.
|
||||
@@ -1,12 +1,14 @@
|
||||
# 开发路线图
|
||||
|
||||
## 当前阶段:V2.5 已完成 — 下一阶段 V2.6 大数据性能增强 + 小宝预警后台化
|
||||
## 当前阶段:V2.6 已完成 — 下一阶段 V2.7 企业协作 + V2.8 运维闭环集成
|
||||
|
||||
V2.4 已将高增长和核心业务领域从“AppData 主写 + 关系表同步副本”推进到“领域 CRUD 主写关系表 + AppData 兼容/迁移兜底”。V2.2 快读 API 和 V2.3 AppData 写后同步继续保留,但它们现在是兼容基础设施,不再是已迁移领域的数据新鲜度主链路。
|
||||
|
||||
V2.5 的目标是正式收口后端权限、审计、AppData 禁写和一致性核对。AppData 不能直接删除,必须按“禁写 → 双读核对 → 移除 fallback → 只读归档/导出 → 后续删表”的顺序推进。
|
||||
|
||||
### V2.5 完成范围
|
||||
V2.6 的目标是在关系表主源稳定后完成大数据性能增强、小宝风险后台化、AI 解读队列和运行时 Ops 看板,让高增长热路径、后台任务和风险摘要不再依赖页面打开。
|
||||
|
||||
### V2.5-V2.6 完成范围
|
||||
|
||||
1. **RBAC 收口**:领域 mutation API 已接入服务端权限校验、资源作用域和当前用户上下文。
|
||||
2. **审计事件**:领域 mutation 通过 `audit_events` 写 append-only audit event,支持后台查询和敏感字段脱敏。
|
||||
@@ -14,6 +16,10 @@ V2.5 的目标是正式收口后端权限、审计、AppData 禁写和一致性
|
||||
4. **导出归档**:已提供 AppData archive export/verify 脚本,包含 checksum、key list 和应用版本元数据。
|
||||
5. **一致性校验**:已提供 counts、partition key、orphan refs、audit coverage 的本地脚本和后台页面。
|
||||
6. **管理端可视化**:已补 `/admin/audit` 与 `/admin/consistency`,并由 `audit:view` / `consistency:view` 控制。
|
||||
7. **性能压测与热查询治理**:已补 deterministic fixture、`perf:check`、`perf:explain`、热查询索引审计和性能预算文档。
|
||||
8. **后台任务运行时**:已补 PostgreSQL-backed `background_jobs`、dedupe、lease、retry、失败记录和单步 worker。
|
||||
9. **小宝后台化**:已补服务端 summary refresh、dirty/enqueue 桥接和 `xiaobao.ai.interpret` AI 解读队列。
|
||||
10. **Ops 看板**:已补 `/admin/ops` 与 `GET /api/v1/ops/runtime`,展示慢请求、慢查询、job 队列和 dirty summary 数。
|
||||
|
||||
## V2 分阶段交付链路
|
||||
|
||||
@@ -42,10 +48,22 @@ V2.5 的目标是正式收口后端权限、审计、AppData 禁写和一致性
|
||||
- 需求池已切到服务端分页、搜索、筛选、排序,不再要求加载全量 AppData 文档。
|
||||
- `packages/shared` 状态契约已统一为当前业务状态机。
|
||||
- V2.6/V2.7 协调边界:Xiaobao risk snapshots/insights 关系表写入和后台化归 V2.6;warning read-state API、部门/角色/密码规则/加班原因配置表归 V2.7。
|
||||
- V2.6.1 已新增 deterministic large-data fixture、HTTP performance harness 和性能预算文档。
|
||||
- V2.6.2 已新增 hot query explain/index audit 脚本、热查询索引迁移和 `docs/performance-hot-queries.md`。
|
||||
- V2.6.3 已新增 PostgreSQL-backed `background_jobs` 运行时、去重/lease/retry 语义和 jobs 单元测试。
|
||||
- V2.6.4 已新增服务端小宝风险 summary refresh、后台 job handler,以及领域写入 dirty/enqueue 桥接。
|
||||
- V2.6.5 已新增服务端小宝 AI 解读队列,summary 刷新后按 signature/cooldown/escalation policy 入队,只写 `xiaobao_risk_insights` 缓存。
|
||||
- V2.6.6 已新增 `/admin/ops` 运行时看板和 `GET /api/v1/ops/runtime`,展示慢请求、慢查询、job 队列和 dirty summary 数。
|
||||
|
||||
### 已完成(按时间倒序)
|
||||
|
||||
**2026-07-08**
|
||||
- V2.6.6 added the Ops runtime dashboard with `ops:view`, redacted slow request/query buffers, background job queue summary, failed job list, and dirty Xiaobao summary count.
|
||||
- V2.6.5 moved Xiaobao AI interpretation behind the background job runtime, reusing `AiService.interpretRisk()` and writing only insight cache rows.
|
||||
- V2.6.4 moved deterministic Xiaobao risk summary refresh into the server, registered the `xiaobao.summary.refresh` background job handler, and enqueue refresh jobs from dirty domain writes.
|
||||
- V2.6.3 added DB-backed background jobs with active dedupe keys, lease-based claiming, expired lock recovery, retry/terminal-failure handling, and a small handler worker.
|
||||
- V2.6.2 added `perf:explain`, hot query explain targets, index audit documentation, and V2.6 hot-path indexes for workspace, Xiaobao warning/dirty queues, project/version lists, and evidence scans.
|
||||
- V2.6.1 added deterministic small/medium/large fixture generation, `perf:check`, and `docs/performance.md` for hot API p50/p95 budgets.
|
||||
- V2.5.0 added server auth context, current-user decorator, permission decorator/guard/service, wildcard super admin support, project/version-member scope checks, and guard/service tests.
|
||||
- V2.5.1 added append-only `audit_events`, audit service/controller/query DTO, sensitive-field redaction, `audit:view`, and audit service/controller tests.
|
||||
- V2.5.2 protected V2.4 domain mutation APIs with server-side permission metadata and audit writes through `@ProtectedMutation()`.
|
||||
|
||||
@@ -339,9 +339,9 @@ Implementation convention:
|
||||
- `xiaobao.warning:manage`:查看所有未结束版本的预警。
|
||||
- `xiaobao.warning:view`:仅查看当前用户在 `version.members` 中的未结束版本。
|
||||
|
||||
页面打开时会聚合版本下的计划、开发任务、测试用例、Bug、日报和工作活动,计算当前风险并保存当天快照。页面使用 `buildXiaobaoWorkItems` 做版本级聚合,不使用个人工作台的 `aggregateWorkItems(userName, ...)` 过滤。快照按同版本同日节流保存:重大变化立即保存,普通变化 10 分钟内不重复写入。
|
||||
V2.6 后小宝当前 summary 由服务端后台刷新:领域写入标记 `xiaobao_risk_summaries.dirty=true` 并排入 `xiaobao.summary.refresh`,worker 从版本下的计划、开发任务、测试用例、Bug、日报和工作活动重新计算风险。页面仍可用前端 `buildXiaobaoWorkItems` 做兼容聚合和快照保存,但默认优先读取 V2.2 summary。
|
||||
|
||||
AI 解读不由人工按钮触发。`at_risk`、`likely_delayed`、`blocked` 自动触发;`attention` 在风险分明显上升、趋势连续上升、关键 Bug 增加、测试失败、阻塞增加、静默风险增加、置信度下降或预测发版日延后时触发。缓存命中时复用解读;同版本最近 6 小时内已有解读时进入 cooldown,不重复请求,风险等级升级时可绕过;缓存保存时间使用客户端时间,不信任模型返回的 `generatedAt` 作为缓存新鲜度。
|
||||
AI 解读不由人工按钮触发。服务端 summary 刷新后按 policy 排入 `xiaobao.ai.interpret`:`at_risk`、`likely_delayed`、`blocked` 自动触发;`attention` 当前服务端只在临近发版且仍有未完成工作时触发,页面完整趋势策略仍保留作为兼容。缓存命中时复用解读;同版本最近 6 小时内已有解读时进入 cooldown,不重复请求,风险等级升级时可绕过;缓存保存时间使用服务端写入时间,不信任模型返回的 `generatedAt` 作为缓存新鲜度。
|
||||
|
||||
静默风险包括长期无更新、无日报、无活动、进行中事项无人处理等信号。日报和工作活动是风险解释的重要证据,必须进入 AI 解读输入。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user