diff --git a/AGENTS.md b/AGENTS.md index 865696c..8acf4f7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -223,7 +223,7 @@ MVP 内所有单元任务通过后才能做 MVP 集成验收;MVP 通过后才 2. 生成链路不得读写点数:无扣费、无退款、无余额校验、无配额。点数只读展示。 3. `retryable` 判定不得随手改:`429 / 5xx / 超时 / 连接错误` 换下一家;`400 / 401 / 内容策略拒绝` 立即返回。修改必须附带覆盖四种情况的单元测试。 4. 对 provider `base_url` 的出站请求必须经过 SSRF 拦截(DNS 解析后、连接前的 `DialContext` 钩子)。不得为了联调临时关闭。 -5. provider `api_key` 必须 AES-GCM 加密落库;明文密钥不得进入代码、日志、响应、工单、Wiki、原型或截图。 +5. provider `api_key` 按用户于 2026-08-22 明确接受的风险允许明文落库;仅管理员可在单个 Provider 页面显式读取,列表接口不得批量返回,读取响应必须禁止缓存。真实密钥仍不得进入代码、日志、审计摘要、错误信息、工单、Wiki、原型或截图。 6. 生产不得使用 GORM AutoMigrate;表结构只经 `migrations/` 演进,每个迁移的 up 与 down 都必须验证过。 7. 管理员(`sys_user`)与终端用户(`users`)分表,不得合并或互相复用凭据。 8. 提交生成的同步链路不得调用上游;上游调用只发生在 worker 中。 diff --git a/docs/00-project-profile.md b/docs/00-project-profile.md index d213a15..9abaa43 100644 --- a/docs/00-project-profile.md +++ b/docs/00-project-profile.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Project-Profile wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Project-Profile.- -wiki_revision: 811dfc91e824a8ce509fe042455a66c6c1a4f433 -synchronized_at: 2026-08-21T15:02:06Z +wiki_revision: 8578dcf0c29f7792135f01d902b8417f0374db05 +synchronized_at: 2026-08-22T01:45:50Z # 项目档案 @@ -167,3 +167,8 @@ synchronized_at: 2026-08-21T15:02:06Z - 当前候选版本已在本机 MySQL 8.4.8 隔离库完成空库 `up/down/up`、重复种子、Go build/vet/race、真实 portal 进程认领、Playwright 四视口和终态验证。 - 用户于 2026-08-21 明确确认 #4 验收通过;MVP-0 的全部单元任务、独立集成验收和父工单均已完成并归档。Epic #3 保持开启,后续 MVP 必须另行确认。 - 验证只使用构造用户、构造图片、mock 上游与测试 fixture;没有连接生产/共享库、调用真实 Provider 额度或发布生产。 +## Provider 凭据风险决策(2026-08-22,待实施) + +用户在了解数据库、备份、接口响应和管理员会话泄露会直接暴露上游密钥的风险后,明确接受 Provider API Key 明文存储和管理员按单条记录主动查看。该目标由 [#30](https://git.ilapage.cn/OPC/chorus/issues/30) 记录,并将在新原型确认后纳入 #24;列表不得批量返回密钥,读取响应不得缓存,真实值仍不得进入代码、日志、审计摘要、错误、工单、Wiki、原型或截图。 + +当前已验收代码仍使用 AES-GCM 和 `CHORUS_MASTER_KEY`,在 #24 的生产迁移完成并通过验收前,运行和部署要求保持不变。 diff --git a/docs/02-architecture-and-code-map.md b/docs/02-architecture-and-code-map.md index 6278d18..bedc6cf 100644 --- a/docs/02-architecture-and-code-map.md +++ b/docs/02-architecture-and-code-map.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Architecture-and-Code-Map wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Architecture-and-Code-Map.- -wiki_revision: a670339f38d3c83e267afa475dcd8b825c8ed8d6 -synchronized_at: 2026-08-22T01:15:06Z +wiki_revision: 5793b6a0b6a077afc8ef2f715f61c4f4189d9267 +synchronized_at: 2026-08-22T01:46:01Z # 架构与代码地图 @@ -301,3 +301,8 @@ go-admin 的 AutoMigrate 只能在隔离、可丢弃数据库中用于研究固 - 生产数据库只接受 `migrations/`,不执行 AutoMigrate。 - `rendered_prompt`、`attempts`、失败 `error_code/error_message` 必须持久化。 - 输出文件先写临时文件并原子落位;图片必须有缩略图。原图、结果和缩略图访问均校验用户归属。 +## 待实施架构变更:Provider 明文凭据 + +[#30](https://git.ilapage.cn/OPC/chorus/issues/30) 已确认目标:#24 将把 `provider_credentials` 调整为明文 API Key 存储,移除管理端 `CHORUS_MASTER_KEY` 和 KeyCipher 装配,并增加受 JWT/Casbin 保护的单 Provider 凭据读取接口。Provider 列表和普通详情不得携带完整密钥;显式读取响应设置 `Cache-Control: no-store`。若迁移发现已有加密凭据,必须停止并走受控转换,不得覆盖或丢弃。 + +本页前文描述的是当前已验收实现;上述变更在 #24 完成、迁移验证和用户验收前不得视为已经上线。 diff --git a/docs/03-business-rules-and-glossary.md b/docs/03-business-rules-and-glossary.md index b401333..3068033 100644 --- a/docs/03-business-rules-and-glossary.md +++ b/docs/03-business-rules-and-glossary.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Business-Rules-and-Glossary wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Business-Rules-and-Glossary.- -wiki_revision: f7c84780525130d468b4e0b0ff84c412846a9fdc -synchronized_at: 2026-08-21T06:55:39Z +wiki_revision: 2d688855b88d9165c79639549e8812ac87a5ec92 +synchronized_at: 2026-08-22T01:46:05Z # 业务规则与术语 @@ -125,3 +125,6 @@ synchronized_at: 2026-08-21T06:55:39Z - 生成物保留期、备份范围、磁盘告警和清理策略; - 生产限流阈值及未来是否开放注册; - 点数来源目前锁定为自有表与管理端发放;若与 cmhub 对接须另建 Epic。 +## 已确认待实施:Provider 凭据明文与单条回显 + +2026-08-22 用户明确接受风险并确认 [#30](https://git.ilapage.cn/OPC/chorus/issues/30):Provider API Key 目标状态改为明文落库,管理员可在单个 Provider 页面显式读取和再次隐藏。列表接口不得批量返回完整值,读取响应必须禁止缓存;日志、审计摘要、错误、工单、Wiki、原型和截图继续禁止记录真实密钥。现有 AES-GCM、版本信封和 `CHORUS_MASTER_KEY` 规则在 #24 完成生产迁移并验收前仍是当前行为。 diff --git a/docs/09-product-requirements-overview.md b/docs/09-product-requirements-overview.md index ca03422..2db4e99 100644 --- a/docs/09-product-requirements-overview.md +++ b/docs/09-product-requirements-overview.md @@ -2,8 +2,8 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Product-Requirements-Overview wiki_url: https://git.ilapage.cn/OPC/chorus/wiki/Product-Requirements-Overview.- -wiki_revision: 9e8b7a7d05f84627f14407000e404d34f7cbf99c -synchronized_at: 2026-08-22T00:39:34Z +wiki_revision: 957788e4c3d27a5b8bff8d1faeaf4c58e288a6a0 +synchronized_at: 2026-08-22T01:46:27Z # 产品需求总览 @@ -257,3 +257,8 @@ MVP-2 的 API Key 存哈希、身份仍属于 `users`。提交、查询、幂等 - [ ] 本页没有复制完整工单或主题文档。 - [ ] 草稿原型没有被描述为正式需求。 - [ ] 不包含凭据、个人数据或生产数据。 +## 2026-08-22 Provider 凭据需求变更 + +用户在获知明文存储和回显风险后明确接受风险:Provider API Key 保存后允许管理员在单个 Provider 编辑页主动查看和隐藏,目标存储形式改为明文。列表仍只展示是否已配置,不批量读取完整密钥;读取失败、无权限、加载和无凭据状态必须可恢复且可访问。 + +设计变更由 [#30](https://git.ilapage.cn/OPC/chorus/issues/30) 跟踪,新快照为 `prototypes/30/v1/index.html`,当前待用户审核。原 #17 v1 的“API Key 只写不可回显”部分被本变更取代,其余管理端设计继续有效。原型确认前不得修改 #24 的生产存储和接口。 diff --git a/prototypes/30/v1/icons.css b/prototypes/30/v1/icons.css new file mode 100644 index 0000000..47fd1be --- /dev/null +++ b/prototypes/30/v1/icons.css @@ -0,0 +1,51 @@ +@font-face { + font-family: "remixicon"; + src: url("./remixicon.woff2") format("woff2"); + font-display: block; +} + +[class^="ri-"]::before, +[class*=" ri-"]::before { + font-family: "remixicon" !important; + font-style: normal; + font-weight: normal !important; + speak: never; + line-height: 1; +} + +.ri-add-line::before { content: "\ea13"; } +.ri-arrow-down-s-line::before { content: "\ea4e"; } +.ri-arrow-left-s-line::before { content: "\ea64"; } +.ri-arrow-right-s-line::before { content: "\ea6e"; } +.ri-check-line::before { content: "\eb7b"; } +.ri-close-line::before { content: "\eb99"; } +.ri-database-2-line::before { content: "\ec16"; } +.ri-drag-move-2-line::before { content: "\ec60"; } +.ri-edit-line::before { content: "\ec86"; } +.ri-error-warning-line::before { content: "\eca1"; } +.ri-eye-line::before { content: "\ecb5"; } +.ri-eye-off-line::before { content: "\ecb7"; } +.ri-file-text-line::before { content: "\ed0f"; } +.ri-fullscreen-line::before { content: "\ed9c"; } +.ri-history-line::before { content: "\ee17"; } +.ri-home-3-line::before { content: "\ee1b"; } +.ri-image-line::before { content: "\ee4b"; } +.ri-information-line::before { content: "\ee59"; } +.ri-key-line::before { content: "\ee71"; } +.ri-list-settings-line::before { content: "\eebd"; } +.ri-loader-4-line::before { content: "\eec6"; } +.ri-lock-line::before { content: "\eece"; } +.ri-menu-fold-line::before { content: "\ef3d"; } +.ri-more-2-line::before { content: "\ef77"; } +.ri-pulse-line::before { content: "\f035"; } +.ri-refresh-line::before { content: "\f064"; } +.ri-route-line::before { content: "\f09b"; } +.ri-save-line::before { content: "\f0b3"; } +.ri-search-line::before { content: "\f0d1"; } +.ri-send-plane-line::before { content: "\f0da"; } +.ri-server-line::before { content: "\f0e0"; } +.ri-settings-3-line::before { content: "\f0e6"; } +.ri-shield-keyhole-line::before { content: "\f107"; } +.ri-stop-circle-line::before { content: "\f19f"; } +.ri-time-line::before { content: "\f20f"; } +.ri-user-line::before { content: "\f264"; } diff --git a/prototypes/30/v1/index.html b/prototypes/30/v1/index.html new file mode 100644 index 0000000..a6ee490 --- /dev/null +++ b/prototypes/30/v1/index.html @@ -0,0 +1,141 @@ + + +
+ + +