diff --git a/docs/PLUGIN-CONTRACT.md b/docs/PLUGIN-CONTRACT.md index bfa43c1..b00f64b 100644 --- a/docs/PLUGIN-CONTRACT.md +++ b/docs/PLUGIN-CONTRACT.md @@ -1003,6 +1003,31 @@ turn 崩溃。base bundle 已经注册了 agent-loop / llm / tools, | `ctx.logger.info` 看不到 | DSH 的 logger 不进 journalctl | 用 `console.error` | | `dsh --patch` 不生效 | `--patch` 只对 `dsh --profile ` 有效 | 配置写进 profile 的 `cordis.patch.yml` | | 第二个实例起不来 | task-board 的 ledger 文件锁 | 注入现有实例,不另起 | +| 平台活着但外网访问不了 | 转发层(socat / nginx)没跟着平台重启 | 见下 | + +**转发层的依赖要写两个方向。** 平台监听 loopback、靠一个 socat 单元暴露到 LAN +或公网时,只写 `Requires=` 是不够的: + +| 指令 | 管什么 | 少了会怎样 | +|---|---|---| +| `Requires=平台` | 平台**停止**时转发也停 | —— | +| `PartOf=平台` | 平台**重启**时转发也重启 | `restart` 后转发永久消失 | +| 平台侧 `Wants=转发` | 平台**启动**时拉起转发 | 手工 `start` 后转发不起来 | + +`Requires` 不含重启语义,`PartOf` 不含启动语义,单元自己的 +`WantedBy=multi-user.target` 只在开机时生效 —— 三者缺一, +`systemctl restart <平台>` 或 `stop` + `start` 之后就会出现 +**「平台进程活着、loopback 通、外网全不通」** 这个很难联想到转发层的现象。 + +2026-09-02 真实发生过一次,隐形 9 小时:为验证插件的离线补投重启了 dsh, +socat 被 `Requires` 带停后再没起来。加 `PartOf` 后又发现 `start` 起不来, +才补上平台侧的 `Wants`。 + +另外给转发单元加 `SuccessExitStatus=143`:被 SIGTERM 停掉是正常路径, +不加会在 `systemctl status` 里留一条红色 `failed`,掩盖真正的故障。 + +> 用 `Wants` 而不是 `Requires` 引用转发层:转发起不来不该阻止平台本身启动, +> loopback 访问仍然可用(插件走的正是 loopback)。 ### 9.9 登记密钥的字段名是 `key_token`