ln-654-resource-lifecycle-auditor by levnikolaevich/claude-code-skills
npx skills add https://github.com/levnikolaevich/claude-code-skills --skill ln-654-resource-lifecycle-auditor路径说明: 文件路径(
shared/、references/、../ln-*)是相对于技能仓库根目录的。如果在当前工作目录未找到,请定位此 SKILL.md 文件所在的目录,然后向上返回一级以找到仓库根目录。如果缺少shared/目录,请通过 WebFetch 从https://raw.githubusercontent.com/levnikolaevich/claude-code-skills/master/skills/{path}获取文件。
专门审计资源获取/释放模式、作用域不匹配和连接池健康状况的工作器。
必读: 加载 shared/references/audit_worker_core_contract.md。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
接收包含以下内容的 contextStore:tech_stack、best_practices、db_config(数据库类型、ORM 设置、池配置、会话工厂)、codebase_root、output_dir。
领域感知: 支持 domain_mode + current_domain。
必读: 加载 shared/references/two_layer_detection.md 了解检测方法。
从 contextStore 解析上下文
检测依赖注入框架
Depends()、Django 中间件、Spring @Autowired/@PersistenceContext、Express 中间件、Go wire/fx发现资源基础设施
sessionmaker、create_engine、DataSource、池创建)Depends()、@Inject、providers、中间件挂载)扫描代码库中的违规情况(6 项检查)
收集发现结果,包含严重性、位置、工作量、建议
使用惩罚算法计算得分
编写报告: 根据 shared/templates/audit_worker_report_template.md 在内存中构建完整的 Markdown 报告,通过单次 Write 调用写入 {output_dir}/654-resource-lifecycle.md
返回摘要: 向协调器返回最小摘要(参见输出格式)
描述: 通过 DI 注入的资源在整个请求/连接作用域内存在,但仅在其中一小部分被使用。
检测(Python/FastAPI):
async def\s+\w+\(.*Depends\(get_db\)|Depends\(get_session\)|db:\s*AsyncSession|session:\s*AsyncSessionsession\.|db\.|await.*repo 使用之间的行数usage_lines / total_lines < 0.2(会话在函数主体中使用少于 20%)则标记
检测(Node.js/Express):
req.db 或 req.knexapp\.use.*pool|app\.use.*knex|app\.use.*prisma(中间件注入)req.db检测(Java/Spring):
@Transactional 但包含长时间的非 DB 处理EntityManager 但仅短暂使用@Autowired.*EntityManager|@PersistenceContext + 方法主体分析检测(Go):
sql.DB 或 *gorm.DB 传递给处理器,使用一次,然后进行长时间处理func.*Handler.*\*sql\.DB|func.*Handler.*\*gorm\.DB严重性:
建议: 将 DB 操作提取到作用域函数中;仅在需要时获取会话;使用 async with get_session() as session: 块,而不是端点级别的 DI 注入。
工作量: 中(重构 DI 为作用域获取)
描述: SSE、WebSocket 或长轮询端点在流持续时间内持有 DB 会话/连接。
检测(Python/FastAPI):
StreamingResponse|EventSourceResponse|SSE|async def.*websocket|@app\.websocketyield\s+.*event|yield\s+.*data:|async for.*yield(SSE 生成器模式)Depends() 的会话 -> 在整个流期间被持有检测(Node.js):
res\.write\(|res\.flush\(|Server-Sent Events|new WebSocket|ws\.on\(检测(Java/Spring):
SseEmitter|WebSocketHandler|StreamingResponseBody@Transactional 是否包装了流式方法检测(Go):
Flusher|http\.Flusher|websocket\.Conn*sql.DB 或事务是否在刷新循环期间被持有严重性:
建议: 将身份验证/权限检查移到流开始之前:获取会话,检查身份验证,释放会话,然后开始流式传输。对于流中任何 DB 访问,使用单独的作用域会话。
工作量: 中(重构端点以在流式传输前释放会话)
描述: 获取资源但没有保证的清理(没有 try/finally、没有上下文管理器、没有 close())。
检测(Python):
session\s*=\s*Session\(\)|session\s*=\s*sessionmaker|engine\.connect\(\) 不在 with 或 async with 内部connection\s*=\s*pool\.acquire\(\)|conn\s*=\s*await.*connect\(\) 后面没有 try:.*finally:.*close\(\)session = get_session() 没有上下文管理器async with session_factory() as session:、with engine.connect() as conn:检测(Node.js):
pool\.connect\(\)|knex\.client\.acquireConnection|\.getConnection\(\) 在同一函数中没有相应的 .release() 或 .end()createConnection\(\) 在 try/finally 中没有 .destroy()检测(Java):
getConnection\(\)|dataSource\.getConnection\(\) 没有 try-with-resourcesConnection conn = ds.getConnection() 没有 try (Connection conn = ...) 语法检测(Go):
sql\.Open\(|db\.Begin\(\) 没有 defer.*Close\(\)|defer.*Rollback\(\)tx, err := db.Begin() 没有 defer tx.Rollback()严重性:
例外: 在流式传输/长轮询开始之前获取并释放的会话 -> 跳过。NullPool / pool_size 配置记录为无服务器设计 -> 跳过。
建议: 确保在所有退出路径上清理资源(上下文管理器、try-finally 或框架管理的生命周期)。
工作量: 小(包装在上下文管理器中或添加 defer)
描述: 缺少池健康监控、没有预检、没有回收、没有溢出限制。
检测(Python/SQLAlchemy):
create_engine\(|create_async_engine\(:
pool_pre_ping=True -> 未检测到陈旧连接pool_recycle -> 连接保持时间超过 DB 服务器超时(默认:MySQL 8 小时,PG 无限制)pool_size -> 使用默认值 5(对于生产环境可能太小)max_overflow -> 高负载下无限制溢出pool_size=0 或 NullPool -> 无连接池(反模式)@event.listens_for(engine, "invalidate") -> 无法查看连接失效情况@event.listens_for(engine, "checkout") -> 无法监控连接检出@event.listens_for(engine, "checkin") -> 无法监控连接归还检测(Node.js):
createPool\(|new Pool\(:
min/max 配置idleTimeoutMillis 或 reapIntervalMillisvalidateConnection、testOnBorrow)检测(Java/Spring):
DataSource|HikariConfig|HikariDataSource:
leakDetectionThresholdmaximumPoolSize(默认为 10)connectionTestQuery 或 connectionInitSql检测(Go):
sql\.Open\(:
db.SetMaxOpenConns()db.SetMaxIdleConns()db.SetConnMaxLifetime()严重性:
上下文相关例外:
建议: 配置 pool_pre_ping=True,pool_recycle < DB 服务器超时,根据预期并发性设置适当的 pool_size,添加池事件监听器进行监控。
工作量: 小(添加配置参数),中(添加事件监听器/监控)
描述: 跳过资源清理的异常/错误处理路径。
检测(Python):
raise 或 return 但没有事先 session.close()、conn.close() 或 cursor.close() 的 except 块except Exception: logger.error(...); raise(重新抛出异常但没有清理)async def.*yield.*session|def.*yield.*session 没有 try:.*finally:.*close\(\)检测(Node.js):
catch\s*\( 块中 throw 或 return 但没有释放连接pool.connect().then(client => { ... }) 没有 .finally(() => client.release()).finally() 的 Promise 链检测(Java):
catch\s*\( 块中没有 finally { conn.close() },而连接在 try 中打开检测(Go):
if err != nil \{.*return 在用于资源清理的 defer 语句之前Open() 和 defer Close() 之间进行错误检查并返回而不关闭严重性:
建议: 在可能失败的代码之前使用上下文管理器/try-with-resources/defer;对于生成器,在 yield 周围添加 try/finally。
工作量: 小(在错误路径之前重构获取逻辑)
描述: 使用框架 DI 将短生命周期资源注入到长生命周期上下文中,而不是使用工厂模式。
检测(Python/FastAPI):
Depends\(get_db\)|Depends\(get_session\)|Depends\(get_async_session\)StreamingResponse、EventSourceResponse)、WebSocket(@app.websocket)、后台任务(BackgroundTasks.add_task)async with session_factory() as session:session: AsyncSession = Depends(get_session)检测(Node.js/Express):
req.db)在 WebSocket 处理器或 SSE 路由中使用const conn = await pool.connect(); try { ... } finally { conn.release() }检测(Java/Spring):
SseEmitter)的 @Controller 中使用 @Autowired EntityManager检测(Go):
*sql.DB 在处理器构造时注入,但应每次操作获取 *sql.Conn严重性:
建议: 对于长生命周期上下文使用工厂模式;注入工厂(sessionmaker、pool),而不是会话/连接本身。
工作量: 中(将 DI 从会话更改为会话工厂,添加作用域获取)
必读: 加载 shared/references/audit_worker_core_contract.md 和 shared/references/audit_scoring.md。
必读: 加载 shared/references/audit_worker_core_contract.md 和 shared/templates/audit_worker_report_template.md。
将报告写入 {output_dir}/654-resource-lifecycle.md,其中 category: "Resource Lifecycle" 和检查项:resource_scope_mismatch、streaming_resource_holding、missing_cleanup、pool_configuration、error_path_leak、factory_vs_injection。
向协调器返回摘要:
Report written: docs/project/.audit/ln-650/{YYYY-MM-DD}/654-resource-lifecycle.md
Score: X.X/10 | Issues: N (C:N H:N M:N L:N)
必读: 加载 shared/references/audit_worker_core_contract.md。
async with、with、try-with-resources、defer 内部的资源(已受管理)必读: 加载 shared/references/audit_worker_core_contract.md。
{output_dir}/654-resource-lifecycle.md(原子性单次 Write 调用)shared/references/audit_output_schema.md版本: 1.0.0 最后更新: 2026-03-03
每周安装次数
99
仓库
GitHub 星标数
253
首次出现
2026年3月3日
安全审计
安装于
claude-code93
cursor91
codex90
cline89
amp89
github-copilot89
Paths: File paths (
shared/,references/,../ln-*) are relative to skills repo root. If not found at CWD, locate this SKILL.md directory and go up one level for repo root. Ifshared/is missing, fetch files via WebFetch fromhttps://raw.githubusercontent.com/levnikolaevich/claude-code-skills/master/skills/{path}.
Specialized worker auditing resource acquisition/release patterns, scope mismatches, and connection pool hygiene.
MANDATORY READ: Load shared/references/audit_worker_core_contract.md.
Receives contextStore with: tech_stack, best_practices, db_config (database type, ORM settings, pool config, session factory), codebase_root, output_dir.
Domain-aware: Supports domain_mode + current_domain.
MANDATORY READ: Load shared/references/two_layer_detection.md for detection methodology.
Parse context from contextStore
Detect DI framework
Depends(), Django middleware, Spring @Autowired/@PersistenceContext, Express middleware, Go wire/fxDiscover resource infrastructure
sessionmaker, create_engine, DataSource, pool creation)Depends(), , providers, middleware mounting)What: Resource injected via DI lives for entire request/connection scope but is used for only a fraction of it.
Detection (Python/FastAPI):
async def\s+\w+\(.*Depends\(get_db\)|Depends\(get_session\)|db:\s*AsyncSession|session:\s*AsyncSessionsession\.|db\.|await.*repo usageusage_lines / total_lines < 0.2 (session used in <20% of function body)
Detection (Node.js/Express):
req.db or req.knex at request startapp\.use.*pool|app\.use.*knex|app\.use.*prisma (middleware injection)req.db only in first 20% of function bodyDetection (Java/Spring):
@Transactional on method with long non-DB processingEntityManager injected but used only briefly@Autowired.*EntityManager|@PersistenceContext + method body analysisDetection (Go):
sql.DB or *gorm.DB passed to handler, used once, then long processingfunc.*Handler.*\*sql\.DB|func.*Handler.*\*gorm\.DBSeverity:
Recommendation: Extract DB operations into scoped function; acquire session only for the duration needed; use async with get_session() as session: block instead of endpoint-level DI injection.
Effort: M (refactor DI to scoped acquisition)
What: SSE, WebSocket, or long-poll endpoint holds DB session/connection for stream duration.
Detection (Python/FastAPI):
StreamingResponse|EventSourceResponse|SSE|async def.*websocket|@app\.websocketyield\s+.*event|yield\s+.*data:|async for.*yield (SSE generator pattern)Depends() in endpoint signature -> held for entire streamDetection (Node.js):
res\.write\(|res\.flush\(|Server-Sent Events|new WebSocket|ws\.on\(Detection (Java/Spring):
SseEmitter|WebSocketHandler|StreamingResponseBody@Transactional wraps streaming methodDetection (Go):
Flusher|http\.Flusher|websocket\.Conn*sql.DB or transaction held during flush loopSeverity:
Recommendation: Move auth/permission check BEFORE stream: acquire session, check auth, release session, THEN start streaming. Use separate scoped session for any mid-stream DB access.
Effort: M (restructure endpoint to release session before streaming)
What: Resource acquired without guaranteed cleanup (no try/finally, no context manager, no close()).
Detection (Python):
session\s*=\s*Session\(\)|session\s*=\s*sessionmaker|engine\.connect\(\) NOT inside with or async withconnection\s*=\s*pool\.acquire\(\)|conn\s*=\s*await.*connect\(\) NOT followed by try:.*finally:.*close\(\)session = get_session() without context managerasync with session_factory() as session:, with engine.connect() as conn:Detection (Node.js):
pool\.connect\(\)|knex\.client\.acquireConnection|\.getConnection\(\) without corresponding .release() or .end() in same functioncreateConnection\(\) without .destroy() in try/finallyDetection (Java):
getConnection\(\)|dataSource\.getConnection\(\) without try-with-resourcesConnection conn = ds.getConnection() without try (Connection conn = ...) syntaxDetection (Go):
sql\.Open\(|db\.Begin\(\) without defer.*Close\(\)|defer.*Rollback\(\)tx, err := db.Begin() without defer tx.Rollback()Severity:
Exception: Session acquired and released before streaming/long-poll begins → skip. NullPool / pool_size config documented as serverless design → skip.
Recommendation: Ensure resources are cleaned up on all exit paths (context managers, try-finally, or framework-managed lifecycle).
Effort: S (wrap in context manager or add defer)
What: Missing pool health monitoring, no pre-ping, no recycle, no overflow limits.
Detection (Python/SQLAlchemy):
create_engine\(|create_async_engine\(:
pool_pre_ping=True -> stale connections not detectedpool_recycle -> connections kept beyond DB server timeout (default: MySQL 8h, PG unlimited)pool_size -> uses default 5 (may be too small for production)max_overflow -> unbounded overflow under loadpool_size=0 or NullPool in web service -> no pooling (anti-pattern)@event.listens_for(engine, "invalidate") -> no visibility into connection invalidationDetection (Node.js):
createPool\(|new Pool\(:
min/max configurationidleTimeoutMillis or reapIntervalMillisvalidateConnection, testOnBorrow)Detection (Java/Spring):
DataSource|HikariConfig|HikariDataSource:
leakDetectionThresholdmaximumPoolSize (defaults to 10)connectionTestQuery or connectionInitSqlDetection (Go):
sql\.Open\(:
db.SetMaxOpenConns()db.SetMaxIdleConns()db.SetConnMaxLifetime()Severity:
Context-dependent exceptions:
Recommendation: Configure pool_pre_ping=True, pool_recycle < DB server timeout, appropriate pool_size for expected concurrency, add pool event listeners for monitoring.
Effort: S (add config parameters), M (add event listeners/monitoring)
What: Exception/error handling paths that skip resource cleanup.
Detection (Python):
except blocks containing raise or return without prior session.close(), conn.close(), or cursor.close()except Exception: logger.error(...); raise (re-raise without cleanup)async def.*yield.*session|def.*yield.*session without try:.*finally:.*close\(\)Detection (Node.js):
catch\s*\( blocks that throw or return without releasing connectionpool.connect().then(client => { ... }) without .finally(() => client.release()).finally() for cleanupDetection (Java):
catch\s*\( blocks without finally { conn.close() } when connection opened in tryDetection (Go):
if err != nil \{.*return before defer statement for resource cleanupOpen() and defer Close() that returns without closingSeverity:
Recommendation: Use context managers/try-with-resources/defer BEFORE any code that can fail; for generators, add try/finally around yield.
Effort: S (restructure acquisition to before-error-path)
What: Using framework DI to inject short-lived resources into long-lived contexts instead of using factory pattern.
Detection (Python/FastAPI):
Depends\(get_db\)|Depends\(get_session\)|Depends\(get_async_session\)StreamingResponse, EventSourceResponse), WebSocket (@app.websocket), background task (BackgroundTasks.add_task)async with session_factory() as session: at point of needsession: AsyncSession = Depends(get_session) at endpoint levelDetection (Node.js/Express):
req.db) used in WebSocket handler or SSE routeconst conn = await pool.connect(); try { ... } finally { conn.release() } at point of needDetection (Java/Spring):
@Autowired EntityManager in @Controller with SSE endpoint (SseEmitter)Detection (Go):
*sql.DB injected at handler construction time but *sql.Conn should be acquired per-operationSeverity:
Recommendation: Use factory pattern for long-lived contexts; inject the factory (sessionmaker, pool), not the session/connection itself.
Effort: M (change DI from session to session factory, add scoped acquisition)
MANDATORY READ: Load shared/references/audit_worker_core_contract.md and shared/references/audit_scoring.md.
MANDATORY READ: Load shared/references/audit_worker_core_contract.md and shared/templates/audit_worker_report_template.md.
Write report to {output_dir}/654-resource-lifecycle.md with category: "Resource Lifecycle" and checks: resource_scope_mismatch, streaming_resource_holding, missing_cleanup, pool_configuration, error_path_leak, factory_vs_injection.
Return summary to coordinator:
Report written: docs/project/.audit/ln-650/{YYYY-MM-DD}/654-resource-lifecycle.md
Score: X.X/10 | Issues: N (C:N H:N M:N L:N)
MANDATORY READ: Load shared/references/audit_worker_core_contract.md.
async with, with, try-with-resources, defer (already managed)MANDATORY READ: Load shared/references/audit_worker_core_contract.md.
{output_dir}/654-resource-lifecycle.md (atomic single Write call)shared/references/audit_output_schema.mdVersion: 1.0.0 Last Updated: 2026-03-03
Weekly Installs
99
Repository
GitHub Stars
253
First Seen
Mar 3, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
claude-code93
cursor91
codex90
cline89
amp89
github-copilot89
Skills CLI 使用指南:AI Agent 技能包管理器安装与管理教程
44,900 周安装
Assess技能:AI代码评估工具,提供结构化评分与改进建议 | Claude钩子集成
77 周安装
verify 技能:AI驱动代码验证工具 - 并行代理测试、安全审计与质量评分
77 周安装
Tailwind CSS 4 最佳实践指南:样式决策树、cn()函数使用与核心规则
77 周安装
OpenAI Agents Python 最终发布评审指南:自动化发布流程与风险管理
77 周安装
API安全加固指南:多层防护REST API,防御常见漏洞攻击(Express/Node.js)
77 周安装
前端设计技能:告别AI垃圾美学,创建独特、生产级前端界面与代码
77 周安装
@InjectScan codebase for violations (6 checks)
Collect findings with severity, location, effort, recommendation
Calculate score using penalty algorithm
Write Report: Build full markdown report in memory per shared/templates/audit_worker_report_template.md, write to {output_dir}/654-resource-lifecycle.md in single Write call
Return Summary: Return minimal summary to coordinator (see Output Format)
@event.listens_for(engine, "checkout") -> no connection checkout monitoring@event.listens_for(engine, "checkin") -> no connection return monitoring