Files
rond-with-you/.workbuddy/memory/2026-10-09.md
T
tamakyi d4e4257a23 启动模板自检 + 站长导航放行 + 统计脚本关口收紧
排查:/admin/settings 渲染到一半就断
- 现象:页面在「统计脚本」那张卡片处截断,没有保存按钮、没有 </form></html>,而 HTTP 仍是 200。
- 根因:跑的是旧二进制(改动前编译),磁盘上的模板却是新的。debug=true 下 pageSet()
  每次渲染都从磁盘重解析模板,于是新 settings.html 引用了旧 setting.Settings 里没有的
  TrackEnabled —— 执行期报错,而 render 只把错误写进日志,客户端只看到半张页面。
- 判据:strings <二进制> | grep -c cleanTrackScript(旧 0 / 新 2)。别用 strings | grep
  TrackScript —— config 里本来就有这个名字,旧二进制也命中,是个假信号。

启动自检(防复发)
- template_smoke.go:pageProbe 给 24 个页面各配一份最小可用数据,New() 里全部渲染一遍,
  任一页失败就拒绝启动。pageProbe 与 pageFiles 双向校验,新加页面必须补探针,
  漏配按失败处理(不是省事)。
- smokeOne 用 recover 兜住方法里的 panic,报「哪一页坏了」而不是崩栈。
- 实测:往 settings.html 插一个不存在的字段 → 启动即报
  「模板自检未通过…admin/settings: can't evaluate field …」,退出码 1。
- 门禁 template_smoke_test.go:一条跑全量自检,一条变异验证(探针换成字段更少的类型
  必须报错且点名该页)。

站长导航被页面开关误伤
- guardPage 只拦访客(站长始终能访问全部公开页),但导航写的是 {{if .Settings.HasPage "x"}},
  没有 IsAdmin 分支 ⇒ 页面开关一关,站长自己也只剩「主页」一个入口 —— 能访问却点不到。
  改成 {{if or .IsAdmin (.Settings.HasPage "x")}}(map/places/timeline/stats/report 五处)。
- 门禁 nav_visibility_test.go:三向不变量(站长仍有全部入口 / 访客一个都没有 /
  全开放时访客也看得到),做过变异验证。
- 访客侧「只有主页」是按后台配置应有的状态,没有动数据。

统计脚本关口收紧(cleanTrackScript)
- src= 只在 <script …> 开标签内部找。原来对整段做 strings.Index,脚本体里一句
  `img.src=u` 就被命中、整段被判危险而清空 —— 页面照样提示「设置已保存」,站长看不出没挂上。
- 开闭标签从「只拒 shut > open」改成严格配平:末尾未闭合的 <script> 会把页面收尾整段吞进脚本。
- 不再静默:签名改成 (script, warn),说明码经 ?warn= 回显成人话;判为危险时整段不采纳、
  库里原脚本与开关都不动(把站长手上好用的脚本一并清掉更糟)。
- 门禁 TestCleanTrackScript 重写:逐条边界 + 定义性不变量(采纳了非空结果时,
  里面开闭标签数必定相等)+ TestTrackWarnMessage(未识别码不得回显)。变异验证做过。
- 文案订正:settings.html 的「conf/app.ini 的 track_script 会作为这里的默认值」有歧义 ——
  它不回填文本框,而是「这个框留空时、注入那一刻才回落到 ini」。

其余
- bin/ 目录删除(15 个 exe / 412MB),二进制只留仓库根 rond.exe;
  技能 rond-web-verify 与 memory details 十八里 bin/rond.exe 的写法同步改掉。
- 验收:./scripts/verify.sh 全绿且 0 skip(PASS=346 FAIL=0 SKIP=0)。
2026-10-09 11:06:41 +08:00

6.2 KiB
Raw Blame History

2026-10-09

排查:/admin/settings 报错(旧二进制 + 新模板)

现象:「统计脚本做成后台开关」那次提交(4015ddf)之后,访问 /admin/settings 报错。

根因(已实测复现):跑的是旧二进制(根目录 rond.exe,10-08 18:06 编译,早于 18:27 的提交), 磁盘上的模板却是新的。debug=true 下 pageSet() 每次渲染都从磁盘重解析模板, 于是新 settings.html:148 引用了旧 setting.Settings 结构体里没有的 TrackEnabled → 执行期报错:

渲染 admin/settings 失败: template: settings.html:148:85: executing "content"
at <.Settings.TrackEnabled>: can't evaluate field TrackEnabled in type setting.Settings

render 是流式直写 ⇒ header 已发(HTTP 200)但表单在「统计脚本」卡片处截断, 没保存按钮、没 </form></html>。这就是用户看到的「报错」。

判据:strings <二进制> | grep -c cleanTrackScript —— 旧根二进制 0,新编译的 2。 (注意别用 strings | grep TrackScript 判定,config 里本来就有这个名字,旧二进制也命中。)

修复:go build -o rond.exe .(+ bin/rond.exe),重启。旧二进制备份到 bin/rond.exe.old-20261008-stale。修后 /admin/settings 完整(19642B,含 </html>/保存按钮)。

教训:Go 结构与模板字段是成对改的,debug=true 的热加载只覆盖模板 —— 改 Go 必须重编译重启, 否则就是「新模板 + 旧结构 = 执行期报错」。想根治可在启动时把所有页面各渲染一遍做冒烟(现在没有)。

其他发现(未改代码)

  1. P1 待确认:settings 行 pages=null(写入时间 2026-10-08 18:14:05)⇒ 访客侧 /map /places /timeline /stats /report 全部 404、导航只剩 1 个链接。代码语义是 「全不选 = 访客只能看主页」,属合法状态,像是测 404 分档时留下的。没动数据,等确认。
  2. P2:cleanTrackScript 的 src= 检查是全文 strings.Index,会误伤脚本体内的 src=。实测:<script>var i=new Image();i.src=u;</script> → 返回 ""(整段被静默清空), 而页面仍提示「设置已保存」⇒ 静默失效。建议只在标签属性里查 src,或把「被清空」回传前端显式提示。
  3. P2:开闭标签只拒 shut > open;末尾未闭合 <script>(open > shut)会吞掉后面内容。 实测 <script>x</script><script>y 与 <script>y 都被放行。建议改成要求 open == shut。
  4. 运维:根 rond.exe 与 bin/rond.exe 两份二进制容易走偏(这次根目录那份就是旧的)。 考虑只保留 bin/,或在启动日志打印构建时间便于比对。

回归:go vet 干净、gofmt -l 空、JS 单测 34/34、go test ./... 13 包全 ok 0 FAIL。 (注:internal/web 里 110 例是 DB 门控的,不开 ROND_TEST_CONF/ROND_SRC 会 skip,不算真跑过。)


用户确认后的收尾(四件)

用户反馈:「管理员访问也只剩主页,这好像不对」+ P2 按建议修 + 二进制只留根目录 + 防复发一并做。

1. P1 更正:不是配置问题,是导航缺 IsAdmin 分支

上面第 1 条判断得不完整。实测:站长访问 /map /places /timeline /stats /report 全是 200 (guardPage 只拦访客),但导航里只有「主页」⇒ layout.html 的页面显隐写的是 {{if .Settings.HasPage "x"}},没有 IsAdmin 分支,与 guardPage 口径不一致。 改成 {{if or .IsAdmin (.Settings.HasPage "x")}} 五处。门禁 nav_visibility_test.go (三向不变量 + 变异验证)。访客侧的 pages=null 没动(仍是「只对访客关」的配置状态)。

2. P2 修复:cleanTrackScript 重写

  • src= 只在 <script …> 开标签内部找(原来对整段 strings.Index,i.src=u 被误伤清空)。
  • 开闭标签从「只拒 shut > open」改成严格配平(末尾未闭合的开标签原来会被放行)。
  • 签名改 (script, warn string),说明码经 ?warn= 回显成人话;判危险时整段不采纳、 库里原脚本与开关不动。
  • 实测(测试实例 8081 / rond_fog_test,用完已还原):i.src=u 现在原样落库; 不配平 → ?warn=unbalanced 且库值不变;javascript: → ?warn=badsrc 且库值不变; 5000 字符 → ?warn=truncated 且落库 4096。注入范围精确复核:只在公开页(/、/map), 后台与登录页 0。

3. bin/ 删除

15 个 exe、412MB 全删;只保留根 rond.exe。技能 rond-web-verify 与 details 十八的 bin/rond.exe 写法已同步改掉。

4. 防复发:启动自检 smokeRender

template_smoke.go:pageProbe(24 个页面各一份最小可用数据,键与 pageFiles 双向校验)

  • New() 里全量渲染一遍,失败即 log.Fatalf 拒启。实测:往 settings.html 插一个不存在的 字段 → 启动报 模板自检未通过…admin/settings: can't evaluate field …,退出码 1。 门禁 template_smoke_test.go(含变异验证:把探针换成字段更少的类型必须报错)。

5. 用户裁决 + 文案订正

  • 访客侧 pages=null 不动:用户明确说「访客那一侧是根据我在后台配置的显示范围公开的, 倒不如说原来默认就是这样才对」⇒ 那是预期配置,不是故障。已把这个结论写进 details 四十一,免得后续会话又去「修」数据。
  • settings.html 的统计脚本文案订正(P3):原文两处不准 —— ①「多一个 </script> 会被判为粘贴错误」漏了「少一个也会拒」(判据已改成严格配平); ②「conf/app.ini 的 track_script 会作为这里的默认值」有歧义:它不会回填文本框, 而是「这个框留空时,注入时回落到 ini 的值」。已改成准确说法。 实测热加载生效(debug=true,无需重编),页面 19996B、含 </html>,旧文案 0 命中。
  • 验收:官方 ./scripts/verify.sh → PASS=346 FAIL=0 SKIP=0(改动前那次全量; 之后只动了这一个模板文案,重跑了全部模板门禁与 TestSmokeRender*,全绿)。