Implement the full QPER intelligent analysis pipeline: - Phase E+: Block-based standardization for all 7 R tools, DynamicReport renderer, Word export enhancement - Phase Q: LLM intent parsing with dynamic Zod validation against real column names, ClarificationCard component, DataProfile is_id_like tagging - Phase P: ConfigLoader with Zod schema validation and hot-reload API, DecisionTableService (4-dimension matching), FlowTemplateService with EPV protection, PlannedTrace audit output - Phase R: ReflectionService with statistical slot injection, sensitivity analysis conflict rules, ConclusionReport with section reveal animation, conclusion caching API, graceful R error classification End-to-end test: 40/40 passed across two complete analysis scenarios. Co-authored-by: Cursor <cursoragent@cursor.com>
4.9 KiB
SSA-Pro R 服务代码深度审查报告
审查对象: SSA-Pro R Service Source Code (v1.0)
审查文件: Dockerfile, plumber.R, data_loader.R, guardrails.R, etc.
审查时间: 2026-02-18
审查结论: 🟡 总体优秀,但存在阻断性缺失 (Blocker)
1. 🚨 阻断性问题 (Critical Issues)
这些问题会导致服务无法启动或无法下载数据,必须在联调前修复。
1.1 data_loader.R 中缺失 OSS 签名函数
- 问题描述:在 data_loader.R 第 63 行调用了 generate_oss_signature(config, "GET", oss_key),但我翻遍了上传的所有文件,没有找到这个函数的定义。
- 风险:代码运行到下载 OSS 步骤时会直接报错 Error: could not find function "generate_oss_signature"。
- 修复建议:
- 方案 A (推荐):在 utils/ 下新建 oss_signer.R,实现阿里云 OSS 的 HMAC-SHA1 签名逻辑(需要引入 digest 和 base64enc 包)。
- 方案 B (替代):如果不想手写签名,可以使用系统调用 awscli (配置阿里云 endpoint) 或寻找现成的 R 包(如 aliyunr,但需验证维护状态)。
1.2 plumber.R 的动态加载性能隐患
- 问题描述:在 plumber.R 的 POST /api/v1/skills/<tool_code> 接口中,第 38 行使用了 source(tool_file)。这意味着每次请求都会重新从磁盘读取并解析 R 脚本。
- 风险:
- 开发环境:这是好事,支持热重载。
- 生产环境:这是性能杀手。在高并发下,频繁的磁盘 I/O 和语法解析会显著增加延迟。
- 修复建议:
- 引入 DEV_MODE 变量判断。
- 生产环境:在服务启动时(第 13 行左右)预先加载所有 tools/ 下的脚本,或者使用 environment 缓存已加载的函数。
- 开发环境:保持现有的动态 source 逻辑。
2. 工程与安全隐患 (Engineering & Security Risks)
2.1 Docker 容器的 Root 权限风险
- 问题描述:Dockerfile 未指定用户,默认使用 root 运行 R 服务。
- 风险:如果 R 代码中存在漏洞(如允许执行系统命令 system()),攻击者将获得容器的 Root 权限,可能逃逸或破坏文件系统。
- 修复建议:在 Dockerfile 末尾添加非特权用户切换:
RUN useradd -m appuser
USER appuser
2.2 路径遍历攻击 (Path Traversal)
- 问题描述:plumber.R 第 33 行:
tool_file <- file.path("tools", paste0(tolower(gsub("ST_", "", tool_code)), ".R"))
虽然做了 gsub,但如果 tool_code 包含 ../ 等字符,仍可能尝试访问上层目录。 - 修复建议:增加严格的白名单校验,或者校验 tool_code 只能包含字母、数字和下划线。
if (!grepl("^[A-Z0-9_]+$", tool_code)) {
return(list(status="error", message="Invalid tool code format"))
}
3. 最佳实践点赞 (Highlights) ✅
- 依赖锁定 (renv.lock):使用了 renv 进行包管理,这是 R 工程化的基石,做得非常棒。
- 护栏设计 (guardrails.R):
- 包含了 LARGE_SAMPLE_THRESHOLD (5000) 的抽样逻辑,避免了大样本下 Shapiro 检验过敏的问题,非常专业的统计学处理。
- 接口设计清晰 (passed, action, reason)。
- 结果格式化 (result_formatter.R):统一处理了 P 值 < 0.001 的显示,符合 APA 规范。
- 环境隔离 (docker-compose.yml):正确使用了环境变量注入 OSS 配置,且区分了开发/生产环境。
4. 优化代码清单 (Code Improvement Snippets)
补全 OSS 签名逻辑 (utils/oss_signer.R)
这部分逻辑比较复杂,我直接提供一个简版实现供参考:
library(digest)
library(base64enc)
generate_oss_signature <- function(config, verb, resource) {
date <- format(Sys.time(), "%a, %d %b %Y %H:%M:%S GMT", tz="GMT")
content_type <- ""
content_md5 <- ""
canonicalized_resource <- paste0("/", config$bucket, "/", resource)
string_to_sign <- paste(verb, content_md5, content_type, date, "", canonicalized_resource, sep="\n")
signature <- base64encode(hmac(config$access_key_secret, string_to_sign, algo="sha1", raw=TRUE))
auth_header <- paste0("OSS ", config$access_key_id, ":", signature)
return(c("Authorization" = auth_header, "Date" = date))
}
注意:需要在 renv.lock 中补充 digest 包。
5. 总结
这份代码作为 MVP 已经达到了 85分 的水平。
接下来的行动指南:
- 必须做:补全 generate_oss_signature 函数(或相关文件)。
- 必须做:在 renv 中添加 digest 依赖。
- 建议做:优化 plumber.R 的生产环境加载逻辑。
请将这份报告发给 R 开发工程师,让他们快速修正,然后就可以开始构建镜像了。