Files
tamabox/.workbuddy/memory/MEMORY.md
T
tamakyi d4e6da76f1 docs(memory): 记录第二轮复查结论与六项修复的验证方式
- 新增 topics/quality.md:业务正确性 / 运维 / 前端体验四类结论,含
  「私聊取最早 50 条」「Classic() 的 Logger 记 RequestURI」这两个坑的成因,
  以及处置覆盖面、Redis 两种故障模式、产品缺口(无 page view / 提问者找不回自己的提问)
- 2026-10-29.md:本轮六项修复的改动与验证结果,另记两个实现坑
  (limit 兜底不该抬大用户配置;Python bytes 字面量不支持 \uXXXX)
- topics/sec.md / 2026-10-27.md:补上一轮遗漏的字体自动发现与 CSP enforce 结论
- MEMORY.md:索引加 quality,处置覆盖面一条标注投票链路已补齐
2026-10-29 15:53:57 +08:00

7.6 KiB
Raw Blame History

TamaBox-v4 长期笔记(索引版)

明细已拆分到 topics/*.md(按需 Read 全文): coop 协作 / build 构建测试 / embed 行尾·模板·embed / review 审核处置举报 / gorm GORM / style 前端样式 / theme 主题 / builder 主题生成器 / share 分享卡 / honeypot 蜜罐多家族伪装 / stats 全站数据页 / sec 安全评估·客户端 IP 信任 / quality 业务正确性·运维·前端(2026-10-29) / misc 其它约定。

协作

  • 结论分级 P0/P1/P2;先根因取证 + 实测复现,别只静态推断。
  • 改代码前先出变更清单;重大问题显式指出。用户常授权自主推进。
  • 用户是运营者也是圈内人:处置必须可解释、可留痕、可申诉,不做自动级联封号。

构建与测试(详见 topics/build.md)

  • 无 libwebp/GCC:internal/storage/s3.go 挡编译 → overlay 换桩 dev/s3stub/s3_stub.go。
  • 「编译卡死」= proxy.golang.org 不可达。每条 go 命令前 export GOPROXY=https://goproxy.cn,direct GOSUMDB=off GOFLAGS=-mod=mod。
  • DB 测试:DB_TYPE=postgres DB_USER=postgres DB_PASSWORD=15207786347hXPm DB_HOST=127.0.0.1 DB_PORT=5432(DSN 不带库名)。
  • store 方法内用 NewXStore(db.DB),别引用包级单例。
  • 本沙箱起不了 TamaBox web 2026-10-27 起可在 WSL2 Debian 上真跑(PG+Redis+systemd,端口 5877): 详见 topics/build.md「本地部署」小节。要点:env -u GOROOT(bashrc 指着 1.26.3)、 [recaptcha] captcha_type = math、Windows 侧 127.0.0.1:5877 被占要用 WSL eth0 IP。 HTTP 端到端与 P1-3 的双路径 A/B 都能在这里做(回环=可信、跨主机=不可信)。
  • python urllib 不稳定(用 curl);python 别用 /tmp;PIL 在 ~/.workbuddy/binaries/python/envs/default。

行尾 / 模板 / embed(topics/embed.md)

  • 行尾混合不可推断,改前用 Python 数 b'\r\n';gofmt 走 dev/gofmt_keep_crlf.py。
  • templates/embed.go 是显式清单:新增顶层模板必须加 //go:embed。
  • //go:embed 的 * 不匹配 _/. 开头文件。

审核 / 处置 / 举报(topics/review.md)

  • 线上通道 = 七牛;裁决在 censor/policy.go + moderation.Check,新增调用点必须走 moderation.Check,不可用时 fail-closed。
  • 严格度存 users.moderation_strictness;受处置用户强制 strict(moderation.EffectiveStrictness),查询失败回退用户设置。
  • 同请求渲染只能用 ctx.SetError/SetInternalError,不能 *Flash。
  • 处置四级 L1–L4;到期靠 expires_at 无 cron;restrict 是替换语义;比较用 RestrictionAtLeast。
  • L2 强制私密须在审核通过后、与写回答同一条 UPDATE(AnswerByIDPrivate)。
  • ListAPI 不经 Pager 中间件,L4 与页面密码须自校验;分享卡拦截须在缓存查询之前。
  • 举报:免登录+验证码+限流;同 IP 同题唯一索引 → 幂等;箱主只看次数不给 IP。
  • 告警 24h≥8 或 7d≥20 → 邮件;[security] security_alert_email 为空则静默跳过。
  • 处置覆盖面:新增任何「用户发起」的写入口都要问一句「这里要不要查 ActiveLevel」。 提问链路 7 处齐全;投票链路曾 0 处(L4 后 /vote/{token} 照常可投、可发新投票、探索页照常曝光), 2026-10-29 已补齐:vote.Page/vote.Submit 拦 L4、VotePublish 拦 L2、探索页按 ActiveLevels 批量过滤。

GORM(topics/gorm.md)

  • 默认值必须带引号;事务里每句 tx.WithContext(ctx);链式对象带状态,统计/更新各自重建 query。
  • 软删除+唯一索引 = 槽位永久占用;级联删除一律 Unscoped()。

前端样式(topics/style.md)

  • static/css/base.css(?v= 取 conf.StaticVersion,改完 +1)。令牌在 :root + html[data-theme="dark"],新样式一律 var(--tb-*)。
  • 移动端(≤640px)语言/主题按钮在固定底栏 #tb-mobile-utils;箱主页有意无语言切换。
  • UIkit 3.3.3:.uk-flex::before/::after{display:none};主色是编译期常量,需在 base.css 末尾映射。
  • 视觉自检:TEST_PREVIEW=1 go test ./templates -run TestGenPreview;截图用 chrome --headless=old。

主题(topics/theme.md、topics/builder.md)

  • 三个注入点按箱主/发布者的 Theme;投票页语言也跟发布者(applyOwnerLocale)。
  • 一套主题 = static/css/themes/<slug>.css,只覆盖令牌;显示名用 {{ themeName ... }},别直接 printf "theme.name.%s"。
  • [theme] available 是硬白名单(启动时读一次);css 必须成对写亮/暗两个选择器。
  • 装饰层固定 10 槽,三组 --tb-deco/-size/-position 必须等长;位置用两值 calc(0%|50%|100% ± N)。
  • 主题生成器 dev/theme-builder/:非破坏性图片处理、layerSize/unitGeom 必须共用同一函数、 hideDeco 会把 @media 10 槽全写 none(窄屏素材消失的头号来源)。

安全(topics/sec.md)

  • 权威头 CF-Connecting-IP / EO-Client-IP 只在 TCP 对端可信(回环 或 trusted_proxies 命中) 才采信,公网对端一律忽略;唯一读取点 internal/shared/ip.go,别在别处另读 header。
  • 生产回源 = cloudflared Tunnel 回本机(对端 127.0.0.1)→ 零配置;trust_proxy 两套环境都 true。
  • EdgeOne 已取消(境内速度差)。重新启用前必须把 EO 回源网段写进 trusted_proxies, 否则 EO 线退化成按边缘 IP 聚合(限流互挤、自动封禁误伤整片)。app.sample.ini 已注明。
  • 跳转参数只走 shared.SafeRedirectTarget;url.Parse 会解 %0d%0a,必须逐 rune 查 u.Path。
  • 同一 handler 里 GET 有所有权校验 ≠ POST 有(私聊 SendMessage 曾漏,可跨箱骚扰)。逐分支核对。
  • CSP 默认 enforce(逃生口 csp = report|off 后重启);script-src 必须含 mami.shiroko.one (umami 动态注入,grep 抓不到)与按 sentry_dsn 条件放行的 browser.sentry-cdn.com。 改 CSP 白名单后必须跑 csp_sweep.py(真浏览器巡检),静态检查不算数。
  • 注册防枚举:邮箱重复/停用与正常注册共用同一个成功出口;代价是忘密只能走找回。
  • flamego.Classic() 自带 Logger() 会记 RequestURI(含 query) —— ?t= 私密题钥匙、 ?code= 改密凭证都会明文进日志(已实测)。要自写访问日志,只记 URL.Path。
  • 报告 outputs/security-audit-2026-10-25.md + 复现脚本 outputs/sec-audit-2026-10-25/; 非安全向的复盘见 outputs/review-2026-10-29.md。

其它约定(topics/misc.md)

  • 校验用 valid:"required;maxlen:N" 标签。
  • 只有箱主 /user 面板,无管理员角色、无站方后台(用户要求不要加):站方动作只走 CLI / 邮件 / 改配置重启。
  • CLI 有两个构建入口必须同步:根 go build . 与 Dockerfile 的 ./cmd/。
  • 现有 CLI:web censor uid ban restore reports restrict unrestrict hide-public。
  • git https://git.shiroko.one/tamakyi/tamabox(main),git push 可直推;outputs/ 已 gitignore。
  • ImageGen 的 background: "transparent" 至今不生效(返回 RGB、无 alpha 通道)。要透明素材: 提示词把背景写成一个具体纯色(不要写 white,白衬衫/光环会被一起吃), 再按该色值算 alpha:alpha = clip((maxChannelDiff - 6) / 12),最后 MinFilter(3) 收 1px。 闭合图形(如光环圆环)内部的白/底色用 floodfill 填不到,按色值抠才干净。
  • 生成图的右下角有 "AI生成 WORKBUDDY" 水印,做素材时统一裁掉底部约 10%(切口平直,正好贴页面下沿)。