mcpField
L
ln-652-transaction-correctness-auditor

ln-652-transaction-correctness-auditor

github.com/levnikolaevich数据与数据库584370 次安装2 天前更新
代码仓库

关于 ln-652-transaction-correctness-auditor

专门审查数据库事务正确性、范围及触发器交互的工作者技能。它会生成按严重程度分类的发现和合规评分,但不会修改代码。

主要功能

  1. 01检查事务边界与提交
  2. 02审查回滚处理
  3. 03检查触发器和通知行为
  4. 04比对事件发布方与订阅方
  5. 05生成结构化报告和评分

适用场景

  1. 01审计代码库中的事务处理
  2. 02查找影响通知的提交缺失
  3. 03识别范围过宽或拆分过细的事务

MCP 相关

如可用,该技能优先使用 hex-line MCP 读取、搜索和编辑文件,并在引用链或调用路径有帮助时使用 hex-graph。MCP 不可用或不受支持时则使用内置工具。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/levnikolaevich/claude-code-skills --skill ln-652-transaction-correctness-auditor

安装后在 Claude Code 中输入/ln-652-transaction-correctness-auditor确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
audit_output_schema.md
audit_scoring.md
audit_summary_contract.md
audit_worker_core_contract.md
mcp_integration_patterns.md
mcp_tool_preferences.md
two_layer_detection.md
references/templates/
audit_worker_report_template.md

详细介绍

**路径:**文件路径(references/、../ln-*)均相对于此技能目录。

事务正确性审计员(L3 Worker)

**类型:**L3 Worker

专门审计数据库事务模式的正确性、范围和触发器交互的 Worker。

用途与范围

  • 审计事务正确性(优先级:高)
  • 检查提交模式、事务边界、回滚处理以及触发器/通知语义
  • 将结构化发现写入文件,包含严重程度、位置、工作量和建议
  • 计算事务正确性类别的合规评分(X/10)

输入

**必须读取:**加载 references/audit_worker_core_contract.md 和 references/mcp_tool_preferences.md。 工具策略:你可能作为独立子 Agent 运行,此时宿主的 AGENTS.md 不在适用范围内,因此读取文件、搜索和编辑时默认优先使用 hex-line MCP。只有在 MCP 行为不明确时才加载 references/mcp_integration_patterns.md。

接收包含以下内容的 contextStore:tech_stack、best_practices、db_config(数据库类型、ORM 设置、触发器/通知模式)、codebase_root、output_dir。

**支持领域感知:**支持 domain_mode 和 current_domain。

当引用链或调用路径能实质性改善事务分析时,优先使用 hex-graph。若可用,则本地代码/配置读取优先使用 hex-line。如果 MCP 不可用、不受支持或未建立索引,则继续使用内置的 Read/Grep/Glob/Bash,并在报告中说明回退情况。

工作流程

检测策略:采用两层检测(候选扫描,然后上下文验证);仅在验证方法不明确时加载 references/two_layer_detection.md。

  1. 从 contextStore 解析上下文

    • 提取 tech_stack、best_practices、db_config、output_dir
    • 确定 scan_path
  2. 发现事务基础设施

    • 查找包含触发器的迁移文件(pg_notify、CREATE TRIGGER、NOTIFY)
    • 查找会话/事务配置(expire_on_commit、autocommit、隔离级别)
    • 梳理受触发器影响的表
  3. 扫描代码库中的违规项

    • 跟踪受触发器影响表的 UPDATE 路径
    • 分析事务边界(begin/commit 范围)
    • 检查提交操作周围的错误处理
  4. 收集发现,包含严重程度、位置、工作量和建议

  5. 使用惩罚算法计算评分

  6. **编写报告:**按照 references/templates/audit_worker_report_template.md 在内存中构建完整的 Markdown 报告,并通过单次 Write 调用写入 {output_dir}/ln-652--global.md

  7. **返回摘要:**向协调器返回最简摘要(参见输出格式)

审计规则(优先级:高)

1. 缺少中间提交

问题: UPDATE 后未提交,但数据库触发器/NOTIFY 依赖事务提交

检测:

  • 步骤 1: 在迁移文件中查找触发器:
    • 在 alembic/versions/、migrations/ 中搜索 pg_notify|NOTIFY|CREATE TRIGGER|CREATE OR REPLACE FUNCTION.*trigger
    • 提取:触发器函数名称、表名、触发事件(INSERT/UPDATE)
  • 步骤 2: 查找会更新受触发器影响的表的代码:
    • 搜索与触发器表相关的 repo.*update|session\.execute.*update|\.progress|\.status
  • 步骤 3: 检查连续更新之间是否调用了 commit():
    • 如果在循环或一系列操作中,对触发器表执行了多次 UPDATE,却未在中间调用 commit(),则 NOTIFY 事件会延迟到最终提交时才触发
    • 没有中间提交会导致实时进度跟踪失效

严重级别:

  • 严重: 基于 NOTIFY/LISTEN 的实时功能(SSE、WebSocket)缺少提交
  • 高: 会更新物化数据的触发器缺少提交

例外情况: 单个原子操作且没有可观察的中间状态 → 将严重级别从严重下调为中等。若事务范围有文档说明其为有意设计(ADR、架构注释)→ 下调一个级别

建议:

  • 在进度里程碑处调用 session.commit()(限频:每达到 N% 或每隔 T 秒)
  • 或将实时通知移出数据库触发器(使用 Redis pub/sub、进程内事件)

工作量: S-M(添加策略性提交或重新设计通知路径)

2. 事务范围过大

问题: 单个事务包含无关操作,包括耗时较长的外部调用

检测:

  • 查找 async with session.begin() 或显式事务代码块
  • 检查代码块中是否包含外部调用:await httpx.、await aiohttp.、await requests.、await grpc.
  • 检查代码块中是否包含文件 I/O:open(、.read(、.write(
  • 模式:同一事务中包含数据库写入 + 外部 API 调用 + 另一次数据库写入

严重级别:

  • 高: 事务内有外部 HTTP/gRPC 调用(网络延迟期间会占用数据库连接)
  • 中等: 事务内有文件 I/O

建议: 拆分为多个事务;使用 Saga/Outbox 模式保证跨服务一致性

工作量: M-L(重新组织事务边界)

3. 事务范围过窄

问题: 逻辑上应为原子操作的操作被拆分到多个提交中

检测:

  • 对应当保持原子性的操作多次调用 session.commit()
  • 模式:创建父实体后提交,再创建子实体并提交(应在单个事务中完成)
  • 模式:更新状态与创建审计日志分开提交

严重级别:

  • 高: 父子实体分开提交(失败时有产生孤立数据的风险)
  • 中等: 相关更新分开提交(失败时状态不一致)

建议: 使用 async with session.begin() 或工作单元模式,将相关操作封装在单个事务中

工作量: M(重新组织提交边界)

4. 缺少回滚处理

问题: 调用 session.commit() 时未妥善处理错误和回滚

检测:

  • 查找未置于 try/except 代码块或上下文管理器中的 session.commit()
  • 查找位于 try 中、但 except 中没有 session.rollback() 的 session.commit()
  • 模式:服务方法中直接调用 await session.commit()
  • 例外:async with session.begin() 会自动回滚(安全)

严重级别:

  • 中等: 缺少回滚(失败后会话会处于损坏状态)
  • 低: 使用上下文管理器时缺少显式回滚(会自动处理)

建议: 使用 async with session.begin()(自动回滚),或添加显式的 try/except/rollback 模式

工作量: S(使用上下文管理器封装或添加错误处理)

5. 长时间持有事务

内容: 事务在缓慢或阻塞操作期间保持打开状态

检测:

  • 衡量作用域:统计事务开始到提交之间的代码行数
  • 如果 begin() 和 commit() 之间超过 50 行代码,则标记
  • 如果事务中包含对外部服务的 await 调用(网络延迟),则标记
  • 如果事务中包含 time.sleep() 或 asyncio.sleep(),则标记

严重程度:

  • HIGH: 事务在外部 API 调用期间保持打开状态(存在连接池耗尽风险)
  • MEDIUM: 事务跨越超过 50 行代码(逻辑复杂,发生锁竞争的可能性较高)

建议: 尽量缩小事务范围;在开启事务前准备数据,并在数据库操作完成后立即提交

工作量: M(重构代码以缩短事务窗口)

6. 事件频道名称一致性

内容: 发布者的频道/主题名称与订阅者的频道/主题名称不匹配

检测:

  • 步骤 1: 收集发布者的频道名称(扩展第 2 阶段的触发器发现):
    • 迁移触发器:从 pg_notify('channel_name', ...)、NOTIFY channel_name 中提取字符串参数
    • 应用代码:在 src/、app/ 中搜索 \.publish\(["']|\.emit\(["']|redis.*publish\(["']|\.send_to\(["']
    • 提取:{channel_name, source_file, source_line, technology}
  • 步骤 2: 收集订阅者的频道名称:
    • PostgreSQL:在应用代码中(不只是迁移文件)搜索 LISTEN\s+(\w+)
    • Redis:在 src/、app/ 中搜索 \.subscribe\(["']([^"']+)
    • EventEmitter/WebSocket:在处理程序/监听器目录中搜索 \.on\(["']([^"']+)
    • 提取:{channel_name, source_file, source_line, technology}
  • 步骤 3: 交叉核对发布者与订阅者:
    • 完全匹配:publisher.channel_name == subscriber.channel_name -> 正常
    • 近似不匹配:Levenshtein 距离 <= 2,或其中一个是另一个的子串 -> 标记为不匹配
    • 孤立发布者:频道存在于发布者中,但不存在于订阅者中 -> 标记为孤立
    • 孤立订阅者:频道存在于订阅者中,但不存在于发布者中 -> 标记为孤立

第 2 层上下文分析(强制):

  • 如果频道名称来自共享配置常量或环境变量(例如 CHANNEL = os.environ["EVENT_CHANNEL"]),且发布者和订阅者使用相同来源 -> 不属于不匹配
  • 如果频道使用动态后缀模式(例如 job_events:{job_id}),且两端使用相同模板 -> 不属于孤立
  • 从发布者和订阅者发现结果中排除测试文件(**/test*/**、**/*.test.*)

严重程度:

  • CRITICAL: 频道名称不匹配(近似不匹配:发布者向 job_events 发送事件,订阅者却监听 job_event)
  • HIGH: 孤立发布者——事件已发送但从未被消费(如果事件携带状态变更,则存在数据丢失风险)
  • MEDIUM: 孤立订阅者——已注册监听器,但未找到发布者(死代码或未来功能)

建议:

  • 对于不匹配:统一频道名称,在发布者和订阅者之间共享同一个常量
  • 对于孤立发布者:添加订阅者,或移除未使用的 NOTIFY/发布操作
  • 对于孤立订阅者:添加发布者,或移除无用的监听器

工作量: S(修复拼写错误/添加常量)到 M(设计缺失的订阅者/发布者)

评分算法

必须阅读: 加载 references/audit_scoring.md。

输出格式

务必阅读: 加载 references/templates/audit_worker_report_template.md。

按照 references/audit_summary_contract.md 编写 JSON 摘要。在托管模式下,调用方会同时传入 runId 和 summaryArtifactPath;在独立模式下,工作器会按照共享契约生成自己的运行专属产物路径。

将报告写入 {output_dir}/ln-652--global.md,并设置 category: "Transaction Correctness",检查项包括:missing_intermediate_commits、scope_too_wide、scope_too_narrow、missing_rollback、long_held_transaction、event_channel_consistency。

按照 references/audit_summary_contract.md 返回摘要。

当 summaryArtifactPath 缺失时,将独立模式的运行时摘要写入 .hex-skills/runtime-artifacts/runs/{run_id}/evaluation-worker/{worker}--{identifier}.json,并可选择在结构化输出中回显相同摘要。

Report written: .hex-skills/runtime-artifacts/runs/{run_id}/audit-report/ln-652--global.md
Score: X.X/10 | Issues: N (C:N H:N M:N L:N)

关键规则

遵循已加载的 references/audit_worker_core_contract.md。

  • 不要自动修复: 仅报告
  • 先发现触发器: 分析事务模式前,始终先扫描迁移文件中的触发器/NOTIFY
  • 考虑 ORM: 检查 ORM 上下文管理器是否会自动回滚(async with session.begin() 是安全的)
  • 排除测试事务: 不要标记使用手动提交/回滚的测试夹具
  • 考虑数据库差异: PostgreSQL 的 NOTIFY 语义与 MySQL 事件调度器不同

完成标准

遵循已加载的 references/audit_worker_core_contract.md。

  • contextStore 已成功解析(包括 output_dir)
  • 已确定 scan_path
  • 已从迁移文件中发现触发器/NOTIFY 基础设施
  • 已完成全部 6 项检查:
    • 缺少中间提交、范围过宽、范围过窄、缺少回滚、事务持有时间过长、事件通道一致性
  • 已收集问题,包含严重程度、位置、工作量和建议
  • 已使用惩罚算法计算评分
  • 已将报告写入 {output_dir}/ln-652--global.md(通过一次原子 Write 调用)
  • 已按照契约写入摘要

参考文件

  • 审计输出架构: references/audit_output_schema.md

版本: 1.1.0 最后更新: 2026-03-15

评论

支持 Markdown