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

94 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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*`,全绿)。