Files
cc-web/.planning/2026-08-25-instance-custom-icon/findings.md

5.1 KiB
Raw Blame History

实例自定义图标调研记录

已知需求

  • 同一套 cc-web 部署到多台机器时,需要通过不同图标快速区分实例。
  • 用户希望在设置中自行选择图标。
  • 自定义结果在拉取最新版后必须保留。

待确认事实

  • 当前默认图标的所有消费点。
  • 设置页和设置 API 的扩展模式。
  • 项目现有的 Git 外置运行数据目录与备份方式。
  • 相关测试框架和浏览器缓存策略。

代码库初步事实

  • 项目为无框架的 Node.js 单体:server.js 提供服务,public/app.js、public/index.html、public/style.css 构成主界面。
  • 默认浏览器/PWA 图标均为 Git 跟踪文件:public/favicon.ico、favicon-32x32.png、apple-touch-icon.png、icon-192.png、icon-512.png,直接替换它们会在升级时产生冲突或被覆盖,因此不能作为实例自定义存储。
  • 设置入口位于 public/index.html,设置页 HTML 由 public/app.js 中的构建函数生成;已有“外观”子页,可复用其导航卡和设置状态样式。
  • 回归入口为 npm run regression,项目还包含多个 scripts/*-unit.js 与浏览器集成脚本,适合增加聚焦回归脚本并挂入总回归。
  • 首轮本地全文检索被仓库中的大文本记录污染;后续必须收窄到 server.js、public/、scripts/,并用精确标识符核验行号。

图标与存储入口

  • public/index.html 的浏览器图标链接位于 head,登录页 Logo 使用 icon-192.png;public/app.js 的通知图标和重新渲染的登录框也直接使用 /icon-192.png;public/sw.js 的通知默认值同样硬编码该路径。
  • 这意味着仅改 favicon 不足以形成一致的实例身份,至少应统一浏览器页签、登录 Logo 与通知图标;Web App Manifest 的静态图标是否能动态化需按 PWA 缓存边界保守处理。
  • 服务端已经支持 CC_WEB_CONFIG_DIR,默认指向仓库内 config/;测试通常把它指向临时目录。实例图标应落在该目录,生产可用外置目录,默认仓库内目录则通过精确 .gitignore 规则保护。
  • .gitignore 已逐项忽略多种 config/*.json 运行配置,但尚无实例图标规则;需要在保留用户现有修改的前提下追加精确规则,不能把整个 config/ 忽略。

选定方案

  • 浏览器端把用户选择的 PNG/JPEG/WebP 居中裁剪并规范化为 512×512 PNG;服务端只接受并验证 512×512 PNG,最大 4 MiB。
  • 运行文件固定为 CONFIG_DIR/instance-icon.png,不保存用户文件名或可控路径;通过临时文件 + rename 原子替换。
  • 统一公开读取 URL 为 /api/instance-icon,默认返回现有 icon-192.png;配置接口返回基于内容哈希的 version,前端以查询参数刷新缓存。
  • 写入和恢复接口使用现有 Bearer token;读取图标与 Manifest 公开,保证登录页也能显示。
  • 提供动态 /api/site.webmanifest:无自定义时保留原 192/512 图标,有自定义时声明 512 图标。已安装 PWA 的操作系统缓存不承诺立即刷新。
  • .gitignore 只追加 config/instance-icon.png 与原子临时文件规则,保留现有用户改动和其他配置可见性。

工作区隔离注意

  • .gitignore 的既有修改位于暂存区(git status 第一列为 M),普通 git diff 不显示;本功能只能在工作树中追加精确规则,不能改写或取消暂存的用户内容。
  • server.js 的配置目录在启动时统一创建,实例图标常量可与其他配置路径集中定义;HTTP 路由可复用附件接口的 extractBearerToken/activeTokens 鉴权方式。
  • 现有静态服务会对所有 public 资源返回 no-store,但动态实例图标仍需显式 nosniff 与内容版本,避免不同响应路径的缓存语义分叉。

并发写入归因修正

  • 被中断的实现代理仍有一个已进入执行阶段的工具调用完成落盘:新增了 scripts/regression.js 的 219 行聚焦回归、服务端大小常量和路径骨架,并提前推进一次 TODO CSV。
  • 因此聚焦测试不是 HEAD 预置,而是该代理的有效测试产出;主线程保留测试、合并重复常量,并承担后续实现。CSV 的第 4/5 阶段状态在代码落下后重新与真实结果对齐。

主线程代码审查

  • 写接口只接受鉴权后的 512×512 PNG,路径完全由服务端固定;配置读取、图标读取和 Manifest 无敏感内容,可供登录前消费。
  • 默认与自定义图标都设置 nosniff;默认 ETag 使用实际文件哈希,自定义 ETag 使用内容版本,拉取新版默认资产后不会错误返回旧图 304。
  • 客户端裁剪取短边居中后绘制到 512×512,不拉伸;上传失败不调用 apply,因此保留旧实例图标。
  • 现有聚焦回归验证真实子进程和临时 CONFIG_DIR,并由 withServer 负责停止服务;测试临时目录清理可作为非阻断维护改进继续审查。
  • 动态 favicon 的源图片在默认态为 192px、自定义态为 512px,head 上固定 sizes 声明可能与默认资源自然尺寸不一致;应在最终审查中确认是否移除固定 sizes 更稳妥。