feat: 探针“未知”语义与 jump 跳板机,看板改为一行一隧道并原地刷新 - #25
Merged
Merged
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
这几处改动在源码里互相咬合——core.py 的命令构建重构既服务于 jump,也服务于改写成 有界读取的探针;health/serve/daemon/doctor 的“未知”语义又依赖 core 抛出的 ProbeError ——拆成多个提交只会得到“新开头 + 旧结尾”的半成品,因此一并提交。 - [ssh] jump:堡垒机原样交给 ssh -J,跳板机身份复用 ~/.ssh/config;与 options 里的 ProxyJump/ProxyCommand 同时出现会被直接拒绝;doctor 只探测本机能直连的第一跳。 - [ssh] user / identity_file 可省略:省略即不再强制 user@ 与 -i;新增 ponte config --ssh-command 打印实际执行命令行。 - ponte reload:只重启设置真的变过的隧道,坏配置在本地就被拒绝,POSIX 下 kill -HUP 等价。 - 探针没跑成 = 未知:不再报成“端口未监听”,也不再计入假死强杀阈值;/healthz 回 200 unverified,status / doctor / 看板显示未知并附原因;确凿失败则回推原因。 - 探针在 Windows 上不再永久挂死:SSH 子进程恢复 close_fds,探针读取双重限时。 - stop/status/logs/watch 在配置写坏时仍可用;restart 仍先校验再动手。 - 启动失败不再只有“未写 PID 文件”:捕获子进程首行输出,包内旧配置的工作目录也修正。 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
doctor 的体检表多一个 --json 形态(ok / counts / checks),退出码照样“有失败就非 0”, 这样 CI 在同一次运行里既能存下报告又能直接据它设门禁。typer 的 add_completion 打开, ponte --install-completion 可安装 bash / zsh / fish / PowerShell 补全。 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
补上 jump 跳板机、reload 热重载、config --ssh-command、doctor --json 与 shell 补全, 以及“未知不是挂了”的说明、排查表条目与中文对照。 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
其余测试都直接喂手工拼的 payload,所以守护进程写出来的字段名与看板读的字段名一旦 不一致,两边各自的单元测试都发现不了。这里用真实 HealthChecker 与 TunnelDaemon 的 落盘路径,经真实回环套接字断言 /healthz、/status.json、/metrics 与看板:未知 ≠ 坏了、 只有确凿失败才 503、没观察到的端口不会被写成“未监听”。 它当场抓到一处真实缺口:探针跑通但看到端口关闭时,状态文件里并没有 error 字符串, /healthz 便只回 503 degraded 而说不出原因。现已从观测到的端口状态回推出原因, 并补上对应的单元测试。 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
一条隧道一张卡片时,3 条就要滚动,而状态页的第一要求是“一眼看全”;刷新又是整页 meta refresh,每 5 秒把你正在读的页面扔掉一次——展开的行合上、滚动位置归零。这次 把这两件事一起改掉,并且把跳板机补上看板。 - 跳板机随 destination 一起成为状态的一部分(ProfileStatus.jump / status --json 的 jump 字段,两者都取自配置):看板在目标下方用琥珀色写出“↳ 经 ops@bastion:2222”。 堡垒机是链路里最先断的一环,也是配置里其它地方都说不出来的那一环。 - 一行一条隧道:端口成了带 ✓/✗ 与“远程/本地”标签的 chips,统计表与事件流收进该行 的 <details>(无脚本照样能展开),异常原因直接写在收起的那一行上——需要点开才知道 原因,等于没有原因;探针没探到的端口组写“未观测”,而不是画成红色的“未监听”。 - 刷新不再整页重载:<noscript> 里的 meta refresh 作为无脚本回退(有脚本的浏览器 根本不会创建它,因此不存在竞态),有脚本时 fetch 同一份服务端渲染原地替换两块 区域,展开的行与滚动位置都保住,判定发生变化的行会闪一下,免得一次断线被读成 “一直如此”。刻意复用服务端渲染而不是在 JS 里再写一遍:两份渲染逻辑正是看板和 ponte status 开始说法不一致的起点。 - 顺带修掉两处只有真渲染才暴露的问题:availability 作为 0..1 比率被按秒数取整, 97.9% 会显示成 100.0%,而看板、/status.json 与 Prometheus 读的都是这个字段; 展开箭头写成 CSS \25be 转义,却被 Python 当八进制转义吃掉,渲染成了控制字符。 - 美化:补齐一直声明却没实现的浅色主题,头部换成品牌图标 + 只显示非零状态的计数 tile,在线率加一道进度条,数字改用等宽数字以免刷新时整行跳动,12px 小字对比度 按 WCAG AA 调到 4.7:1 以上。 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
CodeQL 的 py/incomplete-url-substring-sanitization 报在 `assert "example.com" in result.output`:拿域名字面量做子串包含,放在源码里 确实是一次不完整的地址校验(`evil-example.com.attacker.tld` 同样能过),在测试 里只是误报——但那个形状不该留在代码里,而这条告警的 security severity 是 high (CWE-020,7.8),按 main 的 ruleset(security_alerts_threshold = high_or_higher) 它会挡住合并。 改成断言配置里的 destination:既避开了那个形状,也比原来更严——它现在钉的是 “印出来的就是配的那台服务器”,而不是一个写死的域名片段。另按查询自身的判定 (looksLikeUrl 与 in / startswith / endswith 三种形状)扫了全仓,没有第二处。 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
modusensus
force-pushed
the
feat/serve-dashboard
branch
from
September 20, 2026 02:25
d6e6bbb to
19fe66a
Compare
PR #25 的 CI 有三处失败,只在非 Windows 上出现,本机看不见: - Lint & types(ubuntu):mypy 报 ctypes 没有 windll。typeshed 只对 Windows 声明 这个属性,直接属性访问在 Linux 上就是 attr-defined。改成 cast(Any, ctypes), 两个平台都干净。不能用 # type: ignore:本仓库开了 warn_unused_ignores,那条注 释会在 Windows 上反过来被报成"无用忽略"。 - macOS 的两个测试腿:--show-completion 的测试实际依赖 shell 自动探测。探测可用 时 typer 会把这个选项变成不接受取值的开关,shell 取自父进程链——本机在 Git Bash 下跑恰好探测到 bash,所以一直"通过",而 macOS runner 的父进程链里探测不到可识 别的 shell,命令以 1 退出(本地已按此条件复现)。测试改用 typer 自己的 _TYPER_COMPLETE_TEST_DISABLE_SHELL_DETECTION,让取值真正生效,并把断言改成 zsh 的 #compdef,以证明用的是参数而不是探测结果。 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
modusensus
added a commit
that referenced
this pull request
Sep 21, 2026
看板只从真实的配置与守护进程状态文件取数据,于是"先看一眼前端长什么样"这件事以前只有 两条路:对着真基础设施跑,或者手搓一份状态文件。后者会随 payload 契约漂移而悄悄失真, 而它长得和真数据一模一样——最容易被当成真的。 --demo 把它收进产品:不读配置、不碰守护进程,用一份内置的确定性时间轴驱动同一个 HTTP 服务。三个 profile 覆盖看板会渲染的每一种状态——web 健康→断线→退避→重连;db 连上了但 服务器那一侧端口没监听(**确定失败**,而在线率并不低:这两列本就不是一回事);metrics 探针得不出结论(端口显示"未观测"而不是"未监听",即 #25 的语义)。 时间轴是"现在 − 启动时刻"算出来的纯函数,不是后台定时器线程:同一时刻永远是同一份 payload(测试因此能钉住时刻,而不是靠 sleep 去等一个事件发生),看板的 5 秒轮询自己 提供采样。周期互质(180/120/210 秒),所以三条隧道的状态变化会错开出现。 数据在三处自证是演示:payload 的 demo 标记(/status.json 一样)、页头的"演示数据"徽记 与页脚说明、命令行的一行黄字。一张看板截图里写着服务器地址与端口,它不该被误读成某个人 的真实基础设施——示例主机名一律 example.com。绑定校验照旧:非回环 --host 仍要求令牌。 顺带修掉一处自相矛盾:启动后的第一个周期里还没断过线时,"上次断线"会回头去取上一轮, 于是页面写得出"已运行 1 分 20 秒"+"上次断线 2 分钟前"——一条比进程本身还老的故障记录。 这条是看着运行中的看板发现的,现在钉进了测试:沿全时间轴扫描,任何记录都必须落在 [启动时刻, 现在] 之间。 --------- Co-authored-by: Codebuff <noreply@codebuff.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这批提交把一个"能看"的看板,做成了真的能一眼看全、并且不再自己打断自己的看板;顺带补上了跳板机与探针"未知"语义,并清掉了 CodeQL 那条 security severity = high 的告警。
看板(
ponte serve)<details>,无脚本也能展开;异常原因直接写在收起的那一行上——需要点开才知道原因,等于没有原因。ProfileStatus.jump随destination一起进入状态(status --json的jump),看板在目标下方用琥珀色写出↳ 经 ops@bastion:2222。堡垒机是链路里最先断、也是配置里其它地方都说不出来的那一环。<noscript>里的 meta refresh 作为无脚本回退(有脚本的浏览器根本不会创建它,因此不存在竞态),有脚本时 fetch 同一份服务端渲染原地替换,展开的行与滚动位置都保住,判定发生变化的行会闪一下——免得一次断线被读成"一直如此"。刻意复用服务端渲染而不是在 JS 里再写一遍:两份渲染逻辑正是看板和ponte status开始说法不一致的起点。页脚会说明自己处于什么状态(已更新 / 已暂停 / 连接中断),另有暂停按钮,标签页隐藏时自动停轮询。探针"未知" / 跳板机 / 其它
/healthz回200 unverified,status/doctor/看板显示"未知"并附原因;确凿失败则从观测到的端口状态回推出原因。[ssh] jump成为一等设置(原样交给ssh -J,与[ssh.options]里的 ProxyJump 同时出现会被拒绝)、[ssh] user/identity_file可省略、ponte reload热重载、doctor --json、shell 补全。availability作为 0..1 比率被按秒数取整(97.9% 会显示成 100.0%,而看板、/status.json与 Prometheus 读的都是这个字段);展开箭头写成 CSS\25be转义却被 Python 当八进制转义吃掉。安全
py/incomplete-url-substring-sanitization(tests/test_main.py,security severity high,CWE-020)。触发它的是测试里assert "example.com" in result.output——在测试里是误报,但"拿域名字面量做子串包含"这个形状放在源码里确实是一次不完整的地址校验,所以改的是形状:断言配置里的destination,同时也变得更严(钉住"印出来的就是配的那台服务器")。另按查询自身的判定扫了全仓,没有第二处。这条告警是 main 上当前唯一一条开放告警(ruleset 的security_alerts_threshold是high_or_higher,即它正是挡住合并的那条)。验证
391 个测试、
ponte/serve.py覆盖率 96%、ruff / mypy /_smoke_test.py全绿。集成测试跑的是真实链路:HealthChecker→ 守护进程落盘 →_status_payload→ 真实回环 HTTP → 看板/healthz/metrics,断言↳ 经 ops@bastion:2222与"未观测"确实出现在 HTML 上。看板脚本的行为在真实浏览器里验过:navigation计数恒为 1(没有整页重载)、展开的行与滚动位置跨刷新保留、判定变化的行拿到changed。🤖 Generated with Codebuff