From 321bde10c1356272ac531910f6c25cdeab1b0e46 Mon Sep 17 00:00:00 2001 From: modusensus Date: Mon, 21 Sep 2026 13:38:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(serve):=20--demo=20=E7=94=A8=E5=86=85?= =?UTF-8?q?=E7=BD=AE=E7=A4=BA=E4=BE=8B=E6=95=B0=E6=8D=AE=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E7=9C=8B=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 看板只从真实的配置与守护进程状态文件取数据,于是"先看一眼前端长什么样"这件事以前只有 两条路:对着真基础设施跑,或者手搓一份状态文件。后者会随 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 --- CHANGELOG.md | 14 ++ README.md | 18 ++- ponte/demo.py | 369 +++++++++++++++++++++++++++++++++++++++++++++ ponte/main.py | 59 ++++++-- ponte/serve.py | 29 +++- tests/test_demo.py | 287 +++++++++++++++++++++++++++++++++++ 6 files changed, 759 insertions(+), 17 deletions(-) create mode 100644 ponte/demo.py create mode 100644 tests/test_demo.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 57b6f05..e9b4484 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -199,6 +199,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- **`ponte serve --demo` serves the dashboard on built-in sample data.** The page + names your servers, users and ports, so the only ways to look at it without a + tunnel were to run it against real infrastructure or to hand-write a status + file — and a hand-written one drifts from the payload contract while looking + exactly like the real thing. `--demo` reads no config and never touches a + daemon: it drives a small deterministic timeline that connects, drops, backs + off and reconnects on its own, so the page shows every state it can render — + healthy, broken, and *unknown* (a probe that could not answer, where the ports + read `未观测` rather than `未监听`). It labels itself in three places — + `"demo": true` in `/status.json`, a `演示数据` pill and a footer note on the + page, and a yellow line on the terminal — because a dashboard screenshot must + not be mistakable for somebody's real infrastructure. Sample hosts are + `example.com`. The bind rules are unchanged: a non-loopback `--host` still + demands a token. - **The jump chain is part of the status, next to the destination.** `ProfileStatus.jump` carries the `ssh -J` value, so `ponte status --json` and the dashboard can tell "cannot reach the server" apart from "cannot reach the diff --git a/README.md b/README.md index ca19dc4..0b7548f 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ import package stay `ponte`; a checkout installs the same way (`pipx install .`) | `check [--profile NAME]` | verify tunnel ports are listening (`-R` on the server, `-L`/`-D` locally) | | `doctor [--offline] [--timeout S] [--json]` | one-shot checkup of config, key, connectivity, ports, auto-start and notifications, each row with a fix (`--json` for scripts) | | `notify-test [--profile NAME]` | send a test alert through the configured ntfy / webhook channels | -| `serve [--host H] [--port P] [--token T] [--open]` | local HTTP dashboard, `/healthz` probe, Prometheus `/metrics`, `/status.json` snapshot | +| `serve [--host H] [--port P] [--token T] [--open] [--demo]` | local HTTP dashboard, `/healthz` probe, Prometheus `/metrics`, `/status.json` snapshot; `--demo` serves built-in sample data | | `install` / `uninstall` | register / remove the OS auto-start service | | `config [--ssh-command]` | print the effective configuration, its source file and any warnings (`--ssh-command` prints the exact `ssh` argv) | @@ -140,6 +140,14 @@ ponte serve # http://127.0.0.1:8787/ (loopback only by default) ponte serve --open # ...and open it in your browser ``` +**No tunnels yet?** `ponte serve --demo` runs the same server on built-in sample +data: a small timeline that connects, drops, backs off and reconnects on its own, +so the page shows every state it has — healthy, broken, and *unknown* (a probe +that could not answer). It reads no config and never touches a daemon, and the +payload (`"demo": true`), the page header and the CLI output all say the data is +a demo: a dashboard screenshot names your servers, so it must not be mistakable +for somebody's real infrastructure. Sample hosts use `example.com`. + | Endpoint | What it answers | |----------|-----------------| | `/` | the dashboard: one row per tunnel — verdict, destination and jump chain, forwarded ports as chips, session age, availability, last disconnect reason; click a row for the full statistics and the event feed. Light and dark, refreshed in place (expanded rows and scroll position survive), and a `