AI 应用文件不能只看路径前缀:四道归属校验如何隔开源码与构建产物

同一张文件表承载多类记录时,文件归属必须由显式范围、兼容规则和操作语义共同决定。
摘要| AI 应用的源码、公开构建产物、归档版本和分片上传审计可能共存在 mci_ai_app_file。若只凭路径里有没有 dist 或 public 判断归属,源码拉取会出现假故障,替换同步还可能误删运行产物。本文结合 Microi吾码当前源码与 12 项定向测试,拆解 StorageScope、规范化路径、旧数据兼容和删除边界如何共同隔开不同文件生命周期。
✦ ① 一张文件表为什么会出现四种身份
AI 应用从编辑到上线至少经历私有源码、构建输出、公开运行文件和历史归档。为了统一版本、审计与应用上下文,这些记录可能存放在同一张文件表中,但它们的读取接口、存储桶和清理策略完全不同。
在线源码拉取只能返回开发者可编辑的私有源文件;运行端应读取版本清单和公开产物。如果把公开构建行混进源码列表,客户端会拿公有桶路径调用私有读取接口,既得到“文件不存在”的假故障,也把工程结构解释错。
核心矛盾| 物理上同表,不代表语义上同类。每个读取、替换与删除动作都必须先确认记录归属。
✦ ② 第一关:显式 StorageScope 优先

显式范围优先;只有旧记录缺少范围时,才进入路径兼容判定。
当前源码先读取 StorageScope。PublicBuildStream、PublicBuildStreamArchived 和 PublicBuildOnly 被明确视为公开构建产物;Private 被明确视为私有源码。显式值一旦存在,就不再靠文件名或目录猜测。
这条规则让新增数据有稳定语义。无论构建工具把文件放在 dist、build 还是任意版本目录,归属都由协议字段决定,而不是依赖随项目变化的路径习惯。
显式优先| 范围字段是业务协议;路径只是存储位置。协议不应被目录命名反向覆盖。
✦ ③ 第二关:旧数据只在两条路径相等时认作公开
StorageScope 引入前的历史记录没有显式身份,必须兼容。但兼容不能用“包含 dist”这种模糊规则。当前实现先统一反斜杠、重复斜杠和首尾斜杠,再要求 HdfsPath 与 PublishHdfsPath 都非空且规范化后完全相等,才把旧记录识别为公开构建文件。

路径相等可以证明旧行指向同一公开对象;单边缺失或路径不同都不能升级为公开。
这个条件很保守:源文件与发布文件路径不同,仍按私有源码处理;任一存储路径缺失,也不会猜成公开。保守判定避免因残缺数据把源码从开发上下文中错误排除。
显式 PublicBuild* → 公开构建
显式 Private → 私有源码
范围为空且 HdfsPath == PublishHdfsPath → 旧公开构建
其他范围为空记录 → 旧私有源码
✦ ④ 第三关:控制面记录既不是源码,也不是构建文件
分片上传会话、发布审计等记录也可能带 FilePath,却不是用户可编辑源码,更不应跟随源码同步被清理。源码注释明确列出这类控制面范围,并规定:只要 StorageScope 非空且不是 Private,就不能被当作旧私有源码。
这比“公开或私有”二分法多了一层。控制面数据服务于可靠上传与审计,它可能没有公开文件,也不属于工程目录。若强行塞进二分逻辑,替换同步很容易误删一次仍在进行的分片会话。
第三种语义| 不是私有源码,不代表一定是公开产物;控制面记录需要独立生命周期。
✦ ⑤ 第四关:替换同步只删除过期私有源码
ReplacePrivateSourceOnly 的删除条件不是“新清单里没有这个路径”就删除。源码先调用 IsPrivateAiApplicationSourceFile,只有确认属于私有源码,且 FilePath 不在本次同步集合中,才允许移除。
因此公开构建行、归档行与控制面记录都会被保留;当前仍存在的源码也被保留;只有明确过期的私有源文件被清理。归属校验先于差集运算,避免一次源码同步演变成跨生命周期清库。
- 公开构建产物:保留,由运行版本和发布流程管理。
- 控制面记录:保留,由对应上传或审计流程管理。
- 当前私有源码:保留。
- 不在同步清单中的过期私有源码:允许移除。
✦ ⑥ 为什么不能只靠 dist、source 或文件后缀
目录名称属于工程约定,不是安全边界。一个源码项目可以把可编辑模板放在 dist-template,也可能把最终产物输出到 assets;同一个 .js 文件既可能是源文件,也可能是压缩后的运行包。用字符串前缀判断,规则会随构建器变化而漂移。
显式 StorageScope 把语义从路径中抽出来,旧数据兼容又只使用严格相等关系。这样新数据不依赖目录,历史数据也不会被宽松猜测。路径规范化只是消除 Windows 与 URL 表达差异,不负责发明业务身份。
规则层次| 业务范围决定身份;规范化路径只为旧数据做确定性比较;文件名与后缀不参与授权。
✦ ⑦ 12 项测试覆盖了哪些误判

本地 .NET 10 定向测试:12 执行、12 通过、0 失败;TRX 与源码摘要已归档。
本轮执行 AiApplicationFileStorageScopeTests,结果为 12 / 12 通过。覆盖反斜杠与斜杠规范化、三种公开范围、私有源路径差异、公开构建保留、控制面记录保留、旧私有源码可替换,以及路径缺失时绝不误判为公开。
测试把最容易被忽略的负向条件也写成断言:路径只有一边存在不能公开;未知非空范围不能当私有;公开行不能被源码差集删除。证据文件保存命令、退出码、TRX 与 SHA-256,便于复核。
证据边界| 这些测试证明分类与删除判定函数符合当前契约,不替代真实对象存储权限、版本清单和线上下载验收。
✦ ⑧ 一套适合混合文件表的归属清单
- 新记录必须写显式范围,不再依靠目录命名。
- 旧记录只使用严格、可解释的兼容条件。
- 源码、公开产物与控制面记录分别定义读取入口。
- 执行删除前先验证归属,再计算是否过期。
- 为路径缺失、斜杠差异、未知范围和误删场景补负向测试。
读取前:确认文件范围
替换前:只选择私有源码集合
删除前:再次确认私有身份与过期状态
发布与控制面:交给各自生命周期
文件治理的难点不是找到一个看起来像源码的路径,而是让每个生命周期只被自己的操作触碰。四道归属校验把读取、同步与发布拆开,AI 应用上下文因此更干净,构建产物也不会被一次源码替换误伤。
结论| 先判身份,再读、替换或删除;路径前缀永远不能代替文件归属协议。
更多推荐




所有评论(0)