一、项目背景

Human_Genes_Functions 是一个面向人类基因信息检索的本地科研数据库项目。

项目的核心目标不是简单保存一份基因列表,而是建立一个可以持续扩展、能够追溯数据来源、支持命令行与网页查询、并且可以重复构建和部署的本地知识系统。

项目基础数据主要包括:

  • 人类参考基因组;
  • GENCODE 基因与转录本注释;
  • NCBI Gene Summary;
  • Gene Ontology 注释;
  • MANE / RefSeq 代表转录本;
  • Mondo 疾病本体;
  • ClinVar gene-condition 关联数据;
  • 对应的基因组和转录本 FASTA 文件。

项目采用 SQLite 作为主要数据库载体,并逐步建立了全文检索、基因详情查询、疾病本体查询、双向基因—疾病关系查询以及网页端展示能力。


二、系统架构与主机职责

整个项目运行在三台职责不同的主机上。为避免暴露真实环境,以下使用脱敏名称:

1. 开发主机

开发主机保存项目的正式 Git 仓库,例如:

/path/to/projects/Human_Genes_Functions

所有正式开发工作均应在此完成,包括:

  • 数据导入脚本;
  • 数据库结构升级;
  • CLI 开发;
  • Web UI 开发;
  • 自动化测试;
  • release 构建;
  • Git 提交和版本追踪。

开发主机是项目的唯一正式开发源。

2. AI 代理主机

AI 代理主机运行自动化代理和任务调度系统。

该主机可以:

  • 连接开发主机执行任务;
  • 检查项目状态;
  • 运行构建和测试命令;
  • 生成开发报告;
  • 辅助部署。

但它不应保存正式项目副本,也不应在自己的空项目目录中生成 Human_Genes_Functions 文件。

3. Web 部署主机

部署主机运行 Apache、PHP 和正式 Web 应用。

正式网站目录采用类似结构:

/web/root/Human_Genes_Functions/
├── app/
├── assets/
├── data/
├── fasta_assets/
├── index.php
├── search.php
├── gene.php
├── disease.php
└── fasta.php

其中:

  • data/ 保存正式 SQLite 数据库;
  • fasta_assets/ 保存大型 FASTA 文件;
  • 其他 PHP、HTML、CSS 文件属于可覆盖更新的应用层。

部署主机只作为运行环境,不作为主要开发位置。


三、Stage 6A:建立 Mondo 疾病本体层

在 Stage 6A 中,项目加入了 Mondo 疾病本体数据。

这一阶段的目标是建立统一的疾病标识层,使疾病可以通过以下形式被识别:

  • Mondo ID;
  • 正式疾病名称;
  • 同义词;
  • 外部数据库交叉引用;
  • 全文关键词。

疾病本体层为后续 ClinVar gene-condition 关系提供了统一目标。

如果没有本体层,ClinVar 中的疾病名称、OMIM 编号、UMLS 编号和其他来源标识很难可靠地归一化到同一个疾病实体。


四、Stage 6B:导入 ClinVar gene-condition 关系

Stage 6B 引入了 ClinVar 的基因—疾病来源关系。

主要数据源包括:

  • gene_condition_source_id
  • disease_names

本次导入批次包含:

  • 13,450 条 gene-condition 原始关系;
  • 67,249 条疾病名称和标识记录。

数据库新增了四张核心表:

clinvar_gene_condition_raw
clinvar_disease_names_raw
gene_disease_associations
gene_disease_mapping_issues

其中:

  • raw 表保存 ClinVar 原始字段;
  • association 表保存标准化后的基因—疾病关系;
  • mapping issues 表保存无法唯一映射、标识冲突或来源异常的问题;
  • 每一条标准化关系都可以追溯回原始数据行。

最终得到:

数据表记录数
ClinVar gene-condition 原始记录13,450
ClinVar disease names 原始记录67,249
标准化基因—疾病关系13,450
映射问题记录1,594

基因映射结果:

状态数量比例
mapped12,93796.19%
ambiguous3052.27%
unmapped2081.55%

疾病映射结果:

状态数量比例
mapped12,56693.41%
ambiguous2011.49%
unmapped6815.06%
unsupported20.01%

基因和疾病同时成功映射的记录为 12,092 条,占全部关系的 89.90%。

映射过程采用保守策略:

  1. 优先使用明确的数据库 ID;
  2. 再使用唯一的交叉引用;
  3. 再尝试唯一疾病名称;
  4. 再尝试唯一同义词;
  5. 无法安全确定时标记为 ambiguous 或 unmapped;
  6. 不使用模糊编辑距离自动猜测;
  7. 不人为伪造疾病 ID。

这种策略牺牲了一部分覆盖率,但保证了科研数据的可解释性和可追溯性。

同时,项目明确限制了数据含义:

gene-condition association 仅表示 ClinVar 数据中的基因与疾病来源关系,并不等同于变异致病性证据,也不包含 review status、遗传方式、致病等级或证据评分。


五、Stage 6B CLI:建立双向查询

数据库关系建立后,命令行工具增加了双向查询能力:

从基因查询疾病

例如:

query_gene.py TP53 --diseases

可以查看 TP53 对应的 ClinVar gene-condition 关系。

从疾病查询基因

例如:

query_disease.py MONDO:0018875 --genes

可以查询 Li-Fraumeni syndrome 对应的相关基因记录。

CLI 支持多种输出格式:

  • 终端文本;
  • JSON;
  • TSV;
  • Markdown。

验收样本包括:

  • TP53:25 条关系;
  • BRCA1:9 条关系;
  • Li-Fraumeni syndrome:5 条基因关联;
  • ABCC8:保留 ambiguous 状态;
  • ABCD4:保留 unmapped 状态;
  • POR:保留 unsupported 状态。

这些状态不会被静默丢弃,也不会被强行转换成错误的唯一结果。


六、Stage 6C:将疾病关系加入 Web UI

Stage 6C 的目标是把 Stage 6B 的数据能力暴露到网页端。

网页原本已经支持:

  • 基因搜索;
  • 基因详情;
  • GO 注释;
  • 转录本信息;
  • NCBI Summary;
  • FASTA 获取。

Stage 6C 新增了:

  • Disease 搜索;
  • Gene → Disease 关系展示;
  • Disease → Gene 关系展示;
  • Mondo ID 查询;
  • 疾病正式名称查询;
  • 疾病同义词查询;
  • UMLS、OMIM 等外部编号查询;
  • All / Gene / Disease 三种搜索类型。

Gene 页面

基因详情页面新增 ClinVar disease associations 区域。

例如 TP53 页面可以显示:

  • 关联疾病;
  • ClinVar 原始疾病名称;
  • 标准化 Mondo 疾病;
  • 映射状态;
  • 来源标识;
  • ambiguous、unmapped、unsupported 等状态。

Disease 页面

疾病详情页新增:

  • Mondo ID;
  • 正式名称;
  • 定义;
  • 同义词;
  • 外部引用;
  • ClinVar gene-condition associations;
  • 相关基因列表。

例如:

Li-Fraumeni syndrome
MONDO:0018875
UMLS:C1835398

三种查询方式都可以解析到同一个疾病实体,并显示 TP53 等相关基因。


七、沿用现有 Web UI,而不是重新设计

开发过程中,一个重要原则是:

Stage 6C 不重新设计整套网站,而是在现有正式网页基础上增加疾病功能。

部署主机上已经存在一套可用 Web UI。

因此,开发主机先完整读取了现网应用,然后构建了一个干净的开发基线:

System/webui/stage6c_webui_candidate/

该候选目录只包含应用代码,不包含:

  • 大型 SQLite 数据库;
  • FASTA 文件;
  • 缓存;
  • 日志;
  • 运行时 sidecar 文件;
  • 现网敏感路径信息。

现网来源记录和排除清单则移到 Web document root 之外保存:

System/webui/stage6c_webui_provenance/

这样既保留了开发来源追踪能力,又避免追溯文档被网页直接访问。


八、安全验收中发现的路径泄露问题

在本地 HTTP 验收中,发现三份开发追溯文件最初位于 Web 根目录:

EARTH_BASELINE_IMPORT.md
EARTH_SOURCE_MANIFEST.tsv
EXCLUDED_RUNTIME_ASSETS.tsv

其中一份文档包含部署主机的真实绝对路径。

在 PHP 内置服务器下,文档可以被直接请求,因此形成了明确的部署阻断项。

修复方式不是删除追溯信息,而是:

  1. 将追溯文档移出 Web 根目录;
  2. 保存到独立 provenance 目录;
  3. .htaccess 中增加敏感路径保护;
  4. 确保运行代码不再包含主机名、IP 或绝对系统路径;
  5. 重新执行页面和安全验收。

.htaccess 增加了对以下内容的限制:

  • 隐藏文件;
  • app/ 内部代码;
  • SQLite 数据库;
  • FASTA 文件;
  • WAL、SHM、journal;
  • 日志;
  • release 元数据;
  • 开发追溯文件。

需要注意的是,PHP 内置服务器不会读取 Apache 的 .htaccess

因此,本地内置服务器只能验证:

  • 文件是否已经移出 document root;
  • 页面是否泄露路径;
  • PHP 是否出现 fatal;
  • 参数是否安全处理。

真正的 403/404 行为仍需在部署主机的 Apache 环境中验证。


九、一次错误的“环境改造建议”

预部署检查过程中,AI 代理发现:

  • Apache 配置使用 AllowOverride None
  • .htaccess 不会在部署主机生效;
  • 新版本配置支持环境变量;
  • 现网配置仍使用固定目录结构。

代理因此建议:

  • 修改 Apache vhost;
  • 注入环境变量;
  • reload Apache;
  • 建立新的部署环境桥接。

但进一步分析后发现,这些操作并不必要。

部署主机原有 Apache 中央配置已经能够阻止访问:

  • /app/config.php
  • /app/db.php
  • 数据库文件
  • .htaccess
  • 追溯文件

也就是说,虽然 .htaccess 没有生效,但 Apache 的全局配置已经完成了同样的安全职责。

因此:

AllowOverride None 不是问题,也不需要为了新版本修改 Apache。

正确方案是让应用兼容现有目录结构,而不是让现有服务器环境迁就应用。


十、配置兼容:环境变量可选,相对目录默认

新版 config.php 最终采用两级配置策略。

数据库路径

优先级:

  1. 如果设置了 HGF_DATABASE_PATH,使用环境变量;
  2. 否则默认使用:
<站点根目录>/data/processed/human_genes_functions.sqlite

FASTA 目录

优先级:

  1. 如果设置了 HGF_FASTA_ASSET_DIR,使用环境变量;
  2. 否则默认使用:
<站点根目录>/fasta_assets/

Base URL

优先级:

  1. 如果设置了 HGF_BASE_URL,使用配置值;
  2. 否则使用相对 URL。

这样既支持未来部署到其他环境,也可以直接覆盖当前正式目录,不需要修改 Apache、不需要设置系统环境变量,也不需要 reload 服务。


十一、AI 代理误入错误主机的问题

在后续任务中,AI 代理曾报告:

  • 找不到 Stage 6C 代码目录;
  • 找不到 release;
  • 当前目录不是 Git 仓库;
  • 项目似乎只剩 Stage 6B 文件。

但此前已经完成的 Git 提交和 release 不可能同时消失。

检查后发现,代理实际上在错误主机的相似路径中执行了任务。

更严重的是,AI 代理主机的空项目目录中被错误创建了:

Human_Genes_Functions/System/Stage6B_build_report.md

该主机本应只运行代理,项目目录应保持为空。

这类问题不能忽略,因为它会造成:

  • 正式项目位置混淆;
  • 旧文件与新文件混淆;
  • 错误主机上产生孤立副本;
  • 后续代理误判项目状态;
  • 文件清理时误删正式数据;
  • Git 历史与真实工作区脱节。

最终处理流程包括:

  1. 明确验证当前主机 hostname;
  2. 确认错误目录不是符号链接;
  3. 确认不是挂载点;
  4. 盘点目录中全部文件;
  5. 核对开发主机正式文件;
  6. 删除代理主机上的误建副本;
  7. 保留空的 projects 根目录;
  8. 再次确认开发主机 Git 仓库未受影响。

这次事件形成了一条重要长期规则:

任何涉及开发主机、代理主机或部署主机的文件操作,都必须先检查 hostname -s。不能根据当前路径名称推断所在主机。

路径可能相似,主机身份才是真正的安全边界。


十二、构建正式 release

完成配置兼容后,项目构建了正式 Stage 6C release:

System/webui/releases/HGF_WebUI_Stage6C_<date>/

release 中只包含 Web 应用文件,大约二十余个文件,体积仅数百 KB。

release 不包含:

  • SQLite 数据库;
  • FASTA;
  • 日志;
  • 缓存;
  • provenance 文档;
  • 开发备份;
  • 本地测试输出。

同时生成:

System/webui/release_manifests/
├── HGF_WebUI_Stage6C_<date>.sha256
├── HGF_WebUI_Stage6C_<date>.files.tsv
└── HGF_WebUI_Stage6C_<date>.RELEASE

其中:

  • .sha256 用于内容完整性验证;
  • .files.tsv 保存文件大小、权限和哈希;
  • .RELEASE 保存 release 元数据;
  • release 元数据位于 Web 根目录之外,避免被公开访问。

十三、正式部署策略

最终部署没有修改 Apache,也没有引入新的目录切换机制。

采用的方案非常直接:

在部署主机原有网站目录中覆盖应用层文件,保留现有数据库和 FASTA 目录。

覆盖内容包括:

app/
assets/
index.php
search.php
gene.php
disease.php
fasta.php
其他 Web 应用文件

保留内容包括:

data/
fasta_assets/

部署流程包括:

  1. 在开发主机验证 release 哈希;
  2. 检查 release 不含数据库和 FASTA;
  3. 验证部署主机 hostname;
  4. 记录现网数据库和 FASTA 状态;
  5. 记录现网页面 HTTP 基线;
  6. 备份现有应用层;
  7. 将 release 上传到临时目录;
  8. 在部署主机再次校验 SHA-256;
  9. 将应用文件同步到原网站目录;
  10. 保留 data/fasta_assets/
  11. 删除不应出现在 Web 根目录的追溯文件和 release 元数据;
  12. 执行正式 HTTP 验收;
  13. 检查敏感路径;
  14. 对比数据库和 FASTA 前后状态;
  15. 检查 Apache 状态和日志;
  16. 删除临时上传目录。

整个过程:

  • 没有修改 Apache 配置;
  • 没有 reload Apache;
  • 没有 restart Apache;
  • 没有迁移 DocumentRoot;
  • 没有设置新的系统环境变量;
  • 没有修改数据库;
  • 没有替换 FASTA 文件;
  • 没有触发回滚。

十四、部署后的自动验收

部署完成后,以下页面均返回 200:

  • 首页;
  • 搜索页;
  • Gene 页面;
  • Disease 页面;
  • FASTA 页面。

关键功能验证结果:

TP53

TP53 基因页正常显示:

ClinVar disease associations

并且能够看到 25 条关联记录。

Li-Fraumeni syndrome

疾病页正常显示:

ClinVar gene-condition associations

并且能够看到 5 条关联记录,其中包括 TP53。

敏感路径

以下路径均返回 403 或 404:

/app/config.php
/app/db.php
/.htaccess
/data/processed/human_genes_functions.sqlite
/EARTH_BASELINE_IMPORT.md
/EARTH_SOURCE_MANIFEST.tsv
/EXCLUDED_RUNTIME_ASSETS.tsv
/RELEASE

没有出现:

  • PHP 源码下载;
  • 数据库下载;
  • 配置泄露;
  • 绝对路径泄露;
  • traceback;
  • PDOException;
  • PHP fatal error。

数据库和 FASTA 的前后清单完全一致。

Apache 保持 active,配置检查仍为 Syntax OK,日志中没有新错误。


十五、网页端人工验证

自动验收之后,还进行了网页端手动测试。

网页整体外观变化不大,因为 Stage 6C 的重点不是重新设计视觉界面,而是扩展搜索和关系数据。

最明显的变化是搜索功能增加了疾病相关提示,并支持:

All
Gene
Disease

手动验证样本包括:

Li-Fraumeni syndrome

搜索疾病名称后,可以进入疾病页面并查看 TP53 等关联基因。

MONDO:0018875

可以直接通过 Mondo ID 定位 Li-Fraumeni syndrome。

UMLS:C1835398

可以通过外部交叉引用定位同一个疾病。

breast cancer

可以检索乳腺癌相关疾病实体。

BRCA1 和 BRCA2

可以从基因页面查看相关 gene-condition 记录。

乳腺癌相关关系还可能涉及:

  • PALB2;
  • TP53;
  • CHEK2;
  • ATM;
  • 其他遗传性乳腺癌和卵巢癌综合征相关基因。

手动测试确认,Stage 6C 新增功能已经真正可用,而不仅仅是自动化测试通过。


十六、项目为什么必须保留持续更新能力

Human_Genes_Functions 不是一次性静态网站。

随着科研和数据库更新,未来可能继续发生:

  • GENCODE 版本更新;
  • 参考基因组注释变化;
  • ClinVar 数据更新;
  • Mondo 本体更新;
  • GO 注释更新;
  • 新的疾病—基因数据库加入;
  • 变异证据层开发;
  • 遗传方式和致病性信息加入;
  • 搜索体验改进;
  • API 开发;
  • 数据可视化;
  • 新的 release 部署。

因此,正式开发仓库必须持续保留:

  • 完整 Git 历史;
  • 原始数据来源记录;
  • 数据下载元数据;
  • 数据处理脚本;
  • 校验脚本;
  • 自动化测试;
  • CLI;
  • Web UI 源码;
  • release 构建能力;
  • 数据库重建能力;
  • 再次部署能力。

正确的长期流程是:

开发主机开发
→ Git 提交
→ 数据和代码测试
→ 构建 release
→ 部署主机应用层更新
→ 自动验收
→ 网页端人工确认

部署主机上的现网文件不能成为唯一副本。

AI 代理主机也不能保存未经版本控制的项目副本。


十七、此次实践得到的主要经验

1. 应用应适应稳定环境,而不是随意改动服务器

当现有 Apache、PHP、权限和目录结构已经正常工作时,新应用应尽量兼容现有环境。

不应因为应用支持环境变量,就强迫服务器修改 vhost 或 reload Apache。

2. 数据层和应用层应分开部署

数据库和 FASTA 体积巨大,而且更新频率与 Web 应用不同。

应用层可以频繁覆盖,数据层则应独立保留和校验。

3. 本地测试服务器不能代替正式 Apache 验收

PHP 内置服务器不执行 .htaccess

它适合验证 PHP 页面和参数安全,但不适合证明 Apache 访问控制是否有效。

4. 保守映射比错误的高覆盖率更重要

基因和疾病映射中保留 ambiguous、unmapped 和 unsupported,是科研数据库可信度的重要组成部分。

错误的唯一映射比明确标记“不确定”更危险。

5. AI 代理必须有主机身份门禁

只依赖目录名称无法区分正式仓库与错误副本。

每次文件操作前都应验证:

hostname -s

不同主机必须使用不同的明确门禁。

6. 自动化代理的结论必须与已知事实交叉核对

当代理声称:

  • 已存在的 Git 仓库不存在;
  • 已提交的 release 消失;
  • 已完成的代码目录不存在;

首先应怀疑主机、路径或执行上下文,而不是立即重新创建项目。

7. 部署越简单,长期维护成本越低

本次最终部署没有改 Apache、没有更换 DocumentRoot,也没有引入新的服务依赖。

只覆盖应用层并保留数据目录,既满足需求,也降低了未来维护和回滚复杂度。


十八、结语

Stage 6C 的完成,使 Human_Genes_Functions 从一个以基因信息为中心的本地数据库,扩展为支持疾病本体与 ClinVar gene-condition 关系查询的双向检索系统。

项目现在可以:

  • 从基因查疾病;
  • 从疾病查基因;
  • 通过疾病名称、同义词、Mondo ID 和外部编号查询;
  • 展示 mapped、ambiguous、unmapped 和 unsupported 状态;
  • 在网页和命令行中使用同一套关系数据;
  • 保持数据库、FASTA、应用代码和部署流程相互独立;
  • 在不改变现有 Apache 环境的情况下完成升级。

更重要的是,这次开发不仅增加了功能,还建立了一套更明确的长期维护原则:

  • 正式开发源唯一;
  • 数据来源可追溯;
  • Git 历史完整;
  • release 可校验;
  • 部署可重复;
  • 主机操作有门禁;
  • 错误副本必须清理;
  • 现网环境保持稳定;
  • 后续科研更新能力始终保留。

这使项目不再只是“当前能够运行”,而是具备了继续成长、持续更新和长期维护的基础。

Leave a Reply

Your email address will not be published. Required fields are marked *