Skip to content

feat(runtime): 增加只读 Runtime 目录探针 - #3

Draft
7015725 wants to merge 341 commits into
agent/modular-ui-bootstrap-20260801from
agent/runtime-client-readonly-20260802
Draft

feat(runtime): 增加只读 Runtime 目录探针#3
7015725 wants to merge 341 commits into
agent/modular-ui-bootstrap-20260801from
agent/runtime-client-readonly-20260802

Conversation

@7015725

@7015725 7015725 commented Aug 1, 2026

Copy link
Copy Markdown
Owner

目的

在实现 Runtime Client 前,先通过真机只读探针确认生产 Runtime 的实际目录结构、状态文件和 PID/端点候选路径,避免根据旧脚本或经验猜测路径。

新增

  • entry/SingBoxHubRuntimeProbe.js
  • 扫描 <ShortXDir>/SingBoxHub,最大深度 5、最多 400 项
  • 返回相对路径、类型、大小、修改时间和 Java File 权限状态
  • 单独汇总名称包含 state/status/pid/lock/socket/endpoint/manifest/version/runtime/health/control/daemon 的候选项
  • 不跟随指向 Runtime 根目录之外的别名或符号链接

安全边界

  • 不执行 Shell
  • 不访问网络
  • 不创建、修改或删除文件
  • 不读取配置、订阅、凭据或任何文件内容
  • 不启动/停止进程
  • 不操作 TUN、路由、防火墙、DNS 或配置

真机门禁

探针结果确认后,才建立只读 Runtime Client 状态协议。当前稳定 UI 分支不受影响。

7015725 commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

Java File.listFiles() 真机返回 null,确认是生产 Runtime 目录权限边界,不是目录为空。

新增第二阶段探针 entry/SingBoxHubRuntimeRootInventory.js

  • 使用 su --mount-master
  • 只执行固定的 find 与文件类型 test
  • 最大深度 5、最多返回 400 项;
  • 不读取任何文件内容;
  • 不调用 Runtime controller;
  • 不执行进程信号、TUN、路由、防火墙、DNS 或配置操作;
  • 输出明确标记 shellExecuted=truefilesModified=falsefileContentsRead=false

仓库脚本已确认生产路径包括 bin/singboxhub-runtimebin/sing-boxmetadata/runtime.meta.jsonruntime/control/control_endpoint.json;本阶段仍只做目录清单,不读取这些文件内容。

7015725 commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

根据 ShortX 实机调用方式,SingBoxHubRuntimeRootInventory.js 已改为 ShellCommand.newBuilder() + shortx.executeAction()

调整:

  • 删除 Java ProcessBuilder
  • 删除 su 路径解析和 su --mount-master
  • 直接使用 ShortX Shell 服务执行固定只读命令;
  • 返回 shellOutshellErrshellCode 解析结果;
  • 通过 id -u 验证 Shell 服务实际 UID;
  • 保留只读 find/test/id 边界,不读取文件内容,不调用 Runtime Controller。

当前探针版本:probeVersion=3;提交:31ab95f30a9f124ccd48cf1765ad1449e9f5521d

7015725 commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

真机门禁:只读 Runtime Client UI 接入

目录探针已确认 ShortX ShellCommand 以 uid=0 执行,并发现生产 Runtime 的控制器、Core、管理 API、策略管理和状态目录。

已发布独立测试模块集 20260802.02

  • entryVersion=13
  • 更新源 agent/runtime-client-readonly-20260802
  • 新增 sbh_16_runtime_status_home.js
  • sbh_14_runtime_client.js 升级到版本 2
  • 通过 ShortX ShellCommand + shortx.executeAction() 执行固定只读检查
  • 校验生产组件存在且可执行
  • 通过 /proc/*/exe 精确匹配生产 SingBoxHub/bin/sing-box PID
  • 首页显示 Runtime 已安装、运行中、组件缺失或状态不可用
  • 启动、停止等写操作继续返回 READ_ONLY_CLIENT

安全边界:不读取配置、策略、端点或日志内容;不调用 Runtime Controller;不启动/停止进程;不操作 TUN、路由、防火墙或 DNS。

Manifest 16 个模块的 SHA-256 已由 GitHub Actions 校验通过。稳定 entryVersion=12 入口未修改。

7015725 added 27 commits August 2, 2026 22:39

7015725 commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Stage 53 Retry 1:Runtime/Core 状态分歧

真机结果:

  • Shell 引号修复生效,shellUid=0
  • 前置门禁与生产配置检查通过;
  • Runtime 控制服务 PID 19373 存活且所有者验证通过;
  • START 发送一次,返回 ALREADY_RUNNING,correlation 匹配;
  • START 前精确匹配 Core 数量为 0
  • START 后未发现符合预期 argv 的 Core,corePid=0
  • 未发送 STOP_CORE,未发送进程信号,未修改配置/TUN/路由;
  • 返回 CORE_START_RECONCILIATION_FAILED

已记录:

  • docs/phases/runtime-stage53-retry1-true-device-already-running-divergence.md
  • docs/phases/runtime-stage53-retry2-core-state-divergence-diagnostic.md

Retry 2 测试入口:SingBoxHub_Stage53_Core状态分歧只读诊断重试2.txt

  • 入口版本:78
  • 模块:sbh_78_runtime_core_state_divergence_diagnostic.js
  • 模块 SHA-256:96aa9634f4279146c0f5c922700433d89918891df811151783b08463749c9180
  • 入口 SHA-256:536796f04e42094f99bf3e33fae3b7767738d28a863497c3fc7bfadced37e566

Retry 2 只发送一次只读 STATUS,并枚举 argv 中包含生产二进制或生产配置路径的候选进程、控制服务直接子进程及网络资源状态。不会发送 START、STOP_CORE、TERM 或 KILL,不修改任何 Runtime 文件。

7015725 commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Stage 53 Retry 2 真机通过;Retry 3 已加入

Retry 2 已确认 Runtime/Core 状态分歧不是内部空状态,而是旧 argv 契约过窄:

  • Runtime STATUS=RUNNING
  • 控制服务 PID 19373
  • 实际 sing-box Core PID 8011
  • PID 8011 的 PPid 为 19373、uid 为 0、state 为 S
  • argv0 为生产 sing-box 二进制;
  • 生产配置位于 argv 索引 5
  • <binary> run -c <config> 四参数规则未命中;
  • TUN、规则和路由仍为空。

已记录:

  • docs/phases/runtime-stage53-retry2-true-device-controller-owned-core-identified.md

Stage 53 Retry 3 已加入:

  • src/sbh_79_runtime_controller_owned_core_stop_reconcile.js
  • docs/phases/runtime-stage53-retry3-controller-owned-core-stop-reconcile.md
  • 测试入口:SingBoxHub_Stage53_控制器持有Core停止归一化重试3.txt
  • 入口版本:79
  • 模块 SHA-256:35da75a098812222f54f67d9fc7cd3c975405f8e099e77e693131c4ef0ead83b
  • 入口 SHA-256:a9ab7c10a8a2ac5eda08aeb21f4a375588a18d81e06bb1ab78faf227af1f324d

Retry 3 要求恰好一个控制器持有 Core,发送一次 STATUS、一次 STOP_CORE,精确确认所选 PID 消失、控制器持有 Core 数量降为 0、控制服务继续运行,再执行停止态 STATUS 和最终 PING。不会发送 TERM/KILL,不写 Runtime 文件,不修改 TUN、路由、DNS 或防火墙。

7015725 commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Stage 53 Retry 3 真机通过;Retry 4 已加入

Retry 3 真机结果:

  • Runtime 控制服务 PID 19373 保持运行;
  • 唯一控制器持有 Core PID 8011 已通过一次认证 STOP_CORE 停止;
  • remainingControllerOwnedCoreCount=0
  • 停止后 STATUS=STOPPED
  • 最终 PING=PONG
  • 未发送 TERM/KILL,未修改配置、TUN、规则或路由;
  • readyForLifecycleRetry=true

已记录:

  • docs/phases/runtime-stage53-retry3-true-device-stop-reconcile-success.md

Stage 53 Retry 4 已加入:

  • src/sbh_80_runtime_core_lifecycle_controller_owned_retry.js
  • docs/phases/runtime-stage53-retry4-controller-owned-lifecycle.md
  • 测试入口:SingBoxHub_Stage53_控制器持有Core启停闭环重试4.txt
  • 入口版本:80
  • 模块 SHA-256:6a7215743adf5b65db77d20aa26db0ff2ba3bf876f6a4c5a4db28350f0f7aa06
  • 入口 SHA-256:c884feab1cc95dda500e123b428c5aa79347f97ef4a842d39af45df403905734

Retry 4 使用真机确认的控制器持有 Core 契约:PPid=Runtime PID、uid 0、argv0 为生产 sing-box 二进制、生产配置允许位于任意后续参数。单按钮执行:

STATUS(STOPPED) -> START -> 控制器持有 Core 精确核验与 4 秒稳定性 -> STOP_CORE -> STATUS(STOPPED) -> PING -> 生命周期审计

最终必须为 Core 已停止、Runtime 控制服务继续运行、TUN/规则/路由为空。失败时仅对已锁定且身份仍匹配的 Core PID 执行精确 TERM/KILL 回滚,不停止控制服务,不自动重试。

静态验证:模块与完整入口 JavaScript 语法通过;Rhino ES5 禁用语法扫描通过;前置、启动观察、停止观察、回滚和审计 5 组生成 Shell 的 sh -n 通过;入口内嵌源码与仓库模块一致。真机验证待执行。

7015725 commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Stage 55:生产生命周期 UI 验收

Stage 54 真机门禁与入口启动记录已确认:

  • Runtime 控制服务 PID 19373 健康;
  • runtimeAttached=trueruntimeState=stopped
  • authenticated PING 通过;
  • Core 未运行;
  • 生产生命周期 UI 已提升;
  • 启动/停止写操作仍锁定。

已加入:

  • src/sbh_82_runtime_production_lifecycle_ui_acceptance.js
  • docs/phases/runtime-stage55-production-lifecycle-ui-acceptance.md
  • 测试入口:SingBoxHub_Stage55_生产生命周期UI验收.txt
  • 入口版本:82
  • 入口 SHA-256:c0694f51ca6f7618b2e69331c56da7f965df55b4a3b2ed7f5312f02f57bc50e9
  • 包装模块 SHA-256:3ccd88a9dda79cea92af01675442b802659a7c32b82b5ec5655bf60a90687580
  • 原始模块 SHA-256:f0eb006e8cce3053866fcfe8e635f88ed686b57d73b2cb3ab89088ff7790696c

Stage 55 执行顺序:

  1. 首页只读刷新一次;
  2. 人工确认 Runtime PID、Core 停止态、三个控制表面、导航、滚动与关闭按钮;
  3. 节点页点击确认验收;
  4. 重新校验 Stage 53 生命周期审计、Stage 54 提升审计、生产配置、endpoint、控制服务、Core 与网络资源;
  5. 原子写入 state/production-lifecycle-ui-acceptance.json

Stage 55 不发送 START、STOP_CORE 或进程信号,启动和停止按钮继续锁定。通过后进入 runtime_production_lifecycle_write_unlock。JavaScript、Rhino ES5 扫描、两组生成 Shell sh -n、内嵌 SHA-256 和 gzip 解包校验均通过;真机验证待执行。

7015725 commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Stage 56 真机解锁通过

真机结果:

  • ok=true
  • preflightPassed=true
  • shellUid=0
  • productionConfigCheckPassed=true
  • acceptanceAuditVerified=true
  • Runtime 控制服务 PID 19373 存活且身份通过
  • Runtime STOPPED
  • 控制器持有 Core 数量 0
  • 宽松 Core 候选数量 0
  • writeActionsUnlocked=true
  • 状态、启动、停止控制均已启用
  • 解锁审计 state/production-lifecycle-write-unlock.json 已创建,字节数 468
  • 未自动 START/STOP_CORE,未发送系统进程信号
  • TUN、规则、路由、DNS、防火墙与配置均未修改
  • readyForProductionLifecycleManualControlAcceptance=true
  • nextAuthorizedOperation=runtime_production_lifecycle_manual_control_acceptance

已新增真机记录:

  • docs/phases/runtime-stage55-true-device-acceptance-success.md
  • Stage 56 设计:docs/phases/runtime-stage56-production-lifecycle-write-unlock.md

下一步直接使用当前 Stage 56 会话,在首页按顺序执行一次:刷新 -> 启动 -> 刷新 -> 停止 -> 刷新。暂不更换入口,避免重启后内存解锁状态丢失。

7015725 commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Stage 56 真机解锁通过

Stage 56 按钮回调结果确认:

  • ok=true
  • preflightPassed=true
  • shellUid=0
  • productionConfigCheckPassed=true
  • acceptanceAuditVerified=true
  • Runtime 控制服务 PID 19373 存活
  • Runtime STOPPED
  • 控制器持有 Core 和宽松 Core 候选均为 0
  • writeActionsUnlocked=true
  • 刷新、启动、停止控制均已启用
  • 解锁审计 state/production-lifecycle-write-unlock.json 已写入,字节数 468
  • 解锁事务未自动 START/STOP_CORE,未发送系统进程信号
  • TUN、规则、路由、DNS、防火墙及配置均未修改
  • readyForProductionLifecycleManualControlAcceptance=true

已记录:

  • docs/phases/runtime-stage56-true-device-write-unlock-success.md

补充说明:入口启动 JSON 中的 runtimeProductionLifecycleWriteActionsUnlocked=false 是点击解锁按钮之前的启动快照,不否定按钮回调的终态。下一阶段必须在同一 Rhino 窗口中完成“刷新 → 启动 → 刷新 → 停止 → 刷新”手动控制验收。

7015725 commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

Stage 56 手动控制通过,但同步链路过慢;Stage 57 已加入

Stage 56 真机手动闭环结果:

  • Runtime 控制服务 PID 19373
  • 启动后 Core PID 32571,身份为控制器持有;
  • 停止后 Core 恢复为 0
  • TUN、规则和路由保持为空;
  • 功能和安全边界通过;
  • 用户实测单次启动或停止等待接近或超过 60 秒,性能验收不通过。

根因:可见回调串行等待完整快照、操作后观察和审计等约三次 ShortX ShellCommand;真机 Shell 传输层长期返回 158,业务 marker 已完成但传输等待会累积。

已加入 Stage 57:

  • src/sbh_84_runtime_production_lifecycle_low_latency.js
  • docs/phases/runtime-stage56-true-device-manual-control-success-slow-path.md
  • docs/phases/runtime-stage57-low-latency-lifecycle-controls.md
  • 测试入口:SingBoxHub_Stage57_低延迟生命周期控制.txt
  • 入口版本:84
  • 入口 SHA-256:67669a84d304d62f0f5d6c4124bfb622e17f9b3abbbfbf7f596fd55ef29f0315
  • 原始模块 SHA-256:ac3c6fea60fca9e25896c3957945c0b5e16b2b9e22107f3ee8cef72be167163c

Stage 57 设计:

  • 一次严格激活门禁;
  • START、STOP_CORE、STATUS 的可见路径仅用认证 LocalSocket;
  • STATUS 每 250ms 轮询,状态收敛后立即更新 UI;
  • 可见路径 Shell 调用 0
  • 每次写操作只在后台执行一次严格 Shell 核验和审计;
  • 后台核验期间锁定下一次写操作;
  • 启动核验失败仅通过 STOP_CORE 回滚,不发送 TERM/KILL;
  • 增加可见完成、状态收敛、严格核验和总耗时字段。

静态验证:模块、包装模块和完整入口 JavaScript 语法通过;三组 Shell 模板 sh -n 通过;内嵌与解压哈希一致。真机性能验证待执行。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant