From 4cb7c477267bfc28c8582e275e02e20acfc2c83e Mon Sep 17 00:00:00 2001 From: ila <2+ila@noreply.git.ilapage.cn> Date: Thu, 20 Aug 2026 14:55:26 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E4=B8=8E=E9=AA=8C=E8=AF=81=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Local-Development-and-Verification.-.md | 145 ++++++++++++++---------- 1 file changed, 85 insertions(+), 60 deletions(-) diff --git a/Local-Development-and-Verification.-.md b/Local-Development-and-Verification.-.md index f054208..992e989 100644 --- a/Local-Development-and-Verification.-.md +++ b/Local-Development-and-Verification.-.md @@ -1,115 +1,140 @@ # 本地开发与验证 -本页覆盖两类工作:**文档与流程**(现在就能跑)和 **Go 服务**(MVP-0 实现工单落地后可跑)。标注“MVP-0 落地后”的步骤在代码存在前会失败,这是预期的。 +本页区分“现在可执行的文档流程”和“产品代码落地后可执行的 Go/前端/数据库流程”。代码不存在或本机版本不满足时必须如实记录,不把预期当作通过。 ## 环境要求 -| 项 | 要求 | 检查命令 | +| 项 | 目标要求 | 检查命令 | |---|---|---| -| Git | 任意近期版本 | `git --version` | -| Python 3 | 仅标准库,供 Harness 工具使用 | `python --version` | -| Go | 1.22 或更高 | `go version` | -| MySQL | 8.0(本地或容器),需支持 `SKIP LOCKED` | `mysql --version` | -| golang-migrate | 命令行工具 | `migrate -version` | -| Tailwind CLI | standalone 可执行文件,无需 npm | `tailwindcss --help` | +| Git | 近期版本 | `git --version` | +| Python | Python 3 标准库 | `python --version` | +| Go | **1.26.5** | `go version` | +| MySQL | 8.0,支持 SKIP LOCKED | `mysql --version` | +| golang-migrate | 可执行文件 | `migrate -version` | +| Node | >=22,仅 admin-ui | `node --version` | +| pnpm | 9.15.1,由 packageManager/Corepack 固定 | `pnpm --version` | +| Tailwind | standalone,仅 portal 样式 | `tailwindcss --help` | -不需要 Node.js、Redis 或消息队列。用到的环境变量: +2026-08-20 盘点:本机 Go 1.23.0、MySQL 5.7.38、未安装 migrate,不能用于产品构建或迁移验收;Node 22.22.1 可用,但当前全局 pnpm 11.21.0,应按 admin-ui 的 `packageManager` 使用 pnpm 9.15.1。升级环境必须单独完成,不伪造验证结果。 -| 变量 | 用途 | 缺失后果 | -|---|---|---| -| `CHORUS_DSN` | MySQL 连接串 | 服务无法启动 | -| `CHORUS_MASTER_KEY` | provider api_key 的 AES-GCM 主密钥 | 无法解密上游密钥,生成全部失败 | -| `GITEA_TOKEN` | Wiki 同步与工单操作 | 只影响文档同步,不影响服务 | +固定来源: -凭据只通过环境变量提供,不写入仓库。 +- `D:\github\goadmin\go-admin` @ `f06540883b41d03782bb6b2c4150f298f328c6b6` +- `D:\github\goadmin\go-admin-ui` @ `67d393d713877572fab0b897296a4c1d525fc81d` +- `D:\github\goadmin\go-admin-doc` @ `424855aacf6905f3fde860c3331385cb25529a0d` + +只从这些固定提交审查/导入,不直接在其工作区开发 chorus,也不让 chorus 构建依赖绝对路径。 + +主要环境变量: + +| 变量 | 用途 | +|---|---| +| `CHORUS_DSN` | MySQL 连接 | +| `CHORUS_MASTER_KEY` / 对应 key ring 配置 | Provider Key AES-GCM 解密与轮换 | +| `CHORUS_SESSION_KEY` | portal 会话,必须与主密钥分离 | +| `CHORUS_STORAGE_ROOT` | 受保护生成物目录 | +| `CHORUS_ENV` | `development/test/production`,生产强制安全开关 | +| `GITEA_TOKEN` | Wiki/工单操作,不影响产品服务 | ## 第一次运行 -### 1. 检查工作区与文档结构 +### 1. 文档与工作区 ```powershell git status --short --branch python dev_scripts/harness.py check --strict python -m unittest discover -s tests -v +$env:GITEA_URL = "https://git.ilapage.cn" +python dev_scripts/harness.py sync --check ``` -预期:分支干净、输出“DevHarness 检查通过”、所有测试通过。 +### 2. 准备隔离数据库(产品代码落地后) -### 2. 准备数据库(MVP-0 落地后) +创建两个无生产数据的库:一个跑应用迁移测试,一个用于 go-admin 结构研究/代码生成。两者不得指向共享或生产实例。 ```powershell -mysql -u root -p -e "CREATE DATABASE chorus DEFAULT CHARSET utf8mb4;" -$env:CHORUS_DSN = "user:pass@tcp(127.0.0.1:3306)/chorus?parseTime=true&charset=utf8mb4" -migrate -path migrations -database "mysql://$env:CHORUS_DSN" up +mysql -u root -p -e "CREATE DATABASE chorus_test DEFAULT CHARSET utf8mb4;" +mysql -u root -p -e "CREATE DATABASE chorus_codegen DEFAULT CHARSET utf8mb4;" +$env:CHORUS_DSN = "user:pass@tcp(127.0.0.1:3306)/chorus_test?parseTime=true&charset=utf8mb4" +migrate -path migrations -database "" up +migrate -path migrations -database "" down +migrate -path migrations -database "" up ``` -预期:迁移版本前进,`generations` 等表已创建。 +连接串格式必须按 golang-migrate 的 MySQL driver 验证,不把 GORM DSN 直接拼成未经验证的 URL。每个迁移先 up、down、再 up;从空库重放全部迁移才算通过。 -### 3. 配置一个上游(MVP-0 落地后) +### 3. go-admin schema-first 生成(MVP-1) -MVP-0 阶段管理端尚未接入,用一次性命令写入一个 provider 与 provider_model: +1. 先在 `chorus_codegen` 执行同一套版本化 SQL。 +2. 启动仅限本机的 admin/admin-ui 开发实例。 +3. 从数据库表列表导入业务表元数据,配置并预览生成结果。 +4. 生成 Go/Vue 文件后检查输出路径、字段类型、敏感字段、权限和重复代码。 +5. 不直接采用“生成迁移脚本”或 `/gen/todb` 的副作用;把菜单/API 配置整理成带 down 的 SQL。 +6. 清空隔离库,从 migrations 重放并重新生成/构建。 +7. 生产构建验证 dev-tools 路由不存在;仅隐藏菜单不算关闭。 -```powershell -$env:CHORUS_MASTER_KEY = "<32 字节 base64 主密钥>" -go run ./cmd/seedprovider --name dev --base-url https://<上游> --api-type chat --model <模型名> -``` +go-admin AutoMigrate 不进入以上标准流程。如确需对照固定提交初始化结构,人工在额外可丢弃库运行一次,导出结构差异后销毁;禁止连接共享/生产库,也禁止把该命令放入应用启动、容器入口或部署脚本。 -预期:命令输出新建的 provider_model id;数据库中 `api_key_enc` 是密文而非明文。 +### 4. 配置 mock 上游与种子用户(MVP-0) -### 4. 启动服务并走通一次生成(MVP-0 落地后) +MVP-0 不开放注册。使用可重复、不会在日志输出密钥的种子命令建立测试用户、默认 prompt template、Provider 和 ProviderModel。默认先连接 mock HTTP 上游,覆盖文本、图片、429、5xx、超时、连接错误、400、401 和内容策略拒绝。 + +真实 Provider 的连通性检查只能由操作者明确触发一次低成本请求,并核对审计与冷却;不能作为自动测试或反复调试方式。 + +### 5. 启动 portal(MVP-0) ```powershell go run ./portal ``` -预期日志包含监听端口与“worker started”。然后在浏览器打开 `http://127.0.0.1:8080`: +浏览器验证: -1. 注册或用种子用户登录,进入双栏首页; -2. 切到「文生文」,输入一句提示词,点生成; -3. 左栏立即出现 loading 卡片,右栏可见状态; -4. 数秒后卡片原地替换为结果,轮询停止(响应中不再有 `hx-trigger`); -5. 切到「图生图」,上传 1~2 张图,标记主体图与参考图,再生成一次; -6. 数据库中该条 `generations` 的 `status=succeeded`,`rendered_prompt` 非空,`attempts` 有一条记录,`generation_outputs.thumb_path` 有值。 - -**第 6 步是 MVP-0 的验收口径**:页面看到结果只是表象,落库字段齐全才算流程真正跑通。 +1. 用种子用户登录,不应出现公开注册链接; +2. 桌面双栏、375px 移动单列均可完成文本和图片提交; +3. 第一张图自动 primary,其余 reference,MVP-0 没有角色编辑/拖拽; +4. 提交后立即显示 queued/running,终态停止轮询; +5. 文本、图片、失败、网络轮询错误和认证过期都有明确界面; +6. 数据库中 `rendered_prompt`、`attempts`、latency 或失败 error 字段齐全; +7. 输出通过鉴权访问,不能猜 URL 读取其他用户文件。 ## 常用调试方式 -| 症状 | 先看哪里 | +| 症状 | 先看 | |---|---| -| 卡片一直转圈 | `generations.status`。仍是 `pending` 说明 worker 没取到任务;`running` 且 `lease_until` 已过期说明 worker 崩了或卡在上游 | -| 结果不对但没报错 | `generations.rendered_prompt`——多数“模型不听话”其实是提示词合成错了 | -| 生成失败 | `generations.attempts` 与 `error_message`,能看出是哪一家、什么错误、耗时多少 | -| 上游连不上 | 先确认不是 SSRF 拦截命中(日志中的拦截记录),再查 `base_url` 与密钥解密 | -| 页面样式丢失 | Tailwind CLI 是否在 watch,`portal/web/static/` 产物是否存在 | +| pending 不动 | worker 是否启动、取任务索引和数据库版本 | +| running 租约过期 | lease_owner/token/until、上游超时、陈旧 worker CAS | +| 成功但内容不对 | rendered_prompt 与 prompt template 版本 | +| 400/401 尝试多家 | retryable 实现错误 | +| 文件存在但页面 403/404 | 用户归属、原子落位、缩略图记录 | +| 上游连不上 | SSRF 日志、DNS/IPv6、redirect、proxy 和 base_url | +| 管理端生成异常 | 是否先迁移再导表,是否误把菜单脚本当业务 DDL | +| 样式丢失 | portal Tailwind 产物或 admin-ui pnpm/Vue CLI 构建 | -调试上游时用 mock HTTP 服务代替真实上游:`internal/core/provider` 的测试已提供可复用的 mock,能构造 429、超时、400 和内容拒绝四种响应。不要用真实额度反复试错。 +不要在日志、SQL、工单或 Wiki 中贴 API Key、Cookie、真实用户输入和生产文件。 -单条 SQL 快速定位: +## 测试策略 -```sql -SELECT id, kind, status, provider_model_id, attempt_count, error_code, latency_ms -FROM generations ORDER BY id DESC LIMIT 10; -``` +- 迁移:空 MySQL 8 隔离库逐个/全量 up-down-up,验证索引、外键、唯一约束和种子幂等。 +- 队列:并发认领、租约过期重新认领、旧 token 最终写 0 行、优雅退出、attempt 原子性。 +- Provider:全部 retryable 类别使用 mock,不消耗真实额度。 +- SSRF:IPv4/IPv6 私网、DNS rebinding、redirect 链、环境代理、结果 URL。 +- 安全:密码/session/CSRF、登录节流、跨用户任务与文件、错误脱敏、密钥轮换。 +- 浏览器:HTMX 动态状态、终态停止、认证过期、网络错误;375/768/1024,无主区域横向滚动,键盘和 reduced-motion。 +- 供应链:Go/Node 依赖锁定、漏洞和许可证检查按实现工单确定命令。 ## 完成修改前 -按顺序执行,全部通过才算完成: - ```powershell git status --short --branch go build ./... go vet ./... go test ./... +pnpm --dir admin-ui install --frozen-lockfile +pnpm --dir admin-ui build:prod python dev_scripts/harness.py check --strict python -m unittest discover -s tests -v python dev_scripts/harness.py sync --check +git diff --check ``` -另外确认: - -- 改了表结构 → 有对应 `migrations/` 文件,且 up 与 down 各跑过一次; -- 改了 `retryable`、SSRF、加解密 → 有针对性单元测试; -- 改了页面结构、流程、状态、权限或异常处理 → 有 `prototypes/<工单号>/<版本>/index.html` 审核快照并已确认; -- 改了入口、命令、业务规则或排错方式 → 已评估对 `docs/` 的影响; -- 未执行或无法覆盖的验证 → 已写进工单,不得默认“应该没问题”。 +只运行受当前范围影响且实际存在的产品命令;不存在或因工具版本不能执行的项写入工单。涉及迁移、安全、队列、权限或 UI 时,还必须执行上面的专项验证并记录结果。