{"repo": "chasingwind-z/yidanshi", "files": {"docs/multi-tenant-design.md": {"745529995cee9070251df9bf620520bcd7743b81": {"t": 1785747376.7065654, "n": 4279, "h": "61e9104483784281", "c": "# 多租户改造设计(备用蓝图 · 只设计未动工)\n\n> 2026-07-22 立此存照。触发条件:小红书宣发后「多人版内测」呼声达标(点赞过 X 钩子)。\n> 在那之前**不动工**——别为还不存在的用户先付四笔账(改造/成本/合规/定位)。\n> 总原则(zzf 拍板):**zzf 出基建(容器/MySQL/COS/抠图配额),用户自带 AI(BYOK:\n> 自己配 LLM/生图 key)**。使用说明与设置界面按此重点设计(§5/§6)。\n\n## 0. 模式定位\n\n- **小程序云端 = 多租户**:任何人打开即自动拥有自己的厨房(openid 即身份,零注册)。\n- **Web/本地 = 自托管单用户**:文件模式一字不动,保留开源故事(\"数据在自己手里\")。\n- 两模式一套代码,env 开关 `YIDANSHI_MULTI_TENANT=1`(只在云端开)。\n\n## 1. 责任分界(BYOK 核心)\n\n| 项 | 谁出 | 说明 |\n|---|---|---|\n| 容器/MySQL/COS 存储 | zzf | 配额内免费给用户 |\n| 抠图(阿里云 SegmentFood) | zzf | **每厨房每日限额**(如 5 张),超额自动降级圆框直裁(现成兜底) |\n| AI 文字(整理菜谱/AI 每日荐/食材百科生成) | **用户 key** | 无 key 全部优雅降级(§4 表),app 照常可用 |\n| AI 生图(插画教程卡生成) | **用户 key** | 贵(Seedream ~0.3 元/张),必须 BYOK |\n| 点菜提醒(Server酱) | **用户 key** | 每厨房自己的 SENDKEY,与 BYOK 同一哲学 |\n\n**无 key 降级表(设计底线:不配任何 key 也是完整可用的记录 App)**\n\n| 功能 | 有 key | 无 key |\n|---|---|---|\n| 记菜/记餐/点菜/长图/教程卡导出 | ✓ | ✓(完全一样) |\n| 每日荐 | AI 朱批理由 | 规则版理由(现成,零成本) |\n| 贴链接 AI 整理成菜谱 | ✓ | 手动录入(表单现成) |\n| 食材小百科 | AI 生成并缓存 | 内置 187 条营养库照查 |\n| 插画生成 | ✓ | 无插画,教程卡照出(版式自适应) |\n\n## 2. 数据模型\n\n- 新表 `kitchens`:`openid PK / created / name(默认\"某某的小厨房\"可改)/ guest_token /\n ai_config(JSON 加密,见 §4)/ serverchan_key(加密)/ quota 计数列(今日抠图数、照片总数)`。\n- `recipes / meals / kvdocs` 各加 `owner_openid` 列 + 联合索引 `(owner_openid, id)`;\n kvdocs 主键改 `(owner_openid, name)`。\n- 文件模式(自托管)不加列不迁移——单用户语义天然成立,storage 双实现继续 parity。\n- 迁移:现库数据全部归 zzf openid(一条 UPDATE);zzf 的厨房就是第一个租户。\n\n## 3. 鉴权改造\n\n- `owner_gate` 退役,换 `identity` 中间件:从 `X-WX-OPENID` 得出「当前厨房」,\n 所有读写自动圈定 `owner_openid=me`——**锁从\"门\"变成\"分户\"**,不再需要\n `YIDANSHI_OWNER_OPENID`(退役为迁移标记)。\n- 客人链路不变但 per-kitchen:`/api/guest/*?t=` 与图片通道 `?t=` 先查 t 属于哪个厨房,\n 数据圈到该厨房。客人可同时存多家口令(miniapp storage 存 `{token, 厨房名}` 列表,\n 「去点菜」入口变成多家选择——解你说的\"只能看一个人的菜单\")。\n- h5/无 openid 请求:多租户模式下只放 guest 链路,管理接口 403(云端 web 管理不开放)。\n\n## 4. BYOK AI 设计\n\n- per-kitchen `ai_config`:`{llm: {preset, base_url, model, api_key}, imagegen: {...}}`。\n- **key 加密落库**:Fernet 对称加密,主密钥 `YIDANSHI_MASTER_KEY` 只在云端 env(zzf 掌管);\n API 永不回显完整 key,只回 `sk-…尾4位`;日志全链路禁 print key。\n- llm.py/imagegen.py 从「进程级配置」改「每请求带厨房配置」——调用签名加 `cfg` 参数,\n 自托管模式仍读全局配置(兼容不破)。\n- **预设通道菜单**(降低配置门槛,选预设只填一个 key):\n DeepSeek(推荐首选,注册送额度,自用每月几毛钱)/ Kimi / 智谱 GLM / 通义 /\n 自定义 OpenAI 兼容(base_url+model 全手填)。\n- **「测一测」**:`POST /api/ai/test` 用当前配置真实调一次(限频 1 次/10 秒),\n 回耗时 + 模型回声 + 失败原文(脱敏 key),让用户配完 10 秒内知道通没通。\n- AI 每日荐缓存改 per-kitchen;无 key 厨房直接走规则版不进冷却逻辑。\n\n## 5. 设置界面设计(重点,纸上视觉不变)\n\n设置页重排为六个纸卡区块,自上而下:\n\n1. **我的厨房**:厨房名(默认\"微信昵称的小厨房\",可改,用于长图题签/点菜页抬头)。\n2. **AI 通道**(核心区块):\n - 预设选择:五张小卡横滑(DeepSeek 卡标「推荐 · 注册送额度」章);\n - key 输入框(密文回显尾 4 位)+ 每个预设配一行**去哪拿 key**:\n 「深度求索开放平台注册 → API Keys → 复制」+ 一句费用预期:\n 「自用大约每月几毛钱,充 10 元管一年」;\n - **[测一测]**按钮 + 状态行(「✓ 通了,1.2 秒」/ 失败原文);\n - 降级说明一行小字:「不配也完全能用:AI 理由换成规则版、菜谱手动录入」。\n3. **插画生图**(可选,折叠收起):同构;顶部一句「生成整套插画约 1.8 元/道菜,\n 丰俭由人」——诚实报价是信任的一部分。\n4. **家人点菜与提醒**:点菜卡片(现有)+ Server酱 SENDKEY 输入(配了才有微信提醒,\n 附「sct.ftqq.com 扫码即得」一行)。\n5. **额度**:「今日抠图 2/5 · 照片 37/500」进度条式一行——透明比隐藏好。\n6. **说明书与数据**:「使用说明 ›」入口 +「导出我的数据」+「注销并删除所有数据」\n (合规必备,二次确认)。\n\n文案纪律:说明性文字平实直述(说明书不用朱批腔);不夸大(\"几毛钱\"要真是几毛钱);\n每个需要用户掏钱/注册的地方,先讲为什么(\"AI 的账单跟着你的 key 走,你的用量你做主\")。\n\n## 6. 使用说明页(新页面「说明书」,从设置进)\n\n大纲(手账排版,每节一张纸卡):\n\n1. **三分钟上手**:记一道菜 → 拍照抠图 → 记一餐 → 翻牌子/今日荐。\n2. **为什么 AI 要自己配 key**:诚实三句——这是个人开发者维护的免费 App;\n 服务器/存储/抠图我请客;AI 按用量计费、跟着你的 key 走,你的用量你做主。\n3. **免费与自费对照表**(§1 降级表的用户版)。\n4. **家人点菜怎么玩**:发卡片 → 家人点菜留讲究 → 你收微信提醒(配 Server酱)。\n5. **隐私承诺**:你的食单只有你和你发过卡片的人可见;key 加密存储、只用于你自己的\n 请求、随时可删;注销即全删。\n6. **常见问题**:图片不显示(网络)/ AI 没反应(key 没配或欠费)/ 找不到点菜入口。\n\n## 7. UGC 合规与滥用防护\n\n- **内容安全(微信硬要求,有 UGC 必接)**:照片上传过 `imgSecCheck`、菜名/备注/点单\n 留言过 `msgSecCheck`——需要小程序 **AppSecret** 换 access_token(zzf 亲自填云端 env,\n 沿用\"不经 Claude 手\"纪律)。违规内容拒绝入库并提示。\n- **备案**:正式发布前完成 ICP 备案(个人可办);内测期走体验版免备案。\n- **滥用防护**:内测期厨房总数上限 + 邀请码开通;单厨房配额(菜谱 ≤100 道、\n 照片 ≤500 张、抠图 5 张/日);接口按 openid 限频;「测一测」限频。\n\n## 8. 成本粗估(zzf 侧,100 活跃厨房)\n\nCOS 存储 100×200MB≈20GB ≈ 2 元/月 + 流量看晒图量(约 0.5 元/GB);\nMySQL 现有实例够用;容器按量随请求涨(估 <30 元/月);抠图限额内 100×5×30=1.5 万张/月\n上限(实际远低),阿里云单价 ~0.003 元/张 ≈ 封顶 45 元/月。**量级:百元内/月**,\n超预算就收紧配额——所有阀门都在 zzf 手里。\n\n## 9. 分期\n\n- **M0**:本设计定稿(本文档)+ 呼声钩子发帖验证需求。\n- **M1**(约 1-2 个会话):数据模型迁移 + identity 中间件 + parity/回归。\n- **M2**(约 1 个会话):BYOK(加密/预设/测一测)+ 设置页/说明书两页。\n- **M3**:内容安全接入 + 邀请码内测(体验版渠道)+ 备案启动。\n- **M4**:提审正式发布。\n\n## 10. 未决问题\n\n- 厨房发现机制:完全私密(现设计)vs 允许\"逛别人家\"(社交化,倾向不做——红海+审核重)。\n- Web 管理端要不要多租户版(现设计:不做,Web 专属自托管)。\n- 客人多家口令列表的 UI(多家点菜切换器)细节,实现时定。\n"}, "f6285fe6f8b31ba01592e93ac077c090987aa4da": {"t": 1785772926.382092, "n": 4279, "h": "61e9104483784281", "c": "# 多租户改造设计(备用蓝图 · 只设计未动工)\n\n> 2026-07-22 立此存照。触发条件:小红书宣发后「多人版内测」呼声达标(点赞过 X 钩子)。\n> 在那之前**不动工**——别为还不存在的用户先付四笔账(改造/成本/合规/定位)。\n> 总原则(zzf 拍板):**zzf 出基建(容器/MySQL/COS/抠图配额),用户自带 AI(BYOK:\n> 自己配 LLM/生图 key)**。使用说明与设置界面按此重点设计(§5/§6)。\n\n## 0. 模式定位\n\n- **小程序云端 = 多租户**:任何人打开即自动拥有自己的厨房(openid 即身份,零注册)。\n- **Web/本地 = 自托管单用户**:文件模式一字不动,保留开源故事(\"数据在自己手里\")。\n- 两模式一套代码,env 开关 `YIDANSHI_MULTI_TENANT=1`(只在云端开)。\n\n## 1. 责任分界(BYOK 核心)\n\n| 项 | 谁出 | 说明 |\n|---|---|---|\n| 容器/MySQL/COS 存储 | zzf | 配额内免费给用户 |\n| 抠图(阿里云 SegmentFood) | zzf | **每厨房每日限额**(如 5 张),超额自动降级圆框直裁(现成兜底) |\n| AI 文字(整理菜谱/AI 每日荐/食材百科生成) | **用户 key** | 无 key 全部优雅降级(§4 表),app 照常可用 |\n| AI 生图(插画教程卡生成) | **用户 key** | 贵(Seedream ~0.3 元/张),必须 BYOK |\n| 点菜提醒(Server酱) | **用户 key** | 每厨房自己的 SENDKEY,与 BYOK 同一哲学 |\n\n**无 key 降级表(设计底线:不配任何 key 也是完整可用的记录 App)**\n\n| 功能 | 有 key | 无 key |\n|---|---|---|\n| 记菜/记餐/点菜/长图/教程卡导出 | ✓ | ✓(完全一样) |\n| 每日荐 | AI 朱批理由 | 规则版理由(现成,零成本) |\n| 贴链接 AI 整理成菜谱 | ✓ | 手动录入(表单现成) |\n| 食材小百科 | AI 生成并缓存 | 内置 187 条营养库照查 |\n| 插画生成 | ✓ | 无插画,教程卡照出(版式自适应) |\n\n## 2. 数据模型\n\n- 新表 `kitchens`:`openid PK / created / name(默认\"某某的小厨房\"可改)/ guest_token /\n ai_config(JSON 加密,见 §4)/ serverchan_key(加密)/ quota 计数列(今日抠图数、照片总数)`。\n- `recipes / meals / kvdocs` 各加 `owner_openid` 列 + 联合索引 `(owner_openid, id)`;\n kvdocs 主键改 `(owner_openid, name)`。\n- 文件模式(自托管)不加列不迁移——单用户语义天然成立,storage 双实现继续 parity。\n- 迁移:现库数据全部归 zzf openid(一条 UPDATE);zzf 的厨房就是第一个租户。\n\n## 3. 鉴权改造\n\n- `owner_gate` 退役,换 `identity` 中间件:从 `X-WX-OPENID` 得出「当前厨房」,\n 所有读写自动圈定 `owner_openid=me`——**锁从\"门\"变成\"分户\"**,不再需要\n `YIDANSHI_OWNER_OPENID`(退役为迁移标记)。\n- 客人链路不变但 per-kitchen:`/api/guest/*?t=` 与图片通道 `?t=` 先查 t 属于哪个厨房,\n 数据圈到该厨房。客人可同时存多家口令(miniapp storage 存 `{token, 厨房名}` 列表,\n 「去点菜」入口变成多家选择——解你说的\"只能看一个人的菜单\")。\n- h5/无 openid 请求:多租户模式下只放 guest 链路,管理接口 403(云端 web 管理不开放)。\n\n## 4. BYOK AI 设计\n\n- per-kitchen `ai_config`:`{llm: {preset, base_url, model, api_key}, imagegen: {...}}`。\n- **key 加密落库**:Fernet 对称加密,主密钥 `YIDANSHI_MASTER_KEY` 只在云端 env(zzf 掌管);\n API 永不回显完整 key,只回 `sk-…尾4位`;日志全链路禁 print key。\n- llm.py/imagegen.py 从「进程级配置」改「每请求带厨房配置」——调用签名加 `cfg` 参数,\n 自托管模式仍读全局配置(兼容不破)。\n- **预设通道菜单**(降低配置门槛,选预设只填一个 key):\n DeepSeek(推荐首选,注册送额度,自用每月几毛钱)/ Kimi / 智谱 GLM / 通义 /\n 自定义 OpenAI 兼容(base_url+model 全手填)。\n- **「测一测」**:`POST /api/ai/test` 用当前配置真实调一次(限频 1 次/10 秒),\n 回耗时 + 模型回声 + 失败原文(脱敏 key),让用户配完 10 秒内知道通没通。\n- AI 每日荐缓存改 per-kitchen;无 key 厨房直接走规则版不进冷却逻辑。\n\n## 5. 设置界面设计(重点,纸上视觉不变)\n\n设置页重排为六个纸卡区块,自上而下:\n\n1. **我的厨房**:厨房名(默认\"微信昵称的小厨房\",可改,用于长图题签/点菜页抬头)。\n2. **AI 通道**(核心区块):\n - 预设选择:五张小卡横滑(DeepSeek 卡标「推荐 · 注册送额度」章);\n - key 输入框(密文回显尾 4 位)+ 每个预设配一行**去哪拿 key**:\n 「深度求索开放平台注册 → API Keys → 复制」+ 一句费用预期:\n 「自用大约每月几毛钱,充 10 元管一年」;\n - **[测一测]**按钮 + 状态行(「✓ 通了,1.2 秒」/ 失败原文);\n - 降级说明一行小字:「不配也完全能用:AI 理由换成规则版、菜谱手动录入」。\n3. **插画生图**(可选,折叠收起):同构;顶部一句「生成整套插画约 1.8 元/道菜,\n 丰俭由人」——诚实报价是信任的一部分。\n4. **家人点菜与提醒**:点菜卡片(现有)+ Server酱 SENDKEY 输入(配了才有微信提醒,\n 附「sct.ftqq.com 扫码即得」一行)。\n5. **额度**:「今日抠图 2/5 · 照片 37/500」进度条式一行——透明比隐藏好。\n6. **说明书与数据**:「使用说明 ›」入口 +「导出我的数据」+「注销并删除所有数据」\n (合规必备,二次确认)。\n\n文案纪律:说明性文字平实直述(说明书不用朱批腔);不夸大(\"几毛钱\"要真是几毛钱);\n每个需要用户掏钱/注册的地方,先讲为什么(\"AI 的账单跟着你的 key 走,你的用量你做主\")。\n\n## 6. 使用说明页(新页面「说明书」,从设置进)\n\n大纲(手账排版,每节一张纸卡):\n\n1. **三分钟上手**:记一道菜 → 拍照抠图 → 记一餐 → 翻牌子/今日荐。\n2. **为什么 AI 要自己配 key**:诚实三句——这是个人开发者维护的免费 App;\n 服务器/存储/抠图我请客;AI 按用量计费、跟着你的 key 走,你的用量你做主。\n3. **免费与自费对照表**(§1 降级表的用户版)。\n4. **家人点菜怎么玩**:发卡片 → 家人点菜留讲究 → 你收微信提醒(配 Server酱)。\n5. **隐私承诺**:你的食单只有你和你发过卡片的人可见;key 加密存储、只用于你自己的\n 请求、随时可删;注销即全删。\n6. **常见问题**:图片不显示(网络)/ AI 没反应(key 没配或欠费)/ 找不到点菜入口。\n\n## 7. UGC 合规与滥用防护\n\n- **内容安全(微信硬要求,有 UGC 必接)**:照片上传过 `imgSecCheck`、菜名/备注/点单\n 留言过 `msgSecCheck`——需要小程序 **AppSecret** 换 access_token(zzf 亲自填云端 env,\n 沿用\"不经 Claude 手\"纪律)。违规内容拒绝入库并提示。\n- **备案**:正式发布前完成 ICP 备案(个人可办);内测期走体验版免备案。\n- **滥用防护**:内测期厨房总数上限 + 邀请码开通;单厨房配额(菜谱 ≤100 道、\n 照片 ≤500 张、抠图 5 张/日);接口按 openid 限频;「测一测」限频。\n\n## 8. 成本粗估(zzf 侧,100 活跃厨房)\n\nCOS 存储 100×200MB≈20GB ≈ 2 元/月 + 流量看晒图量(约 0.5 元/GB);\nMySQL 现有实例够用;容器按量随请求涨(估 <30 元/月);抠图限额内 100×5×30=1.5 万张/月\n上限(实际远低),阿里云单价 ~0.003 元/张 ≈ 封顶 45 元/月。**量级:百元内/月**,\n超预算就收紧配额——所有阀门都在 zzf 手里。\n\n## 9. 分期\n\n- **M0**:本设计定稿(本文档)+ 呼声钩子发帖验证需求。\n- **M1**(约 1-2 个会话):数据模型迁移 + identity 中间件 + parity/回归。\n- **M2**(约 1 个会话):BYOK(加密/预设/测一测)+ 设置页/说明书两页。\n- **M3**:内容安全接入 + 邀请码内测(体验版渠道)+ 备案启动。\n- **M4**:提审正式发布。\n\n## 10. 未决问题\n\n- 厨房发现机制:完全私密(现设计)vs 允许\"逛别人家\"(社交化,倾向不做——红海+审核重)。\n- Web 管理端要不要多租户版(现设计:不做,Web 专属自托管)。\n- 客人多家口令列表的 UI(多家点菜切换器)细节,实现时定。\n"}}}}