ln-654-resource-lifecycle-auditor

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
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.
路径: 文件路径(
shared/
references/
../ln-*
)是相对于技能仓库根目录的。如果在当前工作目录未找到,请定位到本SKILL.md所在目录,然后向上一级即为仓库根目录。

Resource Lifecycle Auditor (L3 Worker)

资源生命周期审计器(L3 Worker)

Specialized worker auditing resource acquisition/release patterns, scope mismatches, and connection pool hygiene.
专门用于审计资源获取/释放模式、范围不匹配以及连接池健康状况的Worker。

Purpose & Scope

目标与范围

  • Worker in ln-650 coordinator pipeline - invoked by ln-650-persistence-performance-auditor
  • Audit resource lifecycle (Priority: HIGH)
  • Check session/connection scope mismatch, streaming endpoint resource holding, cleanup patterns, pool config
  • Write structured findings to file with severity, location, effort, recommendations
  • Calculate compliance score (X/10) for Resource Lifecycle category
  • ln-650协调器流水线中的Worker - 由ln-650-persistence-performance-auditor调用
  • 审计资源生命周期(优先级:高)
  • 检查会话/连接范围不匹配、流式端点资源持有、资源清理模式、连接池配置
  • 将结构化检查结果写入文件,包含严重程度、位置、修复工作量及建议
  • 计算资源生命周期类别的合规分数(X/10)

Inputs (from Coordinator)

输入(来自协调器)

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
.
必读: 加载
shared/references/audit_worker_core_contract.md
接收包含以下内容的
contextStore
tech_stack
best_practices
db_config
(数据库类型、ORM设置、连接池配置、会话工厂)、
codebase_root
output_dir
领域感知: 支持
domain_mode
+
current_domain

Workflow

工作流程

MANDATORY READ: Load
shared/references/two_layer_detection.md
for detection methodology.
  1. Parse context from contextStore
    • Extract tech_stack, best_practices, db_config, output_dir
    • Determine scan_path
  2. Detect DI framework
    • FastAPI
      Depends()
      , Django middleware, Spring
      @Autowired
      /
      @PersistenceContext
      , Express middleware, Go wire/fx
  3. Discover resource infrastructure
    • Find session/connection factory patterns (
      sessionmaker
      ,
      create_engine
      ,
      DataSource
      , pool creation)
    • Find DI registration (
      Depends()
      ,
      @Inject
      , providers, middleware mounting)
    • Find streaming endpoints (SSE, WebSocket, long-poll, streaming response)
    • Map: which endpoints receive which resources via DI
  4. Scan codebase for violations (6 checks)
    • Trace resource injection -> usage -> release across endpoint lifetime
    • Analyze streaming endpoints for held resources
    • Check error paths for cleanup
  5. Collect findings with severity, location, effort, recommendation
  6. Calculate score using penalty algorithm
  7. 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
  8. Return Summary: Return minimal summary to coordinator (see Output Format)
必读: 加载
shared/references/two_layer_detection.md
以了解检测方法。
  1. 解析contextStore中的上下文
    • 提取tech_stack、best_practices、db_config、output_dir
    • 确定扫描路径
  2. 检测DI框架
    • FastAPI的
      Depends()
      、Django中间件、Spring的
      @Autowired
      /
      @PersistenceContext
      、Express中间件、Go的wire/fx
  3. 发现资源基础设施
    • 查找会话/连接工厂模式(
      sessionmaker
      create_engine
      DataSource
      、连接池创建)
    • 查找DI注册(
      Depends()
      @Inject
      、提供者、中间件挂载)
    • 查找流式端点(SSE、WebSocket、长轮询、流式响应)
    • 映射:哪些端点通过DI接收哪些资源
  4. 扫描代码库以查找违规问题(6项检查)
    • 跟踪资源注入 -> 使用 -> 释放的全端点生命周期
    • 分析流式端点的资源持有情况
    • 检查错误路径中的资源清理
  5. 收集包含严重程度、位置、工作量及建议的检查结果
  6. 使用惩罚算法计算分数
  7. 生成报告: 根据
    shared/templates/audit_worker_report_template.md
    在内存中构建完整的Markdown报告,通过单次写入操作保存到
    {output_dir}/654-resource-lifecycle.md
  8. 返回摘要: 向协调器返回极简摘要(参见输出格式)

Audit Rules (Priority: HIGH)

审计规则(优先级:高)

1. Resource Scope Mismatch

1. 资源范围不匹配

What: Resource injected via DI lives for entire request/connection scope but is used for only a fraction of it.
Detection (Python/FastAPI):
  • Step 1 - Find endpoints with DB session dependency:
    • Grep:
      async def\s+\w+\(.*Depends\(get_db\)|Depends\(get_session\)|db:\s*AsyncSession|session:\s*AsyncSession
  • Step 2 - Measure session usage span within endpoint body:
    • Count lines between first and last
      session\.|db\.|await.*repo
      usage
    • Count total lines in endpoint function body
  • Step 3 - Flag if
    usage_lines / total_lines < 0.2
    (session used in <20% of function body)
    • Especially: session used only at function start (auth check, initial load) but function continues with non-DB work
Detection (Node.js/Express):
  • Middleware injects
    req.db
    or
    req.knex
    at request start
  • Grep:
    app\.use.*pool|app\.use.*knex|app\.use.*prisma
    (middleware injection)
  • Route handler uses
    req.db
    only in first 20% of function body
Detection (Java/Spring):
  • @Transactional
    on method with long non-DB processing
  • EntityManager
    injected but used only briefly
  • Grep:
    @Autowired.*EntityManager|@PersistenceContext
    + method body analysis
Detection (Go):
  • sql.DB
    or
    *gorm.DB
    passed to handler, used once, then long processing
  • Grep:
    func.*Handler.*\*sql\.DB|func.*Handler.*\*gorm\.DB
Severity:
  • CRITICAL: Session scope mismatch in streaming endpoint (SSE, WebSocket) - session held for minutes/hours
  • HIGH: Session scope mismatch in endpoint with external API calls (session held during network latency)
  • MEDIUM: Session scope mismatch in endpoint with >50 lines of non-DB processing
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)
问题描述: 通过DI注入的资源在整个请求/连接范围内存在,但仅在其中一小部分时间被使用。
检测方式(Python/FastAPI):
  • 步骤1 - 查找带有数据库会话依赖的端点:
    • 匹配:
      async def\s+\w+\(.*Depends\(get_db\)|Depends\(get_session\)|db:\s*AsyncSession|session:\s*AsyncSession
  • 步骤2 - 测量端点函数体内会话的使用跨度:
    • 统计首次和最后一次
      session\.|db\.|await.*repo
      使用之间的代码行数
    • 统计端点函数体的总行数
  • 步骤3 - 如果
    使用行数 / 总行数 < 0.2
    (会话仅在不到20%的函数体中被使用),则标记为违规:
    • 尤其注意:会话仅在函数开头(权限校验、初始加载)使用,但函数后续执行非数据库相关操作
检测方式(Node.js/Express):
  • 中间件在请求开始时注入
    req.db
    req.knex
  • 匹配:
    app\.use.*pool|app\.use.*knex|app\.use.*prisma
    (中间件注入)
  • 路由处理程序仅在函数体前20%的代码中使用
    req.db
检测方式(Java/Spring):
  • 带有
    @Transactional
    注解的方法包含长时间非数据库处理
  • 注入了
    EntityManager
    但仅短暂使用
  • 匹配:
    @Autowired.*EntityManager|@PersistenceContext
    + 方法体分析
检测方式(Go):
  • sql.DB
    *gorm.DB
    被传递给处理程序,仅使用一次,之后进行长时间处理
  • 匹配:
    func.*Handler.*\*sql\.DB|func.*Handler.*\*gorm\.DB
严重程度:
  • CRITICAL(严重): 流式端点(SSE、WebSocket)中的会话范围不匹配 - 会话被持有数分钟/数小时
  • HIGH(高): 包含外部API调用的端点中的会话范围不匹配 - 会话在网络延迟期间被持有
  • MEDIUM(中): 包含超过50行非数据库处理代码的端点中的会话范围不匹配
建议: 将数据库操作提取到作用域函数中;仅在需要的时间段内获取会话;使用
async with get_session() as session:
代码块替代端点级别的DI注入。
修复工作量: M(重构DI以支持作用域内获取)

2. Streaming Endpoint Resource Holding

2. 流式端点资源持有

What: SSE, WebSocket, or long-poll endpoint holds DB session/connection for stream duration.
Detection (Python/FastAPI):
  • Step 1 - Find streaming endpoints:
    • Grep:
      StreamingResponse|EventSourceResponse|SSE|async def.*websocket|@app\.websocket
    • Grep:
      yield\s+.*event|yield\s+.*data:|async for.*yield
      (SSE generator pattern)
  • Step 2 - Check if streaming function/generator has DB session in scope:
    • Session from
      Depends()
      in endpoint signature -> held for entire stream
    • Session from context manager inside generator -> scoped (OK)
  • Step 3 - Analyze session usage inside generator:
    • If session used once at start (auth/permission check) then stream loops without DB -> scope mismatch
Detection (Node.js):
  • Grep:
    res\.write\(|res\.flush\(|Server-Sent Events|new WebSocket|ws\.on\(
  • Check if connection/pool client acquired before stream loop and not released
Detection (Java/Spring):
  • Grep:
    SseEmitter|WebSocketHandler|StreamingResponseBody
  • Check if
    @Transactional
    wraps streaming method
Detection (Go):
  • Grep:
    Flusher|http\.Flusher|websocket\.Conn
  • Check if
    *sql.DB
    or transaction held during flush loop
Severity:
  • CRITICAL: DB session/connection held for entire SSE/WebSocket stream duration (pool exhaustion under load)
  • HIGH: DB connection held during long-poll (>30s timeout)
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)
问题描述: SSE、WebSocket或长轮询端点在整个流持续期间持有数据库会话/连接。
检测方式(Python/FastAPI):
  • 步骤1 - 查找流式端点:
    • 匹配:
      StreamingResponse|EventSourceResponse|SSE|async def.*websocket|@app\.websocket
    • 匹配:
      yield\s+.*event|yield\s+.*data:|async for.*yield
      (SSE生成器模式)
  • 步骤2 - 检查流式函数/生成器的作用域中是否包含数据库会话:
    • 端点签名中来自
      Depends()
      的会话 -> 会在整个流期间被持有
    • 生成器内部上下文管理器中的会话 -> 作用域正确(合规)
  • 步骤3 - 分析生成器内部的会话使用情况:
    • 如果会话仅在开始时使用一次(权限校验),之后流循环不涉及数据库 -> 范围不匹配
检测方式(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
    或事务是否在刷新循环期间被持有
严重程度:
  • CRITICAL(严重): 数据库会话/连接在整个SSE/WebSocket流持续期间被持有(负载下会导致连接池耗尽)
  • HIGH(高): 数据库连接在长轮询期间被持有(超时>30秒)
建议: 将权限校验移至流开始前:获取会话,校验权限,释放会话,然后开始流式传输。对于流中间的数据库访问,使用独立的作用域会话。
修复工作量: M(重构端点以在流式传输前释放会话)

3. Missing Resource Cleanup Patterns

3. 缺失资源清理模式

What: Resource acquired without guaranteed cleanup (no try/finally, no context manager, no close()).
Detection (Python):
  • Grep:
    session\s*=\s*Session\(\)|session\s*=\s*sessionmaker|engine\.connect\(\)
    NOT inside
    with
    or
    async with
  • Grep:
    connection\s*=\s*pool\.acquire\(\)|conn\s*=\s*await.*connect\(\)
    NOT followed by
    try:.*finally:.*close\(\)
  • Pattern: bare
    session = get_session()
    without context manager
  • Safe patterns to exclude:
    async with session_factory() as session:
    ,
    with engine.connect() as conn:
Detection (Node.js):
  • Grep:
    pool\.connect\(\)|knex\.client\.acquireConnection|\.getConnection\(\)
    without corresponding
    .release()
    or
    .end()
    in same function
  • Grep:
    createConnection\(\)
    without
    .destroy()
    in try/finally
Detection (Java):
  • Grep:
    getConnection\(\)|dataSource\.getConnection\(\)
    without try-with-resources
  • Pattern:
    Connection conn = ds.getConnection()
    without
    try (Connection conn = ...)
    syntax
Detection (Go):
  • Grep:
    sql\.Open\(|db\.Begin\(\)
    without
    defer.*Close\(\)|defer.*Rollback\(\)
  • Pattern:
    tx, err := db.Begin()
    without
    defer tx.Rollback()
Severity:
  • HIGH: Session/connection acquired without cleanup guarantee (leak on exception)
  • MEDIUM: File handle or cursor without cleanup in non-critical path
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)
问题描述: 获取资源但未保证进行清理(无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-resources
  • 模式:
    Connection conn = ds.getConnection()
    未使用
    try (Connection conn = ...)
    语法
检测方式(Go):
  • 匹配:
    sql\.Open\(|db\.Begin\(\)
    且无
    defer.*Close\(\)|defer.*Rollback\(\)
  • 模式:
    tx, err := db.Begin()
    defer tx.Rollback()
严重程度:
  • HIGH(高): 获取会话/连接但未保证清理(异常时会导致泄漏)
  • MEDIUM(中): 非关键路径中文件句柄或游标未进行清理
例外情况: 会话在流式传输/长轮询开始前获取并释放 → 跳过。NullPool /
pool_size
配置被记录为无服务器设计 → 跳过。
建议: 确保在所有退出路径上清理资源(上下文管理器、try-finally或框架管理的生命周期)。
修复工作量: S(包裹在上下文管理器中或添加defer)

4. Connection Pool Configuration Gaps

4. 连接池配置缺陷

What: Missing pool health monitoring, no pre-ping, no recycle, no overflow limits.
Detection (Python/SQLAlchemy):
  • Grep for
    create_engine\(|create_async_engine\(
    :
    • Missing
      pool_pre_ping=True
      -> stale connections not detected
    • Missing
      pool_recycle
      -> connections kept beyond DB server timeout (default: MySQL 8h, PG unlimited)
    • Missing
      pool_size
      -> uses default 5 (may be too small for production)
    • Missing
      max_overflow
      -> unbounded overflow under load
    • pool_size=0
      or
      NullPool
      in web service -> no pooling (anti-pattern)
  • Grep for pool event listeners:
    • Missing
      @event.listens_for(engine, "invalidate")
      -> no visibility into connection invalidation
    • Missing
      @event.listens_for(engine, "checkout")
      -> no connection checkout monitoring
    • Missing
      @event.listens_for(engine, "checkin")
      -> no connection return monitoring
Detection (Node.js):
  • Grep for
    createPool\(|new Pool\(
    :
    • Missing
      min
      /
      max
      configuration
    • Missing
      idleTimeoutMillis
      or
      reapIntervalMillis
    • Missing connection validation (
      validateConnection
      ,
      testOnBorrow
      )
Detection (Java/Spring):
  • Grep:
    DataSource|HikariConfig|HikariDataSource
    :
    • Missing
      leakDetectionThreshold
    • Missing
      maximumPoolSize
      (defaults to 10)
    • Missing
      connectionTestQuery
      or
      connectionInitSql
Detection (Go):
  • Grep:
    sql\.Open\(
    :
    • Missing
      db.SetMaxOpenConns()
    • Missing
      db.SetMaxIdleConns()
    • Missing
      db.SetConnMaxLifetime()
Severity:
  • HIGH: No pool_pre_ping AND no pool_recycle (stale connections served silently)
  • HIGH: No max_overflow limit in web service (unbounded connection creation under load)
  • MEDIUM: Missing pool event listeners (no visibility into pool health)
  • MEDIUM: Missing leak detection threshold (Java/HikariCP)
  • LOW: Pool size at default value (may be adequate for small services)
Context-dependent exceptions:
  • NullPool is valid for serverless/Lambda
  • pool_size=5 may be fine for low-traffic services
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)
问题描述: 缺失连接池健康监控、无预 ping、无连接回收、无溢出限制。
检测方式(Python/SQLAlchemy):
  • 匹配
    create_engine\(|create_async_engine\(
    • 缺失
      pool_pre_ping=True
      → 无法检测 stale 连接
    • 缺失
      pool_recycle
      → 连接保留时间超过数据库服务器超时(默认:MySQL 8小时,PG无限制)
    • 缺失
      pool_size
      → 使用默认值5(对于生产环境可能过小)
    • 缺失
      max_overflow
      → 负载下连接溢出无限制
    • Web服务中使用
      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
      reapIntervalMillis
    • 缺失连接验证(
      validateConnection
      testOnBorrow
检测方式(Java/Spring):
  • 匹配:
    DataSource|HikariConfig|HikariDataSource
    • 缺失
      leakDetectionThreshold
    • 缺失
      maximumPoolSize
      (默认值为10)
    • 缺失
      connectionTestQuery
      connectionInitSql
检测方式(Go):
  • 匹配
    sql\.Open\(
    • 缺失
      db.SetMaxOpenConns()
    • 缺失
      db.SetMaxIdleConns()
    • 缺失
      db.SetConnMaxLifetime()
严重程度:
  • HIGH(高): 无pool_pre_ping且无pool_recycle(静默返回stale连接)
  • HIGH(高): Web服务中无max_overflow限制(负载下连接创建无限制)
  • MEDIUM(中): 缺失连接池事件监听器(无法查看连接池健康状况)
  • MEDIUM(中): 缺失泄漏检测阈值(Java/HikariCP)
  • LOW(低): 连接池大小为默认值(对于小型服务可能足够)
上下文相关例外情况:
  • NullPool在无服务器/Lambda环境中是有效的
  • 对于低流量服务,pool_size=5可能足够
建议: 配置pool_pre_ping=True,pool_recycle < 数据库服务器超时,根据预期并发量设置合适的pool_size,添加连接池事件监听器用于监控。
修复工作量: S(添加配置参数),M(添加事件监听器/监控)

5. Unclosed Resources in Error Paths

5. 错误路径中未关闭资源

What: Exception/error handling paths that skip resource cleanup.
Detection (Python):
  • Find
    except
    blocks containing
    raise
    or
    return
    without prior
    session.close()
    ,
    conn.close()
    , or
    cursor.close()
  • Pattern:
    except Exception: logger.error(...); raise
    (re-raise without cleanup)
  • Find generator functions with DB session where GeneratorExit is not handled:
    • Grep:
      async def.*yield.*session|def.*yield.*session
      without
      try:.*finally:.*close\(\)
Detection (Node.js):
  • Grep:
    catch\s*\(
    blocks that
    throw
    or
    return
    without releasing connection
  • Pattern:
    pool.connect().then(client => { ... })
    without
    .finally(() => client.release())
  • Promise chains without
    .finally()
    for cleanup
Detection (Java):
  • Grep:
    catch\s*\(
    blocks without
    finally { conn.close() }
    when connection opened in
    try
  • Not using try-with-resources for AutoCloseable resources
Detection (Go):
  • Grep:
    if err != nil \{.*return
    before
    defer
    statement for resource cleanup
  • Pattern: error check between
    Open()
    and
    defer Close()
    that returns without closing
Severity:
  • CRITICAL: Session/connection leak in high-frequency endpoint error path (pool exhaustion)
  • HIGH: Resource leak in error path of API handler
  • MEDIUM: Resource leak in error path of background task
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)
问题描述: 异常/错误处理路径跳过了资源清理步骤。
检测方式(Python):
  • 查找包含
    raise
    return
    但未先调用
    session.close()
    conn.close()
    cursor.close()
    except
  • 模式:
    except Exception: logger.error(...); raise
    (重新抛出异常但未清理)
  • 查找带有数据库会话的生成器函数,但未处理GeneratorExit:
    • 匹配:
      async def.*yield.*session|def.*yield.*session
      且无
      try:.*finally:.*close\(\)
检测方式(Node.js):
  • 查找
    catch\s*\(
    块中
    throw
    return
    但未释放连接的情况
  • 模式:
    pool.connect().then(client => { ... })
    .finally(() => client.release())
  • Promise链中无
    .finally()
    用于清理
检测方式(Java):
  • 查找
    catch\s*\(
    块中,当连接在
    try
    中打开时无
    finally { conn.close() }
  • 未对AutoCloseable资源使用try-with-resources
检测方式(Go):
  • 查找
    if err != nil \{.*return
    出现在资源清理的
    defer
    语句之前
  • 模式:在
    Open()
    defer Close()
    之间进行错误检查并返回,未关闭资源
严重程度:
  • CRITICAL(严重): 高频率端点错误路径中的会话/连接泄漏(连接池耗尽)
  • HIGH(高): API处理程序错误路径中的资源泄漏
  • MEDIUM(中): 后台任务错误路径中的资源泄漏
建议: 在任何可能失败的代码之前使用上下文管理器/try-with-resources/defer;对于生成器,在yield周围添加try/finally。
修复工作量: S(重构资源获取逻辑,将其移至错误路径之前)

6. Resource Factory vs Injection Anti-pattern

6. 资源工厂模式与注入反模式

What: Using framework DI to inject short-lived resources into long-lived contexts instead of using factory pattern.
Detection (Python/FastAPI):
  • Step 1 - Find DI-injected sessions in endpoint signatures:
    • Grep:
      Depends\(get_db\)|Depends\(get_session\)|Depends\(get_async_session\)
  • Step 2 - Classify endpoint lifetime:
    • Short-lived: regular REST endpoint (request/response) -> DI injection OK
    • Long-lived: SSE (
      StreamingResponse
      ,
      EventSourceResponse
      ), WebSocket (
      @app.websocket
      ), background task (
      BackgroundTasks.add_task
      )
  • Step 3 - Flag DI injection in long-lived endpoints:
    • Long-lived endpoint should use factory pattern:
      async with session_factory() as session:
      at point of need
    • NOT
      session: AsyncSession = Depends(get_session)
      at endpoint level
Detection (Node.js/Express):
  • Middleware-injected pool connection (
    req.db
    ) used in WebSocket handler or SSE route
  • Should use:
    const conn = await pool.connect(); try { ... } finally { conn.release() }
    at point of need
Detection (Java/Spring):
  • @Autowired EntityManager
    in
    @Controller
    with SSE endpoint (
    SseEmitter
    )
  • Should use: programmatic EntityManager creation from EntityManagerFactory
Detection (Go):
  • *sql.DB
    injected at handler construction time but
    *sql.Conn
    should be acquired per-operation
Severity:
  • CRITICAL: DI-injected session in SSE/WebSocket endpoint (session outlives intended scope by orders of magnitude)
  • HIGH: DI-injected session passed to background task (task outlives request)
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)
问题描述: 使用框架DI将短生命周期资源注入长上下文中,而非使用工厂模式。
检测方式(Python/FastAPI):
  • 步骤1 - 查找端点签名中通过DI注入的会话:
    • 匹配:
      Depends\(get_db\)|Depends\(get_session\)|Depends\(get_async_session\)
  • 步骤2 - 分类端点生命周期:
    • 短生命周期:常规REST端点(请求/响应)→ DI注入合规
    • 长生命周期:SSE(
      StreamingResponse
      EventSourceResponse
      )、WebSocket(
      @app.websocket
      )、后台任务(
      BackgroundTasks.add_task
  • 步骤3 - 标记长生命周期端点中的DI注入:
    • 长生命周期端点应使用工厂模式:在需要时使用
      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):
  • 在带有SSE端点(
    SseEmitter
    )的
    @Controller
    中使用
    @Autowired EntityManager
  • 正确做法:从EntityManagerFactory以编程方式创建EntityManager
检测方式(Go):
  • 在处理程序构造时注入
    *sql.DB
    ,但应在每次操作时获取
    *sql.Conn
严重程度:
  • CRITICAL(严重): SSE/WebSocket端点中使用DI注入的会话(会话存在时间远超预期范围)
  • HIGH(高): DI注入的会话被传递给后台任务(任务生命周期超过请求)
建议: 对长上下文使用工厂模式;注入工厂(sessionmaker、连接池)而非会话/连接本身。
修复工作量: M(将DI从会话改为会话工厂,添加作用域内获取逻辑)

Scoring Algorithm

评分算法

MANDATORY READ: Load
shared/references/audit_worker_core_contract.md
and
shared/references/audit_scoring.md
.
必读: 加载
shared/references/audit_worker_core_contract.md
shared/references/audit_scoring.md

Output Format

输出格式

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)
必读: 加载
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)

Critical Rules

关键规则

MANDATORY READ: Load
shared/references/audit_worker_core_contract.md
.
  • Do not auto-fix: Report only
  • DI-aware: Understand framework dependency injection lifetime scopes (request, singleton, transient)
  • Framework detection first: Identify DI framework before checking injection patterns
  • Streaming detection first: Find all streaming/long-lived endpoints before scope analysis
  • Exclude tests: Do not flag test fixtures, test session setup, mock sessions
  • Exclude CLI/scripts: DI scope mismatch is not relevant for single-run scripts
  • Effort realism: S = <1h, M = 1-4h, L = >4h
  • Pool config is context-dependent: NullPool is valid for serverless/Lambda; pool_size=5 may be fine for low-traffic services
  • Safe pattern awareness: Do not flag resources inside
    async with
    ,
    with
    , try-with-resources,
    defer
    (already managed)
必读: 加载
shared/references/audit_worker_core_contract.md
  • 请勿自动修复: 仅生成报告
  • DI感知: 理解框架依赖注入的生命周期作用域(请求、单例、瞬时)
  • 先检测框架: 在检查注入模式之前先识别DI框架
  • 先检测流式端点: 在范围分析之前先查找所有流式/长生命周期端点
  • 排除测试代码: 不要标记测试夹具、测试会话设置、模拟会话
  • 排除CLI/脚本: DI范围不匹配对单次运行的脚本不适用
  • 工作量真实: S = <1小时,M = 1-4小时,L = >4小时
  • 连接池配置与上下文相关: NullPool在无服务器/Lambda环境中有效;对于低流量服务,pool_size=5可能足够
  • 识别安全模式: 不要标记
    async with
    with
    、try-with-resources、
    defer
    内的资源(已被管理)

Definition of Done

完成标准

MANDATORY READ: Load
shared/references/audit_worker_core_contract.md
.
  • contextStore parsed successfully (including output_dir, db_config)
  • scan_path determined
  • DI framework detected (FastAPI Depends, Django middleware, Spring @Autowired, Express middleware, Go wire)
  • Streaming endpoints inventoried
  • All 6 checks completed:
    • resource scope mismatch, streaming resource holding, missing cleanup, pool configuration, error path leak, factory vs injection
  • Findings collected with severity, location, effort, recommendation
  • Score calculated using penalty algorithm
  • Report written to
    {output_dir}/654-resource-lifecycle.md
    (atomic single Write call)
  • Summary returned to coordinator
必读:
  • 成功解析contextStore(包括output_dir、db_config)
  • 确定扫描路径
  • 检测到DI框架(FastAPI Depends、Django中间件、Spring @Autowired、Express中间件、Go wire)
  • 盘点所有流式端点
  • 完成全部6项检查:
    • 资源范围不匹配、流式资源持有、缺失资源清理、连接池配置、错误路径泄漏、工厂模式与注入反模式
  • 收集包含严重程度、位置、工作量及建议的检查结果
  • 使用惩罚算法计算分数
  • 将报告写入
    {output_dir}/654-resource-lifecycle.md
    (原子单次写入操作)
  • 向协调器返回摘要

Reference Files

参考文件

  • Audit output schema:
    shared/references/audit_output_schema.md

Version: 1.0.0 Last Updated: 2026-03-03
  • 审计输出 schema:
    shared/references/audit_output_schema.md

版本: 1.0.0 最后更新时间: 2026-03-03