📊 评分面板
Security / 安全
6.0 B
有 beta 门禁、cookie 使用 httpOnly;但 lockfile 中存在高危前端依赖,且邀请码被写入 localStorage 并作为 header 复用。
Stability / 稳定性
6.2 B
后端 45 个测试通过且外部 HTTP 有 timeout;但 KG 降级与多处 broad except/pass 会隐藏真实故障。
Performance / 性能
5.8 B
API 参数有多处 limit 上界;但前端单 JS chunk 达 5.77 MB,图谱/Plotly/Cytoscape 没有路由级拆包。
Testing / 测试
5.4 B
后端测试较真实且全部通过;但前端没有 test/typecheck/lint 脚本,npm ci 当前不可复现。
Maintainability / 可维护性
4.8 C
核心文件过大:api.py 3369 行、Workspace.tsx 2267 行,多个函数/组件职责过宽。
Design / 设计原则
4.6 C
SRP、Fail-fast、显式依赖和错误上下文原则被多处违反,主要集中在 API 工厂与前端巨型页面。
Release / 发布
4.5 C
部署文档存在,但缺 CI/CD 与 rollback 自动化;package-lock 不同步且 npm audit 仍报告 6 个漏洞。
Overall / 总体
5.3 B
B:可运行、后端测试扎实,但发布可复现性、前端体积和结构性维护债需要先处理。

📝 总体评估

📋 总体评估

项目概况:SynLethHub 是 React + TypeScript + Vite 前端与 FastAPI + SQLite/Neo4j 后端组成的封闭 beta 代码库,当前功能面覆盖 Copilot、Workspace 图谱、文献 feed、Cases、Trace replay/export 与 beta invite gate。

主要风险:最大阻断项是发布可复现性:跟踪的 package-lock 与 package.json 不同步,npm ci 失败且 npm audit 仍报告 6 个依赖漏洞。其次是证据产品特有的风险:KG/Evidence fallback 会把依赖失败显示为局部或空数据,容易误导研究结论。

亮点:后端测试基础较好,本次实测 45 passed;SQL 多数参数化;FastAPI response_model 覆盖主要端点;部署文档对 beta 拓扑、cookie secret、invite code、反向代理和 smoke test 有明确说明。

优先修复:先修 npm ci/audit、beta invite code 持久化、fallback 显式状态、POST payload 边界;再拆 api.py/Workspace.tsx、补前端测试、做 bundle 拆包。

总评:5.3 / 10,等级 B。这是“能跑且后端有真实测试”的 beta 代码库,不是不可用的项目;但距离稳定公开发布仍有明确工程风险,需要先补发布门禁、前端 QA 和结构性拆分。

12
总发现
0
Critical
1
High
9
Medium
2
Low
0
Info

⚠️ 顶级风险

#发现严重程度类别
1前端 lockfile 不可复现且锁定存在已知漏洞的依赖版本HighRelease / Security
2Beta 邀请码被保存在 localStorage 并作为 x-slh-beta-key 注入请求MediumSecurity
3KG 不可用时图 API 静默降级为 SQLite SL fallback,可能给出不完整图谱MediumStability / Fallback
4核心 API 工厂和前端页面违反文件/函数大小与 SRP 原则MediumMaintainability / Architecture
5前端生产包为单一 5.77 MB JS chunk,缺少路由级拆包MediumPerformance
6多处 broad except/pass 吞掉初始化、缓存和关闭错误,故障不可观测MediumStability / Observability
7POST 请求模型缺少大小和数值边界,trace/export 可接收过大嵌套 payloadMediumBackend API / Type Safety
8SQLite 连接缺少 WAL/busy_timeout,写入与读取并发下存在锁等待风险MediumStability / Performance
9前端 EvidenceTab 对多个证据接口 catch(() => null),把失败伪装成缺层MediumFallback / Frontend State
10前端缺少自动化测试、typecheck、lint 脚本,发布验证依赖人工 smokeMediumTesting / Release
11健康检查端点在 beta public allowlist 中,暴露配置状态与内部层状态LowSecurity / Configuration
12文档与代码边界存在不一致,发布说明依赖人工约束LowDocumentation / Code Consistency

🔍 详细发现

1. 前端 lockfile 不可复现且锁定存在已知漏洞的依赖版本

High Confirmed
📁 Release / Security 📍 frontend/package.json:23-34; frontend/package-lock.json; npm audit 🎯 npm ci / npm audit
问题:发布构建无法用 npm ci 从受控 lockfile 复现,同时 lockfile 对应的依赖图存在已知漏洞。虽然 npm install --package-lock=false 后能拉到更新版本并成功构建,但这恰好证明当前仓库记录的锁文件不是发布可信来源。
原则:配置与发布可复现性;Configuration Safety 9.2;Release readiness
- File: frontend/package.json:23-34 - Function / Module: npm dependency resolution - Relevant behavior: package.json 允许 react-router-dom ^6.28.0、postcss ^8.4.49、vite ^7.3.1;跟踪的 package-lock 锁定 vite 7.3.1、postcss 8.5.8、react-router 6.30.3、picomatch 2.3.1、protocol-buffers-schema 3.6.0。 - Runtime behavior: npm ci 失败:Missing: source-map@0.6.1 from lock file。npm audit --json 报告 6 个漏洞,其中 2 high、4 moderate,涉及 Vite dev server 文件读取/deny 绕过、picomatch ReDoS、React Router open redirect、PostCSS XSS 等。
最小修复 / 长期修复
最小修复:运行 npm install 更新 package-lock,使 lockfile 包含 source-map@0.6.1 并升级到 npm audit clean 的 vite/postcss/react-router/picomatch/protocol-buffers-schema 版本;CI 固定使用 npm ci。 长期修复:添加 GitHub Actions 或等价 CI:npm ci、npm run build、npm audit --audit-level=high;发布前要求 lockfile 零 drift。 为什么重要:稳定公开发布依赖可复现安装;如果 CI 或服务器使用 npm ci,会直接失败;如果使用 npm install,则每次可能解析到不同依赖版本,安全和回滚都不可控。 现实失败场景:beta 分支部署时执行 npm ci 失败;运维改用 npm install 绕过后拉到未审计的较新版本,线上行为与开发机不一致,且旧 lockfile 仍持续触发依赖漏洞扫描。
⏱ 估算: 2-4 小时  ·  回归测试: 在干净目录运行 npm ci && npm run build && npm audit --audit-level=high。

2. Beta 邀请码被保存在 localStorage 并作为 x-slh-beta-key 注入请求

Medium Confirmed
📁 Security 📍 frontend/src/app/betaAccess.ts:15-38; frontend/src/lib/api/client.ts:21-34 🎯 readBetaInviteCode / betaInviteHeaders / apiFetchJson
问题:后端已经发放 httpOnly cookie,但前端仍保留 JS 可读的邀请码并在所有 API 调用中复用。邀请码实际上承担 beta 访问凭证功能,localStorage 对任何 XSS、第三方脚本或浏览器扩展都是可读的。
原则:Secret handling;Explicit security boundaries
- File: frontend/src/app/betaAccess.ts:15-38 - Function / Module: readBetaInviteCode, writeBetaInviteCode, betaInviteHeaders - Relevant behavior: 邀请码写入 window.localStorage,并在 betaInviteHeaders 中读取后作为 x-slh-beta-key 返回。 - File: frontend/src/lib/api/client.ts:21-34 - Function / Module: apiFetchJson - Relevant behavior: 每个 API 请求都会合并 betaInviteHeaders,并设置 credentials: include。
最小修复 / 长期修复
最小修复:授权成功后立即 clearBetaInviteCode,只依赖后端 httpOnly cookie;如需自动重试,仅在提交表单前短暂持有 invite code,不持久化。 长期修复:把 beta key 视为一次性兑换码:后端签发 session cookie 后,邀请码不再作为长期 bearer 凭证。 为什么重要:这不是完整生产认证,但它仍保护封闭 beta 数据面;一旦邀请码泄露,攻击者可绕过 invite gate,直到运维轮换邀请列表。 现实失败场景:某个页面或依赖未来引入 XSS,攻击脚本读取 slh_beta_invite_code_v1 并发送给外部,随后可用 x-slh-beta-key 访问受保护 API。
⏱ 估算: 2-3 小时  ·  回归测试: BetaInviteGate 成功授权后断言 localStorage 不含 slh_beta_invite_code_v1,后续 /api/session 仅靠 cookie 通过。

3. KG 不可用时图 API 静默降级为 SQLite SL fallback,可能给出不完整图谱

Medium Confirmed
📁 Stability / Fallback 📍 backend/src/slh_lit_agent/api.py:1752-1788 🎯 kg_neighbors / kg_paths
问题:图谱 API 的语义是 KG exploration,但 KG 不可用时返回 SQLite SL pair 的轻量图,客户端难以区分“真实 KG 结果为空”和“后端降级后的局部结果”。
原则:Fail Fast 4.4;Don’t hide failure 6.1
- File: backend/src/slh_lit_agent/api.py:1759-1761, 1779-1781 - Function / Module: kg_neighbors, kg_paths - Relevant behavior: app.state.kg_client 为 None 时,neighbors 返回 _fallback_neighbors_from_sl_pairs,paths 返回 _fallback_paths_from_sl_pairs,而不是暴露 KG 不可用状态。 - Related behavior: /api/health/ready 会把 kg 标记为 not_ready,但业务 API 仍返回 fallback 数据。
最小修复 / 长期修复
最小修复:在 fallback 响应中加入 explicit degraded 字段、source=fallback_sqlite、missing_layers=[kg],并在前端以警告样式展示。 长期修复:把 KG required/optional 做成配置;生产 beta 若 KG 是核心功能,缺失时直接 503,而 demo 模式才允许 fallback。 为什么重要:研究型产品中,不完整证据被展示为正常图谱会误导候选排序、路径解释和用户结论。 现实失败场景:生产 Neo4j 连接失败,用户在 Workspace 查询基因路径,系统展示 fallback 结果且没有明显失败标记,用户误以为 KG 没有更多关系。
⏱ 估算: 4-6 小时  ·  回归测试: 模拟 app.state.kg_client=None 调 /api/graph/neighbors,断言响应包含 degraded=true 或返回 503。

4. 核心 API 工厂和前端页面违反文件/函数大小与 SRP 原则

Medium Confirmed
📁 Maintainability / Architecture 📍 backend/src/slh_lit_agent/api.py:1103-3369; frontend/src/pages/Workspace.tsx:896-2267 🎯 create_app / WorkspacePage
问题:核心变更都汇聚到少数巨型文件,导致测试边界不清、重构风险高、多人协作冲突概率大。
原则:SRP 1.1;File Size 1.2;Function Size 1.3;Cohesion 2.2
- File: backend/src/slh_lit_agent/api.py:1103-3369 - Function / Module: create_app - Relevant behavior: create_app 长 2267 行,内部声明路由、认证中间件、KG fallback、Copilot、文献趋势、case/export/report 等多种职责。api.py 总长 3369 行。 - File: frontend/src/pages/Workspace.tsx:896-2267 - Function / Module: WorkspacePage - Relevant behavior: WorkspacePage 文件 2267 行,组件内约 20 个 useState 与 20 个 useEffect,混合查询状态、图布局、trace、context menu、evidence panel 和 UI 渲染。
最小修复 / 长期修复
最小修复:按路由域拆分 api.py:beta/session、graph、sl-pairs、copilot、literature、cases、exports;Workspace 抽出 useGraphWorkspace、GraphPanel、ExpandBrowser、DetailsPanel。 长期修复:建立“路由模块 + service + schema”后端边界,以及“hook + presentational components”前端边界。 为什么重要:这类结构性债务不会立即导致崩溃,但会使后续功能、修 bug、审计安全边界都变慢。 现实失败场景:新增一个 Copilot 证据类型时需要同时修改 api.py 内嵌函数、Workspace 状态、EvidenceTab 展示和 trace 记录;一个小改动容易波及多条路径。
⏱ 估算: 2-4 天  ·  回归测试: 拆分前先保留现有 45 个后端测试;为 Workspace hook 加入状态转换单元测试。

5. 前端生产包为单一 5.77 MB JS chunk,缺少路由级拆包

Medium Confirmed
📁 Performance 📍 frontend/src/pages/*.tsx; frontend/package.json:13-35 🎯 Vite build / static bundle
问题:首页、邀请码页或轻量页面也会被迫加载图谱和 Plotly 等重依赖,首屏网络、解析和执行成本偏高。
原则:Performance scalability;YAGNI/KISS for dependency weight
- File: frontend/package.json:16-22 - Function / Module: dependency graph - Relevant behavior: cytoscape、cytoscape-fcose、plotly.js-dist-min、react-cytoscapejs 等重依赖作为普通依赖进入单入口应用。 - Runtime behavior: npm run build 产物 dist/assets/index-BUivia9l.js = 5,774.56 kB,gzip 1,730.72 kB,并触发 Vite “Some chunks are larger than 500 kB” 警告。
最小修复 / 长期修复
最小修复:用 React.lazy/lazy route 对 Workspace、Copilot、Plot 相关页面做 route-level dynamic import;Plotly/Cytoscape 只在对应页面加载。 长期修复:设置 Rollup manualChunks,增加 bundle analyzer 和 chunk size budget。 为什么重要:封闭 beta 用户可能位于不同网络环境;1.7 MB gzip 的单入口 JS 会拉长首屏时间,也增加缓存失效后的回归成本。 现实失败场景:用户只访问 Guide 或 Beta gate,但浏览器仍下载并解析 Workspace/Copilot/Plotly/Cytoscape 相关代码。
⏱ 估算: 1 天  ·  回归测试: 构建后断言入口 chunk < 800 kB gzip 或核心首屏 chunk 不包含 plotly/cytoscape。

6. 多处 broad except/pass 吞掉初始化、缓存和关闭错误,故障不可观测

Medium Confirmed
📁 Stability / Observability 📍 backend/src/slh_lit_agent/api.py:1139-1141,1163-1180,1719-1732,2884-3091; backend/src/slh_lit_agent/env.py:46-63 🎯 create_app / _resolve_sldb3_path / shutdown / literature_keyword_trends / load_env_files
问题:系统在多个关键位置用 broad except 把错误降级为无上下文状态或直接忽略,导致健康检查、缓存一致性和配置加载问题难以定位。
原则:Don’t Swallow Errors 6.1;Don’t Lose Error Context 6.2
- File: backend/src/slh_lit_agent/api.py:1139-1141 - Function / Module: create_app - Relevant behavior: Neo4j init 异常被替换为固定字符串 “Neo4j client init failed”。 - File: backend/src/slh_lit_agent/api.py:2884-2888, 3069-3091 - Function / Module: literature_keyword_trends - Relevant behavior: cache JSON 解析失败和 cache 写入失败均 pass。 - File: backend/src/slh_lit_agent/env.py:49-62 - Function / Module: load_env_files - Relevant behavior: 读取 .env 文件失败直接 continue,没有日志或返回错误。
最小修复 / 长期修复
最小修复:至少记录 exception class、配置键或 cache_key;对生产关键初始化失败增加 app.state diagnostics 并暴露到内部 ready endpoint。 长期修复:引入结构化日志和错误分类,区分 optional dependency degraded 与 required dependency failed。 为什么重要:错误吞掉后,测试和运维只能看到“功能降级/数据为空”,看不到触发条件、路径和原始异常。 现实失败场景:SLDB3 路径权限错误或 cache 表写入失败,用户看到趋势结果每次重算或缺层,日志没有足够信息定位根因。
⏱ 估算: 1 天  ·  回归测试: 模拟 cache payload 无效、.env 读取失败、Neo4j 初始化失败,断言日志/diagnostic payload 包含错误类型。

7. POST 请求模型缺少大小和数值边界,trace/export 可接收过大嵌套 payload

Medium Confirmed
📁 Backend API / Type Safety 📍 backend/src/slh_lit_agent/api.py:531-590,830-836,3290-3368 🎯 TracePayload / CopilotQueryRequest / trace_export_* / generate_report
问题:GET 参数多数有 Query 上界,但 POST 请求模型没有同等约束;trace payload 可携带大量 steps/artifacts/任意嵌套对象并触发 DB 写入或导出。
原则:Type Safety boundary;Unbounded Resources 10.2
- File: backend/src/slh_lit_agent/api.py:537-562 - Function / Module: TracePayload / TraceStepPayload - Relevant behavior: request、response_summary、data_version、inputs、outputs 使用 dict/list/str/int/float/bool/None 或 dict[str, Any],没有字段大小限制。 - File: backend/src/slh_lit_agent/api.py:830-836 - Function / Module: CopilotQueryRequest - Relevant behavior: neighbors_limit、paths_k、paths_max_len 是普通 int,POST body 没有 Query 的 ge/le 限制。 - File: backend/src/slh_lit_agent/api.py:3290-3319 - Function / Module: trace_export_case_markdown / trace_export_report_pdf - Relevant behavior: 接收完整 TracePayload 后生成 markdown/PDF artifacts。
最小修复 / 长期修复
最小修复:为 Pydantic model 加 Field(max_length, ge, le),限制 steps/artifacts 数量与嵌套 JSON 总大小;超过限制返回 413/422。 长期修复:对导出端点增加后台任务队列、速率限制和 artifact quota。 为什么重要:公开 API 面即使有 beta gate,也应限制资源消耗;否则单个请求可能导致内存、SQLite payload_json 或 PDF 渲染成本失控。 现实失败场景:恶意或损坏的客户端上传数万条 trace steps 并请求 report-pdf,服务端同步构造 markdown/PDF,占用 CPU、内存和磁盘。
⏱ 估算: 1-2 天  ·  回归测试: 构造超长 query、neighbors_limit=100000、steps=10000 的请求,断言 422/413 且不写 artifact。

8. SQLite 连接缺少 WAL/busy_timeout,写入与读取并发下存在锁等待风险

Medium Suspected
📁 Stability / Performance 📍 backend/src/slh_lit_agent/db.py:20-26,346-407; backend/src/slh_lit_agent/api.py:1354-1364 🎯 connect / upsert_trace_payload / home_stats
问题:SQLite 默认 journal/timeout 在多请求写入、读写交错时容易出现 database is locked;当前代码没有显式 busy_timeout 或 WAL 来缓冲并发。
原则:Resource management;No shared mutable state without synchronization 5.4
- File: backend/src/slh_lit_agent/db.py:20-26 - Function / Module: connect - Relevant behavior: 每次连接只设置 PRAGMA foreign_keys = ON,没有 busy_timeout、journal_mode=WAL 或连接池策略。 - File: backend/src/slh_lit_agent/db.py:371-407 - Function / Module: upsert_trace_payload - Relevant behavior: trace upsert 在请求路径中执行 INSERT/UPDATE 并 commit。 - File: backend/src/slh_lit_agent/api.py:1360-1364 - Function / Module: home_stats - Relevant behavior: 请求路径刷新 snapshot,也会写入数据库。
最小修复 / 长期修复
最小修复:connect 时设置 PRAGMA busy_timeout=5000 和 WAL(如果部署文件系统支持),把 home_stats refresh 从每请求写入改成按 data_version 条件更新。 长期修复:高并发或多进程部署时将写入任务队列化,或迁移到服务型数据库。 为什么重要:beta 用户的 trace sync、report export、home stats refresh 都可能在同一数据库上并发执行。 现实失败场景:多个浏览器同时触发 trace upsert 和 home stats refresh,SQLite 短时间写锁冲突,部分请求 500 或丢失 trace 同步。
⏱ 估算: 4-8 小时  ·  回归测试: 并发发起 trace_upsert/home_stats 请求,断言无 database is locked 且响应时间可接受。

9. 前端 EvidenceTab 对多个证据接口 catch(() => null),把失败伪装成缺层

Medium Confirmed
📁 Fallback / Frontend State 📍 frontend/src/components/workspace/EvidenceTab.tsx:41-57 🎯 EvidenceTab useEffect
问题:多个证据层失败时,UI 只看到 null,而非“接口失败/未配置/暂无数据”的明确区别。
原则:Don’t Swallow Errors 6.1;Fail Fast 4.4
- File: frontend/src/components/workspace/EvidenceTab.tsx:41-49 - Function / Module: EvidenceTab - Relevant behavior: slPairLiterature、depmap、tcga、gtex、predictionsPair 均使用 .catch(() => null),只有 slPairEvidence 失败才会让 Promise.all 进入整体 error。 - File: frontend/src/components/workspace/EvidenceTab.tsx:50-57 - Relevant behavior: 成功回调把 null 当作正常 data 层写入。
最小修复 / 长期修复
最小修复:把每个子请求包装成 {ok,data,error},UI 显示“未配置/请求失败/暂无数据”三种状态。 长期修复:后端统一 evidence layer status schema,前端按状态渲染。 为什么重要:研究证据产品必须区分缺证据和取证失败;否则用户会把服务故障解释成生物学证据缺失。 现实失败场景:/api/evidence/tcga 500,EvidenceTab 仍渲染其他层并把 tcga=null,当作没有 TCGA 证据展示。
⏱ 估算: 4-6 小时  ·  回归测试: mock tcga 返回 500,断言 EvidenceTab 展示 TCGA 请求失败而不是空数据。

10. 前端缺少自动化测试、typecheck、lint 脚本,发布验证依赖人工 smoke

Medium Confirmed
📁 Testing / Release 📍 frontend/package.json:6-11; DEPLOY_BETA.md:111-117 🎯 npm scripts / deployment workflow
问题:后端有 17 个测试文件且 45 个测试通过;前端没有同等自动化回归保护。Workspace/Copilot/Home 是风险最高的交互面,却只能靠构建和人工检查发现问题。
原则:Testing authenticity 8.x;Release readiness
- File: frontend/package.json:6-11 - Function / Module: npm scripts - Relevant behavior: 只有 preinstall、dev、dev:lit-agent、build、preview;没有 test、typecheck、lint。 - File: DEPLOY_BETA.md:111-117 - Function / Module: Frontend build deployment - Relevant behavior: 发布步骤只列 npm install 和 npm run build;浏览器检查在文档后续以人工 smoke 形式描述。
最小修复 / 长期修复
最小修复:添加 npm run typecheck、lint、Vitest/RTL smoke;至少覆盖 BetaInviteGate、apiFetchJson、queryState、EvidenceTab 错误状态。 长期修复:加 Playwright e2e,覆盖邀请码、Home、Copilot、Workspace、Trace export 的 beta smoke。 为什么重要:TypeScript strict 只能覆盖编译时类型,不能覆盖路由状态、API 错误、邀请码流程、图谱交互与 trace 导出。 现实失败场景:重构 api endpoints 或 queryState 后,npm run build 仍通过,但 BetaInviteGate 登录流或 Workspace 选中节点状态损坏,直到 tester 反馈才发现。
⏱ 估算: 1-2 天  ·  回归测试: CI 中运行 npm ci、npm run typecheck、npm test、npm run build。

11. 健康检查端点在 beta public allowlist 中,暴露配置状态与内部层状态

Low Confirmed
📁 Security / Configuration 📍 backend/src/slh_lit_agent/api.py:193-199,1272-1312; DEPLOY_BETA.md:52-54 🎯 _BETA_PUBLIC_PATHS / health / health_ready
问题:代码默认把健康端点作为无需邀请码的 public API,而文档把公开健康端点列为部署侧需关闭事项。
原则:Least exposure;Configuration Safety 9.1
- File: backend/src/slh_lit_agent/api.py:193-199 - Function / Module: _BETA_PUBLIC_PATHS - Relevant behavior: /api/health 和 /api/health/ready 被列为 beta public paths。 - File: backend/src/slh_lit_agent/api.py:1296-1312 - Function / Module: health_ready - Relevant behavior: 响应包含 kg、llm、sldb3、beta_access invite_count 等内部状态。 - File: DEPLOY_BETA.md:52-54 - Relevant behavior: 部署文档提醒不要公开代理 health endpoint,除非有意。
最小修复 / 长期修复
最小修复:保留 /api/health 的最小 ok 响应;ready 仅内网或要求管理 key;不要返回 invite_count。 长期修复:区分 public liveness、internal readiness、admin diagnostics 三个端点。 为什么重要:这类信息泄露不等同于凭证泄露,但会帮助外部观察系统依赖状态、配置是否完成和可攻击时间窗口。 现实失败场景:公网代理未按文档 deny /api/health/ready,外部可直接看到 KG/LLM/SLDB3 是否配置、invite_count。
⏱ 估算: 2-4 小时  ·  回归测试: 启用 beta_access_required 后无 invite code 请求 /api/health/ready,应返回 403 或最小化响应。

12. 文档与代码边界存在不一致,发布说明依赖人工约束

Low Confirmed
📁 Documentation / Code Consistency 📍 backend/README.md:13-16,127-144; DEPLOY_BETA.md:48-56; backend/src/slh_lit_agent/api.py:193-199 🎯 README / beta deploy policy
问题:关键发布边界靠文档提醒而不是代码/配置强制;README 对 API 面和 cancer 语义的描述落后于当前代码。
原则:Documentation accuracy;Least surprise 3.1
- File: backend/README.md:13-16 - Function / Module: Backend README - Relevant behavior: 文档仍描述 “Serve API for SynLethHub Home/Download”,而当前 beta surface 已包含 Copilot、Workspace、Database、Cases、Trace。 - File: backend/README.md:127 - Relevant behavior: 文档说明 cancer accepted but schema-agnostic;代码中 fallback/SL pair paths 已对 cancer/PAN 做过滤和排序。 - File: DEPLOY_BETA.md:52-54 vs backend/src/slh_lit_agent/api.py:193-199 - Relevant behavior: 文档要求不要公开 health,代码默认 public allowlist。
最小修复 / 长期修复
最小修复:更新 README 的 API surface、cancer/filter 语义、测试命令;把 health 公开策略从文档转为配置。 长期修复:为发布文档增加机器可执行 smoke 脚本,减少人工解释空间。 为什么重要:运维和后续 agent 依赖文档执行;不一致会导致错误部署、错误测试范围或重复修复已变化的行为。 现实失败场景:新部署人员按 README 理解为文献 feed MVP,遗漏 Copilot/Workspace/Trace 的 smoke;或未关闭 health endpoint。
⏱ 估算: 2-4 小时  ·  回归测试: 文档中的命令在干净 checkout 上可执行;CI 校验 smoke script。

🏗️ 架构与模块边界

已确认/疑似 · 1 个发现
发现严重程度状态
核心 API 工厂和前端页面违反文件/函数大小与 SRP 原则MediumConfirmed
✅ 已验证 / 正向证据
后端 API、KG、DB、LLM、导出模块职责可识别;前后端目录边界清晰。
SQLite schema 初始化集中,FastAPI response_model 覆盖大多数 GET/POST 响应。

🔒 安全

已确认/疑似 · 3 个发现
发现严重程度状态
前端 lockfile 不可复现且锁定存在已知漏洞的依赖版本HighConfirmed
Beta 邀请码被保存在 localStorage 并作为 x-slh-beta-key 注入请求MediumConfirmed
健康检查端点在 beta public allowlist 中,暴露配置状态与内部层状态LowConfirmed
✅ 已验证 / 正向证据
FastAPI docs/ReDoc/OpenAPI 默认关闭。
Beta cookie 使用 httponly、secure 可配置、samesite=lax。
SQL 查询主要使用参数绑定,未发现直接字符串拼接用户输入执行 SQL。

⚡ 稳定性与错误处理

已确认/疑似 · 3 个发现
发现严重程度状态
KG 不可用时图 API 静默降级为 SQLite SL fallback,可能给出不完整图谱MediumConfirmed
多处 broad except/pass 吞掉初始化、缓存和关闭错误,故障不可观测MediumConfirmed
SQLite 连接缺少 WAL/busy_timeout,写入与读取并发下存在锁等待风险MediumSuspected
✅ 已验证 / 正向证据
后端测试 45 passed。
外部 HTTP 客户端有 timeout、retry 与 user-agent。
GET 查询参数多处使用 Query ge/le 上界。

🚀 性能与可扩展性

已确认/疑似 · 2 个发现
发现严重程度状态
前端生产包为单一 5.77 MB JS chunk,缺少路由级拆包MediumConfirmed
SQLite 连接缺少 WAL/busy_timeout,写入与读取并发下存在锁等待风险MediumSuspected
✅ 已验证 / 正向证据
后端列表/图谱端点设置 limit 上界。
关键词趋势有 keyword_trends_cache 缓存表。
Vite 生产构建能完成。

🧪 测试质量

已确认/疑似 · 1 个发现
发现严重程度状态
前端缺少自动化测试、typecheck、lint 脚本,发布验证依赖人工 smokeMediumConfirmed
✅ 已验证 / 正向证据
后端有 17 个测试文件,覆盖 beta access、Copilot、exports、keyword trends、case markdown、db migration。
后端测试真实执行 FastAPI TestClient 和 SQLite in-memory 场景。

📐 可维护性

已确认/疑似 · 2 个发现
发现严重程度状态
核心 API 工厂和前端页面违反文件/函数大小与 SRP 原则MediumConfirmed
文档与代码边界存在不一致,发布说明依赖人工约束LowConfirmed
✅ 已验证 / 正向证据
类型文件与 API endpoints 有独立目录。
后端数据写入 helper 多数集中在 db.py,便于后续拆分。

📋 设计原则符合度

已确认/疑似 · 4 个发现
发现严重程度状态
KG 不可用时图 API 静默降级为 SQLite SL fallback,可能给出不完整图谱MediumConfirmed
核心 API 工厂和前端页面违反文件/函数大小与 SRP 原则MediumConfirmed
多处 broad except/pass 吞掉初始化、缓存和关闭错误,故障不可观测MediumConfirmed
前端 EvidenceTab 对多个证据接口 catch(() => null),把失败伪装成缺层MediumConfirmed
✅ 已验证 / 正向证据
前后端基本按 backend/frontend 分层。
多数数据库操作使用参数化 SQL,避免把数据访问完全散落在前端。

🚢 发布与部署流程

已确认/疑似 · 3 个发现
发现严重程度状态
前端 lockfile 不可复现且锁定存在已知漏洞的依赖版本HighConfirmed
前端缺少自动化测试、typecheck、lint 脚本,发布验证依赖人工 smokeMediumConfirmed
文档与代码边界存在不一致,发布说明依赖人工约束LowConfirmed
✅ 已验证 / 正向证据
DEPLOY_BETA.md 描述了 beta branch、nginx、systemd、smoke test 和双服务器拓扑。
构建在 npm install --package-lock=false 后通过。

📚 文档准确性

已确认/疑似 · 1 个发现
发现严重程度状态
文档与代码边界存在不一致,发布说明依赖人工约束LowConfirmed
✅ 已验证 / 正向证据
存在 README、DEPLOY_BETA.md、LOCAL_CODEBASE_STATUS.md 和 env.example。
部署文档明确提示不要直接公开后端、要设置真实 cookie secret 和 invite codes。

⚙️ 配置安全

已确认/疑似 · 2 个发现
发现严重程度状态
前端 lockfile 不可复现且锁定存在已知漏洞的依赖版本HighConfirmed
健康检查端点在 beta public allowlist 中,暴露配置状态与内部层状态LowConfirmed
✅ 已验证 / 正向证据
后端 .env.example 明确列出 beta、CORS、LLM、Neo4j、SLDB3 配置。
缺失 LLM/KG 时 app.state 有配置错误状态。

📡 可观测性

已确认/疑似 · 1 个发现
发现严重程度状态
多处 broad except/pass 吞掉初始化、缓存和关闭错误,故障不可观测MediumConfirmed
✅ 已验证 / 正向证据
ready endpoint 能展示 DB/KG/LLM/SLDB3 层状态。
Trace 功能记录 route_context、steps、artifacts 并支持导出。

🧯 Fallback / 防御式代码

已确认/疑似 · 2 个发现
发现严重程度状态
KG 不可用时图 API 静默降级为 SQLite SL fallback,可能给出不完整图谱MediumConfirmed
前端 EvidenceTab 对多个证据接口 catch(() => null),把失败伪装成缺层MediumConfirmed
✅ 已验证 / 正向证据
Copilot 在 LLM 未配置时有确定性结构化回答 composer。
文献抓取对 PubMed/PubTator/fulltext 有 timeout 与 retry。

🧪 测试真实性

已确认/疑似 · 1 个发现
发现严重程度状态
前端缺少自动化测试、typecheck、lint 脚本,发布验证依赖人工 smokeMediumConfirmed
✅ 已验证 / 正向证据
后端测试不是纯快照:测试 API beta access、exports、keyword filters/trends、DB migration 等行为。
pytest 实测 45 passed。

🧷 类型安全

已确认/疑似 · 1 个发现
发现严重程度状态
POST 请求模型缺少大小和数值边界,trace/export 可接收过大嵌套 payloadMediumConfirmed
✅ 已验证 / 正向证据
前端 tsconfig strict=true。
后端大量 API response_model 使用 Pydantic BaseModel。

🖥️ 前端状态

已确认/疑似 · 2 个发现
发现严重程度状态
核心 API 工厂和前端页面违反文件/函数大小与 SRP 原则MediumConfirmed
前端 EvidenceTab 对多个证据接口 catch(() => null),把失败伪装成缺层MediumConfirmed
✅ 已验证 / 正向证据
queryState 集中处理 URL 状态。
localTrace 以固定 schema 维护本地 trace 并有过期时间。

🔌 后端 API 设计

已确认/疑似 · 2 个发现
发现严重程度状态
KG 不可用时图 API 静默降级为 SQLite SL fallback,可能给出不完整图谱MediumConfirmed
POST 请求模型缺少大小和数值边界,trace/export 可接收过大嵌套 payloadMediumConfirmed
✅ 已验证 / 正向证据
大多数 GET 参数使用 Query 限制范围,例如 graph limit、paths k/max_len、case pagination。
response_model 覆盖主要端点。

📦 依赖重量

已确认/疑似 · 2 个发现
发现严重程度状态
前端 lockfile 不可复现且锁定存在已知漏洞的依赖版本HighConfirmed
前端生产包为单一 5.77 MB JS chunk,缺少路由级拆包MediumConfirmed
✅ 已验证 / 正向证据
项目依赖数量总体不大:前端 package.json 直接生产依赖 10 个,后端声明依赖 6 个。
重依赖集中在图谱/绘图相关功能,来源可解释。

🧭 代码一致性

已确认/疑似 · 2 个发现
发现严重程度状态
核心 API 工厂和前端页面违反文件/函数大小与 SRP 原则MediumConfirmed
文档与代码边界存在不一致,发布说明依赖人工约束LowConfirmed
✅ 已验证 / 正向证据
前端 API 调用集中在 endpoints.ts 与 apiFetchJson。
后端时间戳、JSON helper、SL pair 规范化有复用函数。

💬 注释与说明覆盖

已确认/疑似 · 2 个发现
发现严重程度状态
多处 broad except/pass 吞掉初始化、缓存和关闭错误,故障不可观测MediumConfirmed
文档与代码边界存在不一致,发布说明依赖人工约束LowConfirmed
✅ 已验证 / 正向证据
关键部署约束在 DEPLOY_BETA.md 中有清晰文字说明。
部分复杂 fallback/PDF writer 有注释解释约束。

📋 设计原则违规

原则违规汇总
原则数量/强度严重程度区域
1.1 Single Responsibility / SRP4 个核心热点Mediumapi.py create_app、WorkspacePage、CopilotPage、db.py init_db
1.2 File Size Limit6 个 >500 行文件Mediumapi.py、Workspace.tsx、kg.py、Home.tsx、db.py、Copilot.tsx
1.3 Function/Method Size多处 >100 行函数Mediumcreate_app、copilot_query、write_basic_pdf、runner run 等
4.4 Fail Fast2 个主要 fallbackMediumKG fallback、EvidenceTab catch-to-null
6.1 Don’t Swallow Errors多处 broad except/passMediumapi.py、env.py、http.py、kg.py
9.2 Fail on Missing Configuration生产配置依赖文档提醒Lowhealth readiness、beta env、SLDB3 自动猜路径
10.2 Unbounded Resources2 个 POST 面MediumTracePayload、export/report payload
✅ 已遵守原则 / 正向模式
参数化 SQL 使用广泛,未发现明显 SQL 注入路径。
后端 API 大多声明 response_model,客户端类型文件也较完整。
外部 HTTP 调用默认有 timeout/retry。
部署文档明确区分 beta、frontend proxy、backend private topology。

🎯 修复顺序

⚡ 立即修复高优先级
#修复项估算风险
1修复 package-lock,同步到 npm ci 可复现;清理 npm audit high。2-4 小时阻断 CI/发布可复现性
2移除 localStorage 中长期保存的 beta invite code,只使用 httpOnly cookie。2-3 小时降低访问凭证泄露面
3让 KG/Evidence fallback 显式返回 degraded/layer_error 状态。0.5-1 天避免误导研究结论
4为 POST 模型增加 Field 上界和 payload size guard。1 天限制单请求资源消耗
📅 排期修复中优先级
#修复项估算
5拆分 api.py 与 Workspace.tsx,先抽 service/hook,不改行为。2-4 天
6添加前端 typecheck/test/lint 与 Playwright beta smoke。1-2 天
7前端路由级 code splitting,拆出 Plotly/Cytoscape 重 chunk。1 天
8SQLite connect 增加 busy_timeout/WAL,并压测并发写路径。0.5-1 天
9更新 README/DEPLOY_BETA,并把 health endpoint 策略配置化。0.5 天

⚡ Quick Wins

npm ci 绿灯
修 lockfile + audit,高价值低成本
清 localStorage 邀请码
安全边界快速收紧
ready endpoint 最小化
减少配置状态外泄
EvidenceTab layer status
避免把失败显示成无证据
route lazy loading
显著降低首屏 JS
添加 npm run typecheck
最快补上前端发布门禁
报告生成于 2026-06-04;审计范围:/Users/davidlee/Downloads/SynLethHub,模式:full,输出:HTML。验证:backend pytest 45 passed;frontend build passed after npm install --package-lock=false;npm ci failed due lockfile mismatch;npm audit reported 6 vulnerabilities.