Skip to content

PLAN-FNOS-011 凭据文件权限异常的可诊断性 ​

字段内容
计划编号PLAN-FNOS-011
计划日期2026-10-09
对应需求FNOS-011 凭据文件权限异常的可诊断性
本轮功能FNOS-011-01 至 FNOS-011-05 全部进入本轮实施
上游依据DSH 0.2.0-rc.2 发行包中 @deepseek-ai/dsh-credentials-local 的 assertOwnerOnly 与 loadInitial;本仓库 plugins/dsh-codebuddy-plugin/src/host/storage.ts
计划状态已完成(随 0.2.0-rc.2.6 发布)

计划目标 ​

让凭据文件「存在但读不了」这一情形在 DSH 自身与各插件中被一致地识别为异常而非未登录或不可用,并把可执行的修复方式呈现给用户;同时确保凭据异常不再让 DSH Web 整体退出。技术边界见需求文档「不在本次范围内」:不自动修复权限、不改变凭据文件格式与位置、不为非凭据文件引入同类判定。

当前实现与目标设计 ​

当前实现 ​

两处判定使用同一条件 (mode & 0o077) === 0,它只覆盖 group/other 位:

位置判定命中 0000 时用户可见结果
dsh-credentials-local 的 assertOwnerOnly(mode & GROUP_OTHER_BITS) === 0 即放行;isENOENT 之外的 stat 失败会抛出放行,随后 readFile 抛 EACCEScredentials 插件初始化失败 → 11 个依赖插件挂起 → DSH Web 以 code 1 退出,界面只有恢复页
dsh-codebuddy 的 isOwnerOnly同上条件;stat 失败(含不存在)一律返回 true放行,随后 readFile 失败被 readDocument 的 catch 吞掉返回 undefined → 呈现「未登录」,账号列表静默变空

0000 的特殊性在于它同时满足「不暴露给他人」(group/other 位为空)与「属主也读不出来」——前者是判定想拦的,后者是判定漏掉的,两种相反状态被同一段判断放行。

目标设计 ​

  1. 判定条件补全:在既有条件之上补充属主可读位检查,即「group/other 位为空且属主可读」。保留既有的拒绝语义(644 等放宽权限的文件继续被拒绝)。
  2. 判定实现收敛:仓库内插件共用一个权限判定实现,避免每个插件各自重写、各自漏判。判定同时返回「可用 / 不可用 / 不存在」三态,供调用方区分。
  3. 错误可诊断:不可用时抛出或上报含文件路径、当前权限位、修复命令的信息。上游对权限过宽的既有文案(... is readable beyond its owner (mode 644); run "chmod 600 ...")是本次文案的范式。
  4. 降级而非中断:DSH 凭据不可用时让应用仍能进入可用状态并提示,而不是整体退出。

影响范围分析 ​

需求功能代码模块配置/数据测试文档目标环境
FNOS-011-01plugins/dsh-codebuddy-plugin/src/host/storage.ts;新增共享权限判定实现(落点见「待决事项」)无数据迁移判定单测覆盖 600/644/0000/400/不存在—DSH Web、DSH Desktop
FNOS-011-02dsh-credentials-local 的判定与错误文案(处置方式见「待决事项」)无启动日志断言含路径、权限位与修复命令docs/troubleshooting.md真实 fnOS NAS
FNOS-011-03凭据插件失败时的启动降级路径无真机:凭据 0000 时应用仍可打开并提示docs/troubleshooting.md真实 fnOS NAS
FNOS-011-04dsh-codebuddy 的 readDocument 三态返回与卡片提示无单测:不可读与不存在的呈现可区分;卡片行为测试docs/plugins/dsh-codebuddy.mdDSH Web、DSH Desktop
FNOS-011-05共享权限判定实现的引入与各插件接入无源码扫描:无重复判定实现docs/development/plugin-development.md本地

不涉及:应用 manifest、wizard、cmd/ 脚本、网关、FPK 构建门禁、published-dsh-plugins.json、非凭据类文件(会话、工作区、日志)的权限处理。

架构与数据流 ​

mermaid
flowchart TD
    subgraph shared["共享权限判定"]
        S["credentialFileState(path)"]
        S --> S1["不存在"]
        S --> S2["可用:group/other 位为空且属主可读"]
        S --> S3["不可用:权限过宽或属主不可读"]
    end
    S1 --> R1["按未登录处理(行为不变)"]
    S2 --> R2["正常加载凭据"]
    S3 --> R3["抛错 / 上报:路径 + 权限位 + 修复命令"]
    R3 --> D1["DSH 凭据:降级启动并提示"]
    R3 --> D2["插件凭据:卡片显示凭据异常"]

判定是纯函数(输入 stat 结果与 path),不涉及 IO 之外的副作用,便于单测覆盖全部权限组合。

分阶段任务 ​

任务 ID对应需求/验收修改内容前置条件验证方式
PLAN-FNOS-011-T01-01FNOS-011-01 / AC-02实现共享权限判定:返回「不存在 / 可用 / 不可用」三态,条件为「group/other 位为空且属主可读」—单测覆盖 600/644/0000/400/不存在五种输入
PLAN-FNOS-011-T01-02FNOS-011-05 / AC-01确定共享实现的落点(待决事项 A)并接入 dsh-codebuddyT01-01源码扫描无重复判定;插件现有测试回归
PLAN-FNOS-011-T02-01FNOS-011-04 / AC-01、AC-02dsh-codebuddy 的 readDocument 改为区分三态:不存在按未登录、不可用上报异常T01-02单测:两种情形返回不同结果;卡片显示异常提示
PLAN-FNOS-011-T03-01FNOS-011-02 / AC-01、AC-02DSH 凭据的判定补属主可读位,错误文案含路径、权限位与修复命令;确认不打印凭据内容T01-01;处置方式待定(待决事项 B)真机:chmod 000 后启动,断言日志内容
PLAN-FNOS-011-T03-02FNOS-011-03 / AC-01、AC-02凭据不可用时降级启动而非整体退出;界面给出提示与修复指引T03-01真机:凭据 0000 时应用可打开;按提示修复后能力恢复
PLAN-FNOS-011-T04-01全部文档同步:troubleshooting 补充判定与修复;plugin-development 登记共享判定用法;docs/plugins/dsh-codebuddy.md 说明凭据异常提示T02-01、T03-02文档构建与站内链接检查

交互和行为设计 ​

  • DSH 凭据不可用:应用启动后仍可打开界面,在凭据相关能力的位置给出提示,内容形如「凭据文件不可读(权限位 0000):<路径>;执行 chmod 600 <路径> 后重启」。提示不阻塞其他不依赖凭据的功能。
  • 插件凭据不可用:插件卡片显示凭据异常与修复方式,与「暂无已登录账号」区分;修复后刷新即恢复正常展示。
  • 权限过宽(如 644):维持现有行为——拒绝加载并给出修复命令,本次不改变该分支。

数据、权限和错误处理 ​

  • 判定与错误信息只引用文件路径与权限位,不读取、不打印、不上报凭据内容。
  • 产品不代替用户修改权限:不自动 chmod,只提示确切的修复命令。
  • 恢复动作的人工约束沿用测试用例文档规范:恢复后显式 chmod 600 并用 stat 核对。

依赖、风险和决策 ​

待决事项(实施前须确认) ​

  • A. 共享判定实现的落点【已定案 2026-10-10】:新建共享包 packages/dsh-plugin-kit(@tnnevol/dsh-plugin-kit)。理由:符合目录结构规范「真正共享的能力应进入 packages/」;@tnnevol/dsh-semi-ui 定位是 UI 主题组件不宜混入文件权限判定;文件副本没有单一真源。
  • B. DSH 自身凭据判定的处置方式【已定案 2026-10-10:废弃 02/03】:维护者确认不修改官方代码、不做安装期补丁,FNOS-011-02/03 废弃、不做排期;插件侧 01/04/05 继续交付——同一根因在插件凭据上的表现已由共享判定 + 三态呈现覆盖。

风险 ​

  • 降级启动的边界:凭据不可用时让应用继续启动,可能导致部分能力在无凭据状态下暴露异常。缓解:只降级「凭据加载失败」这一路径,依赖凭据的能力给出明确提示而非静默失败。
  • 判定收紧的兼容性:补充属主可读位检查后,既有依赖「0000 放行」的行为会改变。核实结论显示正常路径下文件始终为 600,且 0000 本就读不出来,因此该收紧不影响任何可用场景。
  • 上游立场一致性:上游已明确「非 ENOENT 的读取失败必须暴露」,本需求与该立场一致,修复方向不冲突。

测试、打包、发布和回滚 ​

  • 本地:共享判定实现的单测(五种权限输入);dsh-codebuddy 的三态行为单测与卡片测试;全仓 pnpm run check -- --all。
  • 包级:插件版本随 DSH 基线同步的既有约定不变;本轮不因本需求单独发版,随下一次应用版本发布。
  • 真实 NAS:把 DSH 凭据改为 0000 复现启动失败现场,验证错误文案与降级启动;恢复 600 后验证能力恢复。测试前后按凭据规范备份、恢复与核对权限。
  • 回滚:判定与提示为局部改动,回滚即还原相应文件;不涉及数据迁移,回滚后既有凭据与配置不受影响。
  • 测试用例回填到 docs/tests/FNOS-011-credential-permission-diagnostics.md。

参考资料 ​

完成状态 ​

阶段状态
阶段一:共享权限判定实现(@tnnevol/dsh-plugin-kit)本地已完成
阶段二:插件接入与三态呈现(codebuddy + codex-auth)本地已完成
阶段三:DSH 凭据判定与降级启动废弃(2026-10-10)
阶段四:文档同步与验收进行中

变更记录 ​

日期变更说明
2026-10-09初始登记依据 FNOS-011 建立计划:拆为共享判定、插件接入、DSH 凭据降级、文档同步四个阶段。登记两项实施前须确认的待决事项(共享实现落点、上游包处置方式)。
2026-10-10实施定案与本地交付待决事项 A 定案为新建 packages/dsh-plugin-kit;待决事项 B 定案为废弃 FNOS-011-02/03(不修改官方代码,不做排期)。阶段一/二本地完成:共享判定 12 条单测、dsh-codebuddy 三态读取 + credentialState RPC + 详情页警示块(5 条单测)、dsh-codex-auth 接入共享判定、收敛守门用例锁定无重复实现;全量 909+137 用例回归通过。

基于 VitePress 构建