| content |
{"Commits":[{"Sha1":"da76fc5e9 {"Commits":[{"Sha1":"da76fc5e9fcbc3f937fa2bee7743931f9b60e4db","Message":"docs(governance): 沉淀契约断链深挖战役经验(两个 bug 家族 + live 复现纪律)\n\nbaseline-and-experience.md 置顶新增 2026-07-01~07-03 战役经验块:\n- 核心发现:静态审计停在 Zod 边界,语义断链全在 Zod 之后(casing 错位/\n 缺列/mapper 错映射/绕守卫/路由遮蔽),深挖口径为追「Zod→prisma 写入」\n 与「筛选参数→where」两条真实链的断点。\n- Bug 家族 1「controller 绕守卫走裸 batchAction」:11 模块命中、真断链 4、\n 三查判定法(updateStatus 覆写/update 覆写/batchAction 覆写)豁免 5。\n- Bug 家族 2「静态路由被参数化路由遮蔽」:16 文件 32 处死路由全收口,\n 防回潮探测器 audit:route-shadowing 已入仓。\n- live 复现铁律:子代理 5 个「最强候选」全是假阳性(死 controller/\n BaseService 自动筛选/crud fallback 静默丢弃),改前必正负两向真请求复现。\n- 修复分类法(六种证据形态→修法映射表)、状态词汇多源漂移多数决收敛法、\n 测试防剧场增补(mock FieldMapper 须应用真实映射表)、环境坑增补\n (rogue next 遮蔽 3000/Prisma client 重启/非交互迁移纪律)。\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-03T02:46:55-07:00"},{"Sha1":"1329d688e027093bb5a1157466cef5cfdfa0513f","Message":"fix(routes): 全仓收口 32 处路由遮蔽死路由,新增 route-shadowing 审计防回潮\n\n承接 supply-chain 采购单批量路由被 /:id 吞掉的发现(fb706e38d6),写模拟\nExpress 顺序匹配的扫描器全仓核查:同一 routes 文件内,先注册的参数化路由\n(/:id...)会吞掉后注册的静态段路由(/batch、/export、/stats、/calendar、\n/today、/templates 等),使其永远不可达——调用方拿到的是详情 handler 的\nPRISMA_P2023/404(静态段被当 UUID 传给 findFirst)。\n\n实测 16 个文件 32 处真死路由(live 抽验 today/stats/calendar 均复现 P2023),\n覆盖:ad-campaigns 批量启停、campaign-targets/contract-templates/tickets/\npartner-customers/social-interactions 批量删除、knowledge-capture 批量审批+\n规则统计、lead-qualification 批量评分/认定、livestream-schedules 日历/今日、\nmarketing 归因 5 个报表端点、satisfaction 响应导出、social-posts 日历/批量\n发布、cash-flow 高风险付款行为、geo-keywords 导出、inventory 盘点行批量、\nsupply-chain 供应商批量删除。\n\n修复:全部静态路由前移到对应参数化路由之前(纯注册顺序移动,handler/权限/\nvalidate schema 一律未动),每处补中文注释说明顺序约束。\n\n防回潮:新增 scripts/audit-route-shadowing.ts(pnpm run audit:route-shadowing),\n模拟 Express 逐段匹配、已处理 :id(regex) 约束段(UUID 正则不吞 batch,剔除\n7 处假阳性);任何新增遮蔽退出码 1,报告写 reports/route-shadowing-audit.latest.json。\n暂未注册 audit-registry(避免触发 reports-missing-zero,接入棘轮由治理口径决定)。\n\n验证:重扫 361 个 routes 文件 0 遮蔽;backend type-check 全绿;live 抽验 10\n端点全部复活(3 处 P2023→success、attribution 5 端点 200、2 个 export 200);\nroute-registration 审计重复挂载 0。\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-03T02:39:19-07:00"},{"Sha1":"fb706e38d6ba2c08bcea5e43c0da60db2b328e7c","Message":"fix(sn/supply-chain/content-templates): 全仓收口「controller 绕守卫走裸 batchAction」bug 家族\n\n承接 content-creation(ad0aff1667)后全仓扫描 batchAction('update_status')\n家族(11 模块命中),逐模块三查(updateStatus 覆写守卫 / update 覆写守卫 /\nbatchAction 覆写)+ live 复现判责,真断链 3 处全部修复:\n\n- serial-numbers(与 content-creation 完全同族):activate/return/scrap/\n batch-activate 四个动作走裸 batchAction,绕过 assertTransition 守卫(红线 2),\n 且 activate 的 customerId/orderId/activatedAt 被丢弃(客户绑定/激活时间静默\n 丢失、无生命周期事件);带守卫的 service.activate/restockReturned/\n scrapSerialNumber 全是死代码。现全部接回守卫实现。\n live:activate 带 customerId/activatedAt 真落库并读回;activated→return\n 被守卫 400 拦截。新增 4 个 controller 回归锁定测试(断言走守卫方法且\n batchAction 未被调用)。\n- supply-chain 采购单批量确认/取消:两层断链叠加——\n ① batch 路由注册在 /:id/confirm、/:id/cancel 之后,Express 把 \"batch\" 当\n :id,前端 POST /purchase-orders/batch/confirm|cancel 恒 400(批量确认/取消\n 一直是假功能);已把三条 batch 路由前移到 /:id/* 之前。\n ② handler 走裸 batchAction 绕过 canTransitionPurchaseOrder;已改为逐单走\n confirmOrder/cancelOrder 守卫方法并汇总 successCount/failedIds。\n live 混合场景:created 单→confirmed 放行、cancelled 单保持原状进 failedIds。\n- content-templates 记录使用:POST /:id/use 走 batchAction(metadata:{lastUsedAt})\n ——metadata 被忽略、status 为 undefined,什么都不写,前端列表「使用次数」\n 恒 0(死指标)。现实现 service.recordUse(usage_count 自增 + 租户守卫)。\n live:连打两次 usageCount 0→2。顺手修齐既存测试漂移(getTemplateStats 断言\n inactive→archived,对齐 service 真实返回键)。\n\n已核实豁免(live/码面证据,防误改):leads(update 覆写带 canTransitionLead,\n批量状态未绕守卫)、alliance-merchants/products(update 覆写带守卫)、\ncontent-library(batchAction 覆写已专门处理 metadata.categoryId → 真实\nbatchMoveCategory)、marketing-automation(paused 开关型无拓扑)。\n\nbackend type-check 全绿;serial-numbers/supply-chain/content-templates 测试\n93/93 通过;route-registration 审计重复挂载 0。\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-03T02:02:40-07:00"},{"Sha1":"ad0aff1667f4426638d853309430b89468af8966","Message":"fix(content-creation): 视图驱动补全提交审核链路,接回被绕过的状态机守卫\n\n深挖发现该模块存在三层叠加断链:\n1. 红线 2 违反:controller 的 start/submit/complete/cancel/assign 全部绕过\n service 守卫方法,走裸 batchAction('update_status')——状态机从未拦截过任何\n 非法转换(live 实测 draft→pending_review 任意跳转全通);submit 的 req.body\n 被塞进 batchAction 忽略的 metadata payload,content/outputUrls/note 全部丢弃;\n assign 连 status 都不传(等于什么都不干)。带守卫+流程启动的 service.submit\n 是零调用死代码(与 tickets 4d854c3a 同一 bug 家族)。\n2. 状态词汇三源漂移:machine/statuses.ts 用 pending/assigned/submitted/revision\n (纸面定义、库中从未有数据),运行态(DB 31 行、service 写链、前端\n CONTENTDRAFT_STATUS_MAP)用 draft/in_progress/pending_review/completed/\n cancelled;schema 的 CREATION_STATUS 还混有第三套 review/approved/active 死值\n (其注释宣称的\"控制器实写 review/approved\"经核对与代码不符)。\n3. 数据模型缺位:submitCreationSchema 接受的 content(max 100000)/outputUrls/note\n 无处持久化——content 无列、outputUrls 被 mapper 错映射到 UUID 列\n output_item_id(该列为 ai-assist context-provider 真实读取,不得占用)、\n note 无写链。\n\n修复(按红线 4 视图驱动:视图需求→字段提取→数据模型→迁移→全栈实现):\n- 状态机收敛到运行态词汇(红线 0):machine 拓扑/XState states/statuses.ts/\n schema 枚举统一为 draft→in_progress→pending_review→completed(+cancelled、\n 审核退回 pending_review→in_progress);assign 只设 assigned_to 不再是独立状态。\n- 迁移 20260703030000:content_creations 补 content TEXT / output_urls JSONB\n default [] / submit_note VARCHAR(1000);mapper 修正 outputUrls→output_urls、\n 新增 submitNote→submit_note,解除对 output_item_id 的错误占用。\n- service.submit 持久化三字段并流转 pending_review(勿用 BUSINESS_STATUS.\n PENDING_APPROVAL='pending_approval' 错词);补 complete/cancel 守卫方法;\n controller 五个动作全部接回 service 守卫链。\n- 前端 Index:in_progress 行新增「提交审核」Modal(正文必填/成果链接多行 URL/\n 提交说明),完成按钮收窄到 pending_review 行、取消按钮排除 pending_review\n (旧条件在新守卫下会 400)。\n\n真实端到端验证(运行中后端 + 真实 DB):\n- 修复前:submit 200 但 content/outputUrls/note 全丢(DB 直证 metadata={})、\n draft 直接 submit 也 200(守卫失效)。\n- 修复后:draft→submit 正确 400(错误信息含合法目标)、pending_review→cancel\n 正确 400;start→submit 后 content/output_urls/submit_note API+DB 双证落库、\n output_item_id 未污染;complete 落 completedAt。\n\n测试:machine 测试重写 17/17;service 测试补 submit 持久化锁定(mock mapper\n改为应用真实映射表,锁 outputUrls→output_urls 配置本身)7/7;前端 RTL 补提交\n审核 Modal 用例并同步行按钮断言 2/2。前后端 type-check 全绿;sm-drift 审计\ndivergent/duplicate/topology 全 0、unresolved 9 未涨;enum/formrules/\nfield-payload/prisma-zod 审计全绿。\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-03T01:36:49-07:00"},{"Sha1":"9ff572ee948d646916ba12fb3b3f084f2bd05a30","Message":"fix(crm-activities): 落地文档承诺的幂等能力,同 idempotencyKey 不再重复建活动\n\ncrm-activities create 的 Zod schema 接受 idempotencyKey、docs 明确宣称\n「支持幂等性(通过 idempotencyKey 字段)」,但此前无列无逻辑:字段经 crud\nfallback 静默丢弃(不 500,也不去重),相同 key 重复提交会产生多条活动记录——\n契约/文档与实现不符(假契约)。\n\n修复(落地承诺,补列+接线):\n- 迁移 20260703020000:crm_activities 补 idempotency_key VARCHAR(100) +\n 租户内唯一索引 (tenant_id, idempotency_key);Postgres 多 NULL 互异,\n 存量行不冲突;folder 真源 + schema.prisma 镜像同步。\n- service.create:命中既有 idempotency_key 直接返回既有活动(去重);\n 并发下唯一约束触发 P2002 时兜底重取既有,避免竞态重复。\n\n真实端到端验证(运行中后端 + 真实 DB):\n- 修复前同 key 两次得两条不同记录(去重失效复现)。\n- 修复后同 key 两次返回同一 id,DB 仅 1 行且 idempotency_key 落库。\n\n新增回归锁定单测:相同 idempotencyKey 命中既有则返回既有、断言 create 未被调用。\ncrm-activity.service.test.ts 9/9 通过;backend type-check 全绿;\nprisma-zod 契约审计 PASS。\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-03T01:07:46-07:00"}],"HeadCommit":{"Sha1":"da76fc5e9fcbc3f937fa2bee7743931f9b60e4db","Message":"docs(governance): 沉淀契约断链深挖战役经验(两个 bug 家族 + live 复现纪律)\n\nbaseline-and-experience.md 置顶新增 2026-07-01~07-03 战役经验块:\n- 核心发现:静态审计停在 Zod 边界,语义断链全在 Zod 之后(casing 错位/\n 缺列/mapper 错映射/绕守卫/路由遮蔽),深挖口径为追「Zod→prisma 写入」\n 与「筛选参数→where」两条真实链的断点。\n- Bug 家族 1「controller 绕守卫走裸 batchAction」:11 模块命中、真断链 4、\n 三查判定法(updateStatus 覆写/update 覆写/batchAction 覆写)豁免 5。\n- Bug 家族 2「静态路由被参数化路由遮蔽」:16 文件 32 处死路由全收口,\n 防回潮探测器 audit:route-shadowing 已入仓。\n- live 复现铁律:子代理 5 个「最强候选」全是假阳性(死 controller/\n BaseService 自动筛选/crud fallback 静默丢弃),改前必正负两向真请求复现。\n- 修复分类法(六种证据形态→修法映射表)、状态词汇多源漂移多数决收敛法、\n 测试防剧场增补(mock FieldMapper 须应用真实映射表)、环境坑增补\n (rogue next 遮蔽 3000/Prisma client 重启/非交互迁移纪律)。\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e\n","AuthorEmail":"luoguoguo@gmail.com","AuthorName":"luoguoguo","CommitterEmail":"luoguoguo@gmail.com","CommitterName":"luoguoguo","Timestamp":"2026-07-03T02:46:55-07:00"},"CompareURL":"luoanwu/juhi-omni-knowledge-hub/compare/7942f4d3803ea963e31be6aef86cd52dbd564635...da76fc5e9fcbc3f937fa2bee7743931f9b60e4db","Len":9}... |